@enterprisestandard/core 0.0.14-beta.20260331.2 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1860,7 +1860,7 @@ type MetaData = {
1860
1860
  version: number;
1861
1861
  created: Date;
1862
1862
  };
1863
- type SecretsSourceType = "vault" | "lfv" | "azure" | "aws" | "gcp" | "dev";
1863
+ type SecretsSourceType = "vault" | "azure" | "aws" | "gcp" | "dev";
1864
1864
  type SecretRequestSeverity = "low" | "medium" | "high" | "critical";
1865
1865
  type SecretLifecycleRequest = {
1866
1866
  reason?: string;
@@ -1917,7 +1917,7 @@ type SecretsValidators = {
1917
1917
  * Optional hook to validate merged source configs before they are resolved.
1918
1918
  * Throw from this callback to reject invalid secrets source configuration.
1919
1919
  */
1920
- validateSourceConfig?(name: string, config: SecretsSourceConfig): void;
1920
+ validateSourceConfig?(sourceName: string, config: SecretsSourceConfig): void;
1921
1921
  };
1922
1922
  type Secrets = {
1923
1923
  /** Named secrets sources client configurations from RemoteConfig. */
@@ -1925,27 +1925,27 @@ type Secrets = {
1925
1925
  /** Returns configured secrets source names/keys. */
1926
1926
  listSecretsSources(): string[];
1927
1927
  /** Gets a named secrets source client. Throws when missing. */
1928
- getSecretsSource(name: string): SecretsSource;
1928
+ getSecretsSource(sourceName: string): SecretsSource;
1929
1929
  /** Reads a secret from a named secrets source client. */
1930
- getSecret<T>(name: string, path: string, options?: SecretsOperationOptions): Promise<T>;
1930
+ getSecret<T>(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<T>;
1931
1931
  /** Reads full secret data + metadata from a named secrets source client. */
1932
- getFullSecret<T>(name: string, path: string, options?: SecretsOperationOptions): Promise<Secret<T>>;
1932
+ getFullSecret<T>(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<Secret<T>>;
1933
1933
  /** Writes a secret to a named secrets source client. */
1934
- putSecret(name: string, path: string, value: Record<string, unknown>, options?: SecretsOperationOptions): Promise<void>;
1934
+ putSecret(sourceName: string, path: string, value: Record<string, unknown>, options?: SecretsOperationOptions): Promise<void>;
1935
1935
  /** Deletes a secret from a named secrets source client. */
1936
- deleteSecret(name: string, path: string, options?: SecretsOperationOptions): Promise<void>;
1936
+ deleteSecret(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<void>;
1937
1937
  /** Lists child paths under a base path for a named secrets source client. */
1938
- listPaths(name: string, path: string, options?: SecretsOperationOptions): Promise<string[]>;
1938
+ listPaths(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<string[]>;
1939
1939
  /** Returns true when a path exists for a named secrets source client. */
1940
- exists(name: string, path: string, options?: SecretsOperationOptions): Promise<boolean>;
1940
+ exists(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<boolean>;
1941
1941
  /** Requests rotation for a secret path in a named secrets source client. */
1942
- requestRotate(name: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1942
+ requestRotate(sourceName: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1943
1943
  /** Requests revocation for a secret path in a named secrets source client. */
1944
- requestRevoke(name: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1944
+ requestRevoke(sourceName: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1945
1945
  /** Reads metadata for a secret path in a named secrets source client. */
1946
- getMetadata(name: string, path: string, options?: SecretsOperationOptions): Promise<Record<string, unknown>>;
1946
+ getMetadata(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<Record<string, unknown>>;
1947
1947
  /** Subscribes to secret changes on a named secrets source client. */
1948
- subscribe<T>(name: string, path: string, onChange: (fullSecret: Secret<T>) => void): () => void;
1948
+ subscribe<T>(sourceName: string, path: string, onChange: (fullSecret: Secret<T>) => void): () => void;
1949
1949
  /** Returns true when request matches any configured LFV delivery path. */
1950
1950
  isLfvDeliveryRequest?(request: Request): boolean;
1951
1951
  /** Returns true when request matches any configured LFV events path. */
@@ -1969,7 +1969,7 @@ type FrameworkSecretsModuleConfig = Record<string, FrameworkSecretsSourceConfig>
1969
1969
  * TODO: Let's see if we can do some clean inference and remove this!!!
1970
1970
  */
1971
1971
  type SecretsSourceMap = Record<string, SecretsSource>;
1972
- type SecretsSourceConfig = DevSecretsConfig | GcpSecretsConfig | LfvSecretsConfig | VaultSecretsConfig | AwsSecretsConfig | AzureSecretsConfig;
1972
+ type SecretsSourceConfig = DevSecretsConfig | GcpSecretsConfig | VaultSecretsConfig | AwsSecretsConfig | AzureSecretsConfig;
1973
1973
  /**
1974
1974
  * Raw module config keyed by source name.
1975
1975
  * The secrets module resolves this into a runtime SecretsSourceMap.
@@ -1982,8 +1982,7 @@ type DevSecretsConfig = {
1982
1982
  type GcpSecretsConfig = {
1983
1983
  type: "gcp";
1984
1984
  };
1985
- type LfvSecretsConfig = {
1986
- type: "lfv";
1985
+ type VaultLfvSecretsConfig = {
1987
1986
  /** LFV server base URL for OTP/action endpoints. */
1988
1987
  lfvServerUrl?: string;
1989
1988
  /** LFV client id used for OTP issuance. */
@@ -2017,15 +2016,28 @@ type LfvSecretsConfig = {
2017
2016
  * Runtime-ready LFV source config.
2018
2017
  * Input config can be partially declared/merged, but LFV operations require these fields.
2019
2018
  */
2020
- type ResolvedLfvSecretsConfig = Omit<LfvSecretsConfig, "lfvServerUrl" | "clientId" | "path"> & {
2019
+ type ResolvedVaultLfvSecretsConfig = Omit<VaultLfvSecretsConfig, "lfvServerUrl" | "clientId" | "path"> & {
2021
2020
  lfvServerUrl: string;
2022
2021
  clientId: string;
2023
2022
  path: string;
2024
2023
  };
2024
+ type VaultWebSocketAuthHeader = "X-Vault-Token" | "Authorization";
2025
+ type VaultWebSocketSecretsConfig = {
2026
+ /** Websocket URL for vault command execution and live secret subscriptions. */
2027
+ url?: string;
2028
+ /** Token used during websocket connect/auth. */
2029
+ token?: string;
2030
+ /** Header name used to send the websocket token. Defaults to X-Vault-Token. */
2031
+ header?: VaultWebSocketAuthHeader;
2032
+ };
2025
2033
  type VaultSecretsConfig = {
2026
2034
  type: "vault";
2027
2035
  url?: string;
2028
2036
  token?: string;
2037
+ /** Optional LFV transport capability for reads/lifecycle operations. */
2038
+ lfv?: VaultLfvSecretsConfig;
2039
+ /** Optional websocket capability for vault commands and live subscriptions. */
2040
+ websocket?: VaultWebSocketSecretsConfig;
2029
2041
  /**
2030
2042
  * MINIMUM: 600_000 milliseconds (10 minutes). Polls the path every ttl milliseconds and calls onConfig when config changes.
2031
2043
  */
@@ -2131,7 +2143,6 @@ interface UpsertTenantRequest {
2131
2143
  email?: string;
2132
2144
  webhookUrl?: string;
2133
2145
  callbackUrl?: string;
2134
- tenantUrl: string;
2135
2146
  configSource: TenantSecretsConfig;
2136
2147
  }
2137
2148
  type UpsertTenantResponse = {
@@ -2193,26 +2204,22 @@ type TenantValidators = {
2193
2204
  */
2194
2205
  type TenantConfigEnv = {
2195
2206
  ES_CONFIG_TYPE?: ConfigSourceType;
2196
- ES_APP_ID?: string;
2197
- ES_CONFIG_PATH?: string;
2198
- ES_IONITE_URL?: string;
2199
- ES_LFV_PATH?: string;
2200
- ES_LFV_SERVER_URL?: string;
2201
- ES_LFV_CLIENT_ID?: string;
2202
- ES_LFV_SIGNATURE?: string;
2203
- ES_LFV_DELIVERY_ENDPOINT?: string;
2204
- ES_LFV_VERIFY_PUBLIC_KEY?: string;
2205
- ES_LFV_EVENTS_ENDPOINT?: string;
2206
- ES_LFV_DELIVERY_TIMEOUT?: string;
2207
- ES_LFV_RETRY_INTERVAL?: string;
2208
- ES_LFV_WARN_INTERVAL?: string;
2209
- ES_FILE_PATH?: string;
2210
- ES_FILE_WATCH?: string;
2211
- ES_FILE_TTL?: string;
2212
2207
  ES_VAULT_URL?: string;
2213
2208
  ES_VAULT_TOKEN?: string;
2214
2209
  ES_VAULT_PATH?: string;
2215
2210
  ES_VAULT_TTL?: string;
2211
+ ES_VAULT_LFV_SERVER_URL?: string;
2212
+ ES_VAULT_LFV_CLIENT_ID?: string;
2213
+ ES_VAULT_LFV_SIGNATURE?: string;
2214
+ ES_VAULT_LFV_DELIVERY_ENDPOINT?: string;
2215
+ ES_VAULT_LFV_VERIFY_PUBLIC_KEY?: string;
2216
+ ES_VAULT_LFV_EVENTS_ENDPOINT?: string;
2217
+ ES_VAULT_LFV_DELIVERY_TIMEOUT?: string;
2218
+ ES_VAULT_LFV_RETRY_INTERVAL?: string;
2219
+ ES_VAULT_LFV_WARN_INTERVAL?: string;
2220
+ ES_VAULT_WEBSOCKET_URL?: string;
2221
+ ES_VAULT_WEBSOCKET_TOKEN?: string;
2222
+ ES_VAULT_WEBSOCKET_HEADER?: "X-Vault-Token" | "Authorization";
2216
2223
  ES_AZURE_API_VERSION?: string;
2217
2224
  ES_AZURE_SCOPE?: string;
2218
2225
  ES_AZURE_SECRET_NAME_PREFIX?: string;
@@ -2230,23 +2237,32 @@ type TenantConfigEnv = {
2230
2237
  ES_AWS_TTL?: string;
2231
2238
  ES_GCP_TTL?: string;
2232
2239
  };
2233
- type TenantSecretsConfig = LfvSecretsConfig | (VaultSecretsConfig & {
2240
+ type TenantSecretsConfig = (VaultSecretsConfig & {
2234
2241
  path: string;
2235
2242
  retryInterval?: number;
2236
- }) | (DevSecretsConfig & {
2237
- path?: string;
2238
- appId?: string;
2239
2243
  }) | (AwsSecretsConfig & {
2240
2244
  ttl?: number;
2241
2245
  }) | AzureSecretsConfig | (GcpSecretsConfig & {
2242
2246
  ttl?: number;
2243
- }) | {
2244
- type: "localFile";
2245
- path?: string;
2246
- watch?: boolean;
2247
- ttl?: number;
2247
+ });
2248
+ type TenantStoredConfigLocator = {
2249
+ /** Indicates that the tenant config descriptor is stored securely outside the tenant record. */
2250
+ type: "stored";
2251
+ /** Root secure source type used to fetch the stored tenant config descriptor. */
2252
+ sourceType: "vault";
2253
+ /** Path to the stored tenant config descriptor. */
2254
+ path: string;
2255
+ };
2256
+ type TenantRemoteConfigLocator = {
2257
+ /** Indicates that the tenant RemoteConfig already exists at this secure source path. */
2258
+ type: "remoteConfig";
2259
+ /** Secure source type used to load the RemoteConfig document directly. */
2260
+ sourceType: "vault";
2261
+ /** Path to the tenant RemoteConfig document. */
2262
+ path: string;
2248
2263
  };
2249
- type TenantConfigSourceInput = TenantSecretsConfig | ConfigSource;
2264
+ type TenantConfigLocator = TenantStoredConfigLocator | TenantRemoteConfigLocator;
2265
+ type TenantConfigSourceInput = TenantConfigLocator | ConfigSource;
2250
2266
  type TenantBaseRecord = {
2251
2267
  tenantId: string;
2252
2268
  companyId: string;
@@ -2266,11 +2282,18 @@ type TenantBaseRecord = {
2266
2282
  /** Persisted tenant config metadata, or a runtime ConfigSource for internal-only tenants. */
2267
2283
  configSource: TenantConfigSourceInput;
2268
2284
  /** Runtime helper that returns a ConfigSource for this tenant. */
2269
- config: () => ConfigSource;
2285
+ config: (source?: SecretsSource) => ConfigSource;
2270
2286
  };
2271
2287
  type StoredTenant<TExtended extends object = Record<string, never>> = TenantBaseRecord & TExtended;
2272
2288
  type StoredTenantRecord<TExtended extends object = Record<string, never>> = Omit<StoredTenant<TExtended>, "config">;
2273
2289
  type TenantEsFactory<TExtended extends object = Record<string, never>> = (tenant: StoredTenant<TExtended>) => EnterpriseStandard;
2290
+ type TenantConfigStoreRequest<TExtended extends object = Record<string, never>> = {
2291
+ es: EnterpriseStandard;
2292
+ tenantId: string;
2293
+ request: UpsertTenantRequest;
2294
+ configData: TenantSecretsConfig;
2295
+ existingTenant: StoredTenant<TExtended> | null;
2296
+ };
2274
2297
  type TenantStoreWithESOptions<TExtended extends object = Record<string, never>> = {
2275
2298
  /**
2276
2299
  * TTL for cached per-tenant EnterpriseStandard instances, in milliseconds.
@@ -2294,6 +2317,7 @@ type TenantStoreBase<
2294
2317
  TMode extends UserMode = "singleTenantOnly",
2295
2318
  TExtended extends object = Record<string, never>
2296
2319
  > = TenantUserRegistration<TMode> & {
2320
+ storeConfig(config: TenantConfigStoreRequest<TExtended>): Promise<TenantConfigSourceInput>;
2297
2321
  get(tenantId: string): Promise<StoredTenant<TExtended> | null>;
2298
2322
  list(options?: TenantListOptions): Promise<ListResult<StoredTenant<TExtended>>>;
2299
2323
  upsert(tenant: TenantStoreUpsertRecord<TExtended>): Promise<StoredTenant<TExtended>>;
@@ -2441,7 +2465,7 @@ interface MagicLinkStore<TExtended = object> {
2441
2465
  */
2442
2466
  delete(token: string): Promise<void>;
2443
2467
  }
2444
- type ConfigSourceType = "vault" | "lfv" | "azure" | "aws" | "gcp" | "dev" | "localFile";
2468
+ type ConfigSourceType = "vault" | "azure" | "aws" | "gcp";
2445
2469
  type ESValidators = {
2446
2470
  sso: SSOValidators;
2447
2471
  iam: IAMValidators;
@@ -2523,6 +2547,11 @@ type ConfigSource = {
2523
2547
  */
2524
2548
  subscribe(onConfig: (config: RemoteConfig) => void): undefined | (() => void);
2525
2549
  /**
2550
+ * Default secret client for the config source itself.
2551
+ * For vault-backed sources this is the vault used to read RemoteConfig.
2552
+ */
2553
+ secret: SecretsSource;
2554
+ /**
2526
2555
  * Optional. If not set by the creator, the framework may set this before calling load/subscribe
2527
2556
  * so the source can use the same logger.
2528
2557
  */
@@ -2575,6 +2604,8 @@ type EnterpriseStandardBase = {
2575
2604
  tenantId?: string;
2576
2605
  /** Most recent remote config applied to this instance (from ConfigSource, after beforeChange if any). */
2577
2606
  config?: RemoteConfig;
2607
+ /** Default config-source-backed secret client, typically the vault used for RemoteConfig. */
2608
+ secret: SecretsSource;
2578
2609
  secrets?: Secrets;
2579
2610
  sso?: SSO;
2580
2611
  iam?: IAM;
@@ -2599,6 +2630,7 @@ type EnterpriseStandardStrict<C extends FrameworkConfig> = {
2599
2630
  logger?: Logger;
2600
2631
  tenantId?: string;
2601
2632
  config?: RemoteConfig;
2633
+ secret: SecretsSource;
2602
2634
  secrets: ESModuleFromConfig<C, "secrets", Secrets & NamedSecretsFromConfig<C>>;
2603
2635
  sso: ESModuleFromConfig<C, "sso", SSO>;
2604
2636
  iam: ESModuleFromConfig<C, "iam", IAM>;
@@ -3013,16 +3045,140 @@ interface EnterpriseUser extends BaseUser {
3013
3045
  };
3014
3046
  }
3015
3047
  import { StandardSchemaV1 as StandardSchemaV19 } from "@standard-schema/spec";
3048
+ type RegisterSSOAppPayload = {
3049
+ /** Redirect URIs for the client. */
3050
+ redirectUris: string[];
3051
+ /** Optional back-channel logout URI. */
3052
+ backchannelLogoutUri?: string;
3053
+ /** Optional display name for IdP UIs. */
3054
+ displayName?: string;
3055
+ /** Optional default scope (e.g. openid profile email). */
3056
+ defaultScope?: string;
3057
+ /** Optional customer tenant identifier for the tenant-scoped issuer. */
3058
+ tenantId?: string;
3059
+ /** Optional application identifier so one tenant can register multiple clients. */
3060
+ applicationId?: string;
3061
+ };
3062
+ type RegisterSSOAppResult = {
3063
+ registered: true;
3064
+ /** OIDC client_id; required on success (issued by IdP). */
3065
+ clientId: string;
3066
+ /** OIDC client secret; required on success (issued by IdP). */
3067
+ clientSecret: string;
3068
+ /** OIDC authority/issuer base URL exposed by the IdP. */
3069
+ authority: string;
3070
+ /** OIDC authorization endpoint URL exposed by the IdP. */
3071
+ authorizationUrl: string;
3072
+ /** OIDC JWKS endpoint URL exposed by the IdP. */
3073
+ jwksUri: string;
3074
+ /** OIDC token endpoint URL exposed by the IdP. */
3075
+ tokenUrl: string;
3076
+ appId?: string;
3077
+ message?: string;
3078
+ };
3079
+ type RegisterSSOAppError = {
3080
+ status: number;
3081
+ code?: string;
3082
+ message?: string;
3083
+ details?: unknown;
3084
+ };
3085
+ type SSOAppRegistry = {
3086
+ register: (payload: RegisterSSOAppPayload) => Promise<RegisterSSOAppResult>;
3087
+ };
3088
+ type SSOAppValidators = {
3089
+ registerSSOAppPayload: StandardSchemaV19<unknown, RegisterSSOAppPayload>;
3090
+ };
3091
+ type IAMAppRole = "authoritative_source" | "provisioning_target";
3092
+ type RegisterIAMAppPayload = {
3093
+ /** App/tenant identifier (same tenantId used by the ESA). */
3094
+ tenantId: string;
3095
+ /** Company identifier (reporting only). */
3096
+ companyId: string;
3097
+ /** Company name. */
3098
+ companyName: string;
3099
+ /** Environment type (POC, DEV, QA, PROD). */
3100
+ environmentType: EnvironmentType;
3101
+ /** Base URL of the tenant (if known). */
3102
+ tenantUrl?: string;
3103
+ /** Display name for ESP UIs. */
3104
+ displayName?: string;
3105
+ /** Product identifier (optional categorization for ESPs/ESIs). */
3106
+ productId?: string;
3107
+ /** Application identifier (optional categorization for ESPs/ESIs). */
3108
+ applicationId?: string;
3109
+ /** Base URL for the ESA's SCIM endpoints (e.g. https://tenant/app/api/es/iam). */
3110
+ scimBaseUrl?: string;
3111
+ /** Workload identity configuration the ESP should use to call the ESA. */
3112
+ workload?: WorkloadConfig;
3113
+ /**
3114
+ * SCIM userType values for which this ESA is an HR/source (e.g. Employee, Contractor, Vendor).
3115
+ * The IAM ESP uses this to choose which ESA to pull from or trust for attributes per user type.
3116
+ */
3117
+ sourceUserTypes?: string[];
3118
+ /**
3119
+ * Optional IAM-specific roles for this registration.
3120
+ * Use `authoritative_source` when this app is the source of truth for identity attributes and
3121
+ * `provisioning_target` when onboarding should provision into this app.
3122
+ */
3123
+ iamRoles?: IAMAppRole[];
3124
+ };
3125
+ type RegisterIAMAppResult = {
3126
+ registered: true;
3127
+ appId?: string;
3128
+ message?: string;
3129
+ };
3130
+ type RegisterIAMAppError = {
3131
+ status: number;
3132
+ code?: string;
3133
+ message?: string;
3134
+ details?: unknown;
3135
+ };
3136
+ type IAMAppRegistry = {
3137
+ register: (payload: RegisterIAMAppPayload) => Promise<RegisterIAMAppResult>;
3138
+ };
3139
+ type IAMAppValidators = {
3140
+ registerIAMAppPayload: StandardSchemaV19<unknown, RegisterIAMAppPayload>;
3141
+ };
3142
+ type LfvActionName = "read_secret" | "create_secret" | "update_secret" | "delete_secret" | "request_rotate" | "request_revoke" | "rotate_secret" | "revoke_secret" | "list_paths" | "list_secrets" | "read_metadata" | "read_acl" | "write_acl" | "remove_path";
3143
+ type LfvOtpRequest = {
3144
+ request_id: string;
3145
+ path: string;
3146
+ action: LfvActionName;
3147
+ ttl?: number;
3148
+ };
3149
+ type LfvOtpResponse = {
3150
+ request_id: string;
3151
+ otp: string;
3152
+ expires_at: string;
3153
+ action: LfvActionName;
3154
+ path: string;
3155
+ };
3156
+ type LfvActionRequestBase = {
3157
+ request_id: string;
3158
+ otp: string;
3159
+ path: string;
3160
+ };
3161
+ type LfvActionAcceptedResponse = {
3162
+ request_id: string;
3163
+ operation_id: string;
3164
+ status: "pending" | "accepted" | "completed";
3165
+ };
3166
+ type LfvErrorCode = "invalid_request" | "invalid_signature" | "permission_denied" | "not_found" | "otp_already_used" | "otp_expired" | "rate_limited" | "internal_error";
3167
+ type LfvErrorResponse = {
3168
+ error: LfvErrorCode;
3169
+ message: string;
3170
+ };
3171
+ import { StandardSchemaV1 as StandardSchemaV110 } from "@standard-schema/spec";
3016
3172
  /**
3017
3173
  * Result type for Standard Schema validation (success or failure).
3018
3174
  */
3019
- type ValidateResult<T> = StandardSchemaV19.Result<T>;
3175
+ type ValidateResult<T> = StandardSchemaV110.Result<T>;
3020
3176
  /**
3021
3177
  * A Standard Schema with a top-level `validate()` method for a cleaner API.
3022
3178
  * Use this so callers can call `schema.validate(value)` instead of `schema['~standard'].validate(value)`.
3023
3179
  */
3024
- type StandardSchemaWithValidate<T> = StandardSchemaV19<unknown, T> & {
3025
- validate(value: unknown): Promise<StandardSchemaV19.Result<T>>;
3180
+ type StandardSchemaWithValidate<T> = StandardSchemaV110<unknown, T> & {
3181
+ validate(value: unknown): Promise<StandardSchemaV110.Result<T>>;
3026
3182
  };
3027
3183
  /**
3028
3184
  * Wraps a Standard Schema so it has a top-level `validate(value)` method.
@@ -3033,7 +3189,7 @@ type StandardSchemaWithValidate<T> = StandardSchemaV19<unknown, T> & {
3033
3189
  * const baseUser = withValidate(createBaseUserValidator());
3034
3190
  * const result = await baseUser.validate(requestBody);
3035
3191
  */
3036
- declare function withValidate<T>(schema: StandardSchemaV19<unknown, T>): StandardSchemaWithValidate<T>;
3192
+ declare function withValidate<T>(schema: StandardSchemaV110<unknown, T>): StandardSchemaWithValidate<T>;
3037
3193
  declare function must<T>(value: T | undefined | null, message?: string): T;
3038
3194
  /**
3039
3195
  * Returns a 400 Response with the issues if there are any.
@@ -3066,4 +3222,4 @@ declare function parseJsonc<T>(content: string): T;
3066
3222
  * @returns A promise that resolves when the service is ready.
3067
3223
  */
3068
3224
  declare function waitOn(url: string, test?: (resp: Response) => boolean | Promise<boolean>, pingInterval?: number, warnInterval?: number, timeout?: number): Promise<void>;
3069
- export { workloadTokenResponseSchema, withValidate, waitOn, version, validationFailureResponse, userSchema, tokenResponseSchema, stripJsonComments, silentLogger, setActiveSession, serializeESConfig, sendTenantWebhook, parseJsonc, oidcCallbackSchema, normalizeTenantRoutingStrategy, normalizeTenantPathNamespace, must, mergeConfig, matchTenantPath, listSsoClientIdsFromCookies, list, jwtAssertionClaimsSchema, infoLogger, idTokenClaimsSchema, groupResourceSchema, getActiveSession, findTenantFromStateParam, defaultLogger, decodeUser, debugLogger, consoleLogger, clearActiveSession, claimsToUser, buildTenantPath, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadIncomingOutgoing, WorkloadIdentity, WorkloadConfigMap, WorkloadConfig, WorkloadClient, Workload, VaultSecretsConfig, ValidateResult, UsersInboundHandlerConfig, UserStore, UserSortOptions, UserSortField, UserMode, UserListOptions, User2 as User, UpsertTenantResponse, UpsertTenantRequest, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantUserRegistration, TenantStoreWithESOptions, TenantStoreWithES, TenantStoreUpsertRecord, TenantStore, TenantStatus, TenantSortOptions, TenantSortField, TenantSecretsConfig, TenantRoutingStrategy, TenantRequestError, TenantPathRoutingStrategy, TenantPathNamespace, TenantPathMatch, TenantListOptions, TenantJwtRoutingStrategy, TenantEsFactory, TenantDirectoryTenant, TenantDirectoryResponse, TenantDirectoryAccount, TenantConfigSourceInput, TenantConfigEnv, StoredUser, StoredTenantRecord, StoredTenant, StoredGroup, StateCookie, StandardSchemaWithValidate, SortDirection, SessionStore, Session, ServerOnlyWorkloadConfig, SecretsValidators, SecretsSourceType, SecretsSourceMap, SecretsSourceConfig, SecretsSource, SecretsOperationOptions, SecretsModuleConfig, Secrets, SecretRequestSeverity, SecretLifecycleRequest, Secret, User as ScimUser, ScimResult, ScimListResponse, ScimError, SSOValidators, SSOHandlerConfig, SSOConfig, SSO, Role, ResolvedLfvSecretsConfig, RemoteConfig, Photo, PhoneNumber, OidcCallbackParams, Name, MultipleTenantsForUserError, ModifiableFrameworkConfig, MetaData, MagicLinkStore, MagicLink, LoginConfig, Logger, ListResult, LfvSecretsConfig, JwtBearerWorkloadConfig, JWTAssertionClaims, InMemoryTenantStoreOptions, InMemoryTenantStore, IdTokenClaims, IAMValidators, IAMUsersInbound, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMConfig, IAM, GroupsInboundHandlerConfig, GroupStore, GroupSortOptions, GroupSortField, GroupResource, GroupMember, GroupListOptions, Group, GcpSecretsConfig, FrameworkWorkloadIncomingOutgoing, FrameworkWorkloadConfig, FrameworkStores, FrameworkSecretsSourceConfig, FrameworkSecretsModuleConfig, FrameworkConfig, EnvironmentType, EnterpriseUser, EnterpriseStandardFromConfig, EnterpriseStandardBase, EnterpriseStandard, EnterpriseExtension, Email, ESValidators, ESRoutingOptions, ESRouteModule, ESRouteFilterResult, ESResolvedRoute, ESModuleFromConfig, ESConfigChangeResult, ESConfigChangeOptions, ESConfigChangeCallback, ESConfig, DevSecretsConfig, DEFAULT_TENANT_UI_NAMESPACE, DEFAULT_TENANT_API_NAMESPACE, CreateUserOptions, CreateTenantResponse, CreateTenantRequest, CreateGroupOptions, ConfigSourceType, ConfigSource, ClientCredentialsWorkloadConfig, CachedWorkloadToken, CIAMValidators, CIAMConfigFromCode, CIAMConfig, CIAM, BaseUser, AzureSecretsConfig, AwsSecretsConfig, AwsAuthMethod, ApplicationValidators, Address };
3225
+ export { workloadTokenResponseSchema, withValidate, waitOn, version, validationFailureResponse, userSchema, tokenResponseSchema, stripJsonComments, silentLogger, setActiveSession, serializeESConfig, sendTenantWebhook, parseJsonc, oidcCallbackSchema, normalizeTenantRoutingStrategy, normalizeTenantPathNamespace, must, mergeConfig, matchTenantPath, listSsoClientIdsFromCookies, list, jwtAssertionClaimsSchema, infoLogger, idTokenClaimsSchema, groupResourceSchema, getActiveSession, findTenantFromStateParam, defaultLogger, decodeUser, debugLogger, consoleLogger, clearActiveSession, claimsToUser, buildTenantPath, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadIncomingOutgoing, WorkloadIdentity, WorkloadConfigMap, WorkloadConfig, WorkloadClient, Workload, VaultWebSocketSecretsConfig, VaultWebSocketAuthHeader, VaultSecretsConfig, VaultLfvSecretsConfig, ValidateResult, UsersInboundHandlerConfig, UserStore, UserSortOptions, UserSortField, UserMode, UserListOptions, User2 as User, UpsertTenantResponse, UpsertTenantRequest, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantUserRegistration, TenantStoredConfigLocator, TenantStoreWithESOptions, TenantStoreWithES, TenantStoreUpsertRecord, TenantStore, TenantStatus, TenantSortOptions, TenantSortField, TenantSecretsConfig, TenantRoutingStrategy, TenantRequestError, TenantRemoteConfigLocator, TenantPathRoutingStrategy, TenantPathNamespace, TenantPathMatch, TenantListOptions, TenantJwtRoutingStrategy, TenantEsFactory, TenantDirectoryTenant, TenantDirectoryResponse, TenantDirectoryAccount, TenantConfigStoreRequest, TenantConfigSourceInput, TenantConfigLocator, TenantConfigEnv, StoredUser, StoredTenantRecord, StoredTenant, StoredGroup, StateCookie, StandardSchemaWithValidate, SortDirection, SessionStore, Session, ServerOnlyWorkloadConfig, SecretsValidators, SecretsSourceType, SecretsSourceMap, SecretsSourceConfig, SecretsSource, SecretsOperationOptions, SecretsModuleConfig, Secrets, SecretRequestSeverity, SecretLifecycleRequest, Secret, User as ScimUser, ScimResult, ScimListResponse, ScimError, SSOValidators, SSOHandlerConfig, SSOConfig, SSOAppValidators, SSOAppRegistry, SSO, Role, ResolvedVaultLfvSecretsConfig, RemoteConfig, RegisterSSOAppResult, RegisterSSOAppPayload, RegisterSSOAppError, RegisterIAMAppResult, RegisterIAMAppPayload, RegisterIAMAppError, Photo, PhoneNumber, OidcCallbackParams, Name, MultipleTenantsForUserError, ModifiableFrameworkConfig, MetaData, MagicLinkStore, MagicLink, LoginConfig, Logger, ListResult, LfvOtpResponse, LfvOtpRequest, LfvErrorResponse, LfvErrorCode, LfvActionRequestBase, LfvActionName, LfvActionAcceptedResponse, JwtBearerWorkloadConfig, JWTAssertionClaims, InMemoryTenantStoreOptions, InMemoryTenantStore, IdTokenClaims, IAMValidators, IAMUsersInbound, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMConfig, IAMAppValidators, IAMAppRole, IAMAppRegistry, IAM, GroupsInboundHandlerConfig, GroupStore, GroupSortOptions, GroupSortField, GroupResource, GroupMember, GroupListOptions, Group, GcpSecretsConfig, FrameworkWorkloadIncomingOutgoing, FrameworkWorkloadConfig, FrameworkStores, FrameworkSecretsSourceConfig, FrameworkSecretsModuleConfig, FrameworkConfig, EnvironmentType, EnterpriseUser, EnterpriseStandardFromConfig, EnterpriseStandardBase, EnterpriseStandard, EnterpriseExtension, Email, ESValidators, ESRoutingOptions, ESRouteModule, ESRouteFilterResult, ESResolvedRoute, ESModuleFromConfig, ESConfigChangeResult, ESConfigChangeOptions, ESConfigChangeCallback, ESConfig, DevSecretsConfig, DEFAULT_TENANT_UI_NAMESPACE, DEFAULT_TENANT_API_NAMESPACE, CreateUserOptions, CreateTenantResponse, CreateTenantRequest, CreateGroupOptions, ConfigSourceType, ConfigSource, ClientCredentialsWorkloadConfig, CachedWorkloadToken, CIAMValidators, CIAMConfigFromCode, CIAMConfig, CIAM, BaseUser, AzureSecretsConfig, AwsSecretsConfig, AwsAuthMethod, ApplicationValidators, Address };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{I as B,a as D0,b as T0,c as $0,d as f0,e as x0,f as A0,g as Q0,h as X0,i as Z0,j as G0,k as R0,l as Y0,m as c0,n as y0,o as z0,p as B0,q as H0,t as N0,u as W0,v as C0,w as M0,x as _0}from"./shared/core-tyde8csq.js";var k="0.0.14-beta.20260331.2";var V=["sessionStore","userStore","groupStore","tokenStore","magicLinkStore"];function C(L){if(L===null||typeof L!=="object")return L;let T={};for(let[J,D]of Object.entries(L)){if(V.includes(J)||J==="validators"||J==="setStores")continue;T[J]=D!==null&&typeof D==="object"&&!Array.isArray(D)&&Object.getPrototypeOf(D)===Object.prototype?C(D):D}return T}function E(L){return C(L)}function z(L,T,J,D){let $=T.length,A=D??L,f=A>0?Math.floor(J/A)+1:1,x=A>0?Math.ceil(L/A):0;return{total:L,count:$,items:T,size:A,page:f,pages:x}}class N extends Error{constructor(L,T){super(L,T);this.name="TenantRequestError",Object.setPrototypeOf(this,N.prototype)}}class c extends Error{userId;tenantIds;constructor(L,T,J){super(`Multiple tenants found for user id "${L}"`,J);this.name="MultipleTenantsForUserError",this.userId=L,this.tenantIds=T,Object.setPrototypeOf(this,c.prototype)}}var H=Number.POSITIVE_INFINITY;class M{tenants=new Map;tenantEsMap=new Map;userTenantIds=new Map;ttl;userMode;createEs;findTenantByUserId;findTenantsByUserId;constructor(L){if(this.ttl=O(L.ttl),this.userMode=L.userMode,this.createEs=L.createEs,this.userMode==="singleTenantOnly"){this.findTenantByUserId=this.findSingleTenantByUserId.bind(this),this.findTenantsByUserId=void 0;return}this.findTenantByUserId=void 0,this.findTenantsByUserId=this.findMultipleTenantsByUserId.bind(this)}async get(L){return this.tenants.get(L)??null}async list(L){let T=Array.from(this.tenants.values()),J=Math.max(0,L?.start??0),D=L?.limit,$=L?.sort;if($?.length)T=[...T].sort((X,G)=>{for(let{field:Z,direction:q}of $){let F=X[Z],U=G[Z],y=j(F,U);if(y!==0)return q==="desc"?-y:y}return 0});let A=T.length,f=D!=null?J+D:void 0,x=T.slice(J,f);return z(A,x,J,D)}async upsert(L){let T=new Date,J=this.tenants.get(L.tenantId),D={...J??{},...L,companyId:L.companyId??J?.companyId??"",companyName:L.companyName??J?.companyName??"",environmentType:L.environmentType??J?.environmentType??"DEV",email:L.email??J?.email,webhookUrl:L.webhookUrl??J?.webhookUrl,callbackUrl:L.callbackUrl??J?.callbackUrl,tenantUrl:L.tenantUrl??J?.tenantUrl,status:L.status??J?.status??"completed",createdAt:L.createdAt??J?.createdAt??T,updatedAt:L.updatedAt??T};return this.tenants.set(D.tenantId,D),this.tenantEsMap.delete(D.tenantId),D}async delete(L){this.tenantEsMap.delete(L),this.tenants.delete(L)}async getEs(L){let T=await this.get(L);if(!T)throw Error(`Tenant "${L}" not found`);if(!this.createEs)throw Error("InMemoryTenantStore requires options.createEs to use getEs()");if(this.ttl===0)return this.createEs(B(T));let J=Date.now(),D=this.tenantEsMap.get(L);if(D&&D.expiresAt>J)return D.es;if(D)this.tenantEsMap.delete(L);let $=this.createEs(B(T));return this.tenantEsMap.set(L,{es:$,expiresAt:g(J,this.ttl)}),$}getCachedTenantIds(){if(this.ttl===0)return[];let L=Date.now();for(let[T,J]of this.tenantEsMap.entries())if(J.expiresAt<=L)this.tenantEsMap.delete(T);return Array.from(this.tenantEsMap.keys())}async registerUserTenantId(L,T){if(!L)return;let J=S(T);if(this.userMode==="singleTenantOnly"){this.userTenantIds.set(L,new Set([J]));return}let D=this.userTenantIds.get(L);if(D){D.add(J);return}this.userTenantIds.set(L,new Set([J]))}async findSingleTenantByUserId(L){let T=await this.resolveTenantsByUserId(L);if(T.length>1)throw new c(L,T.map((J)=>J.tenantId));return T[0]??null}async findMultipleTenantsByUserId(L){return this.resolveTenantsByUserId(L)}async resolveTenantsByUserId(L){let T=this.userTenantIds.get(L);if(!T||T.size===0)return[];let J=T.has(null),D=Array.from(T).filter((f)=>f!=null);if(D.length===0)return[];let $=await Promise.all(D.map(async(f)=>({tenantId:f,tenant:await this.get(f)}))),A=$.filter((f)=>f.tenant!=null).map((f)=>f.tenantId);if(A.length===0){if(J)this.userTenantIds.set(L,new Set([null]));else this.userTenantIds.delete(L);return[]}if(A.length!==D.length){let f=J?[null,...A]:A;this.userTenantIds.set(L,new Set(f))}return $.map((f)=>f.tenant).filter((f)=>f!=null)}}function j(L,T){let J=L===void 0||L===null,D=T===void 0||T===null;if(J&&D)return 0;if(J)return 1;if(D)return-1;if(L instanceof Date&&T instanceof Date)return L.getTime()-T.getTime();let $=String(L),A=String(T);return $.localeCompare(A)}function S(L){if(typeof L!=="string")return null;return L.trim()||null}function O(L){if(L===void 0)return H;if(L<=0)return L===0?0:H;return L}function g(L,T){if(!Number.isFinite(T))return H;return L+T}function I(L,T,J){return(async()=>{try{let D=await fetch(L,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(T)});if(!D.ok)J.error(`Failed to send webhook update: ${D.status} ${D.statusText}`)}catch(D){J.error("Failed to send webhook update:",D)}})()}async function P(L,T,J){return I(L,T,J)}var p={beforeTenantSegments:["ui"]},m={beforeTenantSegments:["api"]};function _(L){return{segments:W(L?.segments)}}function W(L){return(L??[]).map((T)=>T.trim()).filter(Boolean)}function h(L){let T=L.trim();if(!T)return"/";let J=T.replace(/\\/g,"/").replace(/\/+/g,"/");return J.startsWith("/")?J:`/${J}`}function K(L){return h(L).split("/").filter(Boolean)}function R(L){return{beforeTenantSegments:W(L?.beforeTenantSegments),afterTenantSegments:W(L?.afterTenantSegments)}}function b(L){if(!L||L.type===void 0||L.type==="path"){let J=L;return{type:"path",ui:R(J?.ui),api:R(J?.api)}}let T=L;return{...T,ui:_(T.ui),api:_(T.api)}}function o(L,T){let J=R(T),D=J.beforeTenantSegments??[],$=J.afterTenantSegments??[],A=K(L),f=D.length+1+$.length;if(A.length<f)return null;for(let Z=0;Z<D.length;Z++)if(A[Z]!==D[Z])return null;let x=D.length,X=A[x];if(!X)return null;for(let Z=0;Z<$.length;Z++)if(A[x+1+Z]!==$[Z])return null;let G=A.slice(x+1+$.length);return{tenantId:decodeURIComponent(X),restSegments:G,restPath:G.length>0?`/${G.join("/")}`:"/"}}function n(L,T="/",J){let D=R(J),$=D.beforeTenantSegments??[],A=D.afterTenantSegments??[],f=K(T),x=[...$,encodeURIComponent(L),...A,...f];return x.length>0?`/${x.join("/")}`:"/"}function Q(L,T,J,D,$){if(L===void 0||L===null){if(J)D.push({message:`${T} is required`,path:$});return}if(typeof L!=="string"){D.push({message:`${T} must be a string`,path:$});return}return L}function Y(L,T,J,D){if(L===void 0||L===null)return;if(typeof L!=="boolean"){J.push({message:`${T} must be a boolean`,path:D});return}return L}function v(L,T,J){if(L===void 0||L===null)return;if(typeof L!=="object"||L===null){T.push({message:"name must be an object",path:J});return}let D=L,$={};return $.formatted=Q(D.formatted,"formatted",!1,T,[...J,"formatted"]),$.familyName=Q(D.familyName,"familyName",!1,T,[...J,"familyName"]),$.givenName=Q(D.givenName,"givenName",!1,T,[...J,"givenName"]),$.middleName=Q(D.middleName,"middleName",!1,T,[...J,"middleName"]),$.honorificPrefix=Q(D.honorificPrefix,"honorificPrefix",!1,T,[...J,"honorificPrefix"]),$.honorificSuffix=Q(D.honorificSuffix,"honorificSuffix",!1,T,[...J,"honorificSuffix"]),$}function d(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"emails must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"email must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function r(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"phoneNumbers must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"phoneNumber must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function l(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"addresses must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"address must be an object",path:f});continue}let x=A;D.push({formatted:Q(x.formatted,"formatted",!1,T,[...f,"formatted"]),streetAddress:Q(x.streetAddress,"streetAddress",!1,T,[...f,"streetAddress"]),locality:Q(x.locality,"locality",!1,T,[...f,"locality"]),region:Q(x.region,"region",!1,T,[...f,"region"]),postalCode:Q(x.postalCode,"postalCode",!1,T,[...f,"postalCode"]),country:Q(x.country,"country",!1,T,[...f,"country"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function t(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"groups must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"group must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,$ref:Q(x.$ref,"$ref",!1,T,[...f,"$ref"]),display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"])})}return D.length>0?D:void 0}function i(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"roles must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"role must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function u(L,T,J){if(L===void 0||L===null)return;if(typeof L!=="object"||L===null){T.push({message:"Enterprise User extension must be an object",path:J});return}let D=L,$={};if($.employeeNumber=Q(D.employeeNumber,"employeeNumber",!1,T,[...J,"employeeNumber"]),$.costCenter=Q(D.costCenter,"costCenter",!1,T,[...J,"costCenter"]),$.organization=Q(D.organization,"organization",!1,T,[...J,"organization"]),$.division=Q(D.division,"division",!1,T,[...J,"division"]),$.department=Q(D.department,"department",!1,T,[...J,"department"]),D.manager!==void 0&&D.manager!==null)if(typeof D.manager!=="object"||D.manager===null)T.push({message:"manager must be an object",path:[...J,"manager"]});else{let A=D.manager;$.manager={value:Q(A.value,"value",!1,T,[...J,"manager","value"]),$ref:Q(A.$ref,"$ref",!1,T,[...J,"manager","$ref"]),displayName:Q(A.displayName,"displayName",!1,T,[...J,"manager","displayName"])}}return $}function a(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={},A=Q(J.userName,"userName",!0,D,["userName"]);if(!A)return{issues:D};$.userName=A,$.id=Q(J.id,"id",!1,D,["id"]),$.externalId=Q(J.externalId,"externalId",!1,D,["externalId"]),$.displayName=Q(J.displayName,"displayName",!1,D,["displayName"]),$.nickName=Q(J.nickName,"nickName",!1,D,["nickName"]),$.profileUrl=Q(J.profileUrl,"profileUrl",!1,D,["profileUrl"]),$.title=Q(J.title,"title",!1,D,["title"]),$.userType=Q(J.userType,"userType",!1,D,["userType"]),$.preferredLanguage=Q(J.preferredLanguage,"preferredLanguage",!1,D,["preferredLanguage"]),$.locale=Q(J.locale,"locale",!1,D,["locale"]),$.timezone=Q(J.timezone,"timezone",!1,D,["timezone"]),$.password=Q(J.password,"password",!1,D,["password"]),$.active=Y(J.active,"active",D,["active"]),$.name=v(J.name,D,["name"]),$.emails=d(J.emails,D,["emails"]),$.phoneNumbers=r(J.phoneNumbers,D,["phoneNumbers"]),$.addresses=l(J.addresses,D,["addresses"]),$.groups=t(J.groups,D,["groups"]),$.roles=i(J.roles,D,["roles"]);let f="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(J[f]!==void 0)$[f]=u(J[f],D,[f]);if(J.schemas!==void 0)if(Array.isArray(J.schemas))$.schemas=J.schemas.filter((x)=>typeof x==="string");else D.push({message:"schemas must be an array",path:["schemas"]});if(J.meta!==void 0)if(typeof J.meta==="object"&&J.meta!==null){let x=J.meta;$.meta={resourceType:typeof x.resourceType==="string"?x.resourceType:void 0,created:typeof x.created==="string"?x.created:void 0,lastModified:typeof x.lastModified==="string"?x.lastModified:void 0,location:typeof x.location==="string"?x.location:void 0,version:typeof x.version==="string"?x.version:void 0}}else D.push({message:"meta must be an object",path:["meta"]});if(D.length>0)return{issues:D};return{value:$}}}}}function e(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"members must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"member must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X){let G=Q(x.type,"type",!1,T,[...f,"type"]);D.push({value:X,$ref:Q(x.$ref,"$ref",!1,T,[...f,"$ref"]),display:Q(x.display,"display",!1,T,[...f,"display"]),type:G==="User"||G==="Group"?G:void 0})}}return D.length>0?D:void 0}function s(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={},A=Q(J.displayName,"displayName",!0,D,["displayName"]);if(!A)return{issues:D};if($.displayName=A,$.id=Q(J.id,"id",!1,D,["id"]),$.externalId=Q(J.externalId,"externalId",!1,D,["externalId"]),$.members=e(J.members,D,["members"]),J.schemas!==void 0)if(Array.isArray(J.schemas))$.schemas=J.schemas.filter((f)=>typeof f==="string");else D.push({message:"schemas must be an array",path:["schemas"]});if(J.meta!==void 0)if(typeof J.meta==="object"&&J.meta!==null){let f=J.meta;$.meta={resourceType:typeof f.resourceType==="string"?f.resourceType:void 0,created:typeof f.created==="string"?f.created:void 0,lastModified:typeof f.lastModified==="string"?f.lastModified:void 0,location:typeof f.location==="string"?f.location:void 0,version:typeof f.version==="string"?f.version:void 0}}else D.push({message:"meta must be an object",path:["meta"]});if(D.length>0)return{issues:D};return{value:$}}}}}function J0(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={...J},A=["iss","sub"];for(let X of A)if(X in J){if(typeof J[X]!=="string")D.push({message:`${X} must be a string`,path:[X]})}else D.push({message:`${X} is required`,path:[X]});if("aud"in J&&J.aud!==void 0){let X=J.aud;if(typeof X!=="string"&&!Array.isArray(X))D.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(X)&&!X.every((G)=>typeof G==="string"))D.push({message:"aud array must contain only strings",path:["aud"]})}let f=["jti","scope"];for(let X of f)if(X in J&&J[X]!==void 0){if(typeof J[X]!=="string")D.push({message:`${X} must be a string`,path:[X]})}let x=["exp","iat"];for(let X of x)if(X in J){if(typeof J[X]!=="number")D.push({message:`${X} must be a number`,path:[X]})}else D.push({message:`${X} is required`,path:[X]});if(D.length>0)return{issues:D};return{value:$}}}}}function L0(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={};if("access_token"in J)if(typeof J.access_token==="string")$.access_token=J.access_token;else D.push({message:"access_token must be a string",path:["access_token"]});else D.push({message:"access_token is required",path:["access_token"]});if("token_type"in J)if(typeof J.token_type==="string")$.token_type=J.token_type;else D.push({message:"token_type must be a string",path:["token_type"]});else D.push({message:"token_type is required",path:["token_type"]});if("scope"in J)if(typeof J.scope==="string"||J.scope===void 0)$.scope=J.scope;else D.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in J)if(typeof J.refresh_token==="string"||J.refresh_token===void 0)$.refresh_token=J.refresh_token;else D.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in J)if(typeof J.expires==="string"||J.expires===void 0)$.expires=J.expires;else D.push({message:"expires must be a string",path:["expires"]});if("expires_in"in J)if(typeof J.expires_in==="number"||J.expires_in===void 0)$.expires_in=J.expires_in;else D.push({message:"expires_in must be a number",path:["expires_in"]});if(D.length>0)return{issues:D};return{value:$}}}}}export{L0 as workloadTokenResponseSchema,f0 as withValidate,G0 as waitOn,k as version,A0 as validationFailureResponse,a as userSchema,T0 as tokenResponseSchema,X0 as stripJsonComments,y0 as silentLogger,W0 as setActiveSession,E as serializeESConfig,P as sendTenantWebhook,Z0 as parseJsonc,D0 as oidcCallbackSchema,b as normalizeTenantRoutingStrategy,R as normalizeTenantPathNamespace,x0 as must,Q0 as mergeConfig,o as matchTenantPath,M0 as listSsoClientIdsFromCookies,z as list,J0 as jwtAssertionClaimsSchema,z0 as infoLogger,$0 as idTokenClaimsSchema,s as groupResourceSchema,N0 as getActiveSession,_0 as findTenantFromStateParam,c0 as defaultLogger,Y0 as decodeUser,B0 as debugLogger,H0 as consoleLogger,C0 as clearActiveSession,R0 as claimsToUser,n as buildTenantPath,N as TenantRequestError,c as MultipleTenantsForUserError,M as InMemoryTenantStore,p as DEFAULT_TENANT_UI_NAMESPACE,m as DEFAULT_TENANT_API_NAMESPACE};
1
+ import{I as B,a as D0,b as T0,c as $0,d as f0,e as x0,f as A0,g as Q0,h as X0,i as Z0,j as G0,k as R0,l as Y0,m as c0,n as y0,o as z0,p as B0,q as H0,t as N0,u as W0,v as C0,w as M0,x as _0}from"./shared/core-kk9hdwwp.js";var k="0.0.14";var V=["sessionStore","userStore","groupStore","tokenStore","magicLinkStore"];function C(L){if(L===null||typeof L!=="object")return L;let T={};for(let[J,D]of Object.entries(L)){if(V.includes(J)||J==="validators"||J==="setStores")continue;T[J]=D!==null&&typeof D==="object"&&!Array.isArray(D)&&Object.getPrototypeOf(D)===Object.prototype?C(D):D}return T}function E(L){return C(L)}function z(L,T,J,D){let $=T.length,A=D??L,f=A>0?Math.floor(J/A)+1:1,x=A>0?Math.ceil(L/A):0;return{total:L,count:$,items:T,size:A,page:f,pages:x}}class N extends Error{constructor(L,T){super(L,T);this.name="TenantRequestError",Object.setPrototypeOf(this,N.prototype)}}class c extends Error{userId;tenantIds;constructor(L,T,J){super(`Multiple tenants found for user id "${L}"`,J);this.name="MultipleTenantsForUserError",this.userId=L,this.tenantIds=T,Object.setPrototypeOf(this,c.prototype)}}var H=Number.POSITIVE_INFINITY;class M{tenants=new Map;tenantEsMap=new Map;userTenantIds=new Map;ttl;userMode;createEs;findTenantByUserId;findTenantsByUserId;constructor(L){if(this.ttl=O(L.ttl),this.userMode=L.userMode,this.createEs=L.createEs,this.userMode==="singleTenantOnly"){this.findTenantByUserId=this.findSingleTenantByUserId.bind(this),this.findTenantsByUserId=void 0;return}this.findTenantByUserId=void 0,this.findTenantsByUserId=this.findMultipleTenantsByUserId.bind(this)}async get(L){return this.tenants.get(L)??null}async list(L){let T=Array.from(this.tenants.values()),J=Math.max(0,L?.start??0),D=L?.limit,$=L?.sort;if($?.length)T=[...T].sort((X,G)=>{for(let{field:Z,direction:q}of $){let F=X[Z],U=G[Z],y=j(F,U);if(y!==0)return q==="desc"?-y:y}return 0});let A=T.length,f=D!=null?J+D:void 0,x=T.slice(J,f);return z(A,x,J,D)}async upsert(L){let T=new Date,J=this.tenants.get(L.tenantId),D={...J??{},...L,companyId:L.companyId??J?.companyId??"",companyName:L.companyName??J?.companyName??"",environmentType:L.environmentType??J?.environmentType??"DEV",email:L.email??J?.email,webhookUrl:L.webhookUrl??J?.webhookUrl,callbackUrl:L.callbackUrl??J?.callbackUrl,tenantUrl:L.tenantUrl??J?.tenantUrl,status:L.status??J?.status??"completed",createdAt:L.createdAt??J?.createdAt??T,updatedAt:L.updatedAt??T};return this.tenants.set(D.tenantId,D),this.tenantEsMap.delete(D.tenantId),D}async delete(L){this.tenantEsMap.delete(L),this.tenants.delete(L)}async getEs(L){let T=await this.get(L);if(!T)throw Error(`Tenant "${L}" not found`);if(!this.createEs)throw Error("InMemoryTenantStore requires options.createEs to use getEs()");if(this.ttl===0)return this.createEs(B(T));let J=Date.now(),D=this.tenantEsMap.get(L);if(D&&D.expiresAt>J)return D.es;if(D)this.tenantEsMap.delete(L);let $=this.createEs(B(T));return this.tenantEsMap.set(L,{es:$,expiresAt:g(J,this.ttl)}),$}getCachedTenantIds(){if(this.ttl===0)return[];let L=Date.now();for(let[T,J]of this.tenantEsMap.entries())if(J.expiresAt<=L)this.tenantEsMap.delete(T);return Array.from(this.tenantEsMap.keys())}async registerUserTenantId(L,T){if(!L)return;let J=S(T);if(this.userMode==="singleTenantOnly"){this.userTenantIds.set(L,new Set([J]));return}let D=this.userTenantIds.get(L);if(D){D.add(J);return}this.userTenantIds.set(L,new Set([J]))}async findSingleTenantByUserId(L){let T=await this.resolveTenantsByUserId(L);if(T.length>1)throw new c(L,T.map((J)=>J.tenantId));return T[0]??null}async findMultipleTenantsByUserId(L){return this.resolveTenantsByUserId(L)}async resolveTenantsByUserId(L){let T=this.userTenantIds.get(L);if(!T||T.size===0)return[];let J=T.has(null),D=Array.from(T).filter((f)=>f!=null);if(D.length===0)return[];let $=await Promise.all(D.map(async(f)=>({tenantId:f,tenant:await this.get(f)}))),A=$.filter((f)=>f.tenant!=null).map((f)=>f.tenantId);if(A.length===0){if(J)this.userTenantIds.set(L,new Set([null]));else this.userTenantIds.delete(L);return[]}if(A.length!==D.length){let f=J?[null,...A]:A;this.userTenantIds.set(L,new Set(f))}return $.map((f)=>f.tenant).filter((f)=>f!=null)}}function j(L,T){let J=L===void 0||L===null,D=T===void 0||T===null;if(J&&D)return 0;if(J)return 1;if(D)return-1;if(L instanceof Date&&T instanceof Date)return L.getTime()-T.getTime();let $=String(L),A=String(T);return $.localeCompare(A)}function S(L){if(typeof L!=="string")return null;return L.trim()||null}function O(L){if(L===void 0)return H;if(L<=0)return L===0?0:H;return L}function g(L,T){if(!Number.isFinite(T))return H;return L+T}function I(L,T,J){return(async()=>{try{let D=await fetch(L,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(T)});if(!D.ok)J.error(`Failed to send webhook update: ${D.status} ${D.statusText}`)}catch(D){J.error("Failed to send webhook update:",D)}})()}async function P(L,T,J){return I(L,T,J)}var p={beforeTenantSegments:["ui"]},m={beforeTenantSegments:["api"]};function _(L){return{segments:W(L?.segments)}}function W(L){return(L??[]).map((T)=>T.trim()).filter(Boolean)}function h(L){let T=L.trim();if(!T)return"/";let J=T.replace(/\\/g,"/").replace(/\/+/g,"/");return J.startsWith("/")?J:`/${J}`}function K(L){return h(L).split("/").filter(Boolean)}function R(L){return{beforeTenantSegments:W(L?.beforeTenantSegments),afterTenantSegments:W(L?.afterTenantSegments)}}function b(L){if(!L||L.type===void 0||L.type==="path"){let J=L;return{type:"path",ui:R(J?.ui),api:R(J?.api)}}let T=L;return{...T,ui:_(T.ui),api:_(T.api)}}function o(L,T){let J=R(T),D=J.beforeTenantSegments??[],$=J.afterTenantSegments??[],A=K(L),f=D.length+1+$.length;if(A.length<f)return null;for(let Z=0;Z<D.length;Z++)if(A[Z]!==D[Z])return null;let x=D.length,X=A[x];if(!X)return null;for(let Z=0;Z<$.length;Z++)if(A[x+1+Z]!==$[Z])return null;let G=A.slice(x+1+$.length);return{tenantId:decodeURIComponent(X),restSegments:G,restPath:G.length>0?`/${G.join("/")}`:"/"}}function n(L,T="/",J){let D=R(J),$=D.beforeTenantSegments??[],A=D.afterTenantSegments??[],f=K(T),x=[...$,encodeURIComponent(L),...A,...f];return x.length>0?`/${x.join("/")}`:"/"}function Q(L,T,J,D,$){if(L===void 0||L===null){if(J)D.push({message:`${T} is required`,path:$});return}if(typeof L!=="string"){D.push({message:`${T} must be a string`,path:$});return}return L}function Y(L,T,J,D){if(L===void 0||L===null)return;if(typeof L!=="boolean"){J.push({message:`${T} must be a boolean`,path:D});return}return L}function v(L,T,J){if(L===void 0||L===null)return;if(typeof L!=="object"||L===null){T.push({message:"name must be an object",path:J});return}let D=L,$={};return $.formatted=Q(D.formatted,"formatted",!1,T,[...J,"formatted"]),$.familyName=Q(D.familyName,"familyName",!1,T,[...J,"familyName"]),$.givenName=Q(D.givenName,"givenName",!1,T,[...J,"givenName"]),$.middleName=Q(D.middleName,"middleName",!1,T,[...J,"middleName"]),$.honorificPrefix=Q(D.honorificPrefix,"honorificPrefix",!1,T,[...J,"honorificPrefix"]),$.honorificSuffix=Q(D.honorificSuffix,"honorificSuffix",!1,T,[...J,"honorificSuffix"]),$}function d(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"emails must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"email must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function r(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"phoneNumbers must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"phoneNumber must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function l(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"addresses must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"address must be an object",path:f});continue}let x=A;D.push({formatted:Q(x.formatted,"formatted",!1,T,[...f,"formatted"]),streetAddress:Q(x.streetAddress,"streetAddress",!1,T,[...f,"streetAddress"]),locality:Q(x.locality,"locality",!1,T,[...f,"locality"]),region:Q(x.region,"region",!1,T,[...f,"region"]),postalCode:Q(x.postalCode,"postalCode",!1,T,[...f,"postalCode"]),country:Q(x.country,"country",!1,T,[...f,"country"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function t(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"groups must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"group must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,$ref:Q(x.$ref,"$ref",!1,T,[...f,"$ref"]),display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"])})}return D.length>0?D:void 0}function i(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"roles must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"role must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X)D.push({value:X,display:Q(x.display,"display",!1,T,[...f,"display"]),type:Q(x.type,"type",!1,T,[...f,"type"]),primary:Y(x.primary,"primary",T,[...f,"primary"])})}return D.length>0?D:void 0}function u(L,T,J){if(L===void 0||L===null)return;if(typeof L!=="object"||L===null){T.push({message:"Enterprise User extension must be an object",path:J});return}let D=L,$={};if($.employeeNumber=Q(D.employeeNumber,"employeeNumber",!1,T,[...J,"employeeNumber"]),$.costCenter=Q(D.costCenter,"costCenter",!1,T,[...J,"costCenter"]),$.organization=Q(D.organization,"organization",!1,T,[...J,"organization"]),$.division=Q(D.division,"division",!1,T,[...J,"division"]),$.department=Q(D.department,"department",!1,T,[...J,"department"]),D.manager!==void 0&&D.manager!==null)if(typeof D.manager!=="object"||D.manager===null)T.push({message:"manager must be an object",path:[...J,"manager"]});else{let A=D.manager;$.manager={value:Q(A.value,"value",!1,T,[...J,"manager","value"]),$ref:Q(A.$ref,"$ref",!1,T,[...J,"manager","$ref"]),displayName:Q(A.displayName,"displayName",!1,T,[...J,"manager","displayName"])}}return $}function a(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={},A=Q(J.userName,"userName",!0,D,["userName"]);if(!A)return{issues:D};$.userName=A,$.id=Q(J.id,"id",!1,D,["id"]),$.externalId=Q(J.externalId,"externalId",!1,D,["externalId"]),$.displayName=Q(J.displayName,"displayName",!1,D,["displayName"]),$.nickName=Q(J.nickName,"nickName",!1,D,["nickName"]),$.profileUrl=Q(J.profileUrl,"profileUrl",!1,D,["profileUrl"]),$.title=Q(J.title,"title",!1,D,["title"]),$.userType=Q(J.userType,"userType",!1,D,["userType"]),$.preferredLanguage=Q(J.preferredLanguage,"preferredLanguage",!1,D,["preferredLanguage"]),$.locale=Q(J.locale,"locale",!1,D,["locale"]),$.timezone=Q(J.timezone,"timezone",!1,D,["timezone"]),$.password=Q(J.password,"password",!1,D,["password"]),$.active=Y(J.active,"active",D,["active"]),$.name=v(J.name,D,["name"]),$.emails=d(J.emails,D,["emails"]),$.phoneNumbers=r(J.phoneNumbers,D,["phoneNumbers"]),$.addresses=l(J.addresses,D,["addresses"]),$.groups=t(J.groups,D,["groups"]),$.roles=i(J.roles,D,["roles"]);let f="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(J[f]!==void 0)$[f]=u(J[f],D,[f]);if(J.schemas!==void 0)if(Array.isArray(J.schemas))$.schemas=J.schemas.filter((x)=>typeof x==="string");else D.push({message:"schemas must be an array",path:["schemas"]});if(J.meta!==void 0)if(typeof J.meta==="object"&&J.meta!==null){let x=J.meta;$.meta={resourceType:typeof x.resourceType==="string"?x.resourceType:void 0,created:typeof x.created==="string"?x.created:void 0,lastModified:typeof x.lastModified==="string"?x.lastModified:void 0,location:typeof x.location==="string"?x.location:void 0,version:typeof x.version==="string"?x.version:void 0}}else D.push({message:"meta must be an object",path:["meta"]});if(D.length>0)return{issues:D};return{value:$}}}}}function e(L,T,J){if(L===void 0||L===null)return;if(!Array.isArray(L)){T.push({message:"members must be an array",path:J});return}let D=[];for(let $=0;$<L.length;$++){let A=L[$],f=[...J,$];if(typeof A!=="object"||A===null){T.push({message:"member must be an object",path:f});continue}let x=A,X=Q(x.value,"value",!0,T,[...f,"value"]);if(X){let G=Q(x.type,"type",!1,T,[...f,"type"]);D.push({value:X,$ref:Q(x.$ref,"$ref",!1,T,[...f,"$ref"]),display:Q(x.display,"display",!1,T,[...f,"display"]),type:G==="User"||G==="Group"?G:void 0})}}return D.length>0?D:void 0}function s(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={},A=Q(J.displayName,"displayName",!0,D,["displayName"]);if(!A)return{issues:D};if($.displayName=A,$.id=Q(J.id,"id",!1,D,["id"]),$.externalId=Q(J.externalId,"externalId",!1,D,["externalId"]),$.members=e(J.members,D,["members"]),J.schemas!==void 0)if(Array.isArray(J.schemas))$.schemas=J.schemas.filter((f)=>typeof f==="string");else D.push({message:"schemas must be an array",path:["schemas"]});if(J.meta!==void 0)if(typeof J.meta==="object"&&J.meta!==null){let f=J.meta;$.meta={resourceType:typeof f.resourceType==="string"?f.resourceType:void 0,created:typeof f.created==="string"?f.created:void 0,lastModified:typeof f.lastModified==="string"?f.lastModified:void 0,location:typeof f.location==="string"?f.location:void 0,version:typeof f.version==="string"?f.version:void 0}}else D.push({message:"meta must be an object",path:["meta"]});if(D.length>0)return{issues:D};return{value:$}}}}}function J0(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={...J},A=["iss","sub"];for(let X of A)if(X in J){if(typeof J[X]!=="string")D.push({message:`${X} must be a string`,path:[X]})}else D.push({message:`${X} is required`,path:[X]});if("aud"in J&&J.aud!==void 0){let X=J.aud;if(typeof X!=="string"&&!Array.isArray(X))D.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(X)&&!X.every((G)=>typeof G==="string"))D.push({message:"aud array must contain only strings",path:["aud"]})}let f=["jti","scope"];for(let X of f)if(X in J&&J[X]!==void 0){if(typeof J[X]!=="string")D.push({message:`${X} must be a string`,path:[X]})}let x=["exp","iat"];for(let X of x)if(X in J){if(typeof J[X]!=="number")D.push({message:`${X} must be a number`,path:[X]})}else D.push({message:`${X} is required`,path:[X]});if(D.length>0)return{issues:D};return{value:$}}}}}function L0(L){return{"~standard":{version:1,vendor:L,validate:(T)=>{if(typeof T!=="object"||T===null)return{issues:[{message:"Expected an object"}]};let J=T,D=[],$={};if("access_token"in J)if(typeof J.access_token==="string")$.access_token=J.access_token;else D.push({message:"access_token must be a string",path:["access_token"]});else D.push({message:"access_token is required",path:["access_token"]});if("token_type"in J)if(typeof J.token_type==="string")$.token_type=J.token_type;else D.push({message:"token_type must be a string",path:["token_type"]});else D.push({message:"token_type is required",path:["token_type"]});if("scope"in J)if(typeof J.scope==="string"||J.scope===void 0)$.scope=J.scope;else D.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in J)if(typeof J.refresh_token==="string"||J.refresh_token===void 0)$.refresh_token=J.refresh_token;else D.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in J)if(typeof J.expires==="string"||J.expires===void 0)$.expires=J.expires;else D.push({message:"expires must be a string",path:["expires"]});if("expires_in"in J)if(typeof J.expires_in==="number"||J.expires_in===void 0)$.expires_in=J.expires_in;else D.push({message:"expires_in must be a number",path:["expires_in"]});if(D.length>0)return{issues:D};return{value:$}}}}}export{L0 as workloadTokenResponseSchema,f0 as withValidate,G0 as waitOn,k as version,A0 as validationFailureResponse,a as userSchema,T0 as tokenResponseSchema,X0 as stripJsonComments,y0 as silentLogger,W0 as setActiveSession,E as serializeESConfig,P as sendTenantWebhook,Z0 as parseJsonc,D0 as oidcCallbackSchema,b as normalizeTenantRoutingStrategy,R as normalizeTenantPathNamespace,x0 as must,Q0 as mergeConfig,o as matchTenantPath,M0 as listSsoClientIdsFromCookies,z as list,J0 as jwtAssertionClaimsSchema,z0 as infoLogger,$0 as idTokenClaimsSchema,s as groupResourceSchema,N0 as getActiveSession,_0 as findTenantFromStateParam,c0 as defaultLogger,Y0 as decodeUser,B0 as debugLogger,H0 as consoleLogger,C0 as clearActiveSession,R0 as claimsToUser,n as buildTenantPath,N as TenantRequestError,c as MultipleTenantsForUserError,M as InMemoryTenantStore,p as DEFAULT_TENANT_UI_NAMESPACE,m as DEFAULT_TENANT_API_NAMESPACE};
package/dist/server.d.ts CHANGED
@@ -1764,7 +1764,7 @@ type MetaData = {
1764
1764
  version: number;
1765
1765
  created: Date;
1766
1766
  };
1767
- type SecretsSourceType = "vault" | "lfv" | "azure" | "aws" | "gcp" | "dev";
1767
+ type SecretsSourceType = "vault" | "azure" | "aws" | "gcp" | "dev";
1768
1768
  type SecretRequestSeverity = "low" | "medium" | "high" | "critical";
1769
1769
  type SecretLifecycleRequest = {
1770
1770
  reason?: string;
@@ -1821,7 +1821,7 @@ type SecretsValidators = {
1821
1821
  * Optional hook to validate merged source configs before they are resolved.
1822
1822
  * Throw from this callback to reject invalid secrets source configuration.
1823
1823
  */
1824
- validateSourceConfig?(name: string, config: SecretsSourceConfig): void;
1824
+ validateSourceConfig?(sourceName: string, config: SecretsSourceConfig): void;
1825
1825
  };
1826
1826
  type Secrets = {
1827
1827
  /** Named secrets sources client configurations from RemoteConfig. */
@@ -1829,27 +1829,27 @@ type Secrets = {
1829
1829
  /** Returns configured secrets source names/keys. */
1830
1830
  listSecretsSources(): string[];
1831
1831
  /** Gets a named secrets source client. Throws when missing. */
1832
- getSecretsSource(name: string): SecretsSource;
1832
+ getSecretsSource(sourceName: string): SecretsSource;
1833
1833
  /** Reads a secret from a named secrets source client. */
1834
- getSecret<T>(name: string, path: string, options?: SecretsOperationOptions): Promise<T>;
1834
+ getSecret<T>(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<T>;
1835
1835
  /** Reads full secret data + metadata from a named secrets source client. */
1836
- getFullSecret<T>(name: string, path: string, options?: SecretsOperationOptions): Promise<Secret<T>>;
1836
+ getFullSecret<T>(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<Secret<T>>;
1837
1837
  /** Writes a secret to a named secrets source client. */
1838
- putSecret(name: string, path: string, value: Record<string, unknown>, options?: SecretsOperationOptions): Promise<void>;
1838
+ putSecret(sourceName: string, path: string, value: Record<string, unknown>, options?: SecretsOperationOptions): Promise<void>;
1839
1839
  /** Deletes a secret from a named secrets source client. */
1840
- deleteSecret(name: string, path: string, options?: SecretsOperationOptions): Promise<void>;
1840
+ deleteSecret(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<void>;
1841
1841
  /** Lists child paths under a base path for a named secrets source client. */
1842
- listPaths(name: string, path: string, options?: SecretsOperationOptions): Promise<string[]>;
1842
+ listPaths(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<string[]>;
1843
1843
  /** Returns true when a path exists for a named secrets source client. */
1844
- exists(name: string, path: string, options?: SecretsOperationOptions): Promise<boolean>;
1844
+ exists(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<boolean>;
1845
1845
  /** Requests rotation for a secret path in a named secrets source client. */
1846
- requestRotate(name: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1846
+ requestRotate(sourceName: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1847
1847
  /** Requests revocation for a secret path in a named secrets source client. */
1848
- requestRevoke(name: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1848
+ requestRevoke(sourceName: string, path: string, request?: SecretLifecycleRequest, options?: SecretsOperationOptions): Promise<void>;
1849
1849
  /** Reads metadata for a secret path in a named secrets source client. */
1850
- getMetadata(name: string, path: string, options?: SecretsOperationOptions): Promise<Record<string, unknown>>;
1850
+ getMetadata(sourceName: string, path: string, options?: SecretsOperationOptions): Promise<Record<string, unknown>>;
1851
1851
  /** Subscribes to secret changes on a named secrets source client. */
1852
- subscribe<T>(name: string, path: string, onChange: (fullSecret: Secret<T>) => void): () => void;
1852
+ subscribe<T>(sourceName: string, path: string, onChange: (fullSecret: Secret<T>) => void): () => void;
1853
1853
  /** Returns true when request matches any configured LFV delivery path. */
1854
1854
  isLfvDeliveryRequest?(request: Request): boolean;
1855
1855
  /** Returns true when request matches any configured LFV events path. */
@@ -1873,7 +1873,7 @@ type FrameworkSecretsModuleConfig = Record<string, FrameworkSecretsSourceConfig>
1873
1873
  * TODO: Let's see if we can do some clean inference and remove this!!!
1874
1874
  */
1875
1875
  type SecretsSourceMap = Record<string, SecretsSource>;
1876
- type SecretsSourceConfig = DevSecretsConfig | GcpSecretsConfig | LfvSecretsConfig | VaultSecretsConfig | AwsSecretsConfig | AzureSecretsConfig;
1876
+ type SecretsSourceConfig = DevSecretsConfig | GcpSecretsConfig | VaultSecretsConfig | AwsSecretsConfig | AzureSecretsConfig;
1877
1877
  /**
1878
1878
  * Raw module config keyed by source name.
1879
1879
  * The secrets module resolves this into a runtime SecretsSourceMap.
@@ -1886,8 +1886,7 @@ type DevSecretsConfig = {
1886
1886
  type GcpSecretsConfig = {
1887
1887
  type: "gcp";
1888
1888
  };
1889
- type LfvSecretsConfig = {
1890
- type: "lfv";
1889
+ type VaultLfvSecretsConfig = {
1891
1890
  /** LFV server base URL for OTP/action endpoints. */
1892
1891
  lfvServerUrl?: string;
1893
1892
  /** LFV client id used for OTP issuance. */
@@ -1917,10 +1916,23 @@ type LfvSecretsConfig = {
1917
1916
  */
1918
1917
  logger?: Logger;
1919
1918
  };
1919
+ type VaultWebSocketAuthHeader = "X-Vault-Token" | "Authorization";
1920
+ type VaultWebSocketSecretsConfig = {
1921
+ /** Websocket URL for vault command execution and live secret subscriptions. */
1922
+ url?: string;
1923
+ /** Token used during websocket connect/auth. */
1924
+ token?: string;
1925
+ /** Header name used to send the websocket token. Defaults to X-Vault-Token. */
1926
+ header?: VaultWebSocketAuthHeader;
1927
+ };
1920
1928
  type VaultSecretsConfig = {
1921
1929
  type: "vault";
1922
1930
  url?: string;
1923
1931
  token?: string;
1932
+ /** Optional LFV transport capability for reads/lifecycle operations. */
1933
+ lfv?: VaultLfvSecretsConfig;
1934
+ /** Optional websocket capability for vault commands and live subscriptions. */
1935
+ websocket?: VaultWebSocketSecretsConfig;
1924
1936
  /**
1925
1937
  * MINIMUM: 600_000 milliseconds (10 minutes). Polls the path every ttl milliseconds and calls onConfig when config changes.
1926
1938
  */
@@ -2018,23 +2030,24 @@ type AzureSecretsConfig = {
2018
2030
  };
2019
2031
  type EnvironmentType = "POC" | "DEV" | "QA" | "PROD";
2020
2032
  type TenantStatus = "pending" | "processing" | "completed" | "failed" | "action_required";
2021
- type TenantSecretsConfig = LfvSecretsConfig | (VaultSecretsConfig & {
2033
+ type TenantStoredConfigLocator = {
2034
+ /** Indicates that the tenant config descriptor is stored securely outside the tenant record. */
2035
+ type: "stored";
2036
+ /** Root secure source type used to fetch the stored tenant config descriptor. */
2037
+ sourceType: "vault";
2038
+ /** Path to the stored tenant config descriptor. */
2039
+ path: string;
2040
+ };
2041
+ type TenantRemoteConfigLocator = {
2042
+ /** Indicates that the tenant RemoteConfig already exists at this secure source path. */
2043
+ type: "remoteConfig";
2044
+ /** Secure source type used to load the RemoteConfig document directly. */
2045
+ sourceType: "vault";
2046
+ /** Path to the tenant RemoteConfig document. */
2022
2047
  path: string;
2023
- retryInterval?: number;
2024
- }) | (DevSecretsConfig & {
2025
- path?: string;
2026
- appId?: string;
2027
- }) | (AwsSecretsConfig & {
2028
- ttl?: number;
2029
- }) | AzureSecretsConfig | (GcpSecretsConfig & {
2030
- ttl?: number;
2031
- }) | {
2032
- type: "localFile";
2033
- path?: string;
2034
- watch?: boolean;
2035
- ttl?: number;
2036
2048
  };
2037
- type TenantConfigSourceInput = TenantSecretsConfig | ConfigSource;
2049
+ type TenantConfigLocator = TenantStoredConfigLocator | TenantRemoteConfigLocator;
2050
+ type TenantConfigSourceInput = TenantConfigLocator | ConfigSource;
2038
2051
  type TenantBaseRecord = {
2039
2052
  tenantId: string;
2040
2053
  companyId: string;
@@ -2054,7 +2067,7 @@ type TenantBaseRecord = {
2054
2067
  /** Persisted tenant config metadata, or a runtime ConfigSource for internal-only tenants. */
2055
2068
  configSource: TenantConfigSourceInput;
2056
2069
  /** Runtime helper that returns a ConfigSource for this tenant. */
2057
- config: () => ConfigSource;
2070
+ config: (source?: SecretsSource) => ConfigSource;
2058
2071
  };
2059
2072
  type StoredTenant<TExtended extends object = Record<string, never>> = TenantBaseRecord & TExtended;
2060
2073
  /**
@@ -2198,6 +2211,11 @@ type ConfigSource = {
2198
2211
  */
2199
2212
  subscribe(onConfig: (config: RemoteConfig) => void): undefined | (() => void);
2200
2213
  /**
2214
+ * Default secret client for the config source itself.
2215
+ * For vault-backed sources this is the vault used to read RemoteConfig.
2216
+ */
2217
+ secret: SecretsSource;
2218
+ /**
2201
2219
  * Optional. If not set by the creator, the framework may set this before calling load/subscribe
2202
2220
  * so the source can use the same logger.
2203
2221
  */
@@ -2219,6 +2237,8 @@ type EnterpriseStandardBase = {
2219
2237
  tenantId?: string;
2220
2238
  /** Most recent remote config applied to this instance (from ConfigSource, after beforeChange if any). */
2221
2239
  config?: RemoteConfig;
2240
+ /** Default config-source-backed secret client, typically the vault used for RemoteConfig. */
2241
+ secret: SecretsSource;
2222
2242
  secrets?: Secrets;
2223
2243
  sso?: SSO;
2224
2244
  iam?: IAM;
@@ -2370,9 +2390,9 @@ declare function ciam<
2370
2390
  * Only checks CIAM; does not check SSO.
2371
2391
  */
2372
2392
  declare function getCIAMUser(request: Request, es: EnterpriseStandard): Promise<User2 | undefined>;
2373
- type TenantConfigSourceFactory = (config: TenantSecretsConfig) => ConfigSource;
2393
+ type TenantConfigSourceFactory = (config: TenantConfigLocator, source?: SecretsSource) => ConfigSource;
2374
2394
  declare function registerTenantConfigSourceFactory(factory: TenantConfigSourceFactory): void;
2375
- declare function tenantConfigSource(tenant: Pick<StoredTenant, "configSource">): ConfigSource;
2395
+ declare function tenantConfigSource(tenant: Pick<StoredTenant, "configSource">, source?: SecretsSource): ConfigSource;
2376
2396
  declare function withTenantConfigMethod<TExtended extends object>(tenant: Omit<StoredTenant<TExtended>, "config">): StoredTenant<TExtended>;
2377
2397
  /**
2378
2398
  * Verifies the JWT signature using the given JWKS URI (cached), then decodes and
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import{A as _M,B as GM,C as JM,D as LM,E as DM,F as jM,G as IM,H as EM,I as PM,c as XM,d as YM,e,k as ZM,r as $M,s as FM,y as NM,z as VM}from"./shared/core-tyde8csq.js";function zM(W,D,j,h,q){if(!j&&!h)return;let E={...j,...h},Y={...E,signingKey:j?.signingKey,magicLinkTtl:E.magicLinkTtl??3600,sessionTtl:E.sessionTtl??86400,cookiesSecure:E.cookiesSecure!==void 0?E.cookiesSecure:!0,cookiesSameSite:E.cookiesSameSite!==void 0?E.cookiesSameSite:"Strict",cookiesPrefix:E.cookiesPrefix??(E.ciamId?`es.ciam.${E.ciamId}`:"es.ciam"),cookiesPath:E.cookiesPath??"/",sessionValidation:E.sessionValidation??"always"};function U(){if(!Y.signingKey)throw Error("Missing CIAM configuration field: signingKey. CIAM signingKey is required for JWT token signing and must be provided via Vault (ciam.signingKey).")}function g(){if(!Y.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and backchannel logout.");return Y.sessionStore}function m(){U(),g()}function i(M=32){let A=new Uint8Array(M);return crypto.getRandomValues(A),Array.from(A,(X)=>X.toString(16).padStart(2,"0")).join("").substring(0,M)}function l(M){let A=typeof M==="string"?new TextEncoder().encode(M):M,X="";return A.forEach((Z)=>{X+=String.fromCharCode(Z)}),btoa(X).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function t(M){let A=M.replace(/-/g,"+").replace(/_/g,"/"),X=A.padEnd(A.length+(4-A.length%4)%4,"=");return atob(X)}async function x(){U();let M=new TextEncoder().encode(Y.signingKey??"");return crypto.subtle.importKey("raw",M,{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async function f(M){let X=l(JSON.stringify({alg:"HS256",typ:"JWT"})),Z=l(JSON.stringify(M)),K=`${X}.${Z}`,_=await x(),O=await crypto.subtle.sign("HMAC",_,new TextEncoder().encode(K)),I=l(new Uint8Array(O));return`${K}.${I}`}async function k(M){let A=M.split(".");if(A.length!==3)throw Error("Invalid JWT");let[X,Z,K]=A,_=`${X}.${Z}`,O=await x(),I=new Uint8Array(t(K).split("").map((T)=>T.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",O,I,new TextEncoder().encode(_)))throw Error("Invalid JWT signature");let u=t(Z),c=JSON.parse(u);if(typeof c.exp==="number"&&c.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return c}function B(M,A,X){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(M=`${Y.cookiesPrefix}.${M}`,typeof A!=="string")A=btoa(JSON.stringify(A));let Z;if(X instanceof Date)Z=`Expires=${X.toUTCString()}`;else if(typeof X==="number")Z=`Max-Age=${X}`;else throw Error("Invalid expires type",X);if(A.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${A.length}`);return`${M}=${A}; ${Z}; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function G(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");return`${Y.cookiesPrefix}.${M}=; Max-Age=0; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function J(M,A,X=!1){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");let Z=A.headers.get("cookie");if(!Z)return null;let K=`${Y.cookiesPrefix}.${M}`,_=Z.split(";").find((C)=>C.trim().startsWith(`${K}=`));if(!_)return null;let O=_.indexOf("="),I=_.substring(O+1).trim();if(!X)return I;try{let C=atob(I);return JSON.parse(C)}catch(C){return console.error(`[CIAM] Failed to parse cookie '${K}':`,C),null}}function P(M,A,X){let Z={expires_in:Y.sessionTtl??86400,token_type:"Bearer",expires:X.toISOString()};return[["Set-Cookie",B("access",M,X)],["Set-Cookie",B("id",A,X)],["Set-Cookie",B("control",Z,X)]]}function v(M){let A=J("access",M),X=J("id",M),Z=J("control",M,!0);if(!A||!X||!Z)return;if(Z.expires&&Date.now()>new Date(Z.expires).getTime())return;return{access:A,id:X,control:Z}}async function w(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=v(M);if(!A)return;let X=await k(A.access),Z=await k(A.id);if(!X.sid||!Z.sub)return;if(Y.sessionValidation!=="disabled"){if(!await g().get(X.sid))return}return z(Z)}catch(A){return}}async function b(M){let A=await w(M);if(A)return A;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function p(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let O=v(M);if(O){let I=await k(O.access);if(I.sid)await g().delete(I.sid)}}catch(O){console.warn("Failed to delete CIAM session:",O)}let A=[["Set-Cookie",G("access")],["Set-Cookie",G("id")],["Set-Cookie",G("control")]],Z=new URL(M.url).searchParams.get("redirect");if(Z)return new Response("Logged out",{status:302,headers:[["Location",Z],...A]});let K=M.headers.get("accept");if(K?.includes("application/json")||K?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out"}),{status:200,headers:[["Content-Type","application/json"],...A]});return new Response("Logout Complete",{status:200,headers:[["Content-Type","text/plain"],...A]})}async function y(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=M.headers.get("content-type");if(!A||!A.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let X=await M.text(),K=new URLSearchParams(X).get("logout_token");if(!K)return new Response("Missing logout_token parameter",{status:400});let O=(await k(K)).sid;if(!O)return new Response("Invalid logout_token: missing sid claim",{status:400});return await g().delete(O),new Response("OK",{status:200})}catch(A){return console.error("Error during CIAM back-channel logout:",A),new Response("Internal Server Error",{status:500})}}function S(M){return M.id||M.email||`ciam-${M.userName}`}function V(M,A,X){return{sub:S(M),iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),email:M.email,name:M.name,preferred_username:M.userName,picture:M.avatar,sid:A}}function Q(M,A,X){return{sub:M,iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:A,scope:"openid profile email"}}function z(M){let A=M.exp?new Date(M.exp*1000):new Date;return{id:M.sub,userName:M.preferred_username??"",name:M.name??"",email:M.email??"",avatar:M.picture,userType:"customer",sso:{profile:M,tenant:{id:"ciam",name:"CIAM"},scope:"openid profile email",tokenType:"Bearer",expires:A}}}async function H(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(!q)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await q.getWorkloadIdentity(M))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let X,Z;try{let n=M.headers.get("content-type");if(!n||!n.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let a=await M.text(),R=JSON.parse(a);if(Z=typeof R?.redirect==="string"&&R.redirect.length>0?R.redirect:void 0,X={userName:R.userName,name:R.name,email:R.email,avatar:R.avatar},!X.userName||!X.name||!X.email)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}})}catch(n){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let _=new URL(M.url).searchParams.get("ttl"),O=_?parseInt(_,10):Y.magicLinkTtl??3600;if(Number.isNaN(O)||O<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let I=i(32),C=new Date(Date.now()+O*1000);if(!Y.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await Y.magicLinkStore.create(I,X,C)}catch(n){return console.error("Error creating magic link:",n),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let u=new URL(M.url),c=Y.magicLinkLoginUrl||"/magic-link/login",T=new URL(c,u.origin);if(T.searchParams.set("token",I),Z)T.searchParams.set("redirect",Z);return new Response(JSON.stringify({magicLink:T.toString(),expiresAt:C.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function F(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=new URL(M.url),X=A.searchParams.get("token");if(!X){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}if(!Y.magicLinkStore){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}let Z=await Y.magicLinkStore.get(X);if(!Z){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}let K=new Date(Date.now()+(Y.sessionTtl??86400)*1000),_=i(32),O=S(Z.user),I=V(Z.user,_,K),C=Q(O,_,K),u=z(I);try{let L={sid:_,sub:O,createdAt:new Date,lastActivityAt:new Date};await g().create(L)}catch(L){console.warn("Failed to create session:",L)}if(Y.userStore)try{let L=u.id;if(L){let r=new Date,o=await Y.userStore.get(L);if(o||Y.enableJitUserProvisioning){let HM={...o??{},...u,id:L,tenantId:o?.tenantId,createdAt:o?.createdAt??r,updatedAt:r,userType:o?.userType??"customer"};await Y.userStore.upsert(HM)}}}catch(L){console.warn("Failed to store user:",L)}try{await Y.magicLinkStore.delete(X)}catch(L){console.warn("Failed to delete magic link:",L)}let c=await f(C),T=await f(I),n=Y.landingUrl||"/",a=A.searchParams.get("redirect"),R=n;if(a)if(a.startsWith("/"))R=a;else try{if(new URL(a).origin===new URL(M.url).origin)R=a}catch{}return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",R],...P(c,T,K)]})}async function $(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=Y.magicLinkUrl||"/magic-link",X=Y.magicLinkLoginUrl||"/magic-link/login",Z=Y.logoutUrl||"/auth/logout",K=Y.logoutBackChannelUrl||"/auth/logout/backchannel",_=new URL(M.url).pathname,O=(T)=>{if(!T)return;try{return new URL(T).pathname}catch{return T.startsWith("/")?T:`/${T}`}};if(O(A)===_&&M.method==="POST")return H(M);if(O(X)===_&&M.method==="GET")return F(M);if(O(Z)===_&&M.method==="GET")return p(M);if(O(K)===_&&M.method==="POST")return y(M);return new Response("Not Found",{status:404})}return{...Y,getUser:w,getRequiredUser:b,logout:p,logoutBackChannel:y,handler:$}}async function BM(W,D){return e(D,"EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function."),D.ciam?.getUser(W)}function N(W,D,j){return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:String(W),scimType:j,detail:D}),{status:W,headers:{"Content-Type":"application/scim+json"}})}function MM(W,D){let j=D?.totalResults??W.length,h=D?.startIndex??1,q=D?.itemsPerPage??W.length;return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:ListResponse"],totalResults:j,startIndex:h,itemsPerPage:q,Resources:W}),{status:200,headers:{"Content-Type":"application/scim+json"}})}function d(W,D=200){return new Response(JSON.stringify(W),{status:D,headers:{"Content-Type":"application/scim+json"}})}function s(W){return{schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],id:W.id,externalId:W.externalId,displayName:W.displayName,members:W.members,meta:{resourceType:"Group",created:W.createdAt.toISOString(),lastModified:W.updatedAt.toISOString()}}}function AM(){return crypto.randomUUID()}function SM(W,D,j,h,q){if(!h&&!q)return;let Y={...h,...q};function U(){if(!j)throw D.error?.("IAM requires workload configuration before use"),Error("IAM requires workload configuration");return j}async function g(){let B=U(),G=typeof B.getServerToken==="function"?await B.getServerToken():await B.getToken();return new Headers({"Content-Type":"application/scim+json",Accept:"application/scim+json",Authorization:`Bearer ${G}`})}async function m(B,G,J,P){if(!Y.url)throw Error("IAM URL not configured for outgoing requests");let v=`${Y.url}${G}`;try{let w=await g(),b=await fetch(v,{method:B,headers:w,body:J?JSON.stringify(J):void 0}),p=await b.json();if(!b.ok)return{success:!1,error:p,status:b.status};let y=await P["~standard"].validate(p);if(y.issues)return console.error("SCIM response validation failed:",y.issues),{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${y.issues.map((S)=>S.message).join("; ")}`},status:400};return{success:!0,data:y.value,status:b.status}}catch(w){return{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"500",detail:w instanceof Error?w.message:"Unknown error occurred"},status:500}}}function i(){return Y.url}let l,t;if(Y.url)t=async(G,J)=>{let P={...G,schemas:G.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return m("POST","/Users",P,W.user)},l={createGroup:async(G,J)=>{let P={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:G,externalId:J?.externalId,members:J?.members};return m("POST","/Groups",P,W.group)}};let x;if(Y.groupStore){let B=Y.groupStore,G=async(S)=>{let V=U(),Q=S.headers.get("Authorization");if(!Q||!Q.startsWith("Bearer "))return!1;try{let z=Q.substring(7);return(await V.validateToken(z)).valid}catch{return!1}},J=async(S,V)=>{if(!await G(S))return N(401,"Authorization required");let z=new URL(S.url),H=V?.basePath??"/Groups",F=z.pathname;if(F.startsWith(H))F=F.substring(H.length);let M=F.match(/^\/([^/]+)$/)?.[1],A=S.method;try{if(M)switch(A){case"GET":return await v(M);case"PUT":return await b(S,M);case"PATCH":return await p(S,M);case"DELETE":return await y(M);default:return N(405,"Method not allowed")}else if(F===""||F==="/")switch(A){case"GET":return await P(S);case"POST":return await w(S);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(X){return console.error("Groups inbound handler error:",X),N(500,X instanceof Error?X.message:"Internal server error")}},P=async(S)=>{let V=new URL(S.url),Q=V.searchParams.get("startIndex"),z=V.searchParams.get("count"),H=Q!=null?parseInt(Q,10):void 0,F=z!=null?parseInt(z,10):void 0,$=H!=null&&!Number.isNaN(H)?Math.max(0,H-1):0,M=F!=null&&!Number.isNaN(F)?F:void 0,A=await B.list({start:$,limit:M}),X=A.items.map(s);return MM(X,{totalResults:A.total,startIndex:$+1,itemsPerPage:A.count})},v=async(S)=>{let V=await B.get(S);if(!V)return N(404,`Group ${S} not found`,"invalidValue");return d(s(V))},w=async(S)=>{let V=await S.json(),Q=await W.group["~standard"].validate(V);if(Q.issues)return console.error("Group creation validation failed:",Q.issues),N(400,`Request validation failed: ${Q.issues.map(($)=>$.message).join("; ")}`,"invalidValue");let z=Q.value;if(!z.displayName)return N(400,"displayName is required","invalidValue");let H=new Date,F={id:AM(),displayName:z.displayName,externalId:z.externalId,members:z.members,createdAt:H,updatedAt:H};return await B.upsert(F),d(s(F),201)},b=async(S,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let z=await S.json(),H=await W.group["~standard"].validate(z);if(H.issues)return console.error("Group replacement validation failed:",H.issues),N(400,`Request validation failed: ${H.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let F=H.value,$={...Q,displayName:F.displayName??Q.displayName,externalId:F.externalId,members:F.members,updatedAt:new Date};return await B.upsert($),d(s($))},p=async(S,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let H=(await S.json()).Operations??[],F={...Q};for(let $ of H)if($.op==="replace"&&$.path&&$.value!==void 0){if($.path==="displayName")F.displayName=$.value}else if($.op==="add"&&$.path&&$.value!==void 0){if($.path==="members"){let M=$.value;F.members=[...F.members??[],...M]}}else if($.op==="remove"&&$.path){if($.path.startsWith("members[")){let M=$.path.match(/members\[value eq "([^"]+)"\]/);if(M)F.members=(F.members??[]).filter((A)=>A.value!==M[1])}}return F.updatedAt=new Date,await B.upsert(F),d(s(F))},y=async(S)=>{if(!await B.get(S))return N(404,`Group ${S} not found`,"invalidValue");return await B.delete(S),new Response(null,{status:204})};x={handler:J}}let f;if(Y.userStore){let B=Y.userStore,G=async(Q)=>{let z=U(),H=Q.headers.get("Authorization");if(!H||!H.startsWith("Bearer "))return!1;try{let F=H.substring(7);return(await z.validateToken(F)).valid}catch{return!1}},J=(Q)=>{return{schemas:["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],id:Q.id,userName:Q.userName||Q.email||Q.id,displayName:Q.name||Q.userName||Q.email,name:Q.name?{givenName:Q.name.split(" ")[0],familyName:Q.name.split(" ").slice(1).join(" ")||void 0}:void 0,emails:Q.email?[{value:Q.email,primary:!0}]:[],active:!0,...Q.userType!=null&&{userType:Q.userType},meta:{resourceType:"User",created:Q.createdAt.toISOString(),lastModified:Q.updatedAt.toISOString()}}},P=(Q)=>{let z=new Date,H=Q.emails?.find((A)=>A.primary)?.value||Q.emails?.[0]?.value,F=Q.name?`${Q.name.givenName||""} ${Q.name.familyName||""}`.trim():Q.displayName,$=Q.id||AM(),M=Q.userName||H||$;return{id:$,userName:M,name:F||Q.displayName||M,email:H||M,avatar:Q.profileUrl,sso:{profile:{sub:$,iss:"iam-provisioned",aud:"iam-provisioned",exp:Math.floor(Date.now()/1000)+3600,iat:Math.floor(Date.now()/1000),email:H||M,email_verified:!0,name:F||Q.displayName||M,preferred_username:M},tenant:{id:"iam-provisioned",name:"IAM Provisioned"},scope:"openid profile email",tokenType:"Bearer",expires:new Date(Date.now()+3600000)},createdAt:Q.meta?.created?new Date(Q.meta.created):z,updatedAt:Q.meta?.lastModified?new Date(Q.meta.lastModified):z,...Q.userType!=null&&{userType:Q.userType}}},v=async(Q,z)=>{if(!await G(Q))return N(401,"Authorization required");let F=new URL(Q.url),$=z?.basePath??"/Users",M=F.pathname;if(M.startsWith($))M=M.substring($.length);let X=M.match(/^\/([^/]+)$/)?.[1],Z=Q.method;try{if(X)switch(Z){case"GET":return await b(X);case"PUT":return await y(Q,X);case"PATCH":return await S(Q,X);case"DELETE":return await V(X);default:return N(405,"Method not allowed")}else if(M===""||M==="/")switch(Z){case"GET":return await w(Q);case"POST":return await p(Q);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(K){return console.error("Users inbound handler error:",K),N(500,K instanceof Error?K.message:"Internal server error")}},w=async(Q)=>{let z=new URL(Q.url),H=z.searchParams.get("startIndex"),F=z.searchParams.get("count"),$=H!=null?parseInt(H,10):void 0,M=F!=null?parseInt(F,10):void 0,A=$!=null&&!Number.isNaN($)?Math.max(0,$-1):0,X=M!=null&&!Number.isNaN(M)?M:void 0,Z=await B.list({start:A,limit:X}),K=Z.items.map(J);return MM(K,{totalResults:Z.total,startIndex:A+1,itemsPerPage:Z.count})},b=async(Q)=>{let z=await B.get(Q);if(!z)return N(404,`User ${Q} not found`,"invalidValue");return d(J(z))},p=async(Q)=>{let z=await Q.json(),H=await W.user["~standard"].validate(z);if(H.issues)return console.error("User creation validation failed:",H.issues),N(400,`Request validation failed: ${H.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let F=H.value;if(!F.userName&&!F.emails?.[0]?.value)return N(400,"userName or email is required","invalidValue");let $=P(F);return await B.upsert($),d(J($),201)},y=async(Q,z)=>{let H=await B.get(z);if(!H)return N(404,`User ${z} not found`,"invalidValue");let F=await Q.json(),$=await W.user["~standard"].validate(F);if($.issues)return console.error("User replacement validation failed:",$.issues),N(400,`Request validation failed: ${$.issues.map((X)=>X.message).join("; ")}`,"invalidValue");let M=$.value,A=P({...M,id:z});return A.createdAt=H.createdAt,A.updatedAt=new Date,await B.upsert(A),d(J(A))},S=async(Q,z)=>{let H=await B.get(z);if(!H)return N(404,`User ${z} not found`,"invalidValue");let $=(await Q.json()).Operations??[],M={...H};for(let A of $)if(A.op==="replace"&&A.path&&A.value!==void 0){if(A.path==="displayName")M.name=A.value;else if(A.path==="userName")M.userName=A.value;else if(A.path.startsWith("name.")){let X=A.path.split(".")[1];if(!M.name)M.name="";if(X==="givenName")M.name=`${A.value} ${M.name.split(" ").slice(1).join(" ")}`.trim();else if(X==="familyName")M.name=`${M.name.split(" ")[0]} ${A.value}`.trim()}else if(A.path==="emails"){let X=A.value,Z=X?.find((K)=>K.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="add"&&A.path&&A.value!==void 0){if(A.path==="emails"){let X=A.value,Z=X?.find((K)=>K.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="remove"&&A.path){if(A.path==="displayName")M.name=""}return M.updatedAt=new Date,await B.upsert(M),d(J(M))},V=async(Q)=>{if(!await B.get(Q))return N(404,`User ${Q} not found`,"invalidValue");return await B.delete(Q),new Response(null,{status:204})};f={handler:v}}async function k(B,G){U();let P=new URL(B.url).pathname,v=G?.usersUrl??Y.usersUrl??"/api/iam/Users",w=G?.groupsUrl??Y.groupsUrl??"/api/iam/Groups";if(P.startsWith(v)&&f)return f.handler(B,{basePath:v});if(P.startsWith(w)&&x)return x.handler(B,{basePath:w});return N(404,"Resource not found")}return{...Y,createUser:t,getBaseUrl:i,groups_outbound:l,groups_inbound:x,users_inbound:f,handler:k}}var KM="@enterprisestandard/core",WM=YM(XM(KM));function QM(W){let D=W.replace(/-/g,"+").replace(/_/g,"/");return atob(D)}async function OM(W,D){let j=W.split(".");if(j.length!==3)throw Error("Invalid JWT");let h=JSON.parse(QM(j[0])),q=JSON.parse(QM(j[1])),E=j[2].replace(/-/g,"+").replace(/_/g,"/"),Y=h.kid;if(!Y)throw Error("JWT header missing kid");let U=await $M(D),g=await FM(U,Y),i=new TextEncoder().encode(`${j[0]}.${j[1]}`),l=Uint8Array.from(atob(E),(B)=>B.charCodeAt(0));if(!await crypto.subtle.verify("RSASSA-PKCS1-v1_5",g,l,i))throw Error("Invalid JWT signature");let x=await WM.validate(q);if(x.issues)throw Error(`ID token claims validation failed: ${x.issues.map((B)=>B.message).join("; ")}`);let f=x.value;if(f===void 0)throw Error("ID token claims missing");let k=f;if(typeof k.exp==="number"&&k.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return ZM(k)}export{PM as withTenantConfigMethod,OM as verifyUser,EM as tenantConfigSource,NM as sso,IM as registerTenantConfigSourceFactory,jM as logoutBackChannel,DM as logout,JM as initiateLogin,SM as iam,_M as getSSOorCIAMUser,VM as getSSOUser,GM as getRequiredSSOorCIAMUser,BM as getCIAMUser,zM as ciam,LM as callback};
1
+ import{A as _M,B as GM,C as JM,D as LM,E as DM,F as jM,G as IM,H as EM,I as PM,c as XM,d as YM,e,k as ZM,r as $M,s as FM,y as NM,z as VM}from"./shared/core-kk9hdwwp.js";function zM(W,D,j,h,q){if(!j&&!h)return;let E={...j,...h},Y={...E,signingKey:j?.signingKey,magicLinkTtl:E.magicLinkTtl??3600,sessionTtl:E.sessionTtl??86400,cookiesSecure:E.cookiesSecure!==void 0?E.cookiesSecure:!0,cookiesSameSite:E.cookiesSameSite!==void 0?E.cookiesSameSite:"Strict",cookiesPrefix:E.cookiesPrefix??(E.ciamId?`es.ciam.${E.ciamId}`:"es.ciam"),cookiesPath:E.cookiesPath??"/",sessionValidation:E.sessionValidation??"always"};function U(){if(!Y.signingKey)throw Error("Missing CIAM configuration field: signingKey. CIAM signingKey is required for JWT token signing and must be provided via Vault (ciam.signingKey).")}function g(){if(!Y.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and backchannel logout.");return Y.sessionStore}function m(){U(),g()}function i(M=32){let A=new Uint8Array(M);return crypto.getRandomValues(A),Array.from(A,(X)=>X.toString(16).padStart(2,"0")).join("").substring(0,M)}function l(M){let A=typeof M==="string"?new TextEncoder().encode(M):M,X="";return A.forEach((Z)=>{X+=String.fromCharCode(Z)}),btoa(X).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function t(M){let A=M.replace(/-/g,"+").replace(/_/g,"/"),X=A.padEnd(A.length+(4-A.length%4)%4,"=");return atob(X)}async function x(){U();let M=new TextEncoder().encode(Y.signingKey??"");return crypto.subtle.importKey("raw",M,{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async function f(M){let X=l(JSON.stringify({alg:"HS256",typ:"JWT"})),Z=l(JSON.stringify(M)),K=`${X}.${Z}`,_=await x(),O=await crypto.subtle.sign("HMAC",_,new TextEncoder().encode(K)),I=l(new Uint8Array(O));return`${K}.${I}`}async function k(M){let A=M.split(".");if(A.length!==3)throw Error("Invalid JWT");let[X,Z,K]=A,_=`${X}.${Z}`,O=await x(),I=new Uint8Array(t(K).split("").map((T)=>T.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",O,I,new TextEncoder().encode(_)))throw Error("Invalid JWT signature");let u=t(Z),c=JSON.parse(u);if(typeof c.exp==="number"&&c.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return c}function B(M,A,X){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(M=`${Y.cookiesPrefix}.${M}`,typeof A!=="string")A=btoa(JSON.stringify(A));let Z;if(X instanceof Date)Z=`Expires=${X.toUTCString()}`;else if(typeof X==="number")Z=`Max-Age=${X}`;else throw Error("Invalid expires type",X);if(A.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${A.length}`);return`${M}=${A}; ${Z}; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function G(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");return`${Y.cookiesPrefix}.${M}=; Max-Age=0; Path=${Y.cookiesPath}; HttpOnly;${Y.cookiesSecure?" Secure;":""} SameSite=${Y.cookiesSameSite};`}function J(M,A,X=!1){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");let Z=A.headers.get("cookie");if(!Z)return null;let K=`${Y.cookiesPrefix}.${M}`,_=Z.split(";").find((C)=>C.trim().startsWith(`${K}=`));if(!_)return null;let O=_.indexOf("="),I=_.substring(O+1).trim();if(!X)return I;try{let C=atob(I);return JSON.parse(C)}catch(C){return console.error(`[CIAM] Failed to parse cookie '${K}':`,C),null}}function P(M,A,X){let Z={expires_in:Y.sessionTtl??86400,token_type:"Bearer",expires:X.toISOString()};return[["Set-Cookie",B("access",M,X)],["Set-Cookie",B("id",A,X)],["Set-Cookie",B("control",Z,X)]]}function v(M){let A=J("access",M),X=J("id",M),Z=J("control",M,!0);if(!A||!X||!Z)return;if(Z.expires&&Date.now()>new Date(Z.expires).getTime())return;return{access:A,id:X,control:Z}}async function w(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=v(M);if(!A)return;let X=await k(A.access),Z=await k(A.id);if(!X.sid||!Z.sub)return;if(Y.sessionValidation!=="disabled"){if(!await g().get(X.sid))return}return z(Z)}catch(A){return}}async function b(M){let A=await w(M);if(A)return A;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function p(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let O=v(M);if(O){let I=await k(O.access);if(I.sid)await g().delete(I.sid)}}catch(O){console.warn("Failed to delete CIAM session:",O)}let A=[["Set-Cookie",G("access")],["Set-Cookie",G("id")],["Set-Cookie",G("control")]],Z=new URL(M.url).searchParams.get("redirect");if(Z)return new Response("Logged out",{status:302,headers:[["Location",Z],...A]});let K=M.headers.get("accept");if(K?.includes("application/json")||K?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out"}),{status:200,headers:[["Content-Type","application/json"],...A]});return new Response("Logout Complete",{status:200,headers:[["Content-Type","text/plain"],...A]})}async function y(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();try{let A=M.headers.get("content-type");if(!A||!A.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let X=await M.text(),K=new URLSearchParams(X).get("logout_token");if(!K)return new Response("Missing logout_token parameter",{status:400});let O=(await k(K)).sid;if(!O)return new Response("Invalid logout_token: missing sid claim",{status:400});return await g().delete(O),new Response("OK",{status:200})}catch(A){return console.error("Error during CIAM back-channel logout:",A),new Response("Internal Server Error",{status:500})}}function S(M){return M.id||M.email||`ciam-${M.userName}`}function V(M,A,X){return{sub:S(M),iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),email:M.email,name:M.name,preferred_username:M.userName,picture:M.avatar,sid:A}}function Q(M,A,X){return{sub:M,iss:"ciam",aud:"ciam",exp:Math.floor(X.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:A,scope:"openid profile email"}}function z(M){let A=M.exp?new Date(M.exp*1000):new Date;return{id:M.sub,userName:M.preferred_username??"",name:M.name??"",email:M.email??"",avatar:M.picture,userType:"customer",sso:{profile:M,tenant:{id:"ciam",name:"CIAM"},scope:"openid profile email",tokenType:"Bearer",expires:A}}}async function H(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");if(!q)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await q.getWorkloadIdentity(M))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let X,Z;try{let n=M.headers.get("content-type");if(!n||!n.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let a=await M.text(),R=JSON.parse(a);if(Z=typeof R?.redirect==="string"&&R.redirect.length>0?R.redirect:void 0,X={userName:R.userName,name:R.name,email:R.email,avatar:R.avatar},!X.userName||!X.name||!X.email)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}})}catch(n){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let _=new URL(M.url).searchParams.get("ttl"),O=_?parseInt(_,10):Y.magicLinkTtl??3600;if(Number.isNaN(O)||O<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let I=i(32),C=new Date(Date.now()+O*1000);if(!Y.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await Y.magicLinkStore.create(I,X,C)}catch(n){return console.error("Error creating magic link:",n),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let u=new URL(M.url),c=Y.magicLinkLoginUrl||"/magic-link/login",T=new URL(c,u.origin);if(T.searchParams.set("token",I),Z)T.searchParams.set("redirect",Z);return new Response(JSON.stringify({magicLink:T.toString(),expiresAt:C.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function F(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=new URL(M.url),X=A.searchParams.get("token");if(!X){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}if(!Y.magicLinkStore){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}let Z=await Y.magicLinkStore.get(X);if(!Z){let L=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:L}})}let K=new Date(Date.now()+(Y.sessionTtl??86400)*1000),_=i(32),O=S(Z.user),I=V(Z.user,_,K),C=Q(O,_,K),u=z(I);try{let L={sid:_,sub:O,createdAt:new Date,lastActivityAt:new Date};await g().create(L)}catch(L){console.warn("Failed to create session:",L)}if(Y.userStore)try{let L=u.id;if(L){let r=new Date,o=await Y.userStore.get(L);if(o||Y.enableJitUserProvisioning){let HM={...o??{},...u,id:L,tenantId:o?.tenantId,createdAt:o?.createdAt??r,updatedAt:r,userType:o?.userType??"customer"};await Y.userStore.upsert(HM)}}}catch(L){console.warn("Failed to store user:",L)}try{await Y.magicLinkStore.delete(X)}catch(L){console.warn("Failed to delete magic link:",L)}let c=await f(C),T=await f(I),n=Y.landingUrl||"/",a=A.searchParams.get("redirect"),R=n;if(a)if(a.startsWith("/"))R=a;else try{if(new URL(a).origin===new URL(M.url).origin)R=a}catch{}return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",R],...P(c,T,K)]})}async function $(M){if(!Y)throw Error("Enterprise Standard CIAM Manager not initialized");m();let A=Y.magicLinkUrl||"/magic-link",X=Y.magicLinkLoginUrl||"/magic-link/login",Z=Y.logoutUrl||"/auth/logout",K=Y.logoutBackChannelUrl||"/auth/logout/backchannel",_=new URL(M.url).pathname,O=(T)=>{if(!T)return;try{return new URL(T).pathname}catch{return T.startsWith("/")?T:`/${T}`}};if(O(A)===_&&M.method==="POST")return H(M);if(O(X)===_&&M.method==="GET")return F(M);if(O(Z)===_&&M.method==="GET")return p(M);if(O(K)===_&&M.method==="POST")return y(M);return new Response("Not Found",{status:404})}return{...Y,getUser:w,getRequiredUser:b,logout:p,logoutBackChannel:y,handler:$}}async function BM(W,D){return e(D,"EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function."),D.ciam?.getUser(W)}function N(W,D,j){return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:String(W),scimType:j,detail:D}),{status:W,headers:{"Content-Type":"application/scim+json"}})}function MM(W,D){let j=D?.totalResults??W.length,h=D?.startIndex??1,q=D?.itemsPerPage??W.length;return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:ListResponse"],totalResults:j,startIndex:h,itemsPerPage:q,Resources:W}),{status:200,headers:{"Content-Type":"application/scim+json"}})}function d(W,D=200){return new Response(JSON.stringify(W),{status:D,headers:{"Content-Type":"application/scim+json"}})}function s(W){return{schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],id:W.id,externalId:W.externalId,displayName:W.displayName,members:W.members,meta:{resourceType:"Group",created:W.createdAt.toISOString(),lastModified:W.updatedAt.toISOString()}}}function AM(){return crypto.randomUUID()}function SM(W,D,j,h,q){if(!h&&!q)return;let Y={...h,...q};function U(){if(!j)throw D.error?.("IAM requires workload configuration before use"),Error("IAM requires workload configuration");return j}async function g(){let B=U(),G=typeof B.getServerToken==="function"?await B.getServerToken():await B.getToken();return new Headers({"Content-Type":"application/scim+json",Accept:"application/scim+json",Authorization:`Bearer ${G}`})}async function m(B,G,J,P){if(!Y.url)throw Error("IAM URL not configured for outgoing requests");let v=`${Y.url}${G}`;try{let w=await g(),b=await fetch(v,{method:B,headers:w,body:J?JSON.stringify(J):void 0}),p=await b.json();if(!b.ok)return{success:!1,error:p,status:b.status};let y=await P["~standard"].validate(p);if(y.issues)return console.error("SCIM response validation failed:",y.issues),{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${y.issues.map((S)=>S.message).join("; ")}`},status:400};return{success:!0,data:y.value,status:b.status}}catch(w){return{success:!1,error:{schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:"500",detail:w instanceof Error?w.message:"Unknown error occurred"},status:500}}}function i(){return Y.url}let l,t;if(Y.url)t=async(G,J)=>{let P={...G,schemas:G.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return m("POST","/Users",P,W.user)},l={createGroup:async(G,J)=>{let P={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:G,externalId:J?.externalId,members:J?.members};return m("POST","/Groups",P,W.group)}};let x;if(Y.groupStore){let B=Y.groupStore,G=async(S)=>{let V=U(),Q=S.headers.get("Authorization");if(!Q||!Q.startsWith("Bearer "))return!1;try{let z=Q.substring(7);return(await V.validateToken(z)).valid}catch{return!1}},J=async(S,V)=>{if(!await G(S))return N(401,"Authorization required");let z=new URL(S.url),H=V?.basePath??"/Groups",F=z.pathname;if(F.startsWith(H))F=F.substring(H.length);let M=F.match(/^\/([^/]+)$/)?.[1],A=S.method;try{if(M)switch(A){case"GET":return await v(M);case"PUT":return await b(S,M);case"PATCH":return await p(S,M);case"DELETE":return await y(M);default:return N(405,"Method not allowed")}else if(F===""||F==="/")switch(A){case"GET":return await P(S);case"POST":return await w(S);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(X){return console.error("Groups inbound handler error:",X),N(500,X instanceof Error?X.message:"Internal server error")}},P=async(S)=>{let V=new URL(S.url),Q=V.searchParams.get("startIndex"),z=V.searchParams.get("count"),H=Q!=null?parseInt(Q,10):void 0,F=z!=null?parseInt(z,10):void 0,$=H!=null&&!Number.isNaN(H)?Math.max(0,H-1):0,M=F!=null&&!Number.isNaN(F)?F:void 0,A=await B.list({start:$,limit:M}),X=A.items.map(s);return MM(X,{totalResults:A.total,startIndex:$+1,itemsPerPage:A.count})},v=async(S)=>{let V=await B.get(S);if(!V)return N(404,`Group ${S} not found`,"invalidValue");return d(s(V))},w=async(S)=>{let V=await S.json(),Q=await W.group["~standard"].validate(V);if(Q.issues)return console.error("Group creation validation failed:",Q.issues),N(400,`Request validation failed: ${Q.issues.map(($)=>$.message).join("; ")}`,"invalidValue");let z=Q.value;if(!z.displayName)return N(400,"displayName is required","invalidValue");let H=new Date,F={id:AM(),displayName:z.displayName,externalId:z.externalId,members:z.members,createdAt:H,updatedAt:H};return await B.upsert(F),d(s(F),201)},b=async(S,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let z=await S.json(),H=await W.group["~standard"].validate(z);if(H.issues)return console.error("Group replacement validation failed:",H.issues),N(400,`Request validation failed: ${H.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let F=H.value,$={...Q,displayName:F.displayName??Q.displayName,externalId:F.externalId,members:F.members,updatedAt:new Date};return await B.upsert($),d(s($))},p=async(S,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let H=(await S.json()).Operations??[],F={...Q};for(let $ of H)if($.op==="replace"&&$.path&&$.value!==void 0){if($.path==="displayName")F.displayName=$.value}else if($.op==="add"&&$.path&&$.value!==void 0){if($.path==="members"){let M=$.value;F.members=[...F.members??[],...M]}}else if($.op==="remove"&&$.path){if($.path.startsWith("members[")){let M=$.path.match(/members\[value eq "([^"]+)"\]/);if(M)F.members=(F.members??[]).filter((A)=>A.value!==M[1])}}return F.updatedAt=new Date,await B.upsert(F),d(s(F))},y=async(S)=>{if(!await B.get(S))return N(404,`Group ${S} not found`,"invalidValue");return await B.delete(S),new Response(null,{status:204})};x={handler:J}}let f;if(Y.userStore){let B=Y.userStore,G=async(Q)=>{let z=U(),H=Q.headers.get("Authorization");if(!H||!H.startsWith("Bearer "))return!1;try{let F=H.substring(7);return(await z.validateToken(F)).valid}catch{return!1}},J=(Q)=>{return{schemas:["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],id:Q.id,userName:Q.userName||Q.email||Q.id,displayName:Q.name||Q.userName||Q.email,name:Q.name?{givenName:Q.name.split(" ")[0],familyName:Q.name.split(" ").slice(1).join(" ")||void 0}:void 0,emails:Q.email?[{value:Q.email,primary:!0}]:[],active:!0,...Q.userType!=null&&{userType:Q.userType},meta:{resourceType:"User",created:Q.createdAt.toISOString(),lastModified:Q.updatedAt.toISOString()}}},P=(Q)=>{let z=new Date,H=Q.emails?.find((A)=>A.primary)?.value||Q.emails?.[0]?.value,F=Q.name?`${Q.name.givenName||""} ${Q.name.familyName||""}`.trim():Q.displayName,$=Q.id||AM(),M=Q.userName||H||$;return{id:$,userName:M,name:F||Q.displayName||M,email:H||M,avatar:Q.profileUrl,sso:{profile:{sub:$,iss:"iam-provisioned",aud:"iam-provisioned",exp:Math.floor(Date.now()/1000)+3600,iat:Math.floor(Date.now()/1000),email:H||M,email_verified:!0,name:F||Q.displayName||M,preferred_username:M},tenant:{id:"iam-provisioned",name:"IAM Provisioned"},scope:"openid profile email",tokenType:"Bearer",expires:new Date(Date.now()+3600000)},createdAt:Q.meta?.created?new Date(Q.meta.created):z,updatedAt:Q.meta?.lastModified?new Date(Q.meta.lastModified):z,...Q.userType!=null&&{userType:Q.userType}}},v=async(Q,z)=>{if(!await G(Q))return N(401,"Authorization required");let F=new URL(Q.url),$=z?.basePath??"/Users",M=F.pathname;if(M.startsWith($))M=M.substring($.length);let X=M.match(/^\/([^/]+)$/)?.[1],Z=Q.method;try{if(X)switch(Z){case"GET":return await b(X);case"PUT":return await y(Q,X);case"PATCH":return await S(Q,X);case"DELETE":return await V(X);default:return N(405,"Method not allowed")}else if(M===""||M==="/")switch(Z){case"GET":return await w(Q);case"POST":return await p(Q);default:return N(405,"Method not allowed")}return N(404,"Resource not found")}catch(K){return console.error("Users inbound handler error:",K),N(500,K instanceof Error?K.message:"Internal server error")}},w=async(Q)=>{let z=new URL(Q.url),H=z.searchParams.get("startIndex"),F=z.searchParams.get("count"),$=H!=null?parseInt(H,10):void 0,M=F!=null?parseInt(F,10):void 0,A=$!=null&&!Number.isNaN($)?Math.max(0,$-1):0,X=M!=null&&!Number.isNaN(M)?M:void 0,Z=await B.list({start:A,limit:X}),K=Z.items.map(J);return MM(K,{totalResults:Z.total,startIndex:A+1,itemsPerPage:Z.count})},b=async(Q)=>{let z=await B.get(Q);if(!z)return N(404,`User ${Q} not found`,"invalidValue");return d(J(z))},p=async(Q)=>{let z=await Q.json(),H=await W.user["~standard"].validate(z);if(H.issues)return console.error("User creation validation failed:",H.issues),N(400,`Request validation failed: ${H.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let F=H.value;if(!F.userName&&!F.emails?.[0]?.value)return N(400,"userName or email is required","invalidValue");let $=P(F);return await B.upsert($),d(J($),201)},y=async(Q,z)=>{let H=await B.get(z);if(!H)return N(404,`User ${z} not found`,"invalidValue");let F=await Q.json(),$=await W.user["~standard"].validate(F);if($.issues)return console.error("User replacement validation failed:",$.issues),N(400,`Request validation failed: ${$.issues.map((X)=>X.message).join("; ")}`,"invalidValue");let M=$.value,A=P({...M,id:z});return A.createdAt=H.createdAt,A.updatedAt=new Date,await B.upsert(A),d(J(A))},S=async(Q,z)=>{let H=await B.get(z);if(!H)return N(404,`User ${z} not found`,"invalidValue");let $=(await Q.json()).Operations??[],M={...H};for(let A of $)if(A.op==="replace"&&A.path&&A.value!==void 0){if(A.path==="displayName")M.name=A.value;else if(A.path==="userName")M.userName=A.value;else if(A.path.startsWith("name.")){let X=A.path.split(".")[1];if(!M.name)M.name="";if(X==="givenName")M.name=`${A.value} ${M.name.split(" ").slice(1).join(" ")}`.trim();else if(X==="familyName")M.name=`${M.name.split(" ")[0]} ${A.value}`.trim()}else if(A.path==="emails"){let X=A.value,Z=X?.find((K)=>K.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="add"&&A.path&&A.value!==void 0){if(A.path==="emails"){let X=A.value,Z=X?.find((K)=>K.primary)?.value||X?.[0]?.value;if(Z)M.email=Z}}else if(A.op==="remove"&&A.path){if(A.path==="displayName")M.name=""}return M.updatedAt=new Date,await B.upsert(M),d(J(M))},V=async(Q)=>{if(!await B.get(Q))return N(404,`User ${Q} not found`,"invalidValue");return await B.delete(Q),new Response(null,{status:204})};f={handler:v}}async function k(B,G){U();let P=new URL(B.url).pathname,v=G?.usersUrl??Y.usersUrl??"/api/iam/Users",w=G?.groupsUrl??Y.groupsUrl??"/api/iam/Groups";if(P.startsWith(v)&&f)return f.handler(B,{basePath:v});if(P.startsWith(w)&&x)return x.handler(B,{basePath:w});return N(404,"Resource not found")}return{...Y,createUser:t,getBaseUrl:i,groups_outbound:l,groups_inbound:x,users_inbound:f,handler:k}}var KM="@enterprisestandard/core",WM=YM(XM(KM));function QM(W){let D=W.replace(/-/g,"+").replace(/_/g,"/");return atob(D)}async function OM(W,D){let j=W.split(".");if(j.length!==3)throw Error("Invalid JWT");let h=JSON.parse(QM(j[0])),q=JSON.parse(QM(j[1])),E=j[2].replace(/-/g,"+").replace(/_/g,"/"),Y=h.kid;if(!Y)throw Error("JWT header missing kid");let U=await $M(D),g=await FM(U,Y),i=new TextEncoder().encode(`${j[0]}.${j[1]}`),l=Uint8Array.from(atob(E),(B)=>B.charCodeAt(0));if(!await crypto.subtle.verify("RSASSA-PKCS1-v1_5",g,l,i))throw Error("Invalid JWT signature");let x=await WM.validate(q);if(x.issues)throw Error(`ID token claims validation failed: ${x.issues.map((B)=>B.message).join("; ")}`);let f=x.value;if(f===void 0)throw Error("ID token claims missing");let k=f;if(typeof k.exp==="number"&&k.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return ZM(k)}export{PM as withTenantConfigMethod,OM as verifyUser,EM as tenantConfigSource,NM as sso,IM as registerTenantConfigSourceFactory,jM as logoutBackChannel,DM as logout,JM as initiateLogin,SM as iam,_M as getSSOorCIAMUser,VM as getSSOUser,GM as getRequiredSSOorCIAMUser,BM as getCIAMUser,zM as ciam,LM as callback};
@@ -0,0 +1,12 @@
1
+ function DS(X){return{"~standard":{version:1,vendor:X,validate:(Y)=>{if(typeof Y!=="object"||Y===null)return{issues:[{message:"Expected an object"}]};let S=Y,N=[],$={};if("code"in S)if(typeof S.code==="string")$.code=S.code;else N.push({message:"code must be a string",path:["code"]});else if(!("error"in S))N.push({message:"code is required",path:["code"]});if("state"in S)if(typeof S.state==="string"||S.state===void 0)$.state=S.state;else N.push({message:"state must be a string",path:["state"]});if("session_state"in S)if(typeof S.session_state==="string"||S.session_state===void 0)$.session_state=S.session_state;else N.push({message:"session_state must be a string",path:["session_state"]});if("error"in S){if(typeof S.error==="string")$.error=S.error;else N.push({message:"error must be a string",path:["error"]});if("error_description"in S)if(typeof S.error_description==="string"||S.error_description===void 0)$.error_description=S.error_description;else N.push({message:"error_description must be a string",path:["error_description"]});if("error_uri"in S)if(typeof S.error_uri==="string"||S.error_uri===void 0)$.error_uri=S.error_uri;else N.push({message:"error_uri must be a string",path:["error_uri"]})}if("iss"in S)if(typeof S.iss==="string"||S.iss===void 0)$.iss=S.iss;else N.push({message:"iss must be a string",path:["iss"]});if(N.length>0)return{issues:N};return{value:$}}}}}function ES(X){return{"~standard":{version:1,vendor:X,validate:(Y)=>{if(typeof Y!=="object"||Y===null)return{issues:[{message:"Expected an object"}]};let S=Y,N=[],$={};if("access_token"in S)if(typeof S.access_token==="string")$.access_token=S.access_token;else N.push({message:"access_token must be a string",path:["access_token"]});else N.push({message:"access_token is required",path:["access_token"]});if("id_token"in S)if(typeof S.id_token==="string")$.id_token=S.id_token;else N.push({message:"id_token must be a string",path:["id_token"]});else N.push({message:"id_token is required",path:["id_token"]});if("token_type"in S)if(typeof S.token_type==="string")$.token_type=S.token_type;else N.push({message:"token_type must be a string",path:["token_type"]});else N.push({message:"token_type is required",path:["token_type"]});if("refresh_token"in S)if(typeof S.refresh_token==="string"||S.refresh_token===void 0)$.refresh_token=S.refresh_token;else N.push({message:"refresh_token must be a string",path:["refresh_token"]});if("scope"in S)if(typeof S.scope==="string"||S.scope===void 0)$.scope=S.scope;else N.push({message:"scope must be a string",path:["scope"]});if("session_state"in S)if(typeof S.session_state==="string"||S.session_state===void 0)$.session_state=S.session_state;else N.push({message:"session_state must be a string",path:["session_state"]});if("expires"in S)if(typeof S.expires==="string"||S.expires===void 0)$.expires=S.expires;else N.push({message:"expires must be a string",path:["expires"]});if("expires_in"in S)if(typeof S.expires_in==="number"||S.expires_in===void 0)$.expires_in=S.expires_in;else N.push({message:"expires_in must be a number",path:["expires_in"]});if("refresh_expires_in"in S)if(typeof S.refresh_expires_in==="number"||S.refresh_expires_in===void 0)$.refresh_expires_in=S.refresh_expires_in;else N.push({message:"refresh_expires_in must be a number",path:["refresh_expires_in"]});if(N.length>0)return{issues:N};return{value:$}}}}}function i(X){return{"~standard":{version:1,vendor:X,validate:(Y)=>{if(typeof Y!=="object"||Y===null)return{issues:[{message:"Expected an object"}]};let S=Y,N=[],$={...S},B=["iss","aud","sub","sid","name","email","preferred_username","picture"];for(let M of B)if(M in S&&S[M]!==void 0){if(typeof S[M]!=="string")N.push({message:`${M} must be a string`,path:[M]})}let Z=["exp","iat"];for(let M of Z)if(M in S&&S[M]!==void 0){if(typeof S[M]!=="number")N.push({message:`${M} must be a number`,path:[M]})}if(N.length>0)return{issues:N};return{value:$}}}}}function a(X){let Y=X["~standard"];return Object.assign({},X,{validate(S){return Promise.resolve(Y.validate(S))}})}function H(X,Y="Assertion failed. Required value is null or undefined."){if(X===void 0||X===null)throw Error(Y);return X}function o(X,Y){return Response.json({error:"validation_failed",message:Y,issues:X},{status:400,headers:{"Content-Type":"application/json"}})}function PS(X,Y,S=[]){let N={...X,...Y};for(let $ of S)N[$]=X?.[$]??Y?.[$];return N}function BS(X){let Y="",S=0,N=X.length;while(S<N){let $=X[S];if($==='"'||$==="'"){let B=$;Y+=$,S++;while(S<N){let Z=X[S];if(Z==="\\"){if(Y+=Z,S+1<N)Y+=X[S+1],S+=2;else S++;continue}if(Z===B){Y+=Z,S++;break}Y+=Z,S++}continue}if($==="/"&&S+1<N){let B=X[S+1];if(B==="/"){S+=2;while(S<N&&X[S]!==`
2
+ `)S++;if(S<N)Y+=`
3
+ `;S++;continue}if(B==="*"){S+=2;while(S+1<N&&!(X[S]==="*"&&X[S+1]==="/"))S++;S+=2;continue}}Y+=$,S++}return Y}function TS(X){let Y=BS(X);return JSON.parse(Y)}async function zS(X,Y=async(B)=>B.status===200,S=1000,N=1e4,$){let B=Date.now(),Z="Awaiting Ping";return new Promise((M,T)=>{let P=null,y=null,h=async()=>{try{let E=await fetch(X);if(E.ok)if(await Y(E)){if(P)clearInterval(P);if(y)clearInterval(y);M()}else Z=`Response test failed: ${E.status}: ${E.statusText} - ${X}`;else try{let U=await E.json();Z=`Response error: ${E.status}: ${E.statusText} - ${X}: ${JSON.stringify(U)}`}catch(U){Z=`Response error: ${E.status}: ${E.statusText} - ${X}`}}catch(E){Z=`${E instanceof Error?E.message:String(E)} - ${X}`}};if(h(),P=setInterval(h,S),N>0)y=setInterval(()=>{console.warn(`${Z}: ${Date.now()-B}ms`)},N);if($)setTimeout(()=>{if(P)clearInterval(P);if(y)clearInterval(y);T(Error(`Timeout: ${$}ms: ${Z}`))},$)})}var WS="@enterprisestandard/core",MS=a(i(WS));function LS(X){let Y=X.exp!=null?new Date(X.exp*1000):new Date,S=X.iss??"";return{id:X.sub??"",userName:X.preferred_username??"",name:X.name??"",email:X.email??"",avatar:X.picture,sso:{profile:{...X,iss:X.iss??S,aud:X.aud},tenant:{id:X.idp??S,name:S},tokenType:"Bearer",expires:Y}}}function FS(X){let Y=X.replace(/-/g,"+").replace(/_/g,"/");return atob(Y)}async function wS(X){let Y=X.split(".");if(Y.length!==3)throw Error("Invalid JWT");let S=FS(Y[1]),N=JSON.parse(S),$=await MS.validate(N);if($.issues)throw Error(`ID token claims validation failed: ${$.issues.map((B)=>B.message).join("; ")}`);if($.value)return LS($.value);throw Error("ID token claims validation failed")}var x=(X,Y,...S)=>{if(S.length>0)console[X](`[${X.toUpperCase()}]`,Y,...S);else console[X](`[${X.toUpperCase()}]`,Y)},r={debug:()=>{},info:()=>{},warn(X,...Y){x("warn",X,...Y)},error(X,...Y){x("error",X,...Y)}},RS={debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},bS={debug:()=>{},info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")},s=(X,...Y)=>{if(Y.length>0)console.log("[DEBUG]",X,...Y);else console.log("[DEBUG]",X)},CS={debug:s,info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")},qS={debug:s,info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")};var e=new Map;async function m(X,Y=3,S=1000,N=30000){let $=Error("Placeholder Error");for(let B=0;B<=Y;B++)try{return await X()}catch(Z){if($=Z instanceof Error?Z:Error(String(Z)),Z instanceof Error&&Z.message.includes("400"))throw Z;if(B===Y)throw $;let M=Math.min(S*2**B,N),T=Math.random()*0.1*M;await new Promise((P)=>setTimeout(P,M+T)),console.warn(`Retry attempt ${B+1} after ${M+T}ms delay`)}throw $}async function SS(X){let Y=e.get(X);if(Y)return Y;return m(async()=>{let S=await fetch(X);if(!S.ok)throw Error("Failed to fetch JWKS");let N=await S.json();return e.set(X,N),N})}async function XS(X,Y){let S=X.keys.find((N)=>N.kid===Y);if(!S)throw Error("Public key not found");return crypto.subtle.importKey("jwk",{kty:S.kty,n:S.n,e:S.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}function gS(X,Y={}){let S=Y.cookieName??"es.active_session",N=X.headers.get("cookie");if(!N)return;return c(N)[S]}function pS(X,Y={}){let S=Y.cookieName??"es.active_session",N=Y.path??"/",$=Y.secure??!1,B=Y.sameSite??"Lax",Z=Y.maxAge,M=[`${S}=${X}`,`Path=${N}`,"HttpOnly",`SameSite=${B}`];if($)M.push("Secure");if(typeof Z==="number")M.push(`Max-Age=${Z}`);return M.join("; ")}function mS(X={}){let Y=X.cookieName??"es.active_session",S=X.path??"/",N=X.secure??!1,$=X.sameSite??"Lax",B=[`${Y}=`,"Max-Age=0",`Path=${S}`,"HttpOnly",`SameSite=${$}`];if(N)B.push("Secure");return B.join("; ")}function cS(X,Y={}){let S=typeof X==="string"?X:X?.headers.get("cookie")??void 0;if(!S)return[];let $=`${Y.cookiePrefix??"es.sso"}.`,B=new Set;for(let Z of Object.keys(c(S))){if(!Z.startsWith($))continue;let M=Z.slice($.length),T=M.lastIndexOf(".");if(T<=0)continue;let P=M.slice(0,T).trim();if(P)B.add(P)}return Array.from(B)}function uS(X,Y){if(!X)return;let S=c(X);for(let[N,$]of Object.entries(S)){if(!N.startsWith("es.sso.")||!N.endsWith(".state"))continue;try{let B=JSON.parse(atob($));if(B?.state===Y)return{clientId:N.slice(7,-6),stateCookie:B}}catch{}}return}function dS(X,Y,S,N){if(!S&&!N)return;let $={...S,...N},B=!!($.authority&&$.tokenUrl&&$.authorizationUrl&&$.clientId&&$.redirectUri&&$.scope),Z={...$,authority:B?H($.authority,"Missing 'authority' from SSO Config"):$.authority,tokenUrl:B?H($.tokenUrl,"Missing 'tokenUrl' from SSO Config"):$.tokenUrl,authorizationUrl:B?H($.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):$.authorizationUrl,clientId:B?H($.clientId,"Missing 'clientId' from SSO Config"):$.clientId,redirectUri:B?H($.redirectUri,"Missing 'redirectUri' from SSO Config"):$.redirectUri,scope:B?H($.scope,"Missing 'scope' from SSO Config"):$.scope,responseType:$.responseType??"code",cookiesSecure:$.cookiesSecure!==void 0?$.cookiesSecure:!0,cookiesSameSite:$.cookiesSameSite!==void 0?$.cookiesSameSite:"Strict",cookiesPrefix:$.cookiesPrefix??($.clientId?`es.sso.${$.clientId}`:"es.sso"),cookiesPath:$.cookiesPath??"/"};function M(){let K=[];if(!Z.authority)K.push("authority");if(!Z.tokenUrl)K.push("tokenUrl");if(!Z.authorizationUrl)K.push("authorizationUrl");if(!Z.clientId)K.push("clientId");if(!Z.redirectUri)K.push("redirectUri");if(!Z.scope)K.push("scope");if(K.length>0)throw Error(`Missing OIDC configuration fields: ${K.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing enterpriseStandard.`)}async function T(K){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");try{let{tokens:A}=await g(K);if(!A)return;return await f(A)}catch(A){console.error("Error parsing user from cookies:",A);return}}async function P(K){let A=await T(K);if(A)return A;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function y({landingUrl:K,errorUrl:A},G){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");M();let L=t(),W=t(64),Q=Z.redirectUri;try{new URL(Q)}catch{if(G)try{let j=new URL(G),I=Q.startsWith("//")?Q.slice(1):Q.startsWith("/")?Q:`/${Q}`;Q=new URL(I,j.origin).toString()}catch{try{let j=new URL(Z.authorizationUrl),I=Q.startsWith("//")?Q.slice(1):Q.startsWith("/")?Q:`/${Q}`;Q=new URL(I,j.origin).toString()}catch{throw Error(`Invalid redirectUri: "${Z.redirectUri}". It must be a valid absolute URL.`)}}}let F=new URL(Z.authorizationUrl);F.searchParams.append("client_id",Z.clientId),F.searchParams.append("redirect_uri",Q),F.searchParams.append("response_type","code"),F.searchParams.append("scope",Z.scope),F.searchParams.append("state",L);let J=await KS(W);F.searchParams.append("code_challenge",J),F.searchParams.append("code_challenge_method","S256");let D={state:L,codeVerifier:W,landingUrl:K,errorUrl:A};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:F.toString(),"Set-Cookie":k("state",D,86400)}})}async function h(K,A){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");try{let J=R("refresh",K);if(J)await $S(J)}catch(J){console.warn("Failed to revoke token:",J)}if(Z.sessionStore)try{let J=await T(K);if(J?.sso?.profile.sid){let D=J.sso.profile.sid;await Z.sessionStore.delete(D)}}catch(J){console.warn("Failed to delete session:",J)}let G=[["Set-Cookie",C("access")],["Set-Cookie",C("id")],["Set-Cookie",C("refresh")],["Set-Cookie",C("control")],["Set-Cookie",C("state")]],W=new URL(K.url).searchParams.get("redirect");if(W)return new Response("Logged out",{status:302,headers:[["Location",W],...G]});let Q=K.headers.get("accept");if(Q?.includes("application/json")||Q?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out"}),{status:200,headers:[["Content-Type","application/json"],...G]});else return new Response(`
4
+ <!DOCTYPE html><html lang="en"><body>
5
+ <h1>Logout Complete</h1>
6
+ <div style="display: none">
7
+ It is not recommended to show the default logout page. Include '?redirect=/someHomePage' or logout asynchronously.
8
+ Check the <a href="https://EnterpriseStandard.com/sso#logout">Enterprise Standard Packages</a> for more information.
9
+ </div>
10
+ </body></html>
11
+ `,{status:200,headers:[["Content-Type","text/html"],...G]})}async function E(K){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");if(!Z.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{let A=K.headers.get("content-type");if(!A||!A.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let G=await K.text(),W=new URLSearchParams(G).get("logout_token");if(!W)return new Response("Missing logout_token parameter",{status:400});let F=(await n(W)).sid;if(!F)return console.warn("Back-Channel Logout: logout_token missing sid claim"),new Response("Invalid logout_token: missing sid claim",{status:400});return await Z.sessionStore.delete(F),console.log(`Back-Channel Logout: successfully deleted session ${F}`),new Response("OK",{status:200})}catch(A){return console.error("Error during back-channel logout:",A),new Response("Internal Server Error",{status:500})}}async function U(K){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");let A=new URL(K.url),G=new URLSearchParams(A.search),L=Object.fromEntries(G.entries()),W=await X.callbackParams["~standard"].validate(L);if(W.issues)return o(W.issues,"OIDC callback parameters validation failed");let{code:Q,state:F}=W.value;try{let J=R("state",K,!0),{codeVerifier:D,state:j,landingUrl:I}=J??{};if(H(D,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly'),H(j,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly'),H(I,'OIDC "landingUrl" was not present in cookies'),F!==j)throw Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');let w=Z.cookiesSecure?K.url.replace(/^http:\/\//,"https://"):K.url,z=await ZS(Q,D,w),O=await f(z);if(Z.sessionStore)try{let V=O.sso.profile.sid,_=O.id;if(V&&_){let b={sid:V,sub:_,createdAt:new Date,lastActivityAt:new Date};await Z.sessionStore.create(b)}else console.warn("Session creation skipped: missing sid or sub in ID token claims")}catch(V){console.warn("Failed to create session:",V)}if(Z.userStore)try{let V=O.id;if(V){let _=new Date,b=await Z.userStore.get(V);if(b||Z.enableJitUserProvisioning){let QS={...b??{},...O,id:V,tenantId:b?.tenantId,createdAt:b?.createdAt??_,updatedAt:_};await Z.userStore.upsert(QS)}else console.warn("JIT user provisioning disabled: user not found in store and will not be created")}else console.warn("User storage skipped: missing sub in ID token claims")}catch(V){console.warn("Failed to store user:",V)}return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",I],["Set-Cookie",C("state")],...p(z,O.sso.expires)]})}catch(J){console.error("Error during sign-in callback:",J);try{let D=R("state",K,!0),{errorUrl:j}=D??{};if(j)return new Response("Redirecting to error url",{status:302,headers:[["Location",j]]})}catch(D){console.warn("Error parsing the errorUrl from the OIDC cookie")}return console.warn("No error page was found in the cookies. The user will be shown a default error page."),new Response("An error occurred during authentication, please return to the application homepage and try again.",{status:500})}}async function f(K){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");let A=await n(K.id_token),G=Number(K.refresh_expires_in??K.expires_in??3600),L=K.expires?new Date(K.expires):new Date(Date.now()+G*1000);return{id:A.sub,userName:A.preferred_username||"",name:A.name||"",email:A.email||"",emails:[{value:A.email||"",primary:!0}],avatar:A.picture,sso:{profile:{...A,iss:A.iss||Z.authority,aud:A.aud||Z.clientId},tenant:{id:A.idp||A.iss||Z.authority||"",name:A.iss||Z.authority||""},scope:K.scope,tokenType:K.token_type,sessionState:K.session_state,expires:L}}}async function ZS(K,A,G){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");M();let{tokenUrl:L,redirectUri:W}=Z;try{new URL(W)}catch{if(G)try{let F=new URL(G),J=W.startsWith("//")?W.slice(1):W.startsWith("/")?W:`/${W}`;W=new URL(J,F.origin).toString()}catch{try{let F=new URL(L),J=W.startsWith("//")?W.slice(1):W.startsWith("/")?W:`/${W}`;W=new URL(J,F.origin).toString()}catch{throw Error(`Invalid redirectUri: "${Z.redirectUri}". It must be a valid absolute URL.`)}}}let Q=new URLSearchParams;if(Q.append("grant_type","authorization_code"),Q.append("code",K),Q.append("redirect_uri",W),Q.append("client_id",Z.clientId),Z.clientSecret)Q.append("client_secret",Z.clientSecret);Q.append("code_verifier",A);try{let F=await fetch(L,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Q.toString()}),J=await F.json();if(!F.ok){console.error("Token exchange error:",J);let j=J;throw Error(`Token exchange failed: ${j.error||F.statusText} - ${j.error_description||""}`.trim())}let D=await X.tokenResponse["~standard"].validate(J);if(D.issues)throw console.error("Token response validation failed:",D.issues),Error(`Token response validation failed: ${D.issues}`);return D.value}catch(F){throw console.error("Error during token exchange:",F),F}}async function d(K){return m(async()=>{if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");M();let A=Z.tokenUrl,G=new URLSearchParams;G.append("grant_type","refresh_token"),G.append("refresh_token",K),G.append("client_id",Z.clientId);let L=await fetch(A,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:G.toString()}),W=await L.json();if(!L.ok){console.error("Token refresh error:",W);let Q=W;throw Error(`Token refresh failed: ${Q.error||L.statusText} - ${Q.error_description||""}`.trim())}return W})}async function $S(K){try{if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");if(!Z.revocationEndpoint)return;let A=new URLSearchParams;A.append("token",K),A.append("token_type_hint","refresh_token"),A.append("client_id",Z.clientId);let G=await fetch(Z.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:A.toString()});if(!G.ok)console.warn("Token revocation failed:",G.status,G.statusText);else console.log("Token revoked successfully")}catch(A){console.warn("Error revoking token:",A)}}async function l(){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");if(!Z.jwksUri&&!Z.authority)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let K=Z.jwksUri||`${Z.authority}/protocol/openid-connect/certs`;return SS(K)}async function n(K){try{let A=K.split(".");if(A.length!==3)throw Error("Invalid JWT");let G=JSON.parse(atob(A[0].replace(/-/g,"+").replace(/_/g,"/"))),L=JSON.parse(atob(A[1].replace(/-/g,"+").replace(/_/g,"/"))),W=A[2].replace(/-/g,"+").replace(/_/g,"/"),Q=await NS(G.kid),J=new TextEncoder().encode(`${A[0]}.${A[1]}`);if(!await crypto.subtle.verify("RSASSA-PKCS1-v1_5",Q,Uint8Array.from(atob(W),(I)=>I.charCodeAt(0)),J))throw Error("Invalid JWT signature");let j=await X.idTokenClaims["~standard"].validate(L);if(j.issues)throw console.error("ID token claims validation failed:",j.issues),Error(`ID token claims validation failed: ${j.issues}`);return j.value}catch(A){throw console.error("Error verifying JWT:",A),A}}function t(K=32){let A=new Uint8Array(K);return crypto.getRandomValues(A),Array.from(A,(G)=>G.toString(16).padStart(2,"0")).join("").substring(0,K)}async function KS(K){let G=new TextEncoder().encode(K),L=await crypto.subtle.digest("SHA-256",G),W=Array.from(new Uint8Array(L));return btoa(String.fromCharCode(...W)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function NS(K){let A=await l();return XS(A,K)}function p(K,A){let G=A instanceof Date?A:new Date(A);if(Number.isNaN(G.getTime()))throw Error(`Invalid SSO token expiry: ${String(A)}`);let L={expires_in:K.expires_in,refresh_expires_in:K.refresh_expires_in,scope:K.scope,session_state:K.session_state,token_type:K.token_type,expires:G.toISOString()};return[["Set-Cookie",k("access",K.access_token,G)],["Set-Cookie",k("id",K.id_token,G)],["Set-Cookie",k("refresh",K.refresh_token??"",G)],["Set-Cookie",k("control",L,G)]]}async function g(K){let A=R("access",K),G=R("id",K),L=R("refresh",K),W=R("control",K,!0);if(!A||!G||!L||!W)return{tokens:void 0,refreshHeaders:[]};let Q={access_token:A,id_token:G,refresh_token:L,...W};if(W.expires&&L&&Date.now()>new Date(W.expires).getTime()){Q=await d(L);let F=await f(Q),J=p(Q,F.sso.expires);return{tokens:Q,refreshHeaders:J}}return{tokens:Q,refreshHeaders:[]}}async function AS(K){let{tokens:A}=await g(K);if(!A)return;return A.access_token}function k(K,A,G){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");if(K=`${Z.cookiesPrefix}.${K}`,typeof A!=="string")A=btoa(JSON.stringify(A));let L;if(G instanceof Date)L=`Expires=${G.toUTCString()}`;else if(typeof G==="number")L=`Max-Age=${G}`;else throw Error("Invalid expires type",G);if(A.length>4000)throw Error(`Error setting cookie: ${K}. Cookie length is: ${A.length}`);return`${K}=${A}; ${L}; Path=${Z.cookiesPath}; HttpOnly;${Z.cookiesSecure?" Secure;":""} SameSite=${Z.cookiesSameSite};`}function C(K){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");return`${Z.cookiesPrefix}.${K}=; Max-Age=0; Path=${Z.cookiesPath}; HttpOnly;${Z.cookiesSecure?" Secure;":""} SameSite=${Z.cookiesSameSite};`}function R(K,A,G=!1){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");let L=A.headers.get("cookie");if(!L)return null;let W=L.split(";").find((J)=>J.trim().startsWith(`${Z.cookiesPrefix}.${K}=`));if(!W)return null;let Q=W.split("=")[1].trim();if(!G)return Q;let F=atob(Q);return JSON.parse(F)}async function GS(K,A){if(!Z)throw Error("Enterprise Standard SSO Manager not initialized");let{loginUrl:G,userUrl:L,errorUrl:W,landingUrl:Q,tokenUrl:F,refreshUrl:J,logoutUrl:D,logoutBackChannelUrl:j,jwksUrl:I,redirectUri:w}={...Z,...A},z=new URL(K.url).pathname;if(w){let O;try{O=new URL(w).pathname}catch{try{let V=new URL(K.url),_=w.startsWith("//")?w.slice(1):w;O=new URL(_,V.origin).pathname}catch{O=w.startsWith("/")?w:`/${w}`}}if(O===z)return U(K)}if(G===z){let O=Z.cookiesSecure?K.url.replace(/^http:\/\//,"https://"):K.url;return y({landingUrl:Q||"/",errorUrl:W},O)}if(L===z){let{tokens:O,refreshHeaders:V}=await g(K);if(!O)return new Response("User not logged in",{status:401});let _=await f(O);return new Response(JSON.stringify(_),{headers:[["Content-Type","application/json"],...V]})}if(F===z){let{tokens:O,refreshHeaders:V}=await g(K);if(!O)return new Response("User not logged in",{status:401});return new Response(JSON.stringify({token:O.access_token,expires:O.expires}),{headers:[["Content-Type","application/json"],...V]})}if(J===z){let O=R("refresh",K);if(!O)return new Response("User not logged in",{status:401});let V=await d(O),_=await f(V),b=p(V,_.sso.expires);return new Response("Refresh Complete",{status:200,headers:b})}if(D===z)return h(K,{landingUrl:Q||"/"});if(j===z)return E(K);if(I===z){let O=await l();return new Response(JSON.stringify(O),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...Z,getUser:T,getRequiredUser:P,getJwt:AS,initiateLogin:y,logout:h,logoutBackChannel:E,callbackHandler:U,handler:GS}}function c(X){let Y={},S=X.split(";");for(let N of S){let $=N.trim();if(!$)continue;let B=$.indexOf("=");if(B===-1)continue;let Z=$.slice(0,B).trim(),M=$.slice(B+1).trim();Y[Z]=M}return Y}function q(X){return X=X??"SSO Unavailable",new Response(JSON.stringify({error:X}),{status:503,statusText:X,headers:{"Content-Type":"application/json"}})}function YS(X){if(!X)return[];let Y=X.headers;if(Y.getSetCookie)return Y.getSetCookie();let S=X.headers.get("set-cookie");return S?[S]:[]}function JS(X,Y){let S=new Headers;X.headers.forEach((N,$)=>{if($.toLowerCase()!=="set-cookie")S.set($,N)});for(let N of Y)S.append("Set-Cookie",N);return new Response(X.body,{status:X.status,statusText:X.statusText,headers:S})}var v="EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function.";async function lS(X,Y){return H(Y,v),Y.sso?.getUser(X)}async function OS(X,Y){H(Y,v);let S=Y.logger??r;S.debug?.("getUser called",{hasInstance:!0,hasSso:!!Y.sso,hasCiam:!!Y.ciam});let N=await Y.sso?.getUser(X);if(N)return S.debug?.("Found SSO user",{email:N.email}),N;S.debug?.("No SSO user, trying CIAM");let $=await Y.ciam?.getUser(X);return S.debug?.("CIAM user result",{email:$?.email??void 0}),$}async function nS(X,Y){let S=await OS(X,Y);if(S)return S;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function tS(X,Y){H(Y,v);let S=Y.sso;if(!S)return q();return S.initiateLogin(X)}async function iS(X,Y){H(Y,v);let S=Y.sso;if(!S)return q();return S.callbackHandler(X)}async function aS(X,Y){H(Y,v);let{sso:S,ciam:N}=Y;if(!S&&!N)return q("Logout Unavailable");let $=S?await S.logout(X,{landingUrl:"/"}):void 0,B=N?await N.logout(X):void 0,Z=$??B;if(!Z)return q("Logout Unavailable");let M=[...YS($),...YS(B)];return JS(Z,M)}async function oS(X,Y){H(Y,v);let{sso:S,ciam:N}=Y;if(!S&&!N)return q("Back-Channel Logout Unavailable");let $=X.clone(),B=X.clone(),Z=S?await S.logoutBackChannel($):void 0;if(Z?.status===200)return Z;let M=N?await N.logoutBackChannel(B):void 0;if(M)return M;return Z??q("Back-Channel Logout Unavailable")}var u;function sS(X){u=X}function jS(X,Y){if(VS(X.configSource))return X.configSource;if(!u)throw Error("Tenant config hydration is not registered. Import @enterprisestandard/server before using tenant.config().");return u(X.configSource,Y)}function eS(X){let Y=X.configSource;return{...X,config:(S)=>jS({configSource:Y},S)}}function VS(X){let Y=X;return typeof X==="object"&&X!==null&&typeof Y.load==="function"&&typeof Y.subscribe==="function"}
12
+ export{DS as a,ES as b,i as c,a as d,H as e,o as f,PS as g,BS as h,TS as i,zS as j,LS as k,wS as l,r as m,RS as n,bS as o,CS as p,qS as q,SS as r,XS as s,gS as t,pS as u,mS as v,cS as w,uS as x,dS as y,lS as z,OS as A,nS as B,tS as C,iS as D,aS as E,oS as F,sS as G,jS as H,eS as I};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enterprisestandard/core",
3
- "version": "0.0.14-beta.20260331.2",
3
+ "version": "0.0.14",
4
4
  "description": "Enterprise Standard Core (Server-only)",
5
5
  "private": false,
6
6
  "author": "enterprisestandard",
@@ -27,7 +27,7 @@
27
27
  }
28
28
  },
29
29
  "peerDependencies": {
30
- "@enterprisestandard/zod": "0.0.14-beta.20260331.2",
31
- "@enterprisestandard/valibot": "0.0.14-beta.20260331.2"
30
+ "@enterprisestandard/zod": "^0.0.14",
31
+ "@enterprisestandard/valibot": "^0.0.14"
32
32
  }
33
33
  }
@@ -1,12 +0,0 @@
1
- function DX(Y){return{"~standard":{version:1,vendor:Y,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,N=[],S={};if("code"in X)if(typeof X.code==="string")S.code=X.code;else N.push({message:"code must be a string",path:["code"]});else if(!("error"in X))N.push({message:"code is required",path:["code"]});if("state"in X)if(typeof X.state==="string"||X.state===void 0)S.state=X.state;else N.push({message:"state must be a string",path:["state"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)S.session_state=X.session_state;else N.push({message:"session_state must be a string",path:["session_state"]});if("error"in X){if(typeof X.error==="string")S.error=X.error;else N.push({message:"error must be a string",path:["error"]});if("error_description"in X)if(typeof X.error_description==="string"||X.error_description===void 0)S.error_description=X.error_description;else N.push({message:"error_description must be a string",path:["error_description"]});if("error_uri"in X)if(typeof X.error_uri==="string"||X.error_uri===void 0)S.error_uri=X.error_uri;else N.push({message:"error_uri must be a string",path:["error_uri"]})}if("iss"in X)if(typeof X.iss==="string"||X.iss===void 0)S.iss=X.iss;else N.push({message:"iss must be a string",path:["iss"]});if(N.length>0)return{issues:N};return{value:S}}}}}function EX(Y){return{"~standard":{version:1,vendor:Y,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,N=[],S={};if("access_token"in X)if(typeof X.access_token==="string")S.access_token=X.access_token;else N.push({message:"access_token must be a string",path:["access_token"]});else N.push({message:"access_token is required",path:["access_token"]});if("id_token"in X)if(typeof X.id_token==="string")S.id_token=X.id_token;else N.push({message:"id_token must be a string",path:["id_token"]});else N.push({message:"id_token is required",path:["id_token"]});if("token_type"in X)if(typeof X.token_type==="string")S.token_type=X.token_type;else N.push({message:"token_type must be a string",path:["token_type"]});else N.push({message:"token_type is required",path:["token_type"]});if("refresh_token"in X)if(typeof X.refresh_token==="string"||X.refresh_token===void 0)S.refresh_token=X.refresh_token;else N.push({message:"refresh_token must be a string",path:["refresh_token"]});if("scope"in X)if(typeof X.scope==="string"||X.scope===void 0)S.scope=X.scope;else N.push({message:"scope must be a string",path:["scope"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)S.session_state=X.session_state;else N.push({message:"session_state must be a string",path:["session_state"]});if("expires"in X)if(typeof X.expires==="string"||X.expires===void 0)S.expires=X.expires;else N.push({message:"expires must be a string",path:["expires"]});if("expires_in"in X)if(typeof X.expires_in==="number"||X.expires_in===void 0)S.expires_in=X.expires_in;else N.push({message:"expires_in must be a number",path:["expires_in"]});if("refresh_expires_in"in X)if(typeof X.refresh_expires_in==="number"||X.refresh_expires_in===void 0)S.refresh_expires_in=X.refresh_expires_in;else N.push({message:"refresh_expires_in must be a number",path:["refresh_expires_in"]});if(N.length>0)return{issues:N};return{value:S}}}}}function i(Y){return{"~standard":{version:1,vendor:Y,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,N=[],S={...X},B=["iss","aud","sub","sid","name","email","preferred_username","picture"];for(let M of B)if(M in X&&X[M]!==void 0){if(typeof X[M]!=="string")N.push({message:`${M} must be a string`,path:[M]})}let $=["exp","iat"];for(let M of $)if(M in X&&X[M]!==void 0){if(typeof X[M]!=="number")N.push({message:`${M} must be a number`,path:[M]})}if(N.length>0)return{issues:N};return{value:S}}}}}function a(Y){let Z=Y["~standard"];return Object.assign({},Y,{validate(X){return Promise.resolve(Z.validate(X))}})}function H(Y,Z="Assertion failed. Required value is null or undefined."){if(Y===void 0||Y===null)throw Error(Z);return Y}function o(Y,Z){return Response.json({error:"validation_failed",message:Z,issues:Y},{status:400,headers:{"Content-Type":"application/json"}})}function PX(Y,Z,X=[]){let N={...Y,...Z};for(let S of X)N[S]=Y?.[S]??Z?.[S];return N}function BX(Y){let Z="",X=0,N=Y.length;while(X<N){let S=Y[X];if(S==='"'||S==="'"){let B=S;Z+=S,X++;while(X<N){let $=Y[X];if($==="\\"){if(Z+=$,X+1<N)Z+=Y[X+1],X+=2;else X++;continue}if($===B){Z+=$,X++;break}Z+=$,X++}continue}if(S==="/"&&X+1<N){let B=Y[X+1];if(B==="/"){X+=2;while(X<N&&Y[X]!==`
2
- `)X++;if(X<N)Z+=`
3
- `;X++;continue}if(B==="*"){X+=2;while(X+1<N&&!(Y[X]==="*"&&Y[X+1]==="/"))X++;X+=2;continue}}Z+=S,X++}return Z}function TX(Y){let Z=BX(Y);return JSON.parse(Z)}async function zX(Y,Z=async(B)=>B.status===200,X=1000,N=1e4,S){let B=Date.now(),$="Awaiting Ping";return new Promise((M,T)=>{let P=null,y=null,h=async()=>{try{let E=await fetch(Y);if(E.ok)if(await Z(E)){if(P)clearInterval(P);if(y)clearInterval(y);M()}else $=`Response test failed: ${E.status}: ${E.statusText} - ${Y}`;else try{let U=await E.json();$=`Response error: ${E.status}: ${E.statusText} - ${Y}: ${JSON.stringify(U)}`}catch(U){$=`Response error: ${E.status}: ${E.statusText} - ${Y}`}}catch(E){$=`${E instanceof Error?E.message:String(E)} - ${Y}`}};if(h(),P=setInterval(h,X),N>0)y=setInterval(()=>{console.warn(`${$}: ${Date.now()-B}ms`)},N);if(S)setTimeout(()=>{if(P)clearInterval(P);if(y)clearInterval(y);T(Error(`Timeout: ${S}ms: ${$}`))},S)})}var WX="@enterprisestandard/core",MX=a(i(WX));function FX(Y){let Z=Y.exp!=null?new Date(Y.exp*1000):new Date,X=Y.iss??"";return{id:Y.sub??"",userName:Y.preferred_username??"",name:Y.name??"",email:Y.email??"",avatar:Y.picture,sso:{profile:{...Y,iss:Y.iss??X,aud:Y.aud},tenant:{id:Y.idp??X,name:X},tokenType:"Bearer",expires:Z}}}function LX(Y){let Z=Y.replace(/-/g,"+").replace(/_/g,"/");return atob(Z)}async function wX(Y){let Z=Y.split(".");if(Z.length!==3)throw Error("Invalid JWT");let X=LX(Z[1]),N=JSON.parse(X),S=await MX.validate(N);if(S.issues)throw Error(`ID token claims validation failed: ${S.issues.map((B)=>B.message).join("; ")}`);if(S.value)return FX(S.value);throw Error("ID token claims validation failed")}var x=(Y,Z,...X)=>{if(X.length>0)console[Y](`[${Y.toUpperCase()}]`,Z,...X);else console[Y](`[${Y.toUpperCase()}]`,Z)},r={debug:()=>{},info:()=>{},warn(Y,...Z){x("warn",Y,...Z)},error(Y,...Z){x("error",Y,...Z)}},RX={debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},bX={debug:()=>{},info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")},s=(Y,...Z)=>{if(Z.length>0)console.log("[DEBUG]",Y,...Z);else console.log("[DEBUG]",Y)},CX={debug:s,info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")},qX={debug:s,info:x.bind(console,"info"),warn:x.bind(console,"warn"),error:x.bind(console,"error")};var e=new Map;async function m(Y,Z=3,X=1000,N=30000){let S=Error("Placeholder Error");for(let B=0;B<=Z;B++)try{return await Y()}catch($){if(S=$ instanceof Error?$:Error(String($)),$ instanceof Error&&$.message.includes("400"))throw $;if(B===Z)throw S;let M=Math.min(X*2**B,N),T=Math.random()*0.1*M;await new Promise((P)=>setTimeout(P,M+T)),console.warn(`Retry attempt ${B+1} after ${M+T}ms delay`)}throw S}async function XX(Y){let Z=e.get(Y);if(Z)return Z;return m(async()=>{let X=await fetch(Y);if(!X.ok)throw Error("Failed to fetch JWKS");let N=await X.json();return e.set(Y,N),N})}async function YX(Y,Z){let X=Y.keys.find((N)=>N.kid===Z);if(!X)throw Error("Public key not found");return crypto.subtle.importKey("jwk",{kty:X.kty,n:X.n,e:X.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}function gX(Y,Z={}){let X=Z.cookieName??"es.active_session",N=Y.headers.get("cookie");if(!N)return;return d(N)[X]}function pX(Y,Z={}){let X=Z.cookieName??"es.active_session",N=Z.path??"/",S=Z.secure??!1,B=Z.sameSite??"Lax",$=Z.maxAge,M=[`${X}=${Y}`,`Path=${N}`,"HttpOnly",`SameSite=${B}`];if(S)M.push("Secure");if(typeof $==="number")M.push(`Max-Age=${$}`);return M.join("; ")}function mX(Y={}){let Z=Y.cookieName??"es.active_session",X=Y.path??"/",N=Y.secure??!1,S=Y.sameSite??"Lax",B=[`${Z}=`,"Max-Age=0",`Path=${X}`,"HttpOnly",`SameSite=${S}`];if(N)B.push("Secure");return B.join("; ")}function dX(Y,Z={}){let X=typeof Y==="string"?Y:Y?.headers.get("cookie")??void 0;if(!X)return[];let S=`${Z.cookiePrefix??"es.sso"}.`,B=new Set;for(let $ of Object.keys(d(X))){if(!$.startsWith(S))continue;let M=$.slice(S.length),T=M.lastIndexOf(".");if(T<=0)continue;let P=M.slice(0,T).trim();if(P)B.add(P)}return Array.from(B)}function cX(Y,Z){if(!Y)return;let X=d(Y);for(let[N,S]of Object.entries(X)){if(!N.startsWith("es.sso.")||!N.endsWith(".state"))continue;try{let B=JSON.parse(atob(S));if(B?.state===Z)return{clientId:N.slice(7,-6),stateCookie:B}}catch{}}return}function uX(Y,Z,X,N){if(!X&&!N)return;let S={...X,...N},B=!!(S.authority&&S.tokenUrl&&S.authorizationUrl&&S.clientId&&S.redirectUri&&S.scope),$={...S,authority:B?H(S.authority,"Missing 'authority' from SSO Config"):S.authority,tokenUrl:B?H(S.tokenUrl,"Missing 'tokenUrl' from SSO Config"):S.tokenUrl,authorizationUrl:B?H(S.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):S.authorizationUrl,clientId:B?H(S.clientId,"Missing 'clientId' from SSO Config"):S.clientId,redirectUri:B?H(S.redirectUri,"Missing 'redirectUri' from SSO Config"):S.redirectUri,scope:B?H(S.scope,"Missing 'scope' from SSO Config"):S.scope,responseType:S.responseType??"code",cookiesSecure:S.cookiesSecure!==void 0?S.cookiesSecure:!0,cookiesSameSite:S.cookiesSameSite!==void 0?S.cookiesSameSite:"Strict",cookiesPrefix:S.cookiesPrefix??(S.clientId?`es.sso.${S.clientId}`:"es.sso"),cookiesPath:S.cookiesPath??"/"};function M(){let K=[];if(!$.authority)K.push("authority");if(!$.tokenUrl)K.push("tokenUrl");if(!$.authorizationUrl)K.push("authorizationUrl");if(!$.clientId)K.push("clientId");if(!$.redirectUri)K.push("redirectUri");if(!$.scope)K.push("scope");if(K.length>0)throw Error(`Missing OIDC configuration fields: ${K.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing enterpriseStandard.`)}async function T(K){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");try{let{tokens:A}=await g(K);if(!A)return;return await f(A)}catch(A){console.error("Error parsing user from cookies:",A);return}}async function P(K){let A=await T(K);if(A)return A;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function y({landingUrl:K,errorUrl:A},G){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");M();let F=t(),W=t(64),Q=$.redirectUri;try{new URL(Q)}catch{if(G)try{let j=new URL(G),I=Q.startsWith("//")?Q.slice(1):Q.startsWith("/")?Q:`/${Q}`;Q=new URL(I,j.origin).toString()}catch{try{let j=new URL($.authorizationUrl),I=Q.startsWith("//")?Q.slice(1):Q.startsWith("/")?Q:`/${Q}`;Q=new URL(I,j.origin).toString()}catch{throw Error(`Invalid redirectUri: "${$.redirectUri}". It must be a valid absolute URL.`)}}}let L=new URL($.authorizationUrl);L.searchParams.append("client_id",$.clientId),L.searchParams.append("redirect_uri",Q),L.searchParams.append("response_type","code"),L.searchParams.append("scope",$.scope),L.searchParams.append("state",F);let J=await KX(W);L.searchParams.append("code_challenge",J),L.searchParams.append("code_challenge_method","S256");let D={state:F,codeVerifier:W,landingUrl:K,errorUrl:A};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:L.toString(),"Set-Cookie":k("state",D,86400)}})}async function h(K,A){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");try{let J=R("refresh",K);if(J)await SX(J)}catch(J){console.warn("Failed to revoke token:",J)}if($.sessionStore)try{let J=await T(K);if(J?.sso?.profile.sid){let D=J.sso.profile.sid;await $.sessionStore.delete(D)}}catch(J){console.warn("Failed to delete session:",J)}let G=[["Set-Cookie",C("access")],["Set-Cookie",C("id")],["Set-Cookie",C("refresh")],["Set-Cookie",C("control")],["Set-Cookie",C("state")]],W=new URL(K.url).searchParams.get("redirect");if(W)return new Response("Logged out",{status:302,headers:[["Location",W],...G]});let Q=K.headers.get("accept");if(Q?.includes("application/json")||Q?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out"}),{status:200,headers:[["Content-Type","application/json"],...G]});else return new Response(`
4
- <!DOCTYPE html><html lang="en"><body>
5
- <h1>Logout Complete</h1>
6
- <div style="display: none">
7
- It is not recommended to show the default logout page. Include '?redirect=/someHomePage' or logout asynchronously.
8
- Check the <a href="https://EnterpriseStandard.com/sso#logout">Enterprise Standard Packages</a> for more information.
9
- </div>
10
- </body></html>
11
- `,{status:200,headers:[["Content-Type","text/html"],...G]})}async function E(K){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");if(!$.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{let A=K.headers.get("content-type");if(!A||!A.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let G=await K.text(),W=new URLSearchParams(G).get("logout_token");if(!W)return new Response("Missing logout_token parameter",{status:400});let L=(await n(W)).sid;if(!L)return console.warn("Back-Channel Logout: logout_token missing sid claim"),new Response("Invalid logout_token: missing sid claim",{status:400});return await $.sessionStore.delete(L),console.log(`Back-Channel Logout: successfully deleted session ${L}`),new Response("OK",{status:200})}catch(A){return console.error("Error during back-channel logout:",A),new Response("Internal Server Error",{status:500})}}async function U(K){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");let A=new URL(K.url),G=new URLSearchParams(A.search),F=Object.fromEntries(G.entries()),W=await Y.callbackParams["~standard"].validate(F);if(W.issues)return o(W.issues,"OIDC callback parameters validation failed");let{code:Q,state:L}=W.value;try{let J=R("state",K,!0),{codeVerifier:D,state:j,landingUrl:I}=J??{};if(H(D,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly'),H(j,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly'),H(I,'OIDC "landingUrl" was not present in cookies'),L!==j)throw Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');let w=$.cookiesSecure?K.url.replace(/^http:\/\//,"https://"):K.url,z=await $X(Q,D,w),O=await f(z);if($.sessionStore)try{let V=O.sso.profile.sid,_=O.id;if(V&&_){let b={sid:V,sub:_,createdAt:new Date,lastActivityAt:new Date};await $.sessionStore.create(b)}else console.warn("Session creation skipped: missing sid or sub in ID token claims")}catch(V){console.warn("Failed to create session:",V)}if($.userStore)try{let V=O.id;if(V){let _=new Date,b=await $.userStore.get(V);if(b||$.enableJitUserProvisioning){let QX={...b??{},...O,id:V,tenantId:b?.tenantId,createdAt:b?.createdAt??_,updatedAt:_};await $.userStore.upsert(QX)}else console.warn("JIT user provisioning disabled: user not found in store and will not be created")}else console.warn("User storage skipped: missing sub in ID token claims")}catch(V){console.warn("Failed to store user:",V)}return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",I],["Set-Cookie",C("state")],...p(z,O.sso.expires)]})}catch(J){console.error("Error during sign-in callback:",J);try{let D=R("state",K,!0),{errorUrl:j}=D??{};if(j)return new Response("Redirecting to error url",{status:302,headers:[["Location",j]]})}catch(D){console.warn("Error parsing the errorUrl from the OIDC cookie")}return console.warn("No error page was found in the cookies. The user will be shown a default error page."),new Response("An error occurred during authentication, please return to the application homepage and try again.",{status:500})}}async function f(K){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");let A=await n(K.id_token),G=Number(K.refresh_expires_in??K.expires_in??3600),F=K.expires?new Date(K.expires):new Date(Date.now()+G*1000);return{id:A.sub,userName:A.preferred_username||"",name:A.name||"",email:A.email||"",emails:[{value:A.email||"",primary:!0}],avatar:A.picture,sso:{profile:{...A,iss:A.iss||$.authority,aud:A.aud||$.clientId},tenant:{id:A.idp||A.iss||$.authority||"",name:A.iss||$.authority||""},scope:K.scope,tokenType:K.token_type,sessionState:K.session_state,expires:F}}}async function $X(K,A,G){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");M();let{tokenUrl:F,redirectUri:W}=$;try{new URL(W)}catch{if(G)try{let L=new URL(G),J=W.startsWith("//")?W.slice(1):W.startsWith("/")?W:`/${W}`;W=new URL(J,L.origin).toString()}catch{try{let L=new URL(F),J=W.startsWith("//")?W.slice(1):W.startsWith("/")?W:`/${W}`;W=new URL(J,L.origin).toString()}catch{throw Error(`Invalid redirectUri: "${$.redirectUri}". It must be a valid absolute URL.`)}}}let Q=new URLSearchParams;if(Q.append("grant_type","authorization_code"),Q.append("code",K),Q.append("redirect_uri",W),Q.append("client_id",$.clientId),$.clientSecret)Q.append("client_secret",$.clientSecret);Q.append("code_verifier",A);try{let L=await fetch(F,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Q.toString()}),J=await L.json();if(!L.ok){console.error("Token exchange error:",J);let j=J;throw Error(`Token exchange failed: ${j.error||L.statusText} - ${j.error_description||""}`.trim())}let D=await Y.tokenResponse["~standard"].validate(J);if(D.issues)throw console.error("Token response validation failed:",D.issues),Error(`Token response validation failed: ${D.issues}`);return D.value}catch(L){throw console.error("Error during token exchange:",L),L}}async function u(K){return m(async()=>{if(!$)throw Error("Enterprise Standard SSO Manager not initialized");M();let A=$.tokenUrl,G=new URLSearchParams;G.append("grant_type","refresh_token"),G.append("refresh_token",K),G.append("client_id",$.clientId);let F=await fetch(A,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:G.toString()}),W=await F.json();if(!F.ok){console.error("Token refresh error:",W);let Q=W;throw Error(`Token refresh failed: ${Q.error||F.statusText} - ${Q.error_description||""}`.trim())}return W})}async function SX(K){try{if(!$)throw Error("Enterprise Standard SSO Manager not initialized");if(!$.revocationEndpoint)return;let A=new URLSearchParams;A.append("token",K),A.append("token_type_hint","refresh_token"),A.append("client_id",$.clientId);let G=await fetch($.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:A.toString()});if(!G.ok)console.warn("Token revocation failed:",G.status,G.statusText);else console.log("Token revoked successfully")}catch(A){console.warn("Error revoking token:",A)}}async function l(){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");if(!$.jwksUri&&!$.authority)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let K=$.jwksUri||`${$.authority}/protocol/openid-connect/certs`;return XX(K)}async function n(K){try{let A=K.split(".");if(A.length!==3)throw Error("Invalid JWT");let G=JSON.parse(atob(A[0].replace(/-/g,"+").replace(/_/g,"/"))),F=JSON.parse(atob(A[1].replace(/-/g,"+").replace(/_/g,"/"))),W=A[2].replace(/-/g,"+").replace(/_/g,"/"),Q=await NX(G.kid),J=new TextEncoder().encode(`${A[0]}.${A[1]}`);if(!await crypto.subtle.verify("RSASSA-PKCS1-v1_5",Q,Uint8Array.from(atob(W),(I)=>I.charCodeAt(0)),J))throw Error("Invalid JWT signature");let j=await Y.idTokenClaims["~standard"].validate(F);if(j.issues)throw console.error("ID token claims validation failed:",j.issues),Error(`ID token claims validation failed: ${j.issues}`);return j.value}catch(A){throw console.error("Error verifying JWT:",A),A}}function t(K=32){let A=new Uint8Array(K);return crypto.getRandomValues(A),Array.from(A,(G)=>G.toString(16).padStart(2,"0")).join("").substring(0,K)}async function KX(K){let G=new TextEncoder().encode(K),F=await crypto.subtle.digest("SHA-256",G),W=Array.from(new Uint8Array(F));return btoa(String.fromCharCode(...W)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function NX(K){let A=await l();return YX(A,K)}function p(K,A){let G=A instanceof Date?A:new Date(A);if(Number.isNaN(G.getTime()))throw Error(`Invalid SSO token expiry: ${String(A)}`);let F={expires_in:K.expires_in,refresh_expires_in:K.refresh_expires_in,scope:K.scope,session_state:K.session_state,token_type:K.token_type,expires:G.toISOString()};return[["Set-Cookie",k("access",K.access_token,G)],["Set-Cookie",k("id",K.id_token,G)],["Set-Cookie",k("refresh",K.refresh_token??"",G)],["Set-Cookie",k("control",F,G)]]}async function g(K){let A=R("access",K),G=R("id",K),F=R("refresh",K),W=R("control",K,!0);if(!A||!G||!F||!W)return{tokens:void 0,refreshHeaders:[]};let Q={access_token:A,id_token:G,refresh_token:F,...W};if(W.expires&&F&&Date.now()>new Date(W.expires).getTime()){Q=await u(F);let L=await f(Q),J=p(Q,L.sso.expires);return{tokens:Q,refreshHeaders:J}}return{tokens:Q,refreshHeaders:[]}}async function AX(K){let{tokens:A}=await g(K);if(!A)return;return A.access_token}function k(K,A,G){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");if(K=`${$.cookiesPrefix}.${K}`,typeof A!=="string")A=btoa(JSON.stringify(A));let F;if(G instanceof Date)F=`Expires=${G.toUTCString()}`;else if(typeof G==="number")F=`Max-Age=${G}`;else throw Error("Invalid expires type",G);if(A.length>4000)throw Error(`Error setting cookie: ${K}. Cookie length is: ${A.length}`);return`${K}=${A}; ${F}; Path=${$.cookiesPath}; HttpOnly;${$.cookiesSecure?" Secure;":""} SameSite=${$.cookiesSameSite};`}function C(K){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");return`${$.cookiesPrefix}.${K}=; Max-Age=0; Path=${$.cookiesPath}; HttpOnly;${$.cookiesSecure?" Secure;":""} SameSite=${$.cookiesSameSite};`}function R(K,A,G=!1){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");let F=A.headers.get("cookie");if(!F)return null;let W=F.split(";").find((J)=>J.trim().startsWith(`${$.cookiesPrefix}.${K}=`));if(!W)return null;let Q=W.split("=")[1].trim();if(!G)return Q;let L=atob(Q);return JSON.parse(L)}async function GX(K,A){if(!$)throw Error("Enterprise Standard SSO Manager not initialized");let{loginUrl:G,userUrl:F,errorUrl:W,landingUrl:Q,tokenUrl:L,refreshUrl:J,logoutUrl:D,logoutBackChannelUrl:j,jwksUrl:I,redirectUri:w}={...$,...A},z=new URL(K.url).pathname;if(w){let O;try{O=new URL(w).pathname}catch{try{let V=new URL(K.url),_=w.startsWith("//")?w.slice(1):w;O=new URL(_,V.origin).pathname}catch{O=w.startsWith("/")?w:`/${w}`}}if(O===z)return U(K)}if(G===z){let O=$.cookiesSecure?K.url.replace(/^http:\/\//,"https://"):K.url;return y({landingUrl:Q||"/",errorUrl:W},O)}if(F===z){let{tokens:O,refreshHeaders:V}=await g(K);if(!O)return new Response("User not logged in",{status:401});let _=await f(O);return new Response(JSON.stringify(_),{headers:[["Content-Type","application/json"],...V]})}if(L===z){let{tokens:O,refreshHeaders:V}=await g(K);if(!O)return new Response("User not logged in",{status:401});return new Response(JSON.stringify({token:O.access_token,expires:O.expires}),{headers:[["Content-Type","application/json"],...V]})}if(J===z){let O=R("refresh",K);if(!O)return new Response("User not logged in",{status:401});let V=await u(O),_=await f(V),b=p(V,_.sso.expires);return new Response("Refresh Complete",{status:200,headers:b})}if(D===z)return h(K,{landingUrl:Q||"/"});if(j===z)return E(K);if(I===z){let O=await l();return new Response(JSON.stringify(O),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...$,getUser:T,getRequiredUser:P,getJwt:AX,initiateLogin:y,logout:h,logoutBackChannel:E,callbackHandler:U,handler:GX}}function d(Y){let Z={},X=Y.split(";");for(let N of X){let S=N.trim();if(!S)continue;let B=S.indexOf("=");if(B===-1)continue;let $=S.slice(0,B).trim(),M=S.slice(B+1).trim();Z[$]=M}return Z}function q(Y){return Y=Y??"SSO Unavailable",new Response(JSON.stringify({error:Y}),{status:503,statusText:Y,headers:{"Content-Type":"application/json"}})}function ZX(Y){if(!Y)return[];let Z=Y.headers;if(Z.getSetCookie)return Z.getSetCookie();let X=Y.headers.get("set-cookie");return X?[X]:[]}function JX(Y,Z){let X=new Headers;Y.headers.forEach((N,S)=>{if(S.toLowerCase()!=="set-cookie")X.set(S,N)});for(let N of Z)X.append("Set-Cookie",N);return new Response(Y.body,{status:Y.status,statusText:Y.statusText,headers:X})}var v="EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function.";async function lX(Y,Z){return H(Z,v),Z.sso?.getUser(Y)}async function OX(Y,Z){H(Z,v);let X=Z.logger??r;X.debug?.("getUser called",{hasInstance:!0,hasSso:!!Z.sso,hasCiam:!!Z.ciam});let N=await Z.sso?.getUser(Y);if(N)return X.debug?.("Found SSO user",{email:N.email}),N;X.debug?.("No SSO user, trying CIAM");let S=await Z.ciam?.getUser(Y);return X.debug?.("CIAM user result",{email:S?.email??void 0}),S}async function nX(Y,Z){let X=await OX(Y,Z);if(X)return X;throw new Response("Unauthorized",{status:401,statusText:"Unauthorized"})}async function tX(Y,Z){H(Z,v);let X=Z.sso;if(!X)return q();return X.initiateLogin(Y)}async function iX(Y,Z){H(Z,v);let X=Z.sso;if(!X)return q();return X.callbackHandler(Y)}async function aX(Y,Z){H(Z,v);let{sso:X,ciam:N}=Z;if(!X&&!N)return q("Logout Unavailable");let S=X?await X.logout(Y,{landingUrl:"/"}):void 0,B=N?await N.logout(Y):void 0,$=S??B;if(!$)return q("Logout Unavailable");let M=[...ZX(S),...ZX(B)];return JX($,M)}async function oX(Y,Z){H(Z,v);let{sso:X,ciam:N}=Z;if(!X&&!N)return q("Back-Channel Logout Unavailable");let S=Y.clone(),B=Y.clone(),$=X?await X.logoutBackChannel(S):void 0;if($?.status===200)return $;let M=N?await N.logoutBackChannel(B):void 0;if(M)return M;return $??q("Back-Channel Logout Unavailable")}var c;function sX(Y){c=Y}function jX(Y){if(VX(Y.configSource))return Y.configSource;if(!c)throw Error("Tenant config hydration is not registered. Import @enterprisestandard/server before using tenant.config().");return c(Y.configSource)}function eX(Y){let Z=Y.configSource;return{...Y,config:()=>jX({configSource:Z})}}function VX(Y){let Z=Y;return typeof Y==="object"&&Y!==null&&typeof Z.load==="function"&&typeof Z.subscribe==="function"}
12
- export{DX as a,EX as b,i as c,a as d,H as e,o as f,PX as g,BX as h,TX as i,zX as j,FX as k,wX as l,r as m,RX as n,bX as o,CX as p,qX as q,XX as r,YX as s,gX as t,pX as u,mX as v,dX as w,cX as x,uX as y,lX as z,OX as A,nX as B,tX as C,iX as D,aX as E,oX as F,sX as G,jX as H,eX as I};