@enterprisestandard/core 0.0.9-beta.20260304.1 → 0.0.9

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
@@ -789,7 +789,7 @@ interface User2 extends BaseUser {
789
789
  *
790
790
  * @template TExtended - Type-safe custom data that consumers can add to users
791
791
  */
792
- type StoredUser<TExtended = {}> = User2 & {
792
+ type StoredUser<TExtended = object> = User2 & {
793
793
  /**
794
794
  * Required unique identifier (the `sub` claim from the IdP).
795
795
  * This is the primary key for user storage.
@@ -832,7 +832,7 @@ type StoredUser<TExtended = {}> = User2 & {
832
832
  * }
833
833
  * ```
834
834
  */
835
- interface UserStore<TExtended = {}> {
835
+ interface UserStore<TExtended = object> {
836
836
  /**
837
837
  * Retrieve a user by their subject identifier (sub).
838
838
  *
@@ -1328,13 +1328,27 @@ type WorkloadConfigMap = Record<string, WorkloadConfig>;
1328
1328
  /**
1329
1329
  * Workload config with separate incoming (server) and outgoing (client) roles.
1330
1330
  * - **incoming**: Server-only config for validating tokens presented to this app (jwksUri, issuer).
1331
- * - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client?, es, scope?) from server (client can be omitted when only one client; pass the ES instance).
1331
+ * - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client, es, scope?) from server (client is required and must be one of the outgoing names; pass the ES instance).
1332
1332
  */
1333
1333
  type WorkloadIncomingOutgoing = {
1334
1334
  incoming?: Partial<WorkloadConfig>;
1335
1335
  outgoing?: Record<string, Partial<WorkloadConfig>>;
1336
1336
  };
1337
1337
  /**
1338
+ * Framework-level workload declarations used by app code to define the expected
1339
+ * incoming/outgoing workload shape without needing all remote credentials in code.
1340
+ */
1341
+ type FrameworkWorkloadIncomingOutgoing = {
1342
+ incoming?: Partial<WorkloadConfig>;
1343
+ outgoing?: Record<string, Partial<WorkloadConfig>>;
1344
+ };
1345
+ /**
1346
+ * Workload config shape accepted from framework/app code.
1347
+ * Apps may provide a partial single config or an incoming/outgoing declaration
1348
+ * to expose named outgoing clients in the type system.
1349
+ */
1350
+ type FrameworkWorkloadConfig = Partial<WorkloadConfig> | FrameworkWorkloadIncomingOutgoing;
1351
+ /**
1338
1352
  * Workload Identity extracted from validated tokens
1339
1353
  */
1340
1354
  type WorkloadIdentity = {
@@ -1359,10 +1373,11 @@ type WorkloadIdentity = {
1359
1373
  * Workload Identity Authentication Interface
1360
1374
  */
1361
1375
  type Workload = WorkloadConfig & {
1362
- /** When options.client is set, returns a token for that named client (outbound to another app). */
1363
- getToken: (scope?: string, options?: {
1364
- client?: string;
1365
- }) => Promise<string>;
1376
+ /**
1377
+ * Returns a token for this workload configuration.
1378
+ * The optional argument overrides the configured default scope.
1379
+ */
1380
+ getToken: (scope?: string) => Promise<string>;
1366
1381
  refreshToken: (scope?: string) => Promise<WorkloadTokenResponse>;
1367
1382
  generateJWTAssertion: (scope?: string) => Promise<string>;
1368
1383
  revokeToken: (token: string) => Promise<void>;
@@ -1372,6 +1387,7 @@ type Workload = WorkloadConfig & {
1372
1387
  /** Framework-agnostic request handler for the Workload module (token, validate, jwks, refresh). */
1373
1388
  handler: (request: Request) => Promise<Response>;
1374
1389
  };
1390
+ type WorkloadClient = Pick<Workload, "getToken" | "refreshToken" | "generateJWTAssertion" | "revokeToken">;
1375
1391
  /**
1376
1392
  * SCIM Error response structure
1377
1393
  */
@@ -1629,7 +1645,7 @@ import { StandardSchemaV1 as StandardSchemaV16 } from "@standard-schema/spec";
1629
1645
  *
1630
1646
  * @template TExtended - Type-safe custom data that consumers can add to sessions
1631
1647
  */
1632
- type Session<TExtended = {}> = {
1648
+ type Session<TExtended = object> = {
1633
1649
  /**
1634
1650
  * Session ID from the Identity Provider (from `sid` claim in ID token).
1635
1651
  * This is the unique identifier for the session.
@@ -1682,7 +1698,7 @@ type Session<TExtended = {}> = {
1682
1698
  * }
1683
1699
  * ```
1684
1700
  */
1685
- interface SessionStore<TExtended = {}> {
1701
+ interface SessionStore<TExtended = object> {
1686
1702
  /**
1687
1703
  * Create a new session in the store.
1688
1704
  *
@@ -1914,6 +1930,16 @@ type Secrets = {
1914
1930
  handleLfvEvents?(request: Request): Promise<Response>;
1915
1931
  };
1916
1932
  /**
1933
+ * Partial secrets source config used in framework/app code to declare expected source names.
1934
+ * ConfigSource-backed values may still provide the actual source details at runtime.
1935
+ */
1936
+ type FrameworkSecretsSourceConfig = Partial<SecretsSourceConfig>;
1937
+ /**
1938
+ * Framework-level named secrets source declarations keyed by source name.
1939
+ * Values may be partial or empty when the app only wants to declare expected names/types.
1940
+ */
1941
+ type FrameworkSecretsModuleConfig = Record<string, FrameworkSecretsSourceConfig>;
1942
+ /**
1917
1943
  * TODO: Let's see if we can do some clean inference and remove this!!!
1918
1944
  */
1919
1945
  type SecretsSourceMap = Record<string, SecretsSource>;
@@ -1961,6 +1987,15 @@ type LfvSecretsConfig = {
1961
1987
  */
1962
1988
  logger?: Logger;
1963
1989
  };
1990
+ /**
1991
+ * Runtime-ready LFV source config.
1992
+ * Input config can be partially declared/merged, but LFV operations require these fields.
1993
+ */
1994
+ type ResolvedLfvSecretsConfig = Omit<LfvSecretsConfig, "lfvServerUrl" | "clientId" | "path"> & {
1995
+ lfvServerUrl: string;
1996
+ clientId: string;
1997
+ path: string;
1998
+ };
1964
1999
  type VaultSecretsConfig = {
1965
2000
  type: "vault";
1966
2001
  url?: string;
@@ -2080,8 +2115,8 @@ type FrameworkConfig = {
2080
2115
  logger?: Logger;
2081
2116
  sso?: SSOConfig | null;
2082
2117
  iam?: IAMConfig | null;
2083
- workload?: WorkloadConfig | null;
2084
- secrets?: SecretsModuleConfig | null;
2118
+ workload?: FrameworkWorkloadConfig | null;
2119
+ secrets?: FrameworkSecretsModuleConfig | null;
2085
2120
  ciam?: CIAMConfig | null;
2086
2121
  validators: ESValidators;
2087
2122
  };
@@ -2151,6 +2186,19 @@ type ESModuleFromConfig<
2151
2186
  K extends keyof FrameworkConfig,
2152
2187
  T
2153
2188
  > = C[K] extends null ? never : [Exclude<C[K], undefined>] extends [never] ? T : [Exclude<C[K], undefined>] extends [null] ? never : T;
2189
+ type StringKeys<T> = Extract<keyof T, string>;
2190
+ type EmptyNamedModule = Record<string, never>;
2191
+ type NamedSecretsFromConfig<C extends FrameworkConfig> = Exclude<C["secrets"], null | undefined> extends infer S ? S extends Record<string, unknown> ? { [K in Exclude<StringKeys<S>, keyof Secrets>] : SecretsSource } : EmptyNamedModule : EmptyNamedModule;
2192
+ type NamedWorkloadClientsFromConfig<C extends FrameworkConfig> = Exclude<C["workload"], null | undefined> extends infer W ? W extends {
2193
+ outgoing?: infer O;
2194
+ } ? O extends Record<string, unknown> ? { [K in Exclude<StringKeys<O>, keyof Workload>] : WorkloadClient } : EmptyNamedModule : EmptyNamedModule : EmptyNamedModule;
2195
+ type AggregateWorkload = Omit<Workload, "getToken"> & {
2196
+ getToken: (client: string, scope?: string) => Promise<string>;
2197
+ getServerToken: (scope?: string) => Promise<string>;
2198
+ };
2199
+ type WorkloadModuleFromConfig<C extends FrameworkConfig> = Exclude<C["workload"], null | undefined> extends infer W ? W extends {
2200
+ outgoing?: infer O;
2201
+ } ? O extends Record<string, unknown> ? AggregateWorkload & NamedWorkloadClientsFromConfig<C> : Workload : Workload : Workload;
2154
2202
  /**
2155
2203
  * EnterpriseStandard type driven by the config type C.
2156
2204
  * Module properties are:
@@ -2168,7 +2216,7 @@ type EnterpriseStandardBase = {
2168
2216
  secrets?: Secrets;
2169
2217
  sso?: SSO;
2170
2218
  iam?: IAM;
2171
- workload?: Workload;
2219
+ workload?: Workload | AggregateWorkload;
2172
2220
  ciam?: CIAM;
2173
2221
  /**
2174
2222
  * Framework-agnostic request handler that routes requests to the appropriate
@@ -2189,10 +2237,10 @@ type EnterpriseStandardStrict<C extends FrameworkConfig> = {
2189
2237
  logger?: Logger;
2190
2238
  tenantId?: string;
2191
2239
  config?: RemoteConfig;
2192
- secrets: ESModuleFromConfig<C, "secrets", Secrets>;
2240
+ secrets: ESModuleFromConfig<C, "secrets", Secrets & NamedSecretsFromConfig<C>>;
2193
2241
  sso: ESModuleFromConfig<C, "sso", SSO>;
2194
2242
  iam: ESModuleFromConfig<C, "iam", IAM>;
2195
- workload: ESModuleFromConfig<C, "workload", Workload>;
2243
+ workload: ESModuleFromConfig<C, "workload", WorkloadModuleFromConfig<C>>;
2196
2244
  ciam: ESModuleFromConfig<C, "ciam", CIAM>;
2197
2245
  handler: (request: Request) => Promise<Response>;
2198
2246
  ready(timeout?: number): Promise<void>;
@@ -2245,7 +2293,7 @@ type ESConfigChangeOptions = {
2245
2293
  *
2246
2294
  * @template TExtended - Type-safe custom data that consumers can add to magic links
2247
2295
  */
2248
- type MagicLink<TExtended = {}> = {
2296
+ type MagicLink<TExtended = object> = {
2249
2297
  /**
2250
2298
  * The magic link token (unique identifier)
2251
2299
  */
@@ -2303,7 +2351,7 @@ type MagicLink<TExtended = {}> = {
2303
2351
  * }
2304
2352
  * ```
2305
2353
  */
2306
- interface MagicLinkStore<TExtended = {}> {
2354
+ interface MagicLinkStore<TExtended = object> {
2307
2355
  /**
2308
2356
  * Create a new magic link in the store.
2309
2357
  *
@@ -2486,7 +2534,7 @@ interface UpsertTenantRequest {
2486
2534
  webhookUrl: string;
2487
2535
  callbackUrl: string;
2488
2536
  tenantUrl?: string;
2489
- configEnv: TenantConfigEnv;
2537
+ configSource: TenantSecretsConfig;
2490
2538
  }
2491
2539
  type UpsertTenantResponse = {
2492
2540
  tenantUrl?: string;
@@ -2560,6 +2608,22 @@ type TenantConfigEnv = {
2560
2608
  ES_AWS_TTL?: string;
2561
2609
  ES_GCP_TTL?: string;
2562
2610
  };
2611
+ type TenantSecretsConfig = LfvSecretsConfig | (VaultSecretsConfig & {
2612
+ path: string;
2613
+ retryInterval?: number;
2614
+ }) | (DevSecretsConfig & {
2615
+ path?: string;
2616
+ appId?: string;
2617
+ }) | (AwsSecretsConfig & {
2618
+ ttl?: number;
2619
+ }) | AzureSecretsConfig | (GcpSecretsConfig & {
2620
+ ttl?: number;
2621
+ }) | {
2622
+ type: "localFile";
2623
+ path?: string;
2624
+ watch?: boolean;
2625
+ ttl?: number;
2626
+ };
2563
2627
  type StoredTenant<TExtended extends object = Record<string, never>> = {
2564
2628
  tenantId: string;
2565
2629
  companyId: string;
@@ -2576,8 +2640,8 @@ type StoredTenant<TExtended extends object = Record<string, never>> = {
2576
2640
  expiresAt?: string;
2577
2641
  createdAt: Date;
2578
2642
  updatedAt: Date;
2579
- /** Persisted env-like variables used to construct a ConfigSource at runtime. */
2580
- configEnv: TenantConfigEnv;
2643
+ /** Persisted typed config used to construct a ConfigSource at runtime. */
2644
+ configSource: TenantSecretsConfig;
2581
2645
  /** Runtime helper that returns a ConfigSource for this tenant. */
2582
2646
  config: () => ConfigSource;
2583
2647
  } & TExtended;
@@ -2793,4 +2857,4 @@ declare function parseJsonc<T>(content: string): T;
2793
2857
  * @returns A promise that resolves when the service is ready.
2794
2858
  */
2795
2859
  declare function waitOn(url: string, pingInterval?: number, warnInterval?: number, timeout?: number): Promise<void>;
2796
- export { workloadTokenResponseSchema, withValidate, waitOn, version, validationFailureResponse, userSchema, tokenResponseSchema, stripJsonComments, silentLogger, setActiveSession, serializeESConfig, sendTenantWebhook, parseJsonc, oidcCallbackSchema, must, mergeConfig, list, jwtAssertionClaimsSchema, infoLogger, idTokenClaimsSchema, groupResourceSchema, getActiveSession, findTenantFromStateParam, defaultLogger, decodeUser, debugLogger, consoleLogger, claimsToUser, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadIncomingOutgoing, WorkloadIdentity, WorkloadConfigMap, WorkloadConfig, Workload, VaultSecretsConfig, ValidateResult, UsersInboundHandlerConfig, UserStore, UserSortOptions, UserSortField, UserListOptions, User2 as User, UpsertTenantResponse, UpsertTenantRequest, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantStore, TenantStatus, TenantRequestError, TenantConfigEnv, StoredUser, 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, RemoteConfig, Photo, PhoneNumber, OidcCallbackParams, Name, MetaData, MagicLinkStore, MagicLink, LoginConfig, Logger, ListResult, LfvSecretsConfig, JwtBearerWorkloadConfig, JWTAssertionClaims, InMemoryTenantStore, IdTokenClaims, IAMValidators, IAMUsersInbound, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMConfig, IAM, GroupsInboundHandlerConfig, GroupStore, GroupSortOptions, GroupSortField, GroupResource, GroupMember, GroupListOptions, Group, GcpSecretsConfig, FrameworkConfig, EnvironmentType, EnterpriseUser, EnterpriseStandardFromConfig, EnterpriseStandardBase, EnterpriseStandard, EnterpriseExtension, Email, ESValidators, ESRoutingOptions, ESRouteModule, ESRouteFilterResult, ESResolvedRoute, ESModuleFromConfig, ESConfigChangeResult, ESConfigChangeOptions, ESConfigChangeCallback, ESConfig, DevSecretsConfig, CreateUserOptions, CreateTenantResponse, CreateTenantRequest, CreateGroupOptions, ConfigSourceType, ConfigSource, ClientCredentialsWorkloadConfig, CachedWorkloadToken, CIAMValidators, CIAMConfigFromCode, CIAMConfig, CIAM, BaseUser, AzureSecretsConfig, AwsSecretsConfig, AwsAuthMethod, Address };
2860
+ export { workloadTokenResponseSchema, withValidate, waitOn, version, validationFailureResponse, userSchema, tokenResponseSchema, stripJsonComments, silentLogger, setActiveSession, serializeESConfig, sendTenantWebhook, parseJsonc, oidcCallbackSchema, must, mergeConfig, list, jwtAssertionClaimsSchema, infoLogger, idTokenClaimsSchema, groupResourceSchema, getActiveSession, findTenantFromStateParam, defaultLogger, decodeUser, debugLogger, consoleLogger, claimsToUser, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadIncomingOutgoing, WorkloadIdentity, WorkloadConfigMap, WorkloadConfig, WorkloadClient, Workload, VaultSecretsConfig, ValidateResult, UsersInboundHandlerConfig, UserStore, UserSortOptions, UserSortField, UserListOptions, User2 as User, UpsertTenantResponse, UpsertTenantRequest, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantStore, TenantStatus, TenantSecretsConfig, TenantRequestError, TenantConfigEnv, StoredUser, 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, MetaData, MagicLinkStore, MagicLink, LoginConfig, Logger, ListResult, LfvSecretsConfig, JwtBearerWorkloadConfig, JWTAssertionClaims, InMemoryTenantStore, IdTokenClaims, IAMValidators, IAMUsersInbound, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMConfig, IAM, GroupsInboundHandlerConfig, GroupStore, GroupSortOptions, GroupSortField, GroupResource, GroupMember, GroupListOptions, Group, GcpSecretsConfig, FrameworkWorkloadIncomingOutgoing, FrameworkWorkloadConfig, FrameworkSecretsSourceConfig, FrameworkSecretsModuleConfig, FrameworkConfig, EnvironmentType, EnterpriseUser, EnterpriseStandardFromConfig, EnterpriseStandardBase, EnterpriseStandard, EnterpriseExtension, Email, ESValidators, ESRoutingOptions, ESRouteModule, ESRouteFilterResult, ESResolvedRoute, ESModuleFromConfig, ESConfigChangeResult, ESConfigChangeOptions, ESConfigChangeCallback, ESConfig, DevSecretsConfig, CreateUserOptions, CreateTenantResponse, CreateTenantRequest, CreateGroupOptions, ConfigSourceType, ConfigSource, ClientCredentialsWorkloadConfig, CachedWorkloadToken, CIAMValidators, CIAMConfigFromCode, CIAMConfig, CIAM, BaseUser, AzureSecretsConfig, AwsSecretsConfig, AwsAuthMethod, Address };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as j,b as S,c as P,d as p,e as g,f as b,g as h,h as m,i as d,j as o,k as n,l as v,m as r,n as l,o as t,p as i,q as u,t as a,u as s,v as e}from"./shared/core-q2xp5jrk.js";var W="0.0.9-beta.20260304.1";var B=["sessionStore","userStore","groupStore","tokenStore","magicLinkStore"];function _(H){if(H===null||typeof H!=="object")return H;let C={};for(let[D,x]of Object.entries(H)){if(B.includes(D)||D==="validators")continue;C[D]=x!==null&&typeof x==="object"&&!Array.isArray(x)&&Object.getPrototypeOf(x)===Object.prototype?_(x):x}return C}function E(H){return _(H)}function I(H,C,D,x){let J=C.length,$=x??H,Q=$>0?Math.floor(D/$)+1:1,Z=$>0?Math.ceil(H/$):0;return{total:H,count:J,items:C,size:$,page:Q,pages:Z}}class Y extends Error{constructor(H,C){super(H,C);this.name="TenantRequestError",Object.setPrototypeOf(this,Y.prototype)}}class M{tenants=new Map;async get(H){return this.tenants.get(H)??null}async upsert(H){let C=new Date,D=this.tenants.get(H.tenantId),x={...D??{},...H,status:H.status??D?.status??"completed",createdAt:H.createdAt??D?.createdAt??C,updatedAt:H.updatedAt??C};return this.tenants.set(x.tenantId,x),x}async delete(H){this.tenants.delete(H)}}function K(H,C,D){return(async()=>{try{let x=await fetch(H,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(C)});if(!x.ok)D.error(`Failed to send webhook update: ${x.status} ${x.statusText}`)}catch(x){D.error("Failed to send webhook update:",x)}})()}async function R(H,C,D){return K(H,C,D)}function X(H,C,D,x,J){if(H===void 0||H===null){if(D)x.push({message:`${C} is required`,path:J});return}if(typeof H!=="string"){x.push({message:`${C} must be a string`,path:J});return}return H}function L(H,C,D,x){if(H===void 0||H===null)return;if(typeof H!=="boolean"){D.push({message:`${C} must be a boolean`,path:x});return}return H}function z(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"name must be an object",path:D});return}let x=H,J={};return J.formatted=X(x.formatted,"formatted",!1,C,[...D,"formatted"]),J.familyName=X(x.familyName,"familyName",!1,C,[...D,"familyName"]),J.givenName=X(x.givenName,"givenName",!1,C,[...D,"givenName"]),J.middleName=X(x.middleName,"middleName",!1,C,[...D,"middleName"]),J.honorificPrefix=X(x.honorificPrefix,"honorificPrefix",!1,C,[...D,"honorificPrefix"]),J.honorificSuffix=X(x.honorificSuffix,"honorificSuffix",!1,C,[...D,"honorificSuffix"]),J}function U(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"emails must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"email must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function q(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"phoneNumbers must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"phoneNumber must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function w(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"addresses must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"address must be an object",path:Q});continue}let Z=$;x.push({formatted:X(Z.formatted,"formatted",!1,C,[...Q,"formatted"]),streetAddress:X(Z.streetAddress,"streetAddress",!1,C,[...Q,"streetAddress"]),locality:X(Z.locality,"locality",!1,C,[...Q,"locality"]),region:X(Z.region,"region",!1,C,[...Q,"region"]),postalCode:X(Z.postalCode,"postalCode",!1,C,[...Q,"postalCode"]),country:X(Z.country,"country",!1,C,[...Q,"country"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function T(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"groups must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"group must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"])})}return x.length>0?x:void 0}function V(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"roles must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"role must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function k(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"Enterprise User extension must be an object",path:D});return}let x=H,J={};if(J.employeeNumber=X(x.employeeNumber,"employeeNumber",!1,C,[...D,"employeeNumber"]),J.costCenter=X(x.costCenter,"costCenter",!1,C,[...D,"costCenter"]),J.organization=X(x.organization,"organization",!1,C,[...D,"organization"]),J.division=X(x.division,"division",!1,C,[...D,"division"]),J.department=X(x.department,"department",!1,C,[...D,"department"]),x.manager!==void 0&&x.manager!==null)if(typeof x.manager!=="object"||x.manager===null)C.push({message:"manager must be an object",path:[...D,"manager"]});else{let $=x.manager;J.manager={value:X($.value,"value",!1,C,[...D,"manager","value"]),$ref:X($.$ref,"$ref",!1,C,[...D,"manager","$ref"]),displayName:X($.displayName,"displayName",!1,C,[...D,"manager","displayName"])}}return J}function y(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.userName,"userName",!0,x,["userName"]);if(!$)return{issues:x};J.userName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.displayName=X(D.displayName,"displayName",!1,x,["displayName"]),J.nickName=X(D.nickName,"nickName",!1,x,["nickName"]),J.profileUrl=X(D.profileUrl,"profileUrl",!1,x,["profileUrl"]),J.title=X(D.title,"title",!1,x,["title"]),J.userType=X(D.userType,"userType",!1,x,["userType"]),J.preferredLanguage=X(D.preferredLanguage,"preferredLanguage",!1,x,["preferredLanguage"]),J.locale=X(D.locale,"locale",!1,x,["locale"]),J.timezone=X(D.timezone,"timezone",!1,x,["timezone"]),J.password=X(D.password,"password",!1,x,["password"]),J.active=L(D.active,"active",x,["active"]),J.name=z(D.name,x,["name"]),J.emails=U(D.emails,x,["emails"]),J.phoneNumbers=q(D.phoneNumbers,x,["phoneNumbers"]),J.addresses=w(D.addresses,x,["addresses"]),J.groups=T(D.groups,x,["groups"]),J.roles=V(D.roles,x,["roles"]);let Q="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(D[Q]!==void 0)J[Q]=k(D[Q],x,[Q]);if(D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Z)=>typeof Z==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Z=D.meta;J.meta={resourceType:typeof Z.resourceType==="string"?Z.resourceType:void 0,created:typeof Z.created==="string"?Z.created:void 0,lastModified:typeof Z.lastModified==="string"?Z.lastModified:void 0,location:typeof Z.location==="string"?Z.location:void 0,version:typeof Z.version==="string"?Z.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function N(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"members must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"member must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A){let G=X(Z.type,"type",!1,C,[...Q,"type"]);x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:G==="User"||G==="Group"?G:void 0})}}return x.length>0?x:void 0}function c(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.displayName,"displayName",!0,x,["displayName"]);if(!$)return{issues:x};if(J.displayName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.members=N(D.members,x,["members"]),D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Q)=>typeof Q==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Q=D.meta;J.meta={resourceType:typeof Q.resourceType==="string"?Q.resourceType:void 0,created:typeof Q.created==="string"?Q.created:void 0,lastModified:typeof Q.lastModified==="string"?Q.lastModified:void 0,location:typeof Q.location==="string"?Q.location:void 0,version:typeof Q.version==="string"?Q.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function f(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={...D},$=["iss","sub"];for(let A of $)if(A in D){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if("aud"in D&&D.aud!==void 0){let A=D.aud;if(typeof A!=="string"&&!Array.isArray(A))x.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(A)&&!A.every((G)=>typeof G==="string"))x.push({message:"aud array must contain only strings",path:["aud"]})}let Q=["jti","scope"];for(let A of Q)if(A in D&&D[A]!==void 0){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}let Z=["exp","iat"];for(let A of Z)if(A in D){if(typeof D[A]!=="number")x.push({message:`${A} must be a number`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if(x.length>0)return{issues:x};return{value:J}}}}}function O(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={};if("access_token"in D)if(typeof D.access_token==="string")J.access_token=D.access_token;else x.push({message:"access_token must be a string",path:["access_token"]});else x.push({message:"access_token is required",path:["access_token"]});if("token_type"in D)if(typeof D.token_type==="string")J.token_type=D.token_type;else x.push({message:"token_type must be a string",path:["token_type"]});else x.push({message:"token_type is required",path:["token_type"]});if("scope"in D)if(typeof D.scope==="string"||D.scope===void 0)J.scope=D.scope;else x.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in D)if(typeof D.refresh_token==="string"||D.refresh_token===void 0)J.refresh_token=D.refresh_token;else x.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in D)if(typeof D.expires==="string"||D.expires===void 0)J.expires=D.expires;else x.push({message:"expires must be a string",path:["expires"]});if("expires_in"in D)if(typeof D.expires_in==="number"||D.expires_in===void 0)J.expires_in=D.expires_in;else x.push({message:"expires_in must be a number",path:["expires_in"]});if(x.length>0)return{issues:x};return{value:J}}}}}export{O as workloadTokenResponseSchema,p as withValidate,o as waitOn,W as version,b as validationFailureResponse,y as userSchema,S as tokenResponseSchema,m as stripJsonComments,l as silentLogger,s as setActiveSession,E as serializeESConfig,R as sendTenantWebhook,d as parseJsonc,j as oidcCallbackSchema,g as must,h as mergeConfig,I as list,f as jwtAssertionClaimsSchema,t as infoLogger,P as idTokenClaimsSchema,c as groupResourceSchema,a as getActiveSession,e as findTenantFromStateParam,r as defaultLogger,v as decodeUser,i as debugLogger,u as consoleLogger,n as claimsToUser,Y as TenantRequestError,M as InMemoryTenantStore};
1
+ import{a as j,b as S,c as P,d as p,e as g,f as b,g as h,h as m,i as d,j as o,k as n,l as v,m as r,n as l,o as t,p as i,q as u,t as a,u as s,v as e}from"./shared/core-q2xp5jrk.js";var W="0.0.9";var B=["sessionStore","userStore","groupStore","tokenStore","magicLinkStore"];function _(H){if(H===null||typeof H!=="object")return H;let C={};for(let[D,x]of Object.entries(H)){if(B.includes(D)||D==="validators")continue;C[D]=x!==null&&typeof x==="object"&&!Array.isArray(x)&&Object.getPrototypeOf(x)===Object.prototype?_(x):x}return C}function E(H){return _(H)}function I(H,C,D,x){let J=C.length,$=x??H,Q=$>0?Math.floor(D/$)+1:1,Z=$>0?Math.ceil(H/$):0;return{total:H,count:J,items:C,size:$,page:Q,pages:Z}}class Y extends Error{constructor(H,C){super(H,C);this.name="TenantRequestError",Object.setPrototypeOf(this,Y.prototype)}}class M{tenants=new Map;async get(H){return this.tenants.get(H)??null}async upsert(H){let C=new Date,D=this.tenants.get(H.tenantId),x={...D??{},...H,status:H.status??D?.status??"completed",createdAt:H.createdAt??D?.createdAt??C,updatedAt:H.updatedAt??C};return this.tenants.set(x.tenantId,x),x}async delete(H){this.tenants.delete(H)}}function K(H,C,D){return(async()=>{try{let x=await fetch(H,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(C)});if(!x.ok)D.error(`Failed to send webhook update: ${x.status} ${x.statusText}`)}catch(x){D.error("Failed to send webhook update:",x)}})()}async function R(H,C,D){return K(H,C,D)}function X(H,C,D,x,J){if(H===void 0||H===null){if(D)x.push({message:`${C} is required`,path:J});return}if(typeof H!=="string"){x.push({message:`${C} must be a string`,path:J});return}return H}function L(H,C,D,x){if(H===void 0||H===null)return;if(typeof H!=="boolean"){D.push({message:`${C} must be a boolean`,path:x});return}return H}function z(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"name must be an object",path:D});return}let x=H,J={};return J.formatted=X(x.formatted,"formatted",!1,C,[...D,"formatted"]),J.familyName=X(x.familyName,"familyName",!1,C,[...D,"familyName"]),J.givenName=X(x.givenName,"givenName",!1,C,[...D,"givenName"]),J.middleName=X(x.middleName,"middleName",!1,C,[...D,"middleName"]),J.honorificPrefix=X(x.honorificPrefix,"honorificPrefix",!1,C,[...D,"honorificPrefix"]),J.honorificSuffix=X(x.honorificSuffix,"honorificSuffix",!1,C,[...D,"honorificSuffix"]),J}function U(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"emails must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"email must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function q(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"phoneNumbers must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"phoneNumber must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function w(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"addresses must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"address must be an object",path:Q});continue}let Z=$;x.push({formatted:X(Z.formatted,"formatted",!1,C,[...Q,"formatted"]),streetAddress:X(Z.streetAddress,"streetAddress",!1,C,[...Q,"streetAddress"]),locality:X(Z.locality,"locality",!1,C,[...Q,"locality"]),region:X(Z.region,"region",!1,C,[...Q,"region"]),postalCode:X(Z.postalCode,"postalCode",!1,C,[...Q,"postalCode"]),country:X(Z.country,"country",!1,C,[...Q,"country"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function T(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"groups must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"group must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"])})}return x.length>0?x:void 0}function V(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"roles must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"role must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A)x.push({value:A,display:X(Z.display,"display",!1,C,[...Q,"display"]),type:X(Z.type,"type",!1,C,[...Q,"type"]),primary:L(Z.primary,"primary",C,[...Q,"primary"])})}return x.length>0?x:void 0}function k(H,C,D){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){C.push({message:"Enterprise User extension must be an object",path:D});return}let x=H,J={};if(J.employeeNumber=X(x.employeeNumber,"employeeNumber",!1,C,[...D,"employeeNumber"]),J.costCenter=X(x.costCenter,"costCenter",!1,C,[...D,"costCenter"]),J.organization=X(x.organization,"organization",!1,C,[...D,"organization"]),J.division=X(x.division,"division",!1,C,[...D,"division"]),J.department=X(x.department,"department",!1,C,[...D,"department"]),x.manager!==void 0&&x.manager!==null)if(typeof x.manager!=="object"||x.manager===null)C.push({message:"manager must be an object",path:[...D,"manager"]});else{let $=x.manager;J.manager={value:X($.value,"value",!1,C,[...D,"manager","value"]),$ref:X($.$ref,"$ref",!1,C,[...D,"manager","$ref"]),displayName:X($.displayName,"displayName",!1,C,[...D,"manager","displayName"])}}return J}function y(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.userName,"userName",!0,x,["userName"]);if(!$)return{issues:x};J.userName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.displayName=X(D.displayName,"displayName",!1,x,["displayName"]),J.nickName=X(D.nickName,"nickName",!1,x,["nickName"]),J.profileUrl=X(D.profileUrl,"profileUrl",!1,x,["profileUrl"]),J.title=X(D.title,"title",!1,x,["title"]),J.userType=X(D.userType,"userType",!1,x,["userType"]),J.preferredLanguage=X(D.preferredLanguage,"preferredLanguage",!1,x,["preferredLanguage"]),J.locale=X(D.locale,"locale",!1,x,["locale"]),J.timezone=X(D.timezone,"timezone",!1,x,["timezone"]),J.password=X(D.password,"password",!1,x,["password"]),J.active=L(D.active,"active",x,["active"]),J.name=z(D.name,x,["name"]),J.emails=U(D.emails,x,["emails"]),J.phoneNumbers=q(D.phoneNumbers,x,["phoneNumbers"]),J.addresses=w(D.addresses,x,["addresses"]),J.groups=T(D.groups,x,["groups"]),J.roles=V(D.roles,x,["roles"]);let Q="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(D[Q]!==void 0)J[Q]=k(D[Q],x,[Q]);if(D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Z)=>typeof Z==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Z=D.meta;J.meta={resourceType:typeof Z.resourceType==="string"?Z.resourceType:void 0,created:typeof Z.created==="string"?Z.created:void 0,lastModified:typeof Z.lastModified==="string"?Z.lastModified:void 0,location:typeof Z.location==="string"?Z.location:void 0,version:typeof Z.version==="string"?Z.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function N(H,C,D){if(H===void 0||H===null)return;if(!Array.isArray(H)){C.push({message:"members must be an array",path:D});return}let x=[];for(let J=0;J<H.length;J++){let $=H[J],Q=[...D,J];if(typeof $!=="object"||$===null){C.push({message:"member must be an object",path:Q});continue}let Z=$,A=X(Z.value,"value",!0,C,[...Q,"value"]);if(A){let G=X(Z.type,"type",!1,C,[...Q,"type"]);x.push({value:A,$ref:X(Z.$ref,"$ref",!1,C,[...Q,"$ref"]),display:X(Z.display,"display",!1,C,[...Q,"display"]),type:G==="User"||G==="Group"?G:void 0})}}return x.length>0?x:void 0}function c(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={},$=X(D.displayName,"displayName",!0,x,["displayName"]);if(!$)return{issues:x};if(J.displayName=$,J.id=X(D.id,"id",!1,x,["id"]),J.externalId=X(D.externalId,"externalId",!1,x,["externalId"]),J.members=N(D.members,x,["members"]),D.schemas!==void 0)if(Array.isArray(D.schemas))J.schemas=D.schemas.filter((Q)=>typeof Q==="string");else x.push({message:"schemas must be an array",path:["schemas"]});if(D.meta!==void 0)if(typeof D.meta==="object"&&D.meta!==null){let Q=D.meta;J.meta={resourceType:typeof Q.resourceType==="string"?Q.resourceType:void 0,created:typeof Q.created==="string"?Q.created:void 0,lastModified:typeof Q.lastModified==="string"?Q.lastModified:void 0,location:typeof Q.location==="string"?Q.location:void 0,version:typeof Q.version==="string"?Q.version:void 0}}else x.push({message:"meta must be an object",path:["meta"]});if(x.length>0)return{issues:x};return{value:J}}}}}function f(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={...D},$=["iss","sub"];for(let A of $)if(A in D){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if("aud"in D&&D.aud!==void 0){let A=D.aud;if(typeof A!=="string"&&!Array.isArray(A))x.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(A)&&!A.every((G)=>typeof G==="string"))x.push({message:"aud array must contain only strings",path:["aud"]})}let Q=["jti","scope"];for(let A of Q)if(A in D&&D[A]!==void 0){if(typeof D[A]!=="string")x.push({message:`${A} must be a string`,path:[A]})}let Z=["exp","iat"];for(let A of Z)if(A in D){if(typeof D[A]!=="number")x.push({message:`${A} must be a number`,path:[A]})}else x.push({message:`${A} is required`,path:[A]});if(x.length>0)return{issues:x};return{value:J}}}}}function O(H){return{"~standard":{version:1,vendor:H,validate:(C)=>{if(typeof C!=="object"||C===null)return{issues:[{message:"Expected an object"}]};let D=C,x=[],J={};if("access_token"in D)if(typeof D.access_token==="string")J.access_token=D.access_token;else x.push({message:"access_token must be a string",path:["access_token"]});else x.push({message:"access_token is required",path:["access_token"]});if("token_type"in D)if(typeof D.token_type==="string")J.token_type=D.token_type;else x.push({message:"token_type must be a string",path:["token_type"]});else x.push({message:"token_type is required",path:["token_type"]});if("scope"in D)if(typeof D.scope==="string"||D.scope===void 0)J.scope=D.scope;else x.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in D)if(typeof D.refresh_token==="string"||D.refresh_token===void 0)J.refresh_token=D.refresh_token;else x.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in D)if(typeof D.expires==="string"||D.expires===void 0)J.expires=D.expires;else x.push({message:"expires must be a string",path:["expires"]});if("expires_in"in D)if(typeof D.expires_in==="number"||D.expires_in===void 0)J.expires_in=D.expires_in;else x.push({message:"expires_in must be a number",path:["expires_in"]});if(x.length>0)return{issues:x};return{value:J}}}}}export{O as workloadTokenResponseSchema,p as withValidate,o as waitOn,W as version,b as validationFailureResponse,y as userSchema,S as tokenResponseSchema,m as stripJsonComments,l as silentLogger,s as setActiveSession,E as serializeESConfig,R as sendTenantWebhook,d as parseJsonc,j as oidcCallbackSchema,g as must,h as mergeConfig,I as list,f as jwtAssertionClaimsSchema,t as infoLogger,P as idTokenClaimsSchema,c as groupResourceSchema,a as getActiveSession,e as findTenantFromStateParam,r as defaultLogger,v as decodeUser,i as debugLogger,u as consoleLogger,n as claimsToUser,Y as TenantRequestError,M as InMemoryTenantStore};
package/dist/server.d.ts CHANGED
@@ -719,7 +719,7 @@ interface User2 extends BaseUser {
719
719
  *
720
720
  * @template TExtended - Type-safe custom data that consumers can add to users
721
721
  */
722
- type StoredUser<TExtended = {}> = User2 & {
722
+ type StoredUser<TExtended = object> = User2 & {
723
723
  /**
724
724
  * Required unique identifier (the `sub` claim from the IdP).
725
725
  * This is the primary key for user storage.
@@ -762,7 +762,7 @@ type StoredUser<TExtended = {}> = User2 & {
762
762
  * }
763
763
  * ```
764
764
  */
765
- interface UserStore<TExtended = {}> {
765
+ interface UserStore<TExtended = object> {
766
766
  /**
767
767
  * Retrieve a user by their subject identifier (sub).
768
768
  *
@@ -1245,13 +1245,27 @@ type WorkloadConfigMap = Record<string, WorkloadConfig>;
1245
1245
  /**
1246
1246
  * Workload config with separate incoming (server) and outgoing (client) roles.
1247
1247
  * - **incoming**: Server-only config for validating tokens presented to this app (jwksUri, issuer).
1248
- * - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client?, es, scope?) from server (client can be omitted when only one client; pass the ES instance).
1248
+ * - **outgoing**: Map of named clients for outbound calls; use getWorkloadToken(client, es, scope?) from server (client is required and must be one of the outgoing names; pass the ES instance).
1249
1249
  */
1250
1250
  type WorkloadIncomingOutgoing = {
1251
1251
  incoming?: Partial<WorkloadConfig>;
1252
1252
  outgoing?: Record<string, Partial<WorkloadConfig>>;
1253
1253
  };
1254
1254
  /**
1255
+ * Framework-level workload declarations used by app code to define the expected
1256
+ * incoming/outgoing workload shape without needing all remote credentials in code.
1257
+ */
1258
+ type FrameworkWorkloadIncomingOutgoing = {
1259
+ incoming?: Partial<WorkloadConfig>;
1260
+ outgoing?: Record<string, Partial<WorkloadConfig>>;
1261
+ };
1262
+ /**
1263
+ * Workload config shape accepted from framework/app code.
1264
+ * Apps may provide a partial single config or an incoming/outgoing declaration
1265
+ * to expose named outgoing clients in the type system.
1266
+ */
1267
+ type FrameworkWorkloadConfig = Partial<WorkloadConfig> | FrameworkWorkloadIncomingOutgoing;
1268
+ /**
1255
1269
  * Workload Identity extracted from validated tokens
1256
1270
  */
1257
1271
  type WorkloadIdentity = {
@@ -1276,10 +1290,11 @@ type WorkloadIdentity = {
1276
1290
  * Workload Identity Authentication Interface
1277
1291
  */
1278
1292
  type Workload = WorkloadConfig & {
1279
- /** When options.client is set, returns a token for that named client (outbound to another app). */
1280
- getToken: (scope?: string, options?: {
1281
- client?: string;
1282
- }) => Promise<string>;
1293
+ /**
1294
+ * Returns a token for this workload configuration.
1295
+ * The optional argument overrides the configured default scope.
1296
+ */
1297
+ getToken: (scope?: string) => Promise<string>;
1283
1298
  refreshToken: (scope?: string) => Promise<WorkloadTokenResponse>;
1284
1299
  generateJWTAssertion: (scope?: string) => Promise<string>;
1285
1300
  revokeToken: (token: string) => Promise<void>;
@@ -1557,7 +1572,7 @@ import { StandardSchemaV1 as StandardSchemaV16 } from "@standard-schema/spec";
1557
1572
  *
1558
1573
  * @template TExtended - Type-safe custom data that consumers can add to sessions
1559
1574
  */
1560
- type Session<TExtended = {}> = {
1575
+ type Session<TExtended = object> = {
1561
1576
  /**
1562
1577
  * Session ID from the Identity Provider (from `sid` claim in ID token).
1563
1578
  * This is the unique identifier for the session.
@@ -1610,7 +1625,7 @@ type Session<TExtended = {}> = {
1610
1625
  * }
1611
1626
  * ```
1612
1627
  */
1613
- interface SessionStore<TExtended = {}> {
1628
+ interface SessionStore<TExtended = object> {
1614
1629
  /**
1615
1630
  * Create a new session in the store.
1616
1631
  *
@@ -1840,6 +1855,16 @@ type Secrets = {
1840
1855
  handleLfvEvents?(request: Request): Promise<Response>;
1841
1856
  };
1842
1857
  /**
1858
+ * Partial secrets source config used in framework/app code to declare expected source names.
1859
+ * ConfigSource-backed values may still provide the actual source details at runtime.
1860
+ */
1861
+ type FrameworkSecretsSourceConfig = Partial<SecretsSourceConfig>;
1862
+ /**
1863
+ * Framework-level named secrets source declarations keyed by source name.
1864
+ * Values may be partial or empty when the app only wants to declare expected names/types.
1865
+ */
1866
+ type FrameworkSecretsModuleConfig = Record<string, FrameworkSecretsSourceConfig>;
1867
+ /**
1843
1868
  * TODO: Let's see if we can do some clean inference and remove this!!!
1844
1869
  */
1845
1870
  type SecretsSourceMap = Record<string, SecretsSource>;
@@ -2005,8 +2030,8 @@ type FrameworkConfig = {
2005
2030
  logger?: Logger;
2006
2031
  sso?: SSOConfig | null;
2007
2032
  iam?: IAMConfig | null;
2008
- workload?: WorkloadConfig | null;
2009
- secrets?: SecretsModuleConfig | null;
2033
+ workload?: FrameworkWorkloadConfig | null;
2034
+ secrets?: FrameworkSecretsModuleConfig | null;
2010
2035
  ciam?: CIAMConfig | null;
2011
2036
  validators: ESValidators;
2012
2037
  };
@@ -2029,6 +2054,10 @@ type RemoteConfig = {
2029
2054
  secrets?: SecretsModuleConfig;
2030
2055
  ciam?: CIAMConfig;
2031
2056
  };
2057
+ type AggregateWorkload = Omit<Workload, "getToken"> & {
2058
+ getToken: (client: string, scope?: string) => Promise<string>;
2059
+ getServerToken: (scope?: string) => Promise<string>;
2060
+ };
2032
2061
  /** Base shape shared by all EnterpriseStandard variants (modules optional for backward compatibility). */
2033
2062
  type EnterpriseStandardBase = {
2034
2063
  logger?: Logger;
@@ -2039,7 +2068,7 @@ type EnterpriseStandardBase = {
2039
2068
  secrets?: Secrets;
2040
2069
  sso?: SSO;
2041
2070
  iam?: IAM;
2042
- workload?: Workload;
2071
+ workload?: Workload | AggregateWorkload;
2043
2072
  ciam?: CIAM;
2044
2073
  /**
2045
2074
  * Framework-agnostic request handler that routes requests to the appropriate
@@ -2061,7 +2090,7 @@ type EnterpriseStandard = EnterpriseStandardBase;
2061
2090
  *
2062
2091
  * @template TExtended - Type-safe custom data that consumers can add to magic links
2063
2092
  */
2064
- type MagicLink<TExtended = {}> = {
2093
+ type MagicLink<TExtended = object> = {
2065
2094
  /**
2066
2095
  * The magic link token (unique identifier)
2067
2096
  */
@@ -2119,7 +2148,7 @@ type MagicLink<TExtended = {}> = {
2119
2148
  * }
2120
2149
  * ```
2121
2150
  */
2122
- interface MagicLinkStore<TExtended = {}> {
2151
+ interface MagicLinkStore<TExtended = object> {
2123
2152
  /**
2124
2153
  * Create a new magic link in the store.
2125
2154
  *
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import{A as JM,B as LM,C as DM,D as jM,c as XM,d as YM,e,k as ZM,r as $M,s as HM,w as NM,x as VM,y as _M,z as GM}from"./shared/core-q2xp5jrk.js";function zM(O,L,D,h,q){if(!D&&!h)return;let E={...D,...h},Y={...E,signingKey:D?.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 k(M){let X=l(JSON.stringify({alg:"HS256",typ:"JWT"})),Z=l(JSON.stringify(M)),W=`${X}.${Z}`,_=await x(),S=await crypto.subtle.sign("HMAC",_,new TextEncoder().encode(W)),I=l(new Uint8Array(S));return`${W}.${I}`}async function f(M){let A=M.split(".");if(A.length!==3)throw Error("Invalid JWT");let[X,Z,W]=A,_=`${X}.${Z}`,S=await x(),I=new Uint8Array(t(W).split("").map((T)=>T.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",S,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 j(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 G(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 W=`${Y.cookiesPrefix}.${M}`,_=Z.split(";").find((C)=>C.trim().startsWith(`${W}=`));if(!_)return null;let S=_.indexOf("="),I=_.substring(S+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 '${W}':`,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=G("access",M),X=G("id",M),Z=G("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 f(A.access),Z=await f(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 S=v(M);if(S){let I=await f(S.access);if(I.sid)await g().delete(I.sid)}}catch(S){console.warn("Failed to delete CIAM session:",S)}let A=[["Set-Cookie",j("access")],["Set-Cookie",j("id")],["Set-Cookie",j("control")]],Z=new URL(M.url).searchParams.get("redirect");if(Z)return new Response("Logged out",{status:302,headers:[["Location",Z],...A]});let W=M.headers.get("accept");if(W?.includes("application/json")||W?.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(),W=new URLSearchParams(X).get("logout_token");if(!W)return new Response("Missing logout_token parameter",{status:400});let S=(await f(W)).sid;if(!S)return new Response("Invalid logout_token: missing sid claim",{status:400});return await g().delete(S),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 K(M){return M.id||M.email||`ciam-${M.userName}`}function V(M,A,X){return{sub:K(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 F(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"),S=_?parseInt(_,10):Y.magicLinkTtl??3600;if(Number.isNaN(S)||S<=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()+S*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 H(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 J=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:J}})}if(!Y.magicLinkStore){let J=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:J}})}let Z=await Y.magicLinkStore.get(X);if(!Z){let J=Y.errorUrl||"/";return new Response("Redirecting to error URL",{status:302,headers:{Location:J}})}let W=new Date(Date.now()+(Y.sessionTtl??86400)*1000),_=i(32),S=K(Z.user),I=V(Z.user,_,W),C=Q(S,_,W),u=z(I);try{let J={sid:_,sub:S,createdAt:new Date,lastActivityAt:new Date};await g().create(J)}catch(J){console.warn("Failed to create session:",J)}if(Y.userStore)try{let J=u.id;if(J){let r=new Date,s=await Y.userStore.get(J);if(s||Y.enableJitUserProvisioning){let FM={...s??{},...u,id:J,createdAt:s?.createdAt??r,updatedAt:r,userType:s?.userType??"customer"};await Y.userStore.upsert(FM)}}}catch(J){console.warn("Failed to store user:",J)}try{await Y.magicLinkStore.delete(X)}catch(J){console.warn("Failed to delete magic link:",J)}let c=await k(C),T=await k(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,W)]})}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",W=Y.logoutBackChannelUrl||"/auth/logout/backchannel",_=new URL(M.url).pathname,S=(T)=>{if(!T)return;try{return new URL(T).pathname}catch{return T.startsWith("/")?T:`/${T}`}};if(S(A)===_&&M.method==="POST")return F(M);if(S(X)===_&&M.method==="GET")return H(M);if(S(Z)===_&&M.method==="GET")return p(M);if(S(W)===_&&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(O,L){return e(L,"EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function."),L.ciam?.getUser(O)}function N(O,L,D){return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:String(O),scimType:D,detail:L}),{status:O,headers:{"Content-Type":"application/scim+json"}})}function MM(O,L){let D=L?.totalResults??O.length,h=L?.startIndex??1,q=L?.itemsPerPage??O.length;return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:ListResponse"],totalResults:D,startIndex:h,itemsPerPage:q,Resources:O}),{status:200,headers:{"Content-Type":"application/scim+json"}})}function d(O,L=200){return new Response(JSON.stringify(O),{status:L,headers:{"Content-Type":"application/scim+json"}})}function o(O){return{schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],id:O.id,externalId:O.externalId,displayName:O.displayName,members:O.members,meta:{resourceType:"Group",created:O.createdAt.toISOString(),lastModified:O.updatedAt.toISOString()}}}function AM(){return crypto.randomUUID()}function KM(O,L,D,h,q){if(!h&&!q)return;let Y={...h,...q};function U(){if(!D)throw L.error?.("IAM requires workload configuration before use"),Error("IAM requires workload configuration");return D}async function g(){let B=await U().getToken();return new Headers({"Content-Type":"application/scim+json",Accept:"application/scim+json",Authorization:`Bearer ${B}`})}async function m(B,j,G,P){if(!Y.url)throw Error("IAM URL not configured for outgoing requests");let v=`${Y.url}${j}`;try{let w=await g(),b=await fetch(v,{method:B,headers:w,body:G?JSON.stringify(G):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((K)=>K.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(j,G)=>{let P={...j,schemas:j.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,O.user)},l={createGroup:async(j,G)=>{let P={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:j,externalId:G?.externalId,members:G?.members};return m("POST","/Groups",P,O.group)}};let x;if(Y.groupStore){let B=Y.groupStore,j=async(K)=>{let V=U(),Q=K.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}},G=async(K,V)=>{if(!await j(K))return N(401,"Authorization required");let z=new URL(K.url),F=V?.basePath??"/Groups",H=z.pathname;if(H.startsWith(F))H=H.substring(F.length);let M=H.match(/^\/([^/]+)$/)?.[1],A=K.method;try{if(M)switch(A){case"GET":return await v(M);case"PUT":return await b(K,M);case"PATCH":return await p(K,M);case"DELETE":return await y(M);default:return N(405,"Method not allowed")}else if(H===""||H==="/")switch(A){case"GET":return await P(K);case"POST":return await w(K);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(K)=>{let V=new URL(K.url),Q=V.searchParams.get("startIndex"),z=V.searchParams.get("count"),F=Q!=null?parseInt(Q,10):void 0,H=z!=null?parseInt(z,10):void 0,$=F!=null&&!Number.isNaN(F)?Math.max(0,F-1):0,M=H!=null&&!Number.isNaN(H)?H:void 0,A=await B.list({start:$,limit:M}),X=A.items.map(o);return MM(X,{totalResults:A.total,startIndex:$+1,itemsPerPage:A.count})},v=async(K)=>{let V=await B.get(K);if(!V)return N(404,`Group ${K} not found`,"invalidValue");return d(o(V))},w=async(K)=>{let V=await K.json(),Q=await O.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 F=new Date,H={id:AM(),displayName:z.displayName,externalId:z.externalId,members:z.members,createdAt:F,updatedAt:F};return await B.upsert(H),d(o(H),201)},b=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let z=await K.json(),F=await O.group["~standard"].validate(z);if(F.issues)return console.error("Group replacement validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value,$={...Q,displayName:H.displayName??Q.displayName,externalId:H.externalId,members:H.members,updatedAt:new Date};return await B.upsert($),d(o($))},p=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let F=(await K.json()).Operations??[],H={...Q};for(let $ of F)if($.op==="replace"&&$.path&&$.value!==void 0){if($.path==="displayName")H.displayName=$.value}else if($.op==="add"&&$.path&&$.value!==void 0){if($.path==="members"){let M=$.value;H.members=[...H.members??[],...M]}}else if($.op==="remove"&&$.path){if($.path.startsWith("members[")){let M=$.path.match(/members\[value eq "([^"]+)"\]/);if(M)H.members=(H.members??[]).filter((A)=>A.value!==M[1])}}return H.updatedAt=new Date,await B.upsert(H),d(o(H))},y=async(K)=>{if(!await B.get(K))return N(404,`Group ${K} not found`,"invalidValue");return await B.delete(K),new Response(null,{status:204})};x={handler:G}}let k;if(Y.userStore){let B=Y.userStore,j=async(Q)=>{let z=U(),F=Q.headers.get("Authorization");if(!F||!F.startsWith("Bearer "))return!1;try{let H=F.substring(7);return(await z.validateToken(H)).valid}catch{return!1}},G=(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,F=Q.emails?.find((A)=>A.primary)?.value||Q.emails?.[0]?.value,H=Q.name?`${Q.name.givenName||""} ${Q.name.familyName||""}`.trim():Q.displayName,$=Q.id||AM(),M=Q.userName||F||$;return{id:$,userName:M,name:H||Q.displayName||M,email:F||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:F||M,email_verified:!0,name:H||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 j(Q))return N(401,"Authorization required");let H=new URL(Q.url),$=z?.basePath??"/Users",M=H.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 K(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(W){return console.error("Users inbound handler error:",W),N(500,W instanceof Error?W.message:"Internal server error")}},w=async(Q)=>{let z=new URL(Q.url),F=z.searchParams.get("startIndex"),H=z.searchParams.get("count"),$=F!=null?parseInt(F,10):void 0,M=H!=null?parseInt(H,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}),W=Z.items.map(G);return MM(W,{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(G(z))},p=async(Q)=>{let z=await Q.json(),F=await O.user["~standard"].validate(z);if(F.issues)return console.error("User creation validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value;if(!H.userName&&!H.emails?.[0]?.value)return N(400,"userName or email is required","invalidValue");let $=P(H);return await B.upsert($),d(G($),201)},y=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let H=await Q.json(),$=await O.user["~standard"].validate(H);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=F.createdAt,A.updatedAt=new Date,await B.upsert(A),d(G(A))},K=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let $=(await Q.json()).Operations??[],M={...F};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((W)=>W.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((W)=>W.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(G(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})};k={handler:v}}async function f(B,j){U();let P=new URL(B.url).pathname,v=j?.usersUrl??Y.usersUrl??"/api/iam/Users",w=j?.groupsUrl??Y.groupsUrl??"/api/iam/Groups";if(P.startsWith(v)&&k)return k.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:k,handler:f}}var WM="@enterprisestandard/core",OM=YM(XM(WM));function QM(O){let L=O.replace(/-/g,"+").replace(/_/g,"/");return atob(L)}async function SM(O,L){let D=O.split(".");if(D.length!==3)throw Error("Invalid JWT");let h=JSON.parse(QM(D[0])),q=JSON.parse(QM(D[1])),E=D[2].replace(/-/g,"+").replace(/_/g,"/"),Y=h.kid;if(!Y)throw Error("JWT header missing kid");let U=await $M(L),g=await HM(U,Y),i=new TextEncoder().encode(`${D[0]}.${D[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 OM.validate(q);if(x.issues)throw Error(`ID token claims validation failed: ${x.issues.map((B)=>B.message).join("; ")}`);let k=x.value;if(k===void 0)throw Error("ID token claims missing");let f=k;if(typeof f.exp==="number"&&f.exp<Math.floor(Date.now()/1000))throw Error("Token expired");return ZM(f)}export{SM as verifyUser,NM as sso,jM as logoutBackChannel,DM as logout,JM as initiateLogin,KM as iam,_M as getSSOorCIAMUser,VM as getSSOUser,GM as getRequiredSSOorCIAMUser,BM as getCIAMUser,zM as ciam,LM as callback};
1
+ import{A as JM,B as LM,C as DM,D as jM,c as XM,d as YM,e,k as ZM,r as $M,s as HM,w as NM,x as VM,y as _M,z as GM}from"./shared/core-q2xp5jrk.js";function zM(O,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)),W=`${X}.${Z}`,_=await x(),S=await crypto.subtle.sign("HMAC",_,new TextEncoder().encode(W)),I=l(new Uint8Array(S));return`${W}.${I}`}async function k(M){let A=M.split(".");if(A.length!==3)throw Error("Invalid JWT");let[X,Z,W]=A,_=`${X}.${Z}`,S=await x(),I=new Uint8Array(t(W).split("").map((T)=>T.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",S,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 W=`${Y.cookiesPrefix}.${M}`,_=Z.split(";").find((C)=>C.trim().startsWith(`${W}=`));if(!_)return null;let S=_.indexOf("="),I=_.substring(S+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 '${W}':`,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 S=v(M);if(S){let I=await k(S.access);if(I.sid)await g().delete(I.sid)}}catch(S){console.warn("Failed to delete CIAM session:",S)}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 W=M.headers.get("accept");if(W?.includes("application/json")||W?.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(),W=new URLSearchParams(X).get("logout_token");if(!W)return new Response("Missing logout_token parameter",{status:400});let S=(await k(W)).sid;if(!S)return new Response("Invalid logout_token: missing sid claim",{status:400});return await g().delete(S),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 K(M){return M.id||M.email||`ciam-${M.userName}`}function V(M,A,X){return{sub:K(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 F(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"),S=_?parseInt(_,10):Y.magicLinkTtl??3600;if(Number.isNaN(S)||S<=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()+S*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 H(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 W=new Date(Date.now()+(Y.sessionTtl??86400)*1000),_=i(32),S=K(Z.user),I=V(Z.user,_,W),C=Q(S,_,W),u=z(I);try{let L={sid:_,sub:S,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,s=await Y.userStore.get(L);if(s||Y.enableJitUserProvisioning){let FM={...s??{},...u,id:L,createdAt:s?.createdAt??r,updatedAt:r,userType:s?.userType??"customer"};await Y.userStore.upsert(FM)}}}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,W)]})}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",W=Y.logoutBackChannelUrl||"/auth/logout/backchannel",_=new URL(M.url).pathname,S=(T)=>{if(!T)return;try{return new URL(T).pathname}catch{return T.startsWith("/")?T:`/${T}`}};if(S(A)===_&&M.method==="POST")return F(M);if(S(X)===_&&M.method==="GET")return H(M);if(S(Z)===_&&M.method==="GET")return p(M);if(S(W)===_&&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(O,D){return e(D,"EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function."),D.ciam?.getUser(O)}function N(O,D,j){return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:Error"],status:String(O),scimType:j,detail:D}),{status:O,headers:{"Content-Type":"application/scim+json"}})}function MM(O,D){let j=D?.totalResults??O.length,h=D?.startIndex??1,q=D?.itemsPerPage??O.length;return new Response(JSON.stringify({schemas:["urn:ietf:params:scim:api:messages:2.0:ListResponse"],totalResults:j,startIndex:h,itemsPerPage:q,Resources:O}),{status:200,headers:{"Content-Type":"application/scim+json"}})}function d(O,D=200){return new Response(JSON.stringify(O),{status:D,headers:{"Content-Type":"application/scim+json"}})}function o(O){return{schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],id:O.id,externalId:O.externalId,displayName:O.displayName,members:O.members,meta:{resourceType:"Group",created:O.createdAt.toISOString(),lastModified:O.updatedAt.toISOString()}}}function AM(){return crypto.randomUUID()}function KM(O,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((K)=>K.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,O.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,O.group)}};let x;if(Y.groupStore){let B=Y.groupStore,G=async(K)=>{let V=U(),Q=K.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(K,V)=>{if(!await G(K))return N(401,"Authorization required");let z=new URL(K.url),F=V?.basePath??"/Groups",H=z.pathname;if(H.startsWith(F))H=H.substring(F.length);let M=H.match(/^\/([^/]+)$/)?.[1],A=K.method;try{if(M)switch(A){case"GET":return await v(M);case"PUT":return await b(K,M);case"PATCH":return await p(K,M);case"DELETE":return await y(M);default:return N(405,"Method not allowed")}else if(H===""||H==="/")switch(A){case"GET":return await P(K);case"POST":return await w(K);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(K)=>{let V=new URL(K.url),Q=V.searchParams.get("startIndex"),z=V.searchParams.get("count"),F=Q!=null?parseInt(Q,10):void 0,H=z!=null?parseInt(z,10):void 0,$=F!=null&&!Number.isNaN(F)?Math.max(0,F-1):0,M=H!=null&&!Number.isNaN(H)?H:void 0,A=await B.list({start:$,limit:M}),X=A.items.map(o);return MM(X,{totalResults:A.total,startIndex:$+1,itemsPerPage:A.count})},v=async(K)=>{let V=await B.get(K);if(!V)return N(404,`Group ${K} not found`,"invalidValue");return d(o(V))},w=async(K)=>{let V=await K.json(),Q=await O.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 F=new Date,H={id:AM(),displayName:z.displayName,externalId:z.externalId,members:z.members,createdAt:F,updatedAt:F};return await B.upsert(H),d(o(H),201)},b=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let z=await K.json(),F=await O.group["~standard"].validate(z);if(F.issues)return console.error("Group replacement validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value,$={...Q,displayName:H.displayName??Q.displayName,externalId:H.externalId,members:H.members,updatedAt:new Date};return await B.upsert($),d(o($))},p=async(K,V)=>{let Q=await B.get(V);if(!Q)return N(404,`Group ${V} not found`,"invalidValue");let F=(await K.json()).Operations??[],H={...Q};for(let $ of F)if($.op==="replace"&&$.path&&$.value!==void 0){if($.path==="displayName")H.displayName=$.value}else if($.op==="add"&&$.path&&$.value!==void 0){if($.path==="members"){let M=$.value;H.members=[...H.members??[],...M]}}else if($.op==="remove"&&$.path){if($.path.startsWith("members[")){let M=$.path.match(/members\[value eq "([^"]+)"\]/);if(M)H.members=(H.members??[]).filter((A)=>A.value!==M[1])}}return H.updatedAt=new Date,await B.upsert(H),d(o(H))},y=async(K)=>{if(!await B.get(K))return N(404,`Group ${K} not found`,"invalidValue");return await B.delete(K),new Response(null,{status:204})};x={handler:J}}let f;if(Y.userStore){let B=Y.userStore,G=async(Q)=>{let z=U(),F=Q.headers.get("Authorization");if(!F||!F.startsWith("Bearer "))return!1;try{let H=F.substring(7);return(await z.validateToken(H)).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,F=Q.emails?.find((A)=>A.primary)?.value||Q.emails?.[0]?.value,H=Q.name?`${Q.name.givenName||""} ${Q.name.familyName||""}`.trim():Q.displayName,$=Q.id||AM(),M=Q.userName||F||$;return{id:$,userName:M,name:H||Q.displayName||M,email:F||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:F||M,email_verified:!0,name:H||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 H=new URL(Q.url),$=z?.basePath??"/Users",M=H.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 K(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(W){return console.error("Users inbound handler error:",W),N(500,W instanceof Error?W.message:"Internal server error")}},w=async(Q)=>{let z=new URL(Q.url),F=z.searchParams.get("startIndex"),H=z.searchParams.get("count"),$=F!=null?parseInt(F,10):void 0,M=H!=null?parseInt(H,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}),W=Z.items.map(J);return MM(W,{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(),F=await O.user["~standard"].validate(z);if(F.issues)return console.error("User creation validation failed:",F.issues),N(400,`Request validation failed: ${F.issues.map((M)=>M.message).join("; ")}`,"invalidValue");let H=F.value;if(!H.userName&&!H.emails?.[0]?.value)return N(400,"userName or email is required","invalidValue");let $=P(H);return await B.upsert($),d(J($),201)},y=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let H=await Q.json(),$=await O.user["~standard"].validate(H);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=F.createdAt,A.updatedAt=new Date,await B.upsert(A),d(J(A))},K=async(Q,z)=>{let F=await B.get(z);if(!F)return N(404,`User ${z} not found`,"invalidValue");let $=(await Q.json()).Operations??[],M={...F};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((W)=>W.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((W)=>W.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 WM="@enterprisestandard/core",OM=YM(XM(WM));function QM(O){let D=O.replace(/-/g,"+").replace(/_/g,"/");return atob(D)}async function SM(O,D){let j=O.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 HM(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 OM.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{SM as verifyUser,NM as sso,jM as logoutBackChannel,DM as logout,JM as initiateLogin,KM as iam,_M as getSSOorCIAMUser,VM as getSSOUser,GM as getRequiredSSOorCIAMUser,BM as getCIAMUser,zM as ciam,LM as callback};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enterprisestandard/core",
3
- "version": "0.0.9-beta.20260304.1",
3
+ "version": "0.0.9",
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.9-beta.20260304.1",
31
- "@enterprisestandard/valibot": "0.0.9-beta.20260304.1"
30
+ "@enterprisestandard/zod": "^0.0.9",
31
+ "@enterprisestandard/valibot": "^0.0.9"
32
32
  }
33
33
  }