@ionite/core 0.0.23-beta.20260803.1 → 0.0.23-beta.20260809.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1122,7 +1122,7 @@ type ModuleReadiness = {
1122
1122
  * block. Apps that DO treat delta as a hard dependency can gate on `ion.iam.delta.isReady()` /
1123
1123
  * `ion.iam.delta.ready()` explicitly instead.
1124
1124
  */
1125
- type ModuleName = "sso" | "ciam" | "iam" | "workload" | "otel" | "secrets" | "authz";
1125
+ type ModuleName = "sso" | "ciam" | "iam" | "workload" | "otel" | "secrets" | "kms" | "authz";
1126
1126
  /** Per-module readiness snapshot in {@link ReadinessReport}. */
1127
1127
  type ModuleReadinessState = {
1128
1128
  /** Whether the module is active (present/requested) in the effective config. Inactive modules never block readiness. */
@@ -2052,6 +2052,54 @@ type IAM = IAMConfig & {
2052
2052
  */
2053
2053
  delta?: IamDeltaEmitter;
2054
2054
  };
2055
+ type KmsKeyState = "pending" | "active" | "deprecated" | "revoked";
2056
+ type KmsTokenKey = {
2057
+ id: string;
2058
+ state: KmsKeyState;
2059
+ value?: string;
2060
+ notBefore?: string;
2061
+ notAfter?: string;
2062
+ };
2063
+ type KmsTokenPoolDocument = {
2064
+ kind: "token";
2065
+ active: string;
2066
+ keys: KmsTokenKey[];
2067
+ };
2068
+ /** ConfigSource-owned pointer to a token-pool document. */
2069
+ type KmsPoolConfig = {
2070
+ /** Named `ion.secrets` source. Omit to use the default `ion.secret` source. */
2071
+ source?: string;
2072
+ /** Secret path. Defaults to `/kms/{poolName}`. */
2073
+ path?: string;
2074
+ };
2075
+ /** ConfigSource-owned named token-pool declarations. */
2076
+ type KmsConfig = Record<string, KmsPoolConfig>;
2077
+ type KmsPoolListener = (current: KmsTokenKey | undefined) => void;
2078
+ type KmsPool = {
2079
+ /** Returns the usable active token metadata and value. Throws while the pool is not ready. */
2080
+ current(): KmsTokenKey;
2081
+ /** Returns keys accepted during the current overlap window (active plus usable deprecated keys). */
2082
+ valid(): KmsTokenKey[];
2083
+ /** Notifies immediately and whenever the selected active token changes. */
2084
+ subscribe(listener: KmsPoolListener): () => void;
2085
+ beforeChange(listener: ChangeListener): () => void;
2086
+ afterChange(listener: ChangeListener): () => void;
2087
+ isReady(): boolean;
2088
+ ready(timeout?: number): Promise<void>;
2089
+ };
2090
+ /**
2091
+ * Aggregate KMS module. Named pool handles are also installed as runtime properties
2092
+ * (`ion.kms.<name>`); use `getPool(name)` when the name is dynamic.
2093
+ */
2094
+ type Kms = ModuleReadiness & {
2095
+ readonly config: Readonly<KmsConfig>;
2096
+ listPools(): string[];
2097
+ getPool(name: string): KmsPool;
2098
+ currentToken(name: string): string;
2099
+ validTokens(name: string): KmsTokenKey[];
2100
+ };
2101
+ /** Parse and fail closed on an invalid v1 token-pool document. */
2102
+ declare function parseKmsTokenPool(value: unknown): KmsTokenPoolDocument;
2055
2103
  type OtelSignalName = "traces" | "metrics" | "logs";
2056
2104
  type OtelProtocol = "http/protobuf" | "http/json";
2057
2105
  type OtelProviderType = "otlp" | "grafana-lgtm" | "datadog" | "splunk" | "elastic";
@@ -2095,6 +2143,8 @@ type OtelConfig = {
2095
2143
  protocol?: OtelProtocol;
2096
2144
  headers?: Record<string, string>;
2097
2145
  apiKey?: string;
2146
+ /** Name of a `RemoteConfig.kms` token pool used for exporter authentication. */
2147
+ apiKeyPool?: string;
2098
2148
  apiKeyHeader?: string;
2099
2149
  oauth?: OtelOAuthClientCredentialsConfig;
2100
2150
  version?: string;
@@ -2788,6 +2838,15 @@ type SecretLifecycleRequest = {
2788
2838
  severity?: SecretRequestSeverity;
2789
2839
  incidentRef?: string;
2790
2840
  };
2841
+ type SecretEventName = "rotate_requested" | "revoke_requested" | "created" | "updated" | "deleted" | "rotated" | "revoked" | "removed" | "acl_updated" | "path_removed" | "lease_expiring_soon" | "lease_revoked" | (string & {});
2842
+ type SecretEvent = {
2843
+ path: string;
2844
+ event: SecretEventName;
2845
+ requestId?: string;
2846
+ issuedAt?: string | number;
2847
+ expiresAt?: string | number;
2848
+ };
2849
+ type SecretEventListener = (event: SecretEvent) => void;
2791
2850
  type SecretsOperationOptions = {
2792
2851
  /** Optional timeout in milliseconds for this secrets operation. */
2793
2852
  timeout?: number;
@@ -2801,6 +2860,40 @@ type SecretsSubscriptionOptions = SecretsOperationOptions & {
2801
2860
  */
2802
2861
  mode?: SubscriptionMode;
2803
2862
  };
2863
+ type LfvCallbackKind = "delivery" | "events";
2864
+ type LfvCallbackHeaders = {
2865
+ requestId: string;
2866
+ keyId: string;
2867
+ signature: string;
2868
+ };
2869
+ /**
2870
+ * Original LFV callback bytes and signature headers distributed between App processes. Consumers
2871
+ * MUST independently verify this envelope against their own configured `verifyJwks`; the transport
2872
+ * is never a signature trust anchor.
2873
+ */
2874
+ type LfvCallbackEnvelope = {
2875
+ kind: LfvCallbackKind;
2876
+ /** Normalized `serverUrl|path` routing key. */
2877
+ key: string;
2878
+ /** Random process/source identity used to suppress transport echo. */
2879
+ originId: string;
2880
+ rawBody: string;
2881
+ headers: LfvCallbackHeaders;
2882
+ };
2883
+ type LfvCallbackEnvelopeListener = (envelope: LfvCallbackEnvelope) => void | Promise<void>;
2884
+ /**
2885
+ * Cross-process transport for signed LFV callback envelopes. The default SDK behavior remains the
2886
+ * in-process callback hub; applications opt into a transport (for example Redis Pub/Sub) through
2887
+ * FrameworkConfig.
2888
+ */
2889
+ type LfvCallbackTransport = {
2890
+ publish(envelope: LfvCallbackEnvelope): Promise<void>;
2891
+ subscribe(key: string, listener: LfvCallbackEnvelopeListener): Promise<() => void>;
2892
+ };
2893
+ /** Framework-only LFV runtime wiring. Live transports MUST never be supplied by RemoteConfig. */
2894
+ type FrameworkLfvConfig = {
2895
+ callbackTransport?: LfvCallbackTransport;
2896
+ };
2804
2897
  type SecretsSource = ReactiveHandle & ModuleReadiness & {
2805
2898
  type: SecretsSourceType;
2806
2899
  getFullSecret: <T>(path: string, options?: SecretsOperationOptions) => Promise<Secret<T>>;
@@ -2818,6 +2911,8 @@ type SecretsSource = ReactiveHandle & ModuleReadiness & {
2818
2911
  * @returns a unsubscribe/cleanup function.
2819
2912
  */
2820
2913
  subscribe<T>(path: string, onChange: (fullSecret: Secret<T>) => void, options?: SecretsSubscriptionOptions): Promise<() => void>;
2914
+ /** Optional lifecycle-event stream (LFV events endpoint and equivalent reactive sources). */
2915
+ subscribeEvents?(listener: SecretEventListener): () => void;
2821
2916
  /**
2822
2917
  * Deletes a secret at the given path.
2823
2918
  */
@@ -3383,6 +3478,8 @@ type FrameworkConfig = {
3383
3478
  iam?: IAMConfig | null;
3384
3479
  workload?: FrameworkWorkloadConfig | null;
3385
3480
  secrets?: FrameworkSecretsModuleConfig | null;
3481
+ /** Framework-only distributed LFV callback wiring (for example Redis Pub/Sub). */
3482
+ lfv?: FrameworkLfvConfig;
3386
3483
  ciam?: CIAMConfig | null;
3387
3484
  authz?: AuthzConfig | null;
3388
3485
  otel?: FrameworkOtelConfig | null;
@@ -3439,6 +3536,8 @@ type RemoteConfig = {
3439
3536
  workload?: WorkloadConfig | WorkloadConfigMap | WorkloadIncomingOutgoing;
3440
3537
  /** Optional named secrets-source configs available to this App instance. */
3441
3538
  secrets?: SecretsModuleConfig;
3539
+ /** ConfigSource-owned named managed token pools consumed through `ion.kms`. */
3540
+ kms?: KmsConfig;
3442
3541
  ciam?: CIAMConfig;
3443
3542
  /** OpenTelemetry collector/exporter config loaded from ConfigSource. */
3444
3543
  otel?: OtelConfig;
@@ -3880,6 +3979,7 @@ type IoniteBase = {
3880
3979
  /** Default config-source-backed secret client, typically the vault used for RemoteConfig. */
3881
3980
  secret: SecretsSource;
3882
3981
  secrets?: Secrets;
3982
+ kms?: Kms;
3883
3983
  sso?: SSO;
3884
3984
  iam?: IAM;
3885
3985
  workload?: Workload | AggregateWorkload;
@@ -4777,6 +4877,13 @@ interface AccessIndex {
4777
4877
  hasAll(subject: AccessRef<BaseUser>, targets: AccessCheckTarget[], subjectType?: SubjectType): Promise<AuthzDecision>;
4778
4878
  /** Replace the index rows attributed to `rootId` with `edges` (set-based materialization). */
4779
4879
  materialize(rootId: string, edges: EffectiveEdge[]): Promise<void>;
4880
+ /**
4881
+ * Atomically replace every effective edge for one subject with the complete freshly-expanded
4882
+ * closure. Implementations MUST expose either the previous closure or the replacement to concurrent
4883
+ * readers, never an intermediate empty/partial state. Expansion is completed before this call, so a
4884
+ * failed reconcile preserves the last-known-good closure.
4885
+ */
4886
+ replaceSubject(subject: string, subjectType: SubjectType, edges: EffectiveEdge[]): Promise<void>;
4780
4887
  /** Remove all index rows attributed to `rootId`. */
4781
4888
  removeByRoot(rootId: string): Promise<void>;
4782
4889
  /** Clear all index rows, or only those for a single subject (optionally scoped to a `subjectType`). */
@@ -4985,15 +5092,6 @@ type Authz = {
4985
5092
  * is wired. Always run it off the request path.
4986
5093
  */
4987
5094
  reconcile(): Promise<ReconcileReport>;
4988
- /**
4989
- * Resolve once the internal reconcile queue is drained (every catalog-/resource-change reconcile
4990
- * enqueued so far has finished). Those reconciles are serialized and coalescing (a queued full
4991
- * reconcile absorbs later ones); `settle()` returns the current queue tail so a caller can guarantee
4992
- * request-triggered reconciles complete inside the request lifecycle (serverless-safe — no detached
4993
- * reconcile survives the response). The SCIM mutation path awaits this after its store writes. It
4994
- * never rejects (queued reconcile failures are isolated and logged).
4995
- */
4996
- settle(): Promise<void>;
4997
5095
  };
4998
5096
  /** Why an {@link AccessCheckResult} resolved the way it did. */
4999
5097
  type AccessCheckReason = "ok" | "unauthenticated" | "forbidden" | "not_configured";
@@ -5405,4 +5503,4 @@ type LfvErrorResponse = {
5405
5503
  };
5406
5504
  /** Generates a ULID */
5407
5505
  declare function generateULID(prefix?: string): string;
5408
- export { workloadTokenResponseSchema, withValidate, warnLogger, waitOn, version, validationFailureResponse, userSchema, unionCatalogRead, trustedClientPermissionsForPrincipal, trimTrailingSlash, tokenResponseSchema, toCodeCatalog, stripJsonComments, stableConfigHash, silentLogger, serializeConfig, readyCatalogEntry, parseJsonc, parseEcid, oidcCallbackSchema, normalizeTenantRoutingStrategy, normalizeTenantPathNamespace, must, mergeConfig, matchTenantPath, listGenerator, list, jwtAssertionClaimsSchema, isStoreConflictError, isEcid, isConfigSourceError, isConfigLocator, isCodeCatalog, infoLogger, idTokenClaimsSchema, groupResourceSchema, generateULID, formatEcid, defineCatalog, defaultLogger, deepEqualPlain, decodeUser, debugLogger, configTrustedClientGrants, claimsToUser, buildTenantPath, assertValidSubjectTypeScoping, assertEcid, accessRootId, accessRefId, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadPrincipal, WorkloadIncomingOutgoing, WorkloadIdentityStore, WorkloadIdentity, WorkloadGetToken, WorkloadConfigMap, WorkloadConfig, WorkloadClient, Workload, WorkforceUser, VaultWorkloadAuthConfig, VaultWebSocketSecretsConfig, VaultWebSocketAuthHeader, VaultSecretsConfig, VaultLfvSecretsConfig, VaultConfigLocator, ValidateResult, UsersInboundHandlerConfig, UserStoreOptions, UserStore, UpdateTenantRequest, TrustedProvisioningClient, TrustedIdp, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantStore, TenantStatus, TenantRoutingStrategy, TenantResponse, TenantPathRoutingStrategy, TenantPathNamespace, TenantPathMatch, TenantIonCache, TenantFactory, TenantConfigLocator, SubscriptionMode, SubjectTypeScoping, SubjectType, SubjectScope, SubjectRef, StoreConflictKind, StoreConflictError, StateCookie, StandardSchemaWithValidate, SessionStore, Session, ServerOnlyWorkloadConfig, SecretsValidators, SecretsSubscriptionOptions, SecretsSourceType, SecretsSourceMap, SecretsSourceConfig, SecretsSource, SecretsOperationOptions, SecretsModuleConfig, Secrets, SecretRequestSeverity, SecretLifecycleRequest, Secret, User as ScimUser, ScimServiceProviderConfig, ScimSchemaDefinition, ScimSchemaAttributeDefinition, Role2 as ScimRole, ScimResult, ScimResourceTypeSchemaExtension, ScimResourceType, ScimMutationSummary, ScimListResponse, Group2 as ScimGroup, ScimError, ScimAuthenticationScheme, SSOValidators, SSOHandlerConfig, SSOConfigFromCode, SSOConfig, SSOAppValidators, SSOAppRegistry, SSO, RoutingOptions, RouteModule, RouteFilterResult, Role, ResourceProvider, ResourceChangeListener, ResourceChange, Resource, ResolvedVaultLfvSecretsConfig, ResolvedRoute, RequireReadyResult, RemoteConfigRetryOptions, RemoteConfigRetryHook, RemoteConfigRetryContext, RemoteConfigLoadErrorKind, RemoteConfig, RegisterSSOAppResult, RegisterSSOAppPayload, RegisterSSOAppError, RegisterIAMAppResult, RegisterIAMAppPayload, RegisterIAMAppError, ReconcileReport, ReadyzEndpointConfig, ReadyAccessCatalogEntry, ReadinessReport, ReactiveHandle, Photo, PhoneNumber, Permission, ParsedEcid, PLATFORM_ASSIGNABLE_SUBJECT_TYPES, OtelSignalName, OtelSignalConfig, OtelProviderType, OtelProtocol, OtelOAuthClientCredentialsConfig, OtelMetricsSignalConfig, OtelLogRecord, OtelLogLevel, OtelLevels, OtelConfig, OtelAttributes, OtelAttributeValue, Otel, OidcCallbackParams, OaaSyncResult, OaaSyncOptions, OaaSyncInput, OaaClient, OaaAccessTargetType, OaaAccessChangeBatchItem, Name, ModuleReadinessState, ModuleReadiness, ModuleName, ModifiableFrameworkConfig, MetaData, MagicLinkStore, MagicLink, Logger, ListResult, ListOptions, ListFilter, LfvOtpResponse, LfvOtpRequest, LfvJwks, LfvErrorResponse, LfvErrorCode, LfvEd25519PublicJwk, LfvEd25519PrivateJwk, LfvActionRequestBase, LfvActionName, LfvActionAcceptedResponse, JwtBearerWorkloadConfig, JWTAssertionClaims, IoniteValidators, IoniteUserExtension, IoniteErrorOptions, IoniteError, IoniteBase, Ionite, InMemoryTenantStoreOptions, IdentityResolution, IdTokenClaims, IamDeltaResourceType, IamDeltaReconcileResult, IamDeltaMode, IamDeltaIdMapStore, IamDeltaIdMapKey, IamDeltaEmitter, ION_TENANT_MANAGE, ION_SDK_PERMISSIONS, ION_SCIM_USER_EXTENSION_URN, ION_IAM_USERS_WRITE, ION_IAM_READ, ION_IAM_GROUPS_WRITE, ION_ENDPOINT_PERMISSIONS, ION_CIAM_MAGIC_LINK_CREATE, ION_CAPABILITIEZ_READ, ION_AUTHZ_OAA_SYNC, ION_AUTHZ_GROUP_SCHEMA, IAMValidators, IAMUsersInbound, IAMInboundUsersConfig, IAMInboundUserContext, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMDiscoveryHandlerConfig, IAMDiscoveryContext, IAMDiscoveryConfig, IAMConfigFromCode, IAMConfig, IAMAppValidators, IAMAppRegistry, IAM, GroupsInboundHandlerConfig, GroupResource, GroupMember, Group, GcpSecretsConfig, GcpConfigLocator, FrameworkWorkloadIncomingOutgoing, FrameworkWorkloadConfigFromCode, FrameworkWorkloadConfig, FrameworkStores, FrameworkSecretsSourceConfig, FrameworkSecretsModuleConfig, FrameworkOtelConfig, FrameworkConfigInput, FrameworkConfig, EnvironmentType, EntityStore, EntitlementType, Entitlement, EnterpriseExtension, EndpointPermission, EndpointOperation, Email, EgressOutcome, EgressChannelOutcome, EffectiveEdge, EcidFormatError, ECID_SCHEME, DevSecretsConfig, DEFAULT_TENANT_UI_NAMESPACE, DEFAULT_TENANT_API_NAMESPACE, CustomerStoreOptions, CustomerStore, Customer, CreateUserOptions, CreateTenantRequest, CreateGroupOptions, ConfigSubscriptionOptions, ConfigSourceType, ConfigSourceResolver, ConfigSourceErrorInit, ConfigSourceError, ConfigSourceEnv, ConfigSource, ConfigLocator, ConfigErrorKind, ConfigChangeResult, ConfigChangeOptions, ConfigChangeCallback, ConfigApplyStatus, CodeCatalogNamespace, CodeCatalogInput, CodeCatalog, ClientCredentialsWorkloadConfig, ChangeListener, CatalogChangeListener, CatalogChangeKind, CatalogChange, CapabilityState, CapabilityKey, CapabilityEndpointUrls, CapabilitiezManifest, CachedWorkloadToken, CacheConfig, CIAMValidators, CIAMProviderType, CIAMProviderDescriptor, CIAMProviderConfig, CIAMProviderColors, CIAMProviderBranding, CIAMConfigFromCodeInput, CIAMConfigFromCode, CIAMConfig, CIAM, BaseWorkloadIdentity, BaseUser, BaseTenant, BaseCustomer, AzureSecretsConfig, AzureConfigLocator, AzureAuthMethod, AwsSecretsConfig, AwsConfigLocator, AuthzScimGroupType, AuthzScimGroupExtension, AuthzOaaConfig, AuthzEntityBase, AuthzDecision, AuthzConfig, Authz, AuthenticatedUser, AuthenticatedPrincipal, ApplicationValidators, Address, AccessStatus, AccessRef, AccessProvenance, AccessMutationStatus, AccessMutationResult, AccessIndex, AccessCheckTarget, AccessCheckResult, AccessCheckReason, AccessChange, AccessCatalogStore, AccessAssignmentStore };
5506
+ export { workloadTokenResponseSchema, withValidate, warnLogger, waitOn, version, validationFailureResponse, userSchema, unionCatalogRead, trustedClientPermissionsForPrincipal, trimTrailingSlash, tokenResponseSchema, toCodeCatalog, stripJsonComments, stableConfigHash, silentLogger, serializeConfig, readyCatalogEntry, parseKmsTokenPool, parseJsonc, parseEcid, oidcCallbackSchema, normalizeTenantRoutingStrategy, normalizeTenantPathNamespace, must, mergeConfig, matchTenantPath, listGenerator, list, jwtAssertionClaimsSchema, isStoreConflictError, isEcid, isConfigSourceError, isConfigLocator, isCodeCatalog, infoLogger, idTokenClaimsSchema, groupResourceSchema, generateULID, formatEcid, defineCatalog, defaultLogger, deepEqualPlain, decodeUser, debugLogger, configTrustedClientGrants, claimsToUser, buildTenantPath, assertValidSubjectTypeScoping, assertEcid, accessRootId, accessRefId, X509Certificate, WorkloadValidators, WorkloadTokenStore, WorkloadTokenResponse, WorkloadPrincipal, WorkloadIncomingOutgoing, WorkloadIdentityStore, WorkloadIdentity, WorkloadGetToken, WorkloadConfigMap, WorkloadConfig, WorkloadClient, Workload, WorkforceUser, VaultWorkloadAuthConfig, VaultWebSocketSecretsConfig, VaultWebSocketAuthHeader, VaultSecretsConfig, VaultLfvSecretsConfig, VaultConfigLocator, ValidateResult, UsersInboundHandlerConfig, UserStoreOptions, UserStore, UpdateTenantRequest, TrustedProvisioningClient, TrustedIdp, TokenValidationResult, TokenResponse, TenantWebhookPayload, TenantValidators, TenantStore, TenantStatus, TenantRoutingStrategy, TenantResponse, TenantPathRoutingStrategy, TenantPathNamespace, TenantPathMatch, TenantIonCache, TenantFactory, TenantConfigLocator, SubscriptionMode, SubjectTypeScoping, SubjectType, SubjectScope, SubjectRef, StoreConflictKind, StoreConflictError, StateCookie, StandardSchemaWithValidate, SessionStore, Session, ServerOnlyWorkloadConfig, SecretsValidators, SecretsSubscriptionOptions, SecretsSourceType, SecretsSourceMap, SecretsSourceConfig, SecretsSource, SecretsOperationOptions, SecretsModuleConfig, Secrets, SecretRequestSeverity, SecretLifecycleRequest, SecretEventName, SecretEventListener, SecretEvent, Secret, User as ScimUser, ScimServiceProviderConfig, ScimSchemaDefinition, ScimSchemaAttributeDefinition, Role2 as ScimRole, ScimResult, ScimResourceTypeSchemaExtension, ScimResourceType, ScimMutationSummary, ScimListResponse, Group2 as ScimGroup, ScimError, ScimAuthenticationScheme, SSOValidators, SSOHandlerConfig, SSOConfigFromCode, SSOConfig, SSOAppValidators, SSOAppRegistry, SSO, RoutingOptions, RouteModule, RouteFilterResult, Role, ResourceProvider, ResourceChangeListener, ResourceChange, Resource, ResolvedVaultLfvSecretsConfig, ResolvedRoute, RequireReadyResult, RemoteConfigRetryOptions, RemoteConfigRetryHook, RemoteConfigRetryContext, RemoteConfigLoadErrorKind, RemoteConfig, RegisterSSOAppResult, RegisterSSOAppPayload, RegisterSSOAppError, RegisterIAMAppResult, RegisterIAMAppPayload, RegisterIAMAppError, ReconcileReport, ReadyzEndpointConfig, ReadyAccessCatalogEntry, ReadinessReport, ReactiveHandle, Photo, PhoneNumber, Permission, ParsedEcid, PLATFORM_ASSIGNABLE_SUBJECT_TYPES, OtelSignalName, OtelSignalConfig, OtelProviderType, OtelProtocol, OtelOAuthClientCredentialsConfig, OtelMetricsSignalConfig, OtelLogRecord, OtelLogLevel, OtelLevels, OtelConfig, OtelAttributes, OtelAttributeValue, Otel, OidcCallbackParams, OaaSyncResult, OaaSyncOptions, OaaSyncInput, OaaClient, OaaAccessTargetType, OaaAccessChangeBatchItem, Name, ModuleReadinessState, ModuleReadiness, ModuleName, ModifiableFrameworkConfig, MetaData, MagicLinkStore, MagicLink, Logger, ListResult, ListOptions, ListFilter, LfvOtpResponse, LfvOtpRequest, LfvJwks, LfvErrorResponse, LfvErrorCode, LfvEd25519PublicJwk, LfvEd25519PrivateJwk, LfvCallbackTransport, LfvCallbackKind, LfvCallbackHeaders, LfvCallbackEnvelopeListener, LfvCallbackEnvelope, LfvActionRequestBase, LfvActionName, LfvActionAcceptedResponse, KmsTokenPoolDocument, KmsTokenKey, KmsPoolListener, KmsPoolConfig, KmsPool, KmsKeyState, KmsConfig, Kms, JwtBearerWorkloadConfig, JWTAssertionClaims, IoniteValidators, IoniteUserExtension, IoniteErrorOptions, IoniteError, IoniteBase, Ionite, InMemoryTenantStoreOptions, IdentityResolution, IdTokenClaims, IamDeltaResourceType, IamDeltaReconcileResult, IamDeltaMode, IamDeltaIdMapStore, IamDeltaIdMapKey, IamDeltaEmitter, ION_TENANT_MANAGE, ION_SDK_PERMISSIONS, ION_SCIM_USER_EXTENSION_URN, ION_IAM_USERS_WRITE, ION_IAM_READ, ION_IAM_GROUPS_WRITE, ION_ENDPOINT_PERMISSIONS, ION_CIAM_MAGIC_LINK_CREATE, ION_CAPABILITIEZ_READ, ION_AUTHZ_OAA_SYNC, ION_AUTHZ_GROUP_SCHEMA, IAMValidators, IAMUsersInbound, IAMInboundUsersConfig, IAMInboundUserContext, IAMHandlerConfig, IAMGroupsOutbound, IAMGroupsInbound, IAMDiscoveryHandlerConfig, IAMDiscoveryContext, IAMDiscoveryConfig, IAMConfigFromCode, IAMConfig, IAMAppValidators, IAMAppRegistry, IAM, GroupsInboundHandlerConfig, GroupResource, GroupMember, Group, GcpSecretsConfig, GcpConfigLocator, FrameworkWorkloadIncomingOutgoing, FrameworkWorkloadConfigFromCode, FrameworkWorkloadConfig, FrameworkStores, FrameworkSecretsSourceConfig, FrameworkSecretsModuleConfig, FrameworkOtelConfig, FrameworkLfvConfig, FrameworkConfigInput, FrameworkConfig, EnvironmentType, EntityStore, EntitlementType, Entitlement, EnterpriseExtension, EndpointPermission, EndpointOperation, Email, EgressOutcome, EgressChannelOutcome, EffectiveEdge, EcidFormatError, ECID_SCHEME, DevSecretsConfig, DEFAULT_TENANT_UI_NAMESPACE, DEFAULT_TENANT_API_NAMESPACE, CustomerStoreOptions, CustomerStore, Customer, CreateUserOptions, CreateTenantRequest, CreateGroupOptions, ConfigSubscriptionOptions, ConfigSourceType, ConfigSourceResolver, ConfigSourceErrorInit, ConfigSourceError, ConfigSourceEnv, ConfigSource, ConfigLocator, ConfigErrorKind, ConfigChangeResult, ConfigChangeOptions, ConfigChangeCallback, ConfigApplyStatus, CodeCatalogNamespace, CodeCatalogInput, CodeCatalog, ClientCredentialsWorkloadConfig, ChangeListener, CatalogChangeListener, CatalogChangeKind, CatalogChange, CapabilityState, CapabilityKey, CapabilityEndpointUrls, CapabilitiezManifest, CachedWorkloadToken, CacheConfig, CIAMValidators, CIAMProviderType, CIAMProviderDescriptor, CIAMProviderConfig, CIAMProviderColors, CIAMProviderBranding, CIAMConfigFromCodeInput, CIAMConfigFromCode, CIAMConfig, CIAM, BaseWorkloadIdentity, BaseUser, BaseTenant, BaseCustomer, AzureSecretsConfig, AzureConfigLocator, AzureAuthMethod, AwsSecretsConfig, AwsConfigLocator, AuthzScimGroupType, AuthzScimGroupExtension, AuthzOaaConfig, AuthzEntityBase, AuthzDecision, AuthzConfig, Authz, AuthenticatedUser, AuthenticatedPrincipal, ApplicationValidators, Address, AccessStatus, AccessRef, AccessProvenance, AccessMutationStatus, AccessMutationResult, AccessIndex, AccessCheckTarget, AccessCheckResult, AccessCheckReason, AccessChange, AccessCatalogStore, AccessAssignmentStore };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{A as K0,B as C0,C as W0,D as P0,E as D0,F as k0,G as E0,H as v0,I as w0,J as S0,K as R0,L as T0,M as b0,N as L0,Q as I0,R as N0,S as y0,T as A0,U as _0,V as f0,a as r,b as t,c as s,d as e,e as Q0,f as X0,l as $0,m as J0,n as V0,o as B0,p as x0,q as Z0,r as F0,s as H0,t as q0,u as G0,v as U0,w as j0,x as Y0,y as z0,z as M0}from"./shared/core-02035cvg.js";var S="0.0.23-beta.20260803.1";class j extends Error{kind;recoverable;code;status;path;sourceType;constructor($,J){super($,J.cause!==void 0?{cause:J.cause}:void 0);this.name="ConfigSourceError",this.kind=J.kind,this.recoverable=J.recoverable,this.code=J.code,this.status=J.status,this.path=J.path,this.sourceType=J.sourceType,Object.setPrototypeOf(this,j.prototype)}}function R($){return $ instanceof j}var Z=["workload"],Y={id:"ion:iam:read",name:"Read Identities (SCIM)",description:"Authorizes a workload to list and read Users and Groups via the SCIM endpoints.",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:Z,recommendedSubjectTypes:Z},z={id:"ion:iam:users:write",name:"Manage Identities (SCIM Users)",description:"Authorizes a workload to create, replace, modify (including attribute changes), and delete Users via SCIM, including access-root revocation on user delete.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:Z,recommendedSubjectTypes:Z},M={id:"ion:iam:groups:write",name:"Manage Groups & Access (SCIM Groups)",description:"Authorizes a workload to create, replace, modify, and delete Groups via SCIM, including membership changes that grant or revoke entitlements.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:Z,recommendedSubjectTypes:Z},K={id:"ion:capabilitiez:read",name:"Read Capability Manifest",description:"Authorizes a workload to read the capability manifest at the capabilitiez endpoint (only when RemoteConfig.capabilitiez is enabled).",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:Z,recommendedSubjectTypes:Z},C={id:"ion:ciam:magic-link:create",name:"Issue CIAM Magic Links",description:"Authorizes a caller to mint customer magic-link login credentials via the magic-link endpoint. Grant narrowly.",requestable:!1,permissionTypes:["DataCreate"],assignableSubjectTypes:["workload","user"],recommendedSubjectTypes:Z},W={id:"ion:authz:oaa:sync",name:"Trigger OAA Full Sync",description:"Authorizes a workload (Ops/ECI client) to trigger a full OAA reconcile via the authz OAA sync endpoint (only when RemoteConfig.authz.oaa.fullSync.enabled is true).",requestable:!1,permissionTypes:["DataWrite"],assignableSubjectTypes:Z,recommendedSubjectTypes:Z},P={id:"ion:tenant:manage",name:"Manage Tenants",description:"Authorizes a workload (ECI/TMS client) to create, read, update, and delete tenant records via the tenant-management endpoints.",requestable:!1,permissionTypes:["DataCreate","DataRead","DataWrite","DataDelete"],assignableSubjectTypes:Z,recommendedSubjectTypes:Z},T=[Y,z,M,K,C,W,P],b={"iam.read":{permission:Y,subjectType:["workload"]},"iam.users.write":{permission:z,subjectType:["workload"]},"iam.groups.write":{permission:M,subjectType:["workload"]},"capabilitiez.read":{permission:K,subjectType:["workload"]},"ciam.magic-link.create":{permission:C,subjectType:["workload","user"]},"authz.oaa.sync":{permission:W,subjectType:["workload"]},"tenant.manage":{permission:P,subjectType:["workload"]}};var L=["sessionStore","userStore","customerStore","accessStore","tokenStore","magicLinkStore"];function D($){if($===null||typeof $!=="object")return $;let J={};for(let[Q,X]of Object.entries($)){if(L.includes(Q)||Q==="validators"||Q==="setStores")continue;J[Q]=X!==null&&typeof X==="object"&&!Array.isArray(X)&&Object.getPrototypeOf(X)===Object.prototype?D(X):X}return J}function I($){return D($)}var k={trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},N=k,y={trace:()=>{},debug:console.debug,info:console.info,warn:console.warn,error:console.error},A={trace:()=>{},debug:()=>{},info:console.info,warn:console.warn,error:console.error},_={trace:()=>{},debug:()=>{},info:()=>{},warn:console.warn,error:console.error};function f($,J){if(typeof J!=="number"||J<=0)return $;return new Promise((Q,X)=>{let B=setTimeout(()=>{X(Error(`Authz catalog entry did not become ready within ${J}ms`))},J);$.then(()=>{clearTimeout(B),Q()},(x)=>{clearTimeout(B),X(x)})})}function O($,J){let Q=!1,X,B=J.then(()=>{Q=!0},(F)=>{Q=!1,X=F}),x=$;return Object.defineProperty(x,"ready",{enumerable:!1,configurable:!0,value:(F)=>f(B.then(()=>{if(!Q)throw X}),F)}),Object.defineProperty(x,"isReady",{enumerable:!1,configurable:!0,value:()=>Q}),x}var h={beforeTenantSegments:["ui"]},p={beforeTenantSegments:["api"]};function E($){return($??[]).map((J)=>J.trim()).filter(Boolean)}function g($){let J=$.trim();if(!J)return"/";let Q=J.replace(/\\/g,"/").replace(/\/+/g,"/");return Q.startsWith("/")?Q:`/${Q}`}function v($){return g($).split("/").filter(Boolean)}function U($){return{beforeTenantSegments:E($?.beforeTenantSegments),afterTenantSegments:E($?.afterTenantSegments)}}function d($){return{type:"path",ui:U($?.ui),api:U($?.api)}}function c($,J){let Q=U(J),X=Q.beforeTenantSegments??[],B=Q.afterTenantSegments??[],x=v($),F=X.length+1+B.length;if(x.length<F)return null;for(let H=0;H<X.length;H++)if(x[H]!==X[H])return null;let q=X.length,V=x[q];if(!V)return null;for(let H=0;H<B.length;H++)if(x[q+1+H]!==B[H])return null;let G=x.slice(q+1+B.length);return{id:decodeURIComponent(V),restSegments:G,restPath:G.length>0?`/${G.join("/")}`:"/"}}function m($,J="/",Q){let X=U(Q),B=X.beforeTenantSegments??[],x=X.afterTenantSegments??[],F=v(J),q=[...B,encodeURIComponent($),...x,...F];return q.length>0?`/${q.join("/")}`:"/"}function u($){return{"~standard":{version:1,vendor:$,validate:(J)=>{if(typeof J!=="object"||J===null)return{issues:[{message:"Expected an object"}]};let Q=J,X=[],B={...Q},x=["iss","sub"];for(let V of x)if(V in Q){if(typeof Q[V]!=="string")X.push({message:`${V} must be a string`,path:[V]})}else X.push({message:`${V} is required`,path:[V]});if("aud"in Q&&Q.aud!==void 0){let V=Q.aud;if(typeof V!=="string"&&!Array.isArray(V))X.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(V)&&!V.every((G)=>typeof G==="string"))X.push({message:"aud array must contain only strings",path:["aud"]})}let F=["jti","scope"];for(let V of F)if(V in Q&&Q[V]!==void 0){if(typeof Q[V]!=="string")X.push({message:`${V} must be a string`,path:[V]})}let q=["exp","iat"];for(let V of q)if(V in Q){if(typeof Q[V]!=="number")X.push({message:`${V} must be a number`,path:[V]})}else X.push({message:`${V} is required`,path:[V]});if(X.length>0)return{issues:X};return{value:B}}}}}function l($){return{"~standard":{version:1,vendor:$,validate:(J)=>{if(typeof J!=="object"||J===null)return{issues:[{message:"Expected an object"}]};let Q=J,X=[],B={};if("access_token"in Q)if(typeof Q.access_token==="string")B.access_token=Q.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 Q)if(typeof Q.token_type==="string")B.token_type=Q.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 Q)if(typeof Q.scope==="string"||Q.scope===void 0)B.scope=Q.scope;else X.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in Q)if(typeof Q.refresh_token==="string"||Q.refresh_token===void 0)B.refresh_token=Q.refresh_token;else X.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in Q)if(typeof Q.expires==="string"||Q.expires===void 0)B.expires=Q.expires;else X.push({message:"expires must be a string",path:["expires"]});if("expires_in"in Q)if(typeof Q.expires_in==="number"||Q.expires_in===void 0)B.expires_in=Q.expires_in;else X.push({message:"expires_in must be a number",path:["expires_in"]});if(X.length>0)return{issues:X};return{value:B}}}}}function n($){let J=new Uint8Array($);return crypto.getRandomValues(J),J}function a($){let J="",Q=n($);for(let X=0;X<$;X++){let B=Q[X]%32;J+="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(B)}return J}function o($,J){let Q="";for(let X=J;X>0;X--){let B=$%32;Q="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(B)+Q,$=Math.floor($/32)}return Q}function i($){let J=Date.now(),Q=o(J,10),X=a(16);return`${$??""}${Q}${X}`}export{l as workloadTokenResponseSchema,z0 as withValidate,_ as warnLogger,v0 as waitOn,S as version,K0 as validationFailureResponse,_0 as userSchema,B0 as unionCatalogRead,r as trustedClientPermissionsForPrincipal,D0 as trimTrailingSlash,j0 as tokenResponseSchema,J0 as toCodeCatalog,W0 as stripJsonComments,E0 as stableConfigHash,k as silentLogger,I as serializeConfig,O as readyCatalogEntry,P0 as parseJsonc,q0 as parseEcid,U0 as oidcCallbackSchema,d as normalizeTenantRoutingStrategy,U as normalizeTenantPathNamespace,M0 as must,C0 as mergeConfig,c as matchTenantPath,e as listGenerator,s as list,u as jwtAssertionClaimsSchema,T0 as isStoreConflictError,F0 as isEcid,R as isConfigSourceError,L0 as isConfigLocator,$0 as isCodeCatalog,A as infoLogger,Y0 as idTokenClaimsSchema,f0 as groupResourceSchema,i as generateULID,H0 as formatEcid,V0 as defineCatalog,N as defaultLogger,k0 as deepEqualPlain,S0 as decodeUser,y as debugLogger,t as configTrustedClientGrants,w0 as claimsToUser,m as buildTenantPath,y0 as assertValidSubjectTypeScoping,G0 as assertEcid,X0 as accessRootId,Q0 as accessRefId,R0 as StoreConflictError,N0 as PLATFORM_ASSIGNABLE_SUBJECT_TYPES,b0 as IoniteError,P as ION_TENANT_MANAGE,T as ION_SDK_PERMISSIONS,A0 as ION_SCIM_USER_EXTENSION_URN,z as ION_IAM_USERS_WRITE,Y as ION_IAM_READ,M as ION_IAM_GROUPS_WRITE,b as ION_ENDPOINT_PERMISSIONS,C as ION_CIAM_MAGIC_LINK_CREATE,K as ION_CAPABILITIEZ_READ,W as ION_AUTHZ_OAA_SYNC,I0 as ION_AUTHZ_GROUP_SCHEMA,Z0 as EcidFormatError,x0 as ECID_SCHEME,h as DEFAULT_TENANT_UI_NAMESPACE,p as DEFAULT_TENANT_API_NAMESPACE,j as ConfigSourceError};
1
+ import{A as P0,B as D0,C as E0,D as S0,E as R0,F as b0,G as w0,H as T0,I as L0,J as I0,K as N0,L as k0,M as A0,N as _0,Q as v0,R as f0,S as O0,T as y0,U as h0,V as g0,a as e,b as Q0,c as X0,d as $0,e as J0,f as V0,l as B0,m as Z0,n as F0,o as H0,p as G0,q as q0,r as U0,s as j0,t as x0,u as Y0,v as z0,w as M0,x as K0,y as C0,z as W0}from"./shared/core-f0gk15rd.js";var L="0.0.23-beta.20260809.2";class x extends Error{kind;recoverable;code;status;path;sourceType;constructor($,X){super($,X.cause!==void 0?{cause:X.cause}:void 0);this.name="ConfigSourceError",this.kind=X.kind,this.recoverable=X.recoverable,this.code=X.code,this.status=X.status,this.path=X.path,this.sourceType=X.sourceType,Object.setPrototypeOf(this,x.prototype)}}function I($){return $ instanceof x}var G=["workload"],Y={id:"ion:iam:read",name:"Read Identities (SCIM)",description:"Authorizes a workload to list and read Users and Groups via the SCIM endpoints.",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:G,recommendedSubjectTypes:G},z={id:"ion:iam:users:write",name:"Manage Identities (SCIM Users)",description:"Authorizes a workload to create, replace, modify (including attribute changes), and delete Users via SCIM, including access-root revocation on user delete.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:G,recommendedSubjectTypes:G},M={id:"ion:iam:groups:write",name:"Manage Groups & Access (SCIM Groups)",description:"Authorizes a workload to create, replace, modify, and delete Groups via SCIM, including membership changes that grant or revoke entitlements.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:G,recommendedSubjectTypes:G},K={id:"ion:capabilitiez:read",name:"Read Capability Manifest",description:"Authorizes a workload to read the capability manifest at the capabilitiez endpoint (only when RemoteConfig.capabilitiez is enabled).",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:G,recommendedSubjectTypes:G},C={id:"ion:ciam:magic-link:create",name:"Issue CIAM Magic Links",description:"Authorizes a caller to mint customer magic-link login credentials via the magic-link endpoint. Grant narrowly.",requestable:!1,permissionTypes:["DataCreate"],assignableSubjectTypes:["workload","user"],recommendedSubjectTypes:G},W={id:"ion:authz:oaa:sync",name:"Trigger OAA Full Sync",description:"Authorizes a workload (Ops/ECI client) to trigger a full OAA reconcile via the authz OAA sync endpoint (only when RemoteConfig.authz.oaa.fullSync.enabled is true).",requestable:!1,permissionTypes:["DataWrite"],assignableSubjectTypes:G,recommendedSubjectTypes:G},P={id:"ion:tenant:manage",name:"Manage Tenants",description:"Authorizes a workload (ECI/TMS client) to create, read, update, and delete tenant records via the tenant-management endpoints.",requestable:!1,permissionTypes:["DataCreate","DataRead","DataWrite","DataDelete"],assignableSubjectTypes:G,recommendedSubjectTypes:G},N=[Y,z,M,K,C,W,P],k={"iam.read":{permission:Y,subjectType:["workload"]},"iam.users.write":{permission:z,subjectType:["workload"]},"iam.groups.write":{permission:M,subjectType:["workload"]},"capabilitiez.read":{permission:K,subjectType:["workload"]},"ciam.magic-link.create":{permission:C,subjectType:["workload","user"]},"authz.oaa.sync":{permission:W,subjectType:["workload"]},"tenant.manage":{permission:P,subjectType:["workload"]}};var A=["sessionStore","userStore","customerStore","accessStore","tokenStore","magicLinkStore"];function D($){if($===null||typeof $!=="object")return $;let X={};for(let[Q,J]of Object.entries($)){if(A.includes(Q)||Q==="validators"||Q==="setStores")continue;X[Q]=J!==null&&typeof J==="object"&&!Array.isArray(J)&&Object.getPrototypeOf(J)===Object.prototype?D(J):J}return X}function _($){return D($)}function E($,X){if(!$||typeof $!=="object"||Array.isArray($))throw Error(`${X} must be an object.`);return $}function S($,X){if($===void 0)return;if(typeof $!=="string"||$.length===0||!Number.isFinite(Date.parse($)))throw Error(`${X} must be a valid timestamp string.`);return $}function v($){let X=E($,"KMS token pool");if(X.kind!=="token")throw Error('KMS token pool kind must be "token".');if(typeof X.active!=="string"||X.active.length===0)throw Error("KMS token pool active must be a non-empty key id.");if(!Array.isArray(X.keys)||X.keys.length===0)throw Error("KMS token pool keys must be a non-empty array.");let Q=new Set,J=X.keys.map((F,H)=>{let Z=E(F,`KMS token pool keys[${H}]`);if(typeof Z.id!=="string"||Z.id.length===0)throw Error(`KMS token pool keys[${H}].id must be a non-empty string.`);if(Q.has(Z.id))throw Error(`KMS token pool contains duplicate key id "${Z.id}".`);if(Q.add(Z.id),!["pending","active","deprecated","revoked"].includes(String(Z.state)))throw Error(`KMS token pool keys[${H}].state is invalid.`);if(Z.value!==void 0&&(typeof Z.value!=="string"||Z.value.length===0))throw Error(`KMS token pool keys[${H}].value must be a non-empty string when present.`);return{id:Z.id,state:Z.state,...Z.value===void 0?{}:{value:Z.value},...Z.notBefore===void 0?{}:{notBefore:S(Z.notBefore,`KMS token pool keys[${H}].notBefore`)},...Z.notAfter===void 0?{}:{notAfter:S(Z.notAfter,`KMS token pool keys[${H}].notAfter`)}}}),V=J.find((F)=>F.id===X.active);if(!V)throw Error(`KMS token pool active key "${X.active}" is not present in keys.`);if(V.state!=="active")throw Error(`KMS token pool active key "${X.active}" must have state "active".`);if(!V.value)throw Error(`KMS token pool active key "${X.active}" must include a value.`);return{kind:"token",active:X.active,keys:J}}var R={trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},f=R,O={trace:()=>{},debug:console.debug,info:console.info,warn:console.warn,error:console.error},y={trace:()=>{},debug:()=>{},info:console.info,warn:console.warn,error:console.error},h={trace:()=>{},debug:()=>{},info:()=>{},warn:console.warn,error:console.error};function g($,X){if(typeof X!=="number"||X<=0)return $;return new Promise((Q,J)=>{let V=setTimeout(()=>{J(Error(`Authz catalog entry did not become ready within ${X}ms`))},X);$.then(()=>{clearTimeout(V),Q()},(F)=>{clearTimeout(V),J(F)})})}function p($,X){let Q=!1,J,V=X.then(()=>{Q=!0},(H)=>{Q=!1,J=H}),F=$;return Object.defineProperty(F,"ready",{enumerable:!1,configurable:!0,value:(H)=>g(V.then(()=>{if(!Q)throw J}),H)}),Object.defineProperty(F,"isReady",{enumerable:!1,configurable:!0,value:()=>Q}),F}var d={beforeTenantSegments:["ui"]},c={beforeTenantSegments:["api"]};function b($){return($??[]).map((X)=>X.trim()).filter(Boolean)}function m($){let X=$.trim();if(!X)return"/";let Q=X.replace(/\\/g,"/").replace(/\/+/g,"/");return Q.startsWith("/")?Q:`/${Q}`}function w($){return m($).split("/").filter(Boolean)}function j($){return{beforeTenantSegments:b($?.beforeTenantSegments),afterTenantSegments:b($?.afterTenantSegments)}}function u($){return{type:"path",ui:j($?.ui),api:j($?.api)}}function l($,X){let Q=j(X),J=Q.beforeTenantSegments??[],V=Q.afterTenantSegments??[],F=w($),H=J.length+1+V.length;if(F.length<H)return null;for(let q=0;q<J.length;q++)if(F[q]!==J[q])return null;let Z=J.length,B=F[Z];if(!B)return null;for(let q=0;q<V.length;q++)if(F[Z+1+q]!==V[q])return null;let U=F.slice(Z+1+V.length);return{id:decodeURIComponent(B),restSegments:U,restPath:U.length>0?`/${U.join("/")}`:"/"}}function n($,X="/",Q){let J=j(Q),V=J.beforeTenantSegments??[],F=J.afterTenantSegments??[],H=w(X),Z=[...V,encodeURIComponent($),...F,...H];return Z.length>0?`/${Z.join("/")}`:"/"}function a($){return{"~standard":{version:1,vendor:$,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,J=[],V={...Q},F=["iss","sub"];for(let B of F)if(B in Q){if(typeof Q[B]!=="string")J.push({message:`${B} must be a string`,path:[B]})}else J.push({message:`${B} is required`,path:[B]});if("aud"in Q&&Q.aud!==void 0){let B=Q.aud;if(typeof B!=="string"&&!Array.isArray(B))J.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(B)&&!B.every((U)=>typeof U==="string"))J.push({message:"aud array must contain only strings",path:["aud"]})}let H=["jti","scope"];for(let B of H)if(B in Q&&Q[B]!==void 0){if(typeof Q[B]!=="string")J.push({message:`${B} must be a string`,path:[B]})}let Z=["exp","iat"];for(let B of Z)if(B in Q){if(typeof Q[B]!=="number")J.push({message:`${B} must be a number`,path:[B]})}else J.push({message:`${B} is required`,path:[B]});if(J.length>0)return{issues:J};return{value:V}}}}}function i($){return{"~standard":{version:1,vendor:$,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,J=[],V={};if("access_token"in Q)if(typeof Q.access_token==="string")V.access_token=Q.access_token;else J.push({message:"access_token must be a string",path:["access_token"]});else J.push({message:"access_token is required",path:["access_token"]});if("token_type"in Q)if(typeof Q.token_type==="string")V.token_type=Q.token_type;else J.push({message:"token_type must be a string",path:["token_type"]});else J.push({message:"token_type is required",path:["token_type"]});if("scope"in Q)if(typeof Q.scope==="string"||Q.scope===void 0)V.scope=Q.scope;else J.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in Q)if(typeof Q.refresh_token==="string"||Q.refresh_token===void 0)V.refresh_token=Q.refresh_token;else J.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in Q)if(typeof Q.expires==="string"||Q.expires===void 0)V.expires=Q.expires;else J.push({message:"expires must be a string",path:["expires"]});if("expires_in"in Q)if(typeof Q.expires_in==="number"||Q.expires_in===void 0)V.expires_in=Q.expires_in;else J.push({message:"expires_in must be a number",path:["expires_in"]});if(J.length>0)return{issues:J};return{value:V}}}}}function r($){let X=new Uint8Array($);return crypto.getRandomValues(X),X}function o($){let X="",Q=r($);for(let J=0;J<$;J++){let V=Q[J]%32;X+="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(V)}return X}function t($,X){let Q="";for(let J=X;J>0;J--){let V=$%32;Q="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(V)+Q,$=Math.floor($/32)}return Q}function s($){let X=Date.now(),Q=t(X,10),J=o(16);return`${$??""}${Q}${J}`}export{i as workloadTokenResponseSchema,C0 as withValidate,h as warnLogger,T0 as waitOn,L as version,P0 as validationFailureResponse,h0 as userSchema,H0 as unionCatalogRead,e as trustedClientPermissionsForPrincipal,R0 as trimTrailingSlash,M0 as tokenResponseSchema,Z0 as toCodeCatalog,E0 as stripJsonComments,w0 as stableConfigHash,R as silentLogger,_ as serializeConfig,p as readyCatalogEntry,v as parseKmsTokenPool,S0 as parseJsonc,x0 as parseEcid,z0 as oidcCallbackSchema,u as normalizeTenantRoutingStrategy,j as normalizeTenantPathNamespace,W0 as must,D0 as mergeConfig,l as matchTenantPath,$0 as listGenerator,X0 as list,a as jwtAssertionClaimsSchema,k0 as isStoreConflictError,U0 as isEcid,I as isConfigSourceError,_0 as isConfigLocator,B0 as isCodeCatalog,y as infoLogger,K0 as idTokenClaimsSchema,g0 as groupResourceSchema,s as generateULID,j0 as formatEcid,F0 as defineCatalog,f as defaultLogger,b0 as deepEqualPlain,I0 as decodeUser,O as debugLogger,Q0 as configTrustedClientGrants,L0 as claimsToUser,n as buildTenantPath,O0 as assertValidSubjectTypeScoping,Y0 as assertEcid,V0 as accessRootId,J0 as accessRefId,N0 as StoreConflictError,f0 as PLATFORM_ASSIGNABLE_SUBJECT_TYPES,A0 as IoniteError,P as ION_TENANT_MANAGE,N as ION_SDK_PERMISSIONS,y0 as ION_SCIM_USER_EXTENSION_URN,z as ION_IAM_USERS_WRITE,Y as ION_IAM_READ,M as ION_IAM_GROUPS_WRITE,k as ION_ENDPOINT_PERMISSIONS,C as ION_CIAM_MAGIC_LINK_CREATE,K as ION_CAPABILITIEZ_READ,W as ION_AUTHZ_OAA_SYNC,v0 as ION_AUTHZ_GROUP_SCHEMA,q0 as EcidFormatError,G0 as ECID_SCHEME,d as DEFAULT_TENANT_UI_NAMESPACE,c as DEFAULT_TENANT_API_NAMESPACE,x as ConfigSourceError};
package/dist/server.d.ts CHANGED
@@ -1057,7 +1057,7 @@ type ModuleReadiness = {
1057
1057
  * block. Apps that DO treat delta as a hard dependency can gate on `ion.iam.delta.isReady()` /
1058
1058
  * `ion.iam.delta.ready()` explicitly instead.
1059
1059
  */
1060
- type ModuleName = "sso" | "ciam" | "iam" | "workload" | "otel" | "secrets" | "authz";
1060
+ type ModuleName = "sso" | "ciam" | "iam" | "workload" | "otel" | "secrets" | "kms" | "authz";
1061
1061
  /** Per-module readiness snapshot in {@link ReadinessReport}. */
1062
1062
  type ModuleReadinessState = {
1063
1063
  /** Whether the module is active (present/requested) in the effective config. Inactive modules never block readiness. */
@@ -1982,7 +1982,48 @@ type IAM = IAMConfig & {
1982
1982
  * @param workload - Workload instance for authentication
1983
1983
  * @returns IAM service instance
1984
1984
  */
1985
- declare function iam(validators: IAMValidators, log: Logger, workload: Workload | undefined, authz: Authz, accessStore?: AccessAssignmentStore, accessIndex?: AccessIndex, catalogStore?: AccessCatalogStore, codeCatalog?: CodeCatalog, resources?: ResourceProvider, fromVault?: Partial<IAMConfig>, fromCode?: Partial<IAMConfig>, iamDelta?: IamDeltaEmitter, onAccessMutation?: (summary: ScimMutationSummary) => void, trustedClientGrants?: AccessChange[]): IAM | undefined;
1985
+ declare function iam(validators: IAMValidators, log: Logger, workload: Workload | undefined, authz: Authz, accessStore?: AccessAssignmentStore, accessIndex?: AccessIndex, catalogStore?: AccessCatalogStore, codeCatalog?: CodeCatalog, resources?: ResourceProvider, fromVault?: Partial<IAMConfig>, fromCode?: Partial<IAMConfig>, iamDelta?: IamDeltaEmitter, onAccessMutation?: (summary: ScimMutationSummary) => void, trustedClientGrants?: AccessChange[], authzQueueSettle?: () => Promise<void>): IAM | undefined;
1986
+ type KmsKeyState = "pending" | "active" | "deprecated" | "revoked";
1987
+ type KmsTokenKey = {
1988
+ id: string;
1989
+ state: KmsKeyState;
1990
+ value?: string;
1991
+ notBefore?: string;
1992
+ notAfter?: string;
1993
+ };
1994
+ /** ConfigSource-owned pointer to a token-pool document. */
1995
+ type KmsPoolConfig = {
1996
+ /** Named `ion.secrets` source. Omit to use the default `ion.secret` source. */
1997
+ source?: string;
1998
+ /** Secret path. Defaults to `/kms/{poolName}`. */
1999
+ path?: string;
2000
+ };
2001
+ /** ConfigSource-owned named token-pool declarations. */
2002
+ type KmsConfig = Record<string, KmsPoolConfig>;
2003
+ type KmsPoolListener = (current: KmsTokenKey | undefined) => void;
2004
+ type KmsPool = {
2005
+ /** Returns the usable active token metadata and value. Throws while the pool is not ready. */
2006
+ current(): KmsTokenKey;
2007
+ /** Returns keys accepted during the current overlap window (active plus usable deprecated keys). */
2008
+ valid(): KmsTokenKey[];
2009
+ /** Notifies immediately and whenever the selected active token changes. */
2010
+ subscribe(listener: KmsPoolListener): () => void;
2011
+ beforeChange(listener: ChangeListener): () => void;
2012
+ afterChange(listener: ChangeListener): () => void;
2013
+ isReady(): boolean;
2014
+ ready(timeout?: number): Promise<void>;
2015
+ };
2016
+ /**
2017
+ * Aggregate KMS module. Named pool handles are also installed as runtime properties
2018
+ * (`ion.kms.<name>`); use `getPool(name)` when the name is dynamic.
2019
+ */
2020
+ type Kms = ModuleReadiness & {
2021
+ readonly config: Readonly<KmsConfig>;
2022
+ listPools(): string[];
2023
+ getPool(name: string): KmsPool;
2024
+ currentToken(name: string): string;
2025
+ validTokens(name: string): KmsTokenKey[];
2026
+ };
1986
2027
  type OtelProtocol = "http/protobuf" | "http/json";
1987
2028
  type OtelProviderType = "otlp" | "grafana-lgtm" | "datadog" | "splunk" | "elastic";
1988
2029
  type OtelLogLevel = "trace" | "debug" | "info" | "warn" | "error";
@@ -2019,6 +2060,8 @@ type OtelConfig = {
2019
2060
  protocol?: OtelProtocol;
2020
2061
  headers?: Record<string, string>;
2021
2062
  apiKey?: string;
2063
+ /** Name of a `RemoteConfig.kms` token pool used for exporter authentication. */
2064
+ apiKeyPool?: string;
2022
2065
  apiKeyHeader?: string;
2023
2066
  oauth?: OtelOAuthClientCredentialsConfig;
2024
2067
  version?: string;
@@ -2771,6 +2814,15 @@ type SecretLifecycleRequest = {
2771
2814
  severity?: SecretRequestSeverity;
2772
2815
  incidentRef?: string;
2773
2816
  };
2817
+ type SecretEventName = "rotate_requested" | "revoke_requested" | "created" | "updated" | "deleted" | "rotated" | "revoked" | "removed" | "acl_updated" | "path_removed" | "lease_expiring_soon" | "lease_revoked" | (string & {});
2818
+ type SecretEvent = {
2819
+ path: string;
2820
+ event: SecretEventName;
2821
+ requestId?: string;
2822
+ issuedAt?: string | number;
2823
+ expiresAt?: string | number;
2824
+ };
2825
+ type SecretEventListener = (event: SecretEvent) => void;
2774
2826
  type SecretsOperationOptions = {
2775
2827
  /** Optional timeout in milliseconds for this secrets operation. */
2776
2828
  timeout?: number;
@@ -2801,6 +2853,8 @@ type SecretsSource = ReactiveHandle & ModuleReadiness & {
2801
2853
  * @returns a unsubscribe/cleanup function.
2802
2854
  */
2803
2855
  subscribe<T>(path: string, onChange: (fullSecret: Secret<T>) => void, options?: SecretsSubscriptionOptions): Promise<() => void>;
2856
+ /** Optional lifecycle-event stream (LFV events endpoint and equivalent reactive sources). */
2857
+ subscribeEvents?(listener: SecretEventListener): () => void;
2804
2858
  /**
2805
2859
  * Deletes a secret at the given path.
2806
2860
  */
@@ -3219,6 +3273,8 @@ type RemoteConfig = {
3219
3273
  workload?: WorkloadConfig | WorkloadConfigMap | WorkloadIncomingOutgoing;
3220
3274
  /** Optional named secrets-source configs available to this App instance. */
3221
3275
  secrets?: SecretsModuleConfig;
3276
+ /** ConfigSource-owned named managed token pools consumed through `ion.kms`. */
3277
+ kms?: KmsConfig;
3222
3278
  ciam?: CIAMConfig;
3223
3279
  /** OpenTelemetry collector/exporter config loaded from ConfigSource. */
3224
3280
  otel?: OtelConfig;
@@ -3608,6 +3664,7 @@ type IoniteBase = {
3608
3664
  /** Default config-source-backed secret client, typically the vault used for RemoteConfig. */
3609
3665
  secret: SecretsSource;
3610
3666
  secrets?: Secrets;
3667
+ kms?: Kms;
3611
3668
  sso?: SSO;
3612
3669
  iam?: IAM;
3613
3670
  workload?: Workload | AggregateWorkload;
@@ -4316,6 +4373,13 @@ interface AccessIndex {
4316
4373
  hasAll(subject: AccessRef<BaseUser>, targets: AccessCheckTarget[], subjectType?: SubjectType): Promise<AuthzDecision>;
4317
4374
  /** Replace the index rows attributed to `rootId` with `edges` (set-based materialization). */
4318
4375
  materialize(rootId: string, edges: EffectiveEdge[]): Promise<void>;
4376
+ /**
4377
+ * Atomically replace every effective edge for one subject with the complete freshly-expanded
4378
+ * closure. Implementations MUST expose either the previous closure or the replacement to concurrent
4379
+ * readers, never an intermediate empty/partial state. Expansion is completed before this call, so a
4380
+ * failed reconcile preserves the last-known-good closure.
4381
+ */
4382
+ replaceSubject(subject: string, subjectType: SubjectType, edges: EffectiveEdge[]): Promise<void>;
4319
4383
  /** Remove all index rows attributed to `rootId`. */
4320
4384
  removeByRoot(rootId: string): Promise<void>;
4321
4385
  /** Clear all index rows, or only those for a single subject (optionally scoped to a `subjectType`). */
@@ -4524,15 +4588,6 @@ type Authz = {
4524
4588
  * is wired. Always run it off the request path.
4525
4589
  */
4526
4590
  reconcile(): Promise<ReconcileReport>;
4527
- /**
4528
- * Resolve once the internal reconcile queue is drained (every catalog-/resource-change reconcile
4529
- * enqueued so far has finished). Those reconciles are serialized and coalescing (a queued full
4530
- * reconcile absorbs later ones); `settle()` returns the current queue tail so a caller can guarantee
4531
- * request-triggered reconciles complete inside the request lifecycle (serverless-safe — no detached
4532
- * reconcile survives the response). The SCIM mutation path awaits this after its store writes. It
4533
- * never rejects (queued reconcile failures are isolated and logged).
4534
- */
4535
- settle(): Promise<void>;
4536
4591
  };
4537
4592
  /** Why an {@link AccessCheckResult} resolved the way it did. */
4538
4593
  type AccessCheckReason = "ok" | "unauthenticated" | "forbidden" | "not_configured";
@@ -4675,11 +4730,11 @@ type ReconcileStores = {
4675
4730
  resources?: ResourceProvider;
4676
4731
  };
4677
4732
  /**
4678
- * SDK-internal targeted reconcile of a single subject's derived access: clear the subject's
4679
- * {@link AccessIndex} rows, then re-expand and re-materialize its live {@link AccessAssignmentStore}
4680
- * roots through the catalog. One pass handles both adds and removes and bounds any deny window to this
4681
- * subject; a subject with no live roots is left cleared (its orphan rows swept). Returns the number of
4682
- * roots re-materialized.
4733
+ * SDK-internal targeted reconcile of a single subject's derived access: fully expand its live
4734
+ * {@link AccessAssignmentStore} roots, then atomically replace the subject's {@link AccessIndex}
4735
+ * closure. Readers observe the previous complete closure until the replacement commits; expansion or
4736
+ * replacement failure preserves last-known-good access. A subject with no live roots is atomically
4737
+ * replaced with an empty closure (orphan sweep). Returns the number of roots re-materialized.
4683
4738
  *
4684
4739
  * This is the shared engine behind the SDK's automatic reconciliation (catalog `afterChange` and
4685
4740
  * repair of a partially-applied SCIM mutation). It is NOT part of the public app-facing surface —
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import{A as s9,E as z1,I as o9,K as L9,L as $9,O as a4,P as t4,Q as Y5,R as X9,T as I5,a as D9,d as l9,e as V5,f as W1,g as G1,h as Y9,i as B9,j as W9,k as n4,o as G9,u as A1,v as U9,w as k9,x as D1,y as c5,z as m}from"./shared/core-02035cvg.js";var J2="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",M9=["user","customer","workload"],Z2={user:async(J,Z)=>Z.sso?.getUser(J),customer:async(J,Z)=>Z.ciam?.getCustomer(J),workload:async(J,Z)=>{let $=await Z.workload?.getWorkloadIdentity?.(J);if(!$)return;let X=$.clientId??$.workloadId??$.claims.sub;return X?{...$,id:X}:void 0}};function $2(J){if(J==="any")return M9;let Z=Array.isArray(J)?J:[J];return M9.filter(($)=>Z.includes($))}function X2(J){let Z=J.headers.get("cookie");if(!Z)return[];return Z.split(";").map(($)=>$.slice(0,$.indexOf("=")===-1?$.length:$.indexOf("=")).trim()).filter(Boolean)}function Q2(J,Z){let $=J.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,X=X2(J),Q=new Set;for(let F of X){if(F.startsWith("ion.sso"))Q.add("user");if(F.startsWith("ion.ciam"))Q.add("customer")}let G=X.length>0&&!Q.has("user")&&!Q.has("customer");return Z.filter((F)=>{if(F==="workload")return $;if(X.length===0)return!1;return Q.has(F)||G})}function X5(J){return typeof J==="string"?J:J.id}function _9(J){let{subject:Z,subjectType:$}=J,X;if($==="user")X=Z.sso?.scope;else if($==="customer")X=Z.ciam?.scope;else if($==="workload")X=Z.scope;return new Set((X??"").split(/\s+/).filter(Boolean))}function b1(J,Z,$){let X=_9(J),Q=Z.filter((F)=>X.has(F));return{allow:$==="any"?Q.length>0:Z.length>0&&Q.length===Z.length,metadata:{reason:"scope",wantedScopes:Z,matchedScopes:Q}}}function l5(J,Z){return($)=>{if(J.length===0)return;let X=_9($),Q=J.filter((F)=>X.has(F));return(Z==="any"?Q.length>0:Q.length===J.length)?Q:void 0}}function H1(J,Z,$){return(X)=>{if(Z.length===0||X.subjectType!=="workload")return;let Q=D9(J.config?.authz,X.subject);if(!Q)return;let G=Z.filter((B)=>Q.has(B));return($==="any"?G.length>0:G.length===Z.length)?G:void 0}}function K2(J,Z){if(J.subjectType==="workload"){let $=J.subject.scopesAsEntitlements;if(typeof $==="boolean")return $}return Z.config?.authz?.scopesAsEntitlements===!0}function y1(J,Z,$,X,Q){return{allow:$==="ok",subject:Z?.subject,subjectType:Z?.subjectType,reason:$,decision:X,response(){if($==="ok")return new Response(null,{status:204});if($==="unauthenticated")return J.log.warn("authz.denied",{reason:$,...Q()}),Response.json({error:"Unauthorized"},{status:401});if($==="not_configured")return J.log.warn("authz.denied",{reason:$,subject:Z?.subject?.id,subjectType:Z?.subjectType,...Q()}),Response.json({error:"not_configured"},{status:503});return J.log.warn("authz.denied",{reason:$,subject:Z?.subject?.id,subjectType:Z?.subjectType,...Q()}),Response.json({error:"Forbidden"},{status:403})}}}function Y2(J,Z,$){return new Promise((X)=>{let Q=[],G=J.length,F=!1,B=()=>{if(G-=1,G===0&&!F)F=!0,X({outcomes:Q})};for(let W of J)Z(W).then((L)=>{if(Q.push({principal:W,decision:L}),!F&&L.allow){F=!0,X({matched:{principal:W,decision:L},outcomes:Q});return}B()},(L)=>{$?.(W,L),Q.push({principal:W,decision:{allow:!1,metadata:{reason:"error"}}}),B()})})}async function A5(J,Z,$,X,Q,G,F){m(Z,J2);let B=Q2(J,$2($)),L=(await Promise.all(B.map(async(c)=>{let l=await Z2[c](J,Z);return l?.id?{subject:l,subjectType:c,subjectId:l.id}:void 0}))).filter((c)=>c!==void 0);if(L.length===0)return y1(Z,void 0,"unauthenticated",void 0,Q);let f=async(c)=>{let l=Z.authz.accessIndex;if(!l?.isSubjectDisabled)return!1;return l.isSubjectDisabled(c.subjectId,c.subjectType)},u=async(c)=>{if(F){let l=F(c);if(l&&l.length>0){if(await f(c))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:l}}}}if(G&&K2(c,Z)){let l=G(c);if(l&&l.length>0){if(await f(c))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:l}}}}return X(c)},{matched:t,outcomes:J5}=await Y2(L,u,(c,l)=>{Z.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:c.subjectId,subjectType:c.subjectType,error:l instanceof Error?l.message:String(l),...Q()})});if(t){if(t.decision.metadata?.reason==="scope")Z.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:t.principal.subjectId,subjectType:t.principal.subjectType,matchedScopes:t.decision.metadata.matchedScopes,...Q()});return y1(Z,t.principal,"ok",t.decision,Q)}let r=J5.length>0&&J5.every((c)=>{let l=c.decision.metadata?.reason;return l==="access_index_not_configured"||l==="error"}),G5=J5[0],p=r?"not_configured":"forbidden";return y1(Z,G5?.principal,p,G5?.decision,Q)}async function B2(J,Z,$,X,Q,G="any"){return A5(J,Z,G,(F)=>Z.authz.has(F.subjectId,$,X,Q,F.subjectType),()=>({targetType:$,target:X5(X),resource:Q?X5(Q):void 0}),Q?void 0:l5([X5(X)],"any"),$==="permission"&&!Q?H1(Z,[X5(X)],"any"):void 0)}async function W2(J,Z,$,X,Q="any"){return A5(J,Z,Q,(G)=>Z.authz.hasPermission(G.subjectId,$,X,G.subjectType),()=>({targetType:"permission",target:X5($),resource:X?X5(X):void 0}),X?void 0:l5([X5($)],"any"),X?void 0:H1(Z,[X5($)],"any"))}async function G2(J,Z,$,X,Q="any"){return A5(J,Z,Q,(G)=>Z.authz.hasRole(G.subjectId,$,X,G.subjectType),()=>({targetType:"role",target:X5($),resource:X?X5(X):void 0}),X?void 0:l5([X5($)],"any"))}async function L2(J,Z,$,X,Q="any"){return A5(J,Z,Q,(G)=>Z.authz.hasGroup(G.subjectId,$,X,G.subjectType),()=>({targetType:"group",target:X5($),resource:X?X5(X):void 0}),X?void 0:l5([X5($)],"any"))}async function F2(J,Z,$,X="any"){let Q=$.filter((F)=>!F.resource).map((F)=>X5(F.target)),G=$.filter((F)=>!F.resource&&F.targetType==="permission").map((F)=>X5(F.target));return A5(J,Z,X,(F)=>Z.authz.hasAny(F.subjectId,$,F.subjectType),()=>({targets:$.map((F)=>`${F.targetType}:${X5(F.target)}`)}),Q.length>0?l5(Q,"any"):void 0,G.length>0?H1(Z,G,"any"):void 0)}async function H2(J,Z,$,X="any"){let Q=$.length>0&&$.every((B)=>!B.resource),G=$.length>0&&$.every((B)=>!B.resource&&B.targetType==="permission"),F=$.map((B)=>X5(B.target));return A5(J,Z,X,(B)=>Z.authz.hasAll(B.subjectId,$,B.subjectType),()=>({targets:$.map((B)=>`${B.targetType}:${X5(B.target)}`)}),Q?l5(F,"all"):void 0,G?H1(Z,F,"all"):void 0)}async function V2(J,Z,$,X="any"){return A5(J,Z,X,(Q)=>Promise.resolve(b1(Q,[$],"any")),()=>({scope:$}))}async function N2(J,Z,$,X="any"){return A5(J,Z,X,(Q)=>Promise.resolve(b1(Q,$,"any")),()=>({scopes:$}))}async function M2(J,Z,$,X="any"){return A5(J,Z,X,(Q)=>Promise.resolve(b1(Q,$,"all")),()=>({scopes:$}))}function Q5(J){return typeof J==="string"&&J.length>0?J:void 0}function z9(J){let Z=Q5(J.email);return{sub:String(J.sub??""),email:Z,name:Q5(J.name),userName:Q5(J.preferred_username)??Z,avatar:Q5(J.picture)}}var P9={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:z9},google:{flow:"id_token",authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",jwksUri:"https://www.googleapis.com/oauth2/v3/certs",scope:"openid email profile",branding:{displayName:"Google",iconUrl:"https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg",colors:{light:"#ffffff",dark:"#131314",secondary:"#4285F4"},url:"https://accounts.google.com"},mapClaims:z9},microsoft:{flow:"id_token",authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",jwksUri:"https://login.microsoftonline.com/common/discovery/v2.0/keys",scope:"openid email profile",branding:{displayName:"Microsoft",colors:{light:"#ffffff",dark:"#2f2f2f",secondary:"#0067b8"},url:"https://login.microsoftonline.com"},mapClaims:(J)=>{let Z=Q5(J.email)??Q5(J.preferred_username);return{sub:String(J.sub??J.oid??""),email:Z,name:Q5(J.name),userName:Q5(J.preferred_username)??Z,avatar:Q5(J.picture)}}},apple:{flow:"id_token",authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",jwksUri:"https://appleid.apple.com/auth/keys",scope:"openid email name",extraAuthParams:{response_mode:"form_post"},branding:{displayName:"Apple",colors:{light:"#000000",dark:"#ffffff"},url:"https://appleid.apple.com"},mapClaims:(J)=>{let Z=Q5(J.email);return{sub:String(J.sub??""),email:Z,name:Q5(J.name),userName:Z}}},github:{flow:"userinfo",authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",scope:"read:user user:email",branding:{displayName:"GitHub",colors:{light:"#24292f",dark:"#ffffff"},url:"https://github.com"},mapClaims:(J)=>({sub:String(J.id??J.node_id??""),email:Q5(J.email),name:Q5(J.name)??Q5(J.login),userName:Q5(J.login),avatar:Q5(J.avatar_url)})}};function q1(J){if(J==="magic-link")return;return P9[J]}function V1(J,Z){if(Z.type==="magic-link")return;let $=q1(Z.type);if(!$)return;return{name:J,type:Z.type,flow:$.flow,authorizationUrl:Z.authorizationUrl??$.authorizationUrl,tokenUrl:Z.tokenUrl??$.tokenUrl,jwksUri:Z.jwksUri??$.jwksUri,userInfoUrl:Z.userInfoUrl??$.userInfoUrl,scope:Z.scope??$.scope,clientId:Z.clientId,clientSecret:Z.clientSecret,extraAuthParams:$.extraAuthParams,branding:{...$.branding,...Z.branding},mapClaims:$.mapClaims,config:Z}}function C1(J){return{...q1(J.type)?.branding??{displayName:J.type},...J.branding}}function v1(J){if(!J)return[];return Object.entries(J).filter(([,Z])=>Z.enabled!==!1).map(([Z,$],X)=>({name:Z,config:$,index:X})).sort((Z,$)=>{let X=Z.config.order??Number.MAX_SAFE_INTEGER,Q=$.config.order??Number.MAX_SAFE_INTEGER;if(X!==Q)return X-Q;return Z.index-$.index}).map(({name:Z,config:$})=>({name:Z,config:$}))}var E9=600000,k1=256,W5=new Map;function D2(J){if(typeof J?.ttlMs==="number"&&Number.isFinite(J.ttlMs))E9=Math.min(Math.max(J.ttlMs,60000),86400000);if(typeof J?.maxEntries==="number"&&Number.isFinite(J.maxEntries)){k1=Math.max(1,Math.floor(J.maxEntries));while(W5.size>k1){let Z=W5.keys().next().value;if(Z===void 0)break;W5.delete(Z)}}}function O9(J,Z){W5.delete(J),W5.set(J,Z);while(W5.size>k1){let $=W5.keys().next().value;if($===void 0)break;W5.delete($)}}var o5=new Map,f1=()=>Date.now();function _2(J){f1=J??(()=>Date.now())}var h1={};function z2(J){h1=J??{}}function P2(J){if(!J)return;if(/\bno-store\b/i.test(J))return 60000;let Z=/max-age\s*=\s*(\d+)/i.exec(J);if(!Z)return;let $=Number(Z[1]);return Number.isFinite($)?$*1000:void 0}function O2(J){let $=P2(J)??E9;return Math.min(Math.max($,60000),86400000)}async function g1(J,Z=3,$=1000,X=30000,Q){let G=Error("Placeholder Error");for(let F=0;F<=Z;F++)try{return await J()}catch(B){if(G=B instanceof Error?B:Error(String(B)),B instanceof Error&&B.message.includes("400"))throw B;if(F===Z)throw G;let W=Math.min($*2**F,X),L=Math.random()*0.1*W;await new Promise((f)=>setTimeout(f,W+L)),Q?.warn(`Retry attempt ${F+1} after ${W+L}ms delay`)}throw G}async function r5(J,Z,$){let X=W5.get(J);if(!$?.forceRefresh&&X&&X.expiresAt>f1())return O9(J,X),X.jwks;let Q=o5.get(J);if(Q)return Q;let G=(async()=>{try{return await g1(async()=>{let F=await fetch(J);if(!F.ok)throw Error("Failed to fetch JWKS");let B=await F.json(),W=O2(F.headers.get("cache-control"));return O9(J,{jwks:B,expiresAt:f1()+W,importedKeys:new Map}),B},h1.maxRetries,h1.baseDelayMs,void 0,Z)}catch(F){let B=W5.get(J);if(B)return Z?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),B.jwks;throw F}finally{o5.delete(J)}})();return o5.set(J,G),G}function E2(J){if(J){W5.delete(J),o5.delete(J);return}W5.clear(),o5.clear()}async function j2(J,Z,$){return(await j9(J,Z,$)).jwk}async function j9(J,Z,$){if(!Z?.trim())throw Error("JWT header missing kid");await r5(J,$);let X=W5.get(J),Q=X?.jwks.keys.find((G)=>G.kid===Z);if(!Q)await r5(J,$,{forceRefresh:!0}),X=W5.get(J),Q=X?.jwks.keys.find((G)=>G.kid===Z);if(!X||!Q)throw Error("Public key not found");return{jwk:Q,entry:X}}async function m1(J,Z,$,X,Q){let{jwk:G,entry:F}=await j9(J,Z,Q),B=`${Z}\x00${$}`,W=F.importedKeys.get(B);if(W)return W;let L=X(G);return L.catch(()=>{if(F.importedKeys.get(B)===L)F.importedKeys.delete(B)}),F.importedKeys.set(B,L),L}async function A2(J,Z){let $=J.keys.find((X)=>X.kid===Z);if(!$)throw Error("Public key not found");return A9($)}function A9(J){return crypto.subtle.importKey("jwk",{kty:J.kty,n:J.n,e:J.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function w2(J,Z,$){return m1(J,Z,"rs256",A9,$)}var U1={RS256:{kty:"RSA",importParams:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},verifyParams:{name:"RSASSA-PKCS1-v1_5"}},ES256:{kty:"EC",crv:"P-256",importParams:{name:"ECDSA",namedCurve:"P-256"},verifyParams:{name:"ECDSA",hash:"SHA-256"}}};async function p1(J,Z,$,X){if(typeof $!=="string"||!($ in U1))throw Error(`Unsupported JWT alg "${String($)}" (allowed: ${Object.keys(U1).join(", ")})`);let Q=U1[$];return{key:await m1(J,Z,`oidc:${$}`,(F)=>{if(F.kty!==Q.kty)throw Error(`JWK type "${F.kty}" does not match token alg "${$}"`);if(Q.kty==="EC"){let B=F;if(B.crv!==Q.crv)throw Error(`JWK curve "${String(B.crv)}" does not match token alg "${$}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:B.crv,x:B.x,y:B.y},Q.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:F.kty,n:F.n,e:F.e},Q.importParams,!1,["verify"])},X),algorithm:Q.verifyParams}}function D5(J=32){let Z=new Uint8Array(J);return crypto.getRandomValues(Z),Array.from(Z,($)=>$.toString(16).padStart(2,"0")).join("").substring(0,J)}function N1(J){let Z="";return J.forEach(($)=>{Z+=String.fromCharCode($)}),btoa(Z).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function T9(J){let Z=J.replace(/-/g,"+").replace(/_/g,"/"),$=Z.padEnd(Z.length+(4-Z.length%4)%4,"="),X=atob($),Q=new Uint8Array(X.length);for(let G=0;G<X.length;G++)Q[G]=X.charCodeAt(G);return Q}function w9(J){let Z=new TextDecoder().decode(T9(J));return JSON.parse(Z)}async function J1(J){let Z=new TextEncoder().encode(J),$=await crypto.subtle.digest("SHA-256",Z);return N1(new Uint8Array($))}function l1(J){let Z=new URL(J.authorizationUrl);if(Z.searchParams.set("client_id",J.clientId),Z.searchParams.set("redirect_uri",J.redirectUri),Z.searchParams.set("response_type","code"),Z.searchParams.set("scope",J.scope),Z.searchParams.set("state",J.state),J.codeChallenge)Z.searchParams.set("code_challenge",J.codeChallenge),Z.searchParams.set("code_challenge_method","S256");if(J.nonce)Z.searchParams.set("nonce",J.nonce);for(let[$,X]of Object.entries(J.extraParams??{}))Z.searchParams.set($,X);return Z.toString()}async function c1(J){let Z=new URLSearchParams;if(Z.append("grant_type","authorization_code"),Z.append("code",J.code),Z.append("redirect_uri",J.redirectUri),Z.append("client_id",J.clientId),J.clientSecret)Z.append("client_secret",J.clientSecret);if(J.codeVerifier)Z.append("code_verifier",J.codeVerifier);let $=await fetch(J.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Z.toString()}),X=await $.json();if(!$.ok){let Q=X;throw J.log?.error("OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":$.status,oidc_error:Q.error}),Error(`Token exchange failed: ${Q.error||$.statusText} - ${Q.error_description||""}`.trim())}if(typeof X.access_token!=="string")throw Error("Token exchange response missing access_token");return X}var S9=60;function e5(J){return J.trim().replace(/\/$/,"")}function R9(J){let{claims:Z,audience:$}=J,X=e5(J.issuer),Q=J.nowSec??Math.floor(Date.now()/1000),G=J.clockSkewSec??S9,F=Z.iss;if(typeof F!=="string"||e5(F)!==X)throw Error("ID token issuer mismatch");let B=Z.aud,W=Array.isArray(B)?B.includes($):typeof B==="string"&&B===$,L=typeof Z.azp==="string"&&Z.azp===$;if(!W&&!L)throw Error("ID token audience mismatch");if(typeof Z.exp!=="number")throw Error("ID token missing exp");if(Z.exp<Q-G)throw Error("ID token expired");if(J.expectedNonce!==void 0){if(Z.nonce!==J.expectedNonce)throw Error("ID token nonce mismatch")}}async function x9(J,Z,$){let X=J.split(".");if(X.length!==3)throw Error("Invalid JWT");let Q=w9(X[0]),G=w9(X[1]),F=T9(X[2]),{key:B,algorithm:W}=await p1(Z,Q.kid,Q.alg,$),L=new TextEncoder().encode(`${X[0]}.${X[1]}`);if(!await crypto.subtle.verify(W,B,F,L))throw Error("Invalid JWT signature");return{header:Q,payload:G}}async function R5(J){let{payload:Z}=await x9(J.idToken,J.jwksUri,J.log);return R9({claims:Z,issuer:J.issuer,audience:J.audience,clockSkewSec:J.clockSkewSec,expectedNonce:J.expectedNonce}),Z}var I2="http://schemas.openid.net/event/backchannel-logout";async function d1(J){let{payload:Z}=await x9(J.logoutToken,J.jwksUri,J.log),$=e5(J.issuer),X=Z.iss;if(typeof X!=="string"||e5(X)!==$)throw Error("Logout token issuer mismatch");let Q=Z.aud,G=Array.isArray(Q)?Q.includes(J.audience):typeof Q==="string"&&Q===J.audience,F=typeof Z.azp==="string"&&Z.azp===J.audience;if(!G&&!F)throw Error("Logout token audience mismatch");if(Z.nonce!=null)throw Error("Logout token must not contain a nonce");let B=Z.events;if(!(typeof B==="object"&&B!==null&&!Array.isArray(B)&&Object.hasOwn(B,I2)))throw Error("Logout token missing back-channel logout event");let L=typeof Z.sid==="string"&&Z.sid.length>0,f=typeof Z.sub==="string"&&Z.sub.length>0;if(!L&&!f)throw Error("Logout token missing sid and sub");if(typeof Z.exp==="number"){let u=Math.floor(Date.now()/1000),t=J.clockSkewSec??S9;if(Z.exp<u-t)throw Error("Logout token expired")}return Z}var T2=3600000,S2=60000,R2=86400000,x2=256,w5=new Map,s5=new Map;function I9(J,Z){w5.delete(J),w5.set(J,Z);while(w5.size>x2){let $=w5.keys().next().value;if($===void 0)break;w5.delete($)}}var u1=()=>Date.now();function y2(J){u1=J??(()=>Date.now())}function b2(J){if(J){w5.delete(J),s5.delete(J);return}w5.clear(),s5.clear()}function q2(J){let Z=J?/max-age\s*=\s*(\d+)/i.exec(J):null,$=Z?Number(Z[1]):Number.NaN,X=Number.isFinite($)?$*1000:T2;return Math.min(Math.max(X,S2),R2)}async function n1(J){let Z=w5.get(J);if(Z&&Z.expiresAt>u1())return I9(J,Z),Z.endpoints;let $=s5.get(J);if($)return $;let X=(async()=>{try{let Q=J.replace(/\/$/,""),G=await fetch(`${Q}/.well-known/openid-configuration`,{headers:{Accept:"application/json"}});if(!G.ok)throw Error(`OIDC discovery failed for ${J} with status ${G.status}`);let F=await G.json(),B={authorizationUrl:typeof F.authorization_endpoint==="string"?F.authorization_endpoint:void 0,tokenUrl:typeof F.token_endpoint==="string"?F.token_endpoint:void 0,jwksUri:typeof F.jwks_uri==="string"?F.jwks_uri:void 0,userInfoUrl:typeof F.userinfo_endpoint==="string"?F.userinfo_endpoint:void 0};return I9(J,{endpoints:B,expiresAt:u1()+q2(G.headers.get("cache-control"))}),B}catch(Q){let G=w5.get(J);if(G)return G.endpoints;throw Q}finally{s5.delete(J)}})();return s5.set(J,X),X}async function a1(J,Z){let $=await fetch(J,{headers:{Authorization:`Bearer ${Z}`,Accept:"application/json","User-Agent":"ionite-ciam"}});if(!$.ok)throw Error(`UserInfo request failed with status ${$.status}`);return await $.json()}function C2(J){let Z=J.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),$=atob(Z),X=new Uint8Array($.length);for(let Q=0;Q<$.length;Q++)X[Q]=$.charCodeAt(Q);return X}async function t1(J){let Z=Math.floor(Date.now()/1000),$={alg:"ES256",kid:J.keyId,typ:"JWT"},X={iss:J.teamId,iat:Z,exp:Z+(J.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:J.clientId},Q=N1(new TextEncoder().encode(JSON.stringify($))),G=N1(new TextEncoder().encode(JSON.stringify(X))),F=`${Q}.${G}`,B=await crypto.subtle.importKey("pkcs8",C2(J.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),W=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},B,new TextEncoder().encode(F));return`${F}.${N1(new Uint8Array(W))}`}function v2(J){for(let Z=0;Z<J.length;Z++){let $=J.charCodeAt(Z);if($<=31||$===127)return!0}return!1}function U2(J,Z){let $=null;try{$=new URL(J,Z)}catch{$=null}let X="";try{X=new URL(Z).origin}catch{X=""}return{candidate:J,url:$,requestOrigin:X}}function y9(J,Z,$){let X=U2(J,$),Q=!1;for(let G of Z){let F=G(X);if(F==="deny")return!1;if(F==="allow")Q=!0}return Q}function b9(){return({candidate:J,url:Z})=>{if(v2(J))return"deny";if(J.includes("\\"))return"deny";if(J.startsWith("//"))return"deny";if(!Z)return"deny";if(Z.protocol!=="http:"&&Z.protocol!=="https:")return"deny";if(Z.username||Z.password)return"deny";return"abstain"}}function q9(){return({candidate:J})=>J.startsWith("/")&&!J.startsWith("//")&&!J.startsWith("/\\")?"allow":"abstain"}function C9(){return({url:J,requestOrigin:Z})=>J&&Z&&J.origin===Z?"allow":"abstain"}function k2(...J){let Z=new Set(J.map(($)=>{try{return new URL($).origin}catch{return $}}));return({url:$})=>$&&Z.has($.origin)?"allow":"abstain"}function f2(...J){let Z=J.map(($)=>$.toLowerCase());return({url:$})=>{if(!$)return"abstain";let X=$.hostname.toLowerCase();for(let Q of Z)if(Q.startsWith(".")){if(X===Q.slice(1)||X.endsWith(Q))return"allow"}else if(X===Q)return"allow";return"abstain"}}function i1(){return[b9(),q9(),C9()]}function v9(J,Z,$){if(!J)return!1;return y9(J,Z,$)}function o1(J,Z){if(!J)return Z.fallback;return y9(J,Z.rules,Z.requestUrl)?J:Z.fallback}var h2={rules:i1(),fallback:"/"};function g2(J,Z,$="redirect"){let X=new URL(J.url).searchParams.get($)??void 0;return v9(X,Z.rules,J.url)?{redirect:X}:void 0}function m2(J,Z){let $=J.context;return o1($?.redirect,{rules:Z.rules,fallback:Z.fallback,requestUrl:J.request.url})}function x5(J,Z,$){if(J instanceof Response)return{response:J};if(typeof J==="string")return{location:o1(J,{rules:i1(),fallback:Z,requestUrl:$})};return{location:Z}}function U5(J,Z){if(Z.length===0)return J;let $=new Headers(J.headers);for(let X of Z)$.append("Set-Cookie",X);return new Response(J.body,{status:J.status,statusText:J.statusText,headers:$})}var M1="ciam",p2="id_token",u2="access_token";function l2(J,Z,$,X,Q,G){if(!$&&!X)return;let F=new WeakMap,B={...$,...X},W={...B,magicLinkTtl:B.magicLinkTtl??3600,sessionTtl:B.sessionTtl??86400,cookiesSecure:B.cookiesSecure!==void 0?B.cookiesSecure:!0,cookiesSameSite:B.cookiesSameSite!==void 0?B.cookiesSameSite:"Strict",cookiesPrefix:B.cookiesPrefix??(B.ciamId?`ion.ciam.${B.ciamId}`:"ion.ciam"),cookiesPath:B.cookiesPath??"/"};function L(){if(!W.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return W.sessionStore}function f(){L()}let u=J.callbackParams??c5(U9("ionite.ciam")),t=J.idTokenClaims??c5(D1("ionite.ciam")),J5=J.tokenResponse??c5(k9("ionite.ciam"));function r(K=32){let H=new Uint8Array(K);return crypto.getRandomValues(H),Array.from(H,(N)=>N.toString(16).padStart(2,"0")).join("").substring(0,K)}function G5(K,H,N,z=W.cookiesSameSite??"Strict"){if(!W)throw Error("ionite CIAM Manager not initialized");if(K=`${W.cookiesPrefix}.${K}`,typeof H!=="string")H=btoa(JSON.stringify(H));let j;if(N instanceof Date)j=`Expires=${N.toUTCString()}`;else if(typeof N==="number")j=`Max-Age=${N}`;else throw Error("Invalid expires type",N);if(H.length>4000)throw Error(`Error setting cookie: ${K}. Cookie length is: ${H.length}`);return`${K}=${H}; ${j}; Path=${W.cookiesPath}; HttpOnly;${W.cookiesSecure?" Secure;":""} SameSite=${z};`}function p(K){if(!W)throw Error("ionite CIAM Manager not initialized");return`${W.cookiesPrefix}.${K}=; Max-Age=0; Path=${W.cookiesPath}; HttpOnly;${W.cookiesSecure?" Secure;":""} SameSite=${W.cookiesSameSite};`}function c(K,H,N=!1){if(!W)throw Error("ionite CIAM Manager not initialized");let z=H.headers.get("cookie");if(!z)return null;let j=`${W.cookiesPrefix}.${K}`,M=z.split(";").find((E)=>E.trim().startsWith(`${j}=`));if(!M)return null;let _=M.indexOf("="),D=M.substring(_+1).trim();if(!N)return D;try{let E=atob(D);return JSON.parse(E)}catch(E){return Z.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:j},E),null}}function l(K){return`cstate_${K}`}async function B5(K,H,N,z){let j=await W.afterLogin?.({...H,request:K,context:N}),M=x5(j,"/",K.url);if(M.response)return U5(M.response,z.map(([,_])=>_));return new Response(H.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",M.location],...z]})}function s(K,H){return["Set-Cookie",G5("session",K,H)]}function $5(K){if(!K)return;if(K instanceof Date)return K;let H=new Date(K);return Number.isNaN(H.getTime())?void 0:H}async function j5(K){let H=c("session",K);if(!H)return;let N=await L().get(H);if(N&&W.tenantId&&N.tenantId&&N.tenantId!==W.tenantId)return;if(N?.authType!=="ciam")return;let z=$5(N.expiresAt);if(z&&Date.now()>z.getTime()){await L().delete(H);return}return N}async function q5(K){if(!W)throw Error("ionite CIAM Manager not initialized");f();let H=F.get(K);if(H)return H;let N=t5(K);return F.set(K,N),N}async function t5(K){try{let H=await j5(K);if(!H?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:N5(H.claims)}}catch(H){return Z.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},H),{status:"degraded",error:H instanceof Error?H:void 0}}}async function g5(K){let H=await q5(K);return H.status==="authenticated"?H.value:void 0}async function m5(K){if(!W)throw Error("ionite CIAM Manager not initialized");f();let H;try{H=await g5(K)}catch{H=void 0}let N=await W.beforeLogout?.({request:K,user:H});try{let P=c("session",K);if(P)await L().delete(P)}catch(P){Z.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},P)}let z=[["Set-Cookie",p("session")]],j=await W.afterLogout?.({request:K,context:N}),M=x5(j,"/",K.url);if(M.response)return U5(M.response,z.map(([,P])=>P));let _=M.location??"/",D=K.headers.get("accept");if(D?.includes("application/json")||D?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:_}),{status:200,headers:[["Content-Type","application/json"],...z]});return new Response("Logged out",{status:302,headers:[["Location",_],...z]})}function C5(K){return K.id||K.email||`ciam-${K.userName}`}function T5(K,H,N){return{sub:C5(K),iss:M1,aud:M1,typ:p2,exp:Math.floor(N.getTime()/1000),iat:Math.floor(Date.now()/1000),email:K.email,name:K.name,preferred_username:K.userName,picture:K.avatar,sid:H}}function p5(K,H,N){return{sub:K,iss:M1,aud:M1,typ:u2,exp:Math.floor(N.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:H,scope:"openid profile email"}}function N5(K){let H=K.exp?new Date(K.exp*1000):new Date;return{id:K.sub,userName:K.preferred_username??"",name:K.name??"",email:K.email??"",avatar:K.picture,userType:"customer",ciam:{profile:K,scope:"openid profile email",tokenType:"Bearer",expires:H}}}async function u5(K){if(!W)throw Error("ionite 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(K))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let N,z;try{if(!K.headers.get("content-type")?.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let v=await K.text(),y=JSON.parse(v);z=typeof y?.redirect==="string"&&y.redirect.length>0?y.redirect:void 0;let Y={userName:y.userName,name:y.name,email:y.email,avatar:y.avatar},O=await J.customer.validate(Y);if(O.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}});N=O.value}catch(R){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let M=new URL(K.url).searchParams.get("ttl"),_=M?parseInt(M,10):W.magicLinkTtl??3600;if(Number.isNaN(_)||_<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let D=r(32),E=new Date(Date.now()+_*1000);if(!W.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await W.magicLinkStore.create(D,N,E)}catch(R){return Z.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},R),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let P=new URL(K.url),w=W.magicLinkLoginUrl||"/magic-link/login",q=new URL(w,P.origin);if(q.searchParams.set("token",D),z)q.searchParams.set("redirect",z);return new Response(JSON.stringify({magicLink:q.toString(),expiresAt:E.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function S5(K){if(!W)throw Error("ionite CIAM Manager not initialized");f();let N=new URL(K.url).searchParams.get("token");if(!N)return B5(K,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!W.magicLinkStore)return B5(K,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let z=await W.magicLinkStore.getAndDelete(N);if(!z)return B5(K,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let j=new Date(Date.now()+(W.sessionTtl??86400)*1000),M=r(32),_=C5(z.customer),D=T5(z.customer,M,j),E=p5(_,M,j),P=N5(D),w;try{let R={sid:M,sub:_,authType:"ciam",tenantId:W.tenantId,expiresAt:j,claims:D,accessClaims:E,createdAt:new Date};await L().create(R),w=R}catch(R){throw Z.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},R),R}if(W.customerStore)try{let R=P.id;if(R){let v=new Date,y=await W.customerStore.get(R);if(y||W.enableJitUserProvisioning){let Y={...y??{},...P,id:R,tenantId:y?.tenantId,createdAt:y?.createdAt??v,updatedAt:v,userType:y?.userType??"customer"};await W.customerStore.upsert(Y)}}}catch(R){Z.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},R)}let q=[s(M,j)];return B5(K,{ok:!0,user:P,session:w},void 0,q)}function L5(K,H=200,N=[]){return new Response(JSON.stringify(K),{status:H,headers:[["Content-Type","application/json"],...N]})}function M5(K,H){try{return new URL(K).toString()}catch{let N=new URL(H).origin,z=W.cookiesSecure?N.replace(/^http:\/\//,"https://"):N;return new URL(K,z).toString()}}function x(){let K=W.customerLoginUrl||"/auth/customer/login",H=K.includes("?")?"&":"?";return v1(W.providers).map(({name:N,config:z})=>{let j=C1(z);return{name:N,type:z.type,displayName:j.displayName,loginUrl:`${K}${H}provider=${encodeURIComponent(N)}`,iconUrl:j.iconUrl,colors:j.colors,url:j.url}})}async function U(K){if(!K)return{};let{authorizationUrl:H,tokenUrl:N,jwksUri:z,userInfoUrl:j}=K,M=K.config.authority;if(M&&(!H||!N||K.flow==="id_token"&&!z))try{let D=await n1(M);H=H??D.authorizationUrl,N=N??D.tokenUrl,z=z??D.jwksUri,j=j??D.userInfoUrl}catch(D){Z.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},D)}return{authorizationUrl:H,tokenUrl:N,jwksUri:z,userInfoUrl:j}}async function h(K){if(K.type==="apple"){let{teamId:H,keyId:N,privateKey:z,clientId:j}=K.config;if(H&&N&&z&&j)return t1({teamId:H,keyId:N,privateKey:z,clientId:j})}return K.clientSecret}async function n(K){L();let N=new URL(K.url).searchParams.get("provider");if(!N)return L5({error:"Missing required query parameter: provider"},400);let z=W.providers?.[N];if(!z||z.enabled===!1||z.type==="magic-link")return L5({error:`Unknown or disabled CIAM provider: ${N}`},404);let j=V1(N,z);if(!j?.clientId)return L5({error:`CIAM provider ${N} is not fully configured`},500);let M=await U(j);if(!M.authorizationUrl)return L5({error:`CIAM provider ${N} is missing an authorization endpoint`},500);let _=W.customerCallbackUrl||"/auth/customer/callback",D=M5(_,K.url),E=D5(),P=D5(64),w=D5(),q=j.flow==="id_token",R=q?await J1(P):void 0,v=await W.beforeLogin?.({request:K}),y=l1({authorizationUrl:M.authorizationUrl,clientId:j.clientId,redirectUri:D,scope:j.scope,state:E,codeChallenge:R,nonce:w,extraParams:j.extraAuthParams}),Y={provider:N,state:E,codeVerifier:q?P:void 0,nonce:w,redirectUri:D,...v===void 0?{}:{context:v}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",y],["Set-Cookie",G5(l(E),Y,W.loginStateTtl??600,"Lax")]]})}async function e(K){if(K.method==="POST"){if((K.headers.get("content-type")??"").includes("application/x-www-form-urlencoded")){let N=await K.text();return Object.fromEntries(new URLSearchParams(N).entries())}}return Object.fromEntries(new URL(K.url).searchParams.entries())}async function i(K,H){let N=K.mapClaims(H);if(!N.sub)return{ok:!1};let z=`${K.name}:${N.sub}`,j={id:z,userName:N.userName||N.email||z,name:N.name||"",email:N.email||"",avatar:N.avatar,userType:"customer"},M=z;if(W.customerStore){let q=await W.customerStore.lookup(j)??await W.customerStore.get(z);if(M=q?.id??z,!q&&!W.enableJitUserProvisioning)return Z.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let R=new Date,v={...q??{},...j,id:M,tenantId:q?.tenantId,createdAt:q?.createdAt??R,updatedAt:R,userType:q?.userType??"customer"};await W.customerStore.upsert(v)}let _=new Date(Date.now()+(W.sessionTtl??86400)*1000),D=D5(32),E={sub:M,iss:K.name,aud:K.clientId,exp:Math.floor(_.getTime()/1000),iat:Math.floor(Date.now()/1000),email:N.email,name:N.name,preferred_username:N.userName??N.email,picture:N.avatar,sid:D},P={sid:D,sub:M,authType:"ciam",tenantId:W.tenantId,expiresAt:_,claims:E,accessClaims:{sub:M,sid:D,scope:K.scope},createdAt:new Date},w=L();try{await w.create(P)}catch(q){if(!await w.get(D))throw q;await w.update(D,P)}return{ok:!0,claims:E,sid:D,expires:_}}async function V(K){L();let H,N,z=(j)=>{let M=H?[["Set-Cookie",p(H)]]:[];return B5(K,{ok:!1,error:j},N,M)};try{let j=await e(K),M=await u.validate(j);if(M.issues||!M.value)return z(Error("Invalid CIAM callback parameters"));let{code:_,state:D}=M.value;if(!D)return z(Error("Missing CIAM callback state"));H=l(D);let E=c(H,K,!0);if(N=E?.context,!E?.provider||!E.state||E.state!==D)return Z.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM callback state verification failed"));let P=W.providers?.[E.provider];if(!P)return z(Error("Unknown CIAM provider"));let w=V1(E.provider,P);if(!w?.clientId)return z(Error("CIAM provider not configured"));let q=await U(w);if(!q.tokenUrl)return z(Error("CIAM provider missing token endpoint"));let R=await h(w),v=await c1({tokenUrl:q.tokenUrl,clientId:w.clientId,clientSecret:R,redirectUri:E.redirectUri||M5(W.customerCallbackUrl||"/auth/customer/callback",K.url),code:_,codeVerifier:w.flow==="id_token"?E.codeVerifier:void 0,log:Z}),y;if(w.flow==="id_token"){let b=w.config.authority;if(!v.id_token||!q.jwksUri||!b)return z(Error("CIAM id_token flow misconfigured"));if(!E.nonce)return z(Error("CIAM callback state cookie missing nonce"));if((await J5.validate(v)).issues)return Z.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM token response validation failed"));y=await R5({idToken:v.id_token,jwksUri:q.jwksUri,issuer:b,audience:w.clientId,expectedNonce:E.nonce,log:Z});let C=await t.validate(y);if(!C.issues)y=C.value}else{if(!q.userInfoUrl)return z(Error("CIAM provider missing userinfo endpoint"));y=await a1(q.userInfoUrl,v.access_token);let b=w.config.authority;if(v.id_token&&q.jwksUri&&b){let S=await R5({idToken:v.id_token,jwksUri:q.jwksUri,issuer:b,audience:w.clientId,expectedNonce:E.nonce||void 0,log:Z}),C=typeof S.sub==="string"?S.sub:"";if(C){if(typeof y.sub==="string"&&y.sub.length>0&&y.sub!==C)return Z.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM UserInfo sub mismatch"));y.sub=C}}if(typeof y.sub!=="string"||y.sub.length===0)return Z.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM UserInfo response missing sub"))}let Y=await i(w,y);if(!Y.ok)return z(Error("Failed to persist CIAM customer"));let O=N5(Y.claims);Z.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:w.name});let T=[["Set-Cookie",p(H)],s(Y.sid,Y.expires)];return B5(K,{ok:!0,user:O,session:void 0},N,T)}catch(j){return Z.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},j),z(j)}}async function A(K){if(!W)throw Error("ionite CIAM Manager not initialized");f();let H=W.magicLinkUrl||"/magic-link",N=W.magicLinkLoginUrl||"/magic-link/login",z=W.logoutUrl||"/auth/customer/logout",j=W.customerLoginUrl||"/auth/customer/login",M=W.customerCallbackUrl||"/auth/customer/callback",_=W.customerProvidersUrl||"/auth/customer/providers",D=new URL(K.url).pathname,E=(Y)=>{if(!Y)return;try{return new URL(Y).pathname}catch{return Y.startsWith("/")?Y:`/${Y}`}};if(E(H)===D&&K.method==="POST")return u5(K);if(E(N)===D&&K.method==="GET")return S5(K);if(E(z)===D&&K.method==="GET")return m5(K);if(E(_)===D&&K.method==="GET")return L5({providers:x()});if(E(j)===D&&K.method==="GET")return n(K);if(E(M)===D&&(K.method==="GET"||K.method==="POST"))return V(K);return new Response("Not Found",{status:404})}return{...W,getCustomer:g5,resolveCustomer:q5,logout:m5,handler:A,listCustomerProviders:x}}async function c2(J,Z){return m(Z,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),Z.ciam?.getCustomer(J)}async function d2(J,Z){return m(Z,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await Z.ciam?.resolveCustomer(J)??{status:"unauthenticated"}}var Y1="application/scim+json",n2="urn:ietf:params:scim:api:messages:2.0:ListResponse",Q9="urn:ietf:params:scim:api:messages:2.0:Error",P1="urn:ietf:params:scim:schemas:core:2.0:User",h5="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",O1="urn:ietf:params:scim:schemas:core:2.0:Group",a2="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",f9="urn:ietf:params:scim:schemas:core:2.0:ResourceType",Z1="urn:ietf:params:scim:schemas:core:2.0:Schema",t2="00000000000000000000000000000000";function i2(J){let Z={timestamp:new Date().toISOString()};if(J)Z.actor=J;try{let Q=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),G=Q?.traceId;if(G&&G!==t2){if(Z.traceId=G,Q?.spanId)Z.spanId=Q.spanId}}catch{}return Z}class B1 extends Error{constructor(J){super(J);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,B1.prototype)}}async function o2(J,Z,$,X,Q){let G=X.subjectType??"user";if(!X9.includes(G))throw new B1(`Cannot grant ${X.targetType} "${V5(X.target)}" to a "${G}" principal: only [${X9.join(", ")}] principals are assignable on this platform.`);let F=G9(Z,J);if(!F&&!Q)return;let B=V5(X.target),W;if(Q)W=await Q.getNode(X.targetType,B);else if(F){if(W=await(X.targetType==="group"?F.groups:X.targetType==="role"?F.roles:F.permissions).get(B),!W&&X.targetType==="group")W=await $?.entitlement?.(B)}let L=W?.assignableSubjectTypes;if(L&&L.length>0&&!L.includes(G))throw new B1(`Cannot grant ${X.targetType} "${B}" to a "${G}" principal: this entitlement restricts assignment to [${L.join(", ")}].`)}async function r2(J,Z,$,X){await o2(J.catalogStore,J.codeCatalog,J.resources,Z,X);let Q={...Z,status:Z.status??"active",provenance:Z.provenance??i2()};if(Q.id=W1(Q),await J.accessStore?.grant(Q),J.accessIndex&&(J.catalogStore||J.codeCatalog)){let G=await B9(Q,{catalog:J.catalogStore,code:J.codeCatalog,resources:J.resources,cache:X});await J.accessIndex.materialize(Q.id,G)}return $?.push({op:"add",change:Q}),Q}async function E1(J,Z,$){let X=Z.id??W1(Z);await J.accessStore?.revoke(Z),await J.accessIndex?.removeByRoot(X),$?.push({op:"delete",change:{...Z,id:X}})}async function K9(J,Z){let $=await s2(J,Z),X=await J4(J,Z);return{oaa:$,delta:X}}async function s2(J,Z){if(Z.length===0||!J.authz.oaa.isReady())return{status:"skipped"};return F9(J,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>J.authz.oaa.pushAccessChanges(Z),{count:Z.length})}async function F9(J,Z,$,X,Q){try{return await X(),{status:"ok"}}catch(G){return J.log?.warn($,{"ion.operation":Z,"ion.outcome":"degraded",...Q,error:b5(G)}),{status:"degraded",reason:b5(G)}}}var e2=6;async function J4(J,Z){let $=J.iamDelta;if(!$?.isReady()||Z.length===0)return{status:"skipped"};let X=new Map;for(let W of Z){let L=`${W.change.subjectType??"user"}:${V5(W.change.subject)}\x00${W.change.targetType}:${V5(W.change.target)}`;X.set(L,W)}let Q=[...X.values()],G=Q.map(({op:W,change:L})=>()=>W==="add"?$.onGrant(L):$.onRevoke(L)),B=(await Z4(G,e2)).filter((W)=>W.status==="rejected");if(B.length>0)return J.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:B.length,total:Q.length,error:b5(B[0]?.reason)}),{status:"degraded",reason:b5(B[0]?.reason)};return{status:"ok"}}async function Z4(J,Z){let $=Array(J.length),X=0,Q=async()=>{while(!0){let F=X++;if(F>=J.length)return;let B=J[F];if(!B)continue;try{$[F]={status:"fulfilled",value:await B()}}catch(W){$[F]={status:"rejected",reason:W}}}},G=Array.from({length:Math.min(Z,J.length)},Q);return await Promise.all(G),$}class w1 extends Error{constructor(J){super(J);this.name="DerivedRevokeError",Object.setPrototypeOf(this,w1.prototype)}}class a5 extends Error{summary;clientError;constructor(J,Z,$=!1){super(J);this.name="ScimMutationError",this.summary=Z,this.clientError=$,Object.setPrototypeOf(this,a5.prototype)}}function k(J,Z,$){return new Response(JSON.stringify({schemas:[Q9],status:String(J),scimType:$,detail:Z}),{status:J,headers:{"Content-Type":Y1}})}function d5(J,Z){let $=Z?.totalResults??J.length,X=Z?.startIndex??1,Q=Z?.itemsPerPage??J.length;return new Response(JSON.stringify({schemas:[n2],totalResults:$,startIndex:X,itemsPerPage:Q,Resources:J}),{status:200,headers:{"Content-Type":Y1}})}function H5(J,Z=200){return new Response(JSON.stringify(J),{status:Z,headers:{"Content-Type":Y1}})}function h9(J){return k(J.clientError?409:500,`${J.message}; authz mutation summary: ${JSON.stringify(J.summary)}`,J.clientError?"mutability":"invalidValue")}function K1(J){return W1(J)}function r1(J,Z){return X1(g9(J),g9(Z))}function g9(J){let Z=new Map;if(!J?.id)return Z;for(let $ of J.groups??[]){let X={subject:J.id,targetType:"group",target:$.value,metadata:$.display||$.type?{display:$.display,type:$.type}:void 0};Z.set(K1(X),X)}for(let $ of J.roles??[]){let X={subject:J.id,targetType:"role",target:$.value,metadata:$.display||$.type?{display:$.display,type:$.type,primary:$.primary}:void 0};Z.set(K1(X),X)}for(let $ of J.entitlements??[]){let X={subject:J.id,targetType:"permission",target:$.value,metadata:$.display||$.type?{display:$.display,type:$.type,primary:$.primary}:void 0};Z.set(K1(X),X)}return Z}function $1(J,Z,$,X){let Q=new Map,G=X&&X.length>0?X:void 0;for(let F of J??[]){let B={subject:F.value,targetType:Z,target:$,resources:G,metadata:F.display||F.type?{display:F.display,type:F.type}:void 0};Q.set(K1(B),B)}return Q}function s1(J){let Z=J[Y5]?.resources;return Z&&Z.length>0?Z:void 0}function $4(J,Z,$){let X=J[Y5];if(J.displayName!==void 0&&J.displayName!==(Z.displayName??Z.name))return!0;if(J.externalId!==void 0&&J.externalId!==Z.externalId)return!0;if(X?.type!==void 0&&X.type!==$)return!0;if(X?.requestable!==void 0&&Boolean(X.requestable)!==Boolean(Z.requestable))return!0;if(X?.description!==void 0&&X.description!==Z.description)return!0;if(X?.resources!==void 0){let Q=[...X.resources].sort().join(","),G=[...j1(Z)??[]].sort().join(",");if(Q!==G)return!0}return!1}function m9(J){let Z=new Map;for(let $ of J)Z.set(K1($),$);return Z}async function O5(J,Z,$,X,Q,G,F){let B=[],W=new Set,L=F?F.get(`${X}:${Q}`)??[]:Z?(await Z.listByTarget(X,Q)).items:[];for(let f of L){let u=V5(f.subject);if(W.has(u))continue;W.add(u);let t=f.metadata,J5=f.subjectType==="workload"?"Workload":t?.type??"User";B.push({value:u,...t?.display?{display:t.display}:{},type:J5})}for(let f of G??[]){if(f.targetType!==X||V5(f.target)!==Q)continue;let u=V5(f.subject);if(W.has(u))continue;W.add(u),B.push({value:u,type:"Workload"})}if(X==="group"){let f=await J.groups.get(Q)??await $?.entitlement?.(Q);for(let u of f?.groups??[]){let t=V5(u);if(!t||W.has(t))continue;W.add(t),B.push({value:t,type:"Group"})}}return B.length>0?B:void 0}function X1(J,Z){let $=[];for(let[X,Q]of Z)if(!J.has(X))$.push({action:"grant",change:Q});for(let[X,Q]of J)if(!Z.has(X))$.push({action:"revoke",change:Q});return $}async function e1(J,Z){if(J.oaa.isReady())await J.oaa.pushUser(Z)}async function k5(J,Z,$,X){let Q={metadataApplied:!1,access:[]},G=[],F=new Y9(J.catalogStore,J.resources,J.codeCatalog);try{try{await Z(),Q.metadataApplied=!0}catch(B){for(let W of $)Q.access.push({change:W.change,status:"rolled_back"});throw Q.metadataApplied=!1,new a5(`SCIM metadata write failed: ${b5(B)}`,Q,!1)}if(X)await F9(J,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",X);for(let B=0;B<$.length;B++){let W=$[B];try{if(W.action==="grant")await r2(J,W.change,G,F);else await Y4(J,W.change,G);Q.access.push({change:W.change,status:"applied"})}catch(L){Q.access.push({change:W.change,status:"failed",error:L});for(let u=B+1;u<$.length;u++)Q.access.push({change:$[u].change,status:"rolled_back"});let f=L instanceof w1||L instanceof B1;if(!f)await Q4(J,W.change,F);throw new a5(f?b5(L):`SCIM access mutation failed: ${b5(L)}`,Q,f)}}return Q}finally{await X4(J),Q.egress=await K9(J,G),K4(J,Q)}}function b5(J){return J instanceof Error?J.message:String(J)}async function X4(J){try{await J.authz.settle?.()}catch{}}async function Q4(J,Z,$){if(!J.accessIndex||!J.catalogStore&&!J.codeCatalog||!J.accessStore)return;let X=V5(Z.subject);if(!X)return;let Q=Z.subjectType??"user";try{await W9(X,Q,{accessStore:J.accessStore,accessIndex:J.accessIndex,catalogStore:J.catalogStore,code:J.codeCatalog,resources:J.resources},$)}catch(G){J.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:X,subjectType:Q,error:b5(G)})}}function K4(J,Z){if(!J.onAccessMutation)return;try{J.onAccessMutation(Z)}catch{}}async function Y4(J,Z,$){if(J.accessStore){let X=Z.id??W1(Z);if(!await J.accessStore.get(X)){if((J.accessIndex?await J.accessIndex.has(Z.subject,Z.targetType,Z.target,Z.resources?.[0],Z.subjectType):{allow:!1}).allow)throw new w1(`Cannot revoke ${Z.targetType} "${V5(Z.target)}" for "${V5(Z.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await E1(J,Z,$);return}}await E1(J,Z,$)}function Q1(J){let Z=J[Y5]?.type??"group";if(Z==="group"||Z==="role"||Z==="permission")return Z;throw Error(`Unsupported ionite SCIM Group authz type "${String(Z)}"`)}async function J9(J,Z,$){if(!J.oaa.isReady())return;if($==="role"){await J.oaa.pushRole(Z);return}if($==="permission"){await J.oaa.pushPermission(Z);return}await J.oaa.pushGroup(Z)}function j1(J){let Z=J.resources;if(!Z||Z.length===0)return;let $=Z.map((X)=>typeof X==="string"?X:X.id).filter(Boolean);return $.length>0?$:void 0}function E5(J,Z,$){return{schemas:[O1],id:J.id,externalId:J.externalId,displayName:J.displayName??J.name,members:$,[Y5]:{type:Z,requestable:J.requestable,description:J.description,resources:Z==="group"?j1(J):void 0,assignableSubjectTypes:J.assignableSubjectTypes,recommendedSubjectTypes:J.recommendedSubjectTypes}}}function B4(J,Z){let $=J[Y5],X={id:Z,name:J.displayName,displayName:J.displayName,description:$?.description??J.displayName,externalId:J.externalId,requestable:$?.requestable};if($?.resources!==void 0)X.resources=$.resources;return X}function W4(J){if(!J)return;let Z=J.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!Z)return;return{requestable:Z[1]?.toLowerCase()==="true"}}function p9(J){if(!J)return;let Z=J.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return Z?Z[1]:void 0}async function H9(J,Z){if(!J?.entitlements)return[];let $=J.entitlements.bind(J),X=[];for await(let Q of l9((G,F)=>J.list({start:G,limit:F})))for(let G of $(Q)){if(Z?.requestable!==void 0&&Boolean(G.requestable)!==Z.requestable)continue;X.push(G1(G))}return X}async function G4(J,Z,$,X,Q){let G=[{store:J.groups,type:"group"},{store:J.roles,type:"role"},{store:J.permissions,type:"permission"}],F;if(G.every(({store:W})=>typeof W.getByExternalId==="function"))F=(await Promise.all(G.map(async({store:L,type:f})=>{let u=await L.getByExternalId?.(X);return u?{entity:u,type:f}:void 0}))).filter((L)=>L!==void 0);else{let W={start:0},[L,f,u]=await Promise.all([J.groups.list(W),J.roles.list(W),J.permissions.list(W)]);F=[...L.items.map((J5)=>({entity:J5,type:"group"})),...f.items.map((J5)=>({entity:J5,type:"role"})),...u.items.map((J5)=>({entity:J5,type:"permission"}))].filter(({entity:J5})=>J5.externalId===X)}if($?.entitlements){let W=await H9($);for(let L of W)if(L.externalId===X)F.push({entity:L,type:"group"})}if(F.length>1)throw new L9(`Ambiguous externalId "${X}": ${F.length} entitlements share it (${F.map((W)=>`${W.type}:${W.entity.id}`).join(", ")})`,"unique_violation","externalId");let B=F[0];if(!B)return;return E5(B.entity,B.type,await O5(J,Z,$,B.type,B.entity.id,Q))}async function L4(J,Z,$,X,Q){let G=Math.max(0,X.start),F=X.limit!=null?G+X.limit:void 0,B={start:0,limit:F,filter:X.filter},[W,L,f]=await Promise.all([J.groups.list(B),J.roles.list(B),J.permissions.list(B)]),u=[...W.items.map((s)=>({entity:s,type:"group"})),...L.items.map((s)=>({entity:s,type:"role"})),...f.items.map((s)=>({entity:s,type:"permission"}))],t=W.total+L.total+f.total,J5=u.slice(G,F),r=0,G5=[];if($?.entitlements){let s=await H9($,X.filter);r=s.length;let $5=X.limit!=null?X.limit-J5.length:void 0;if($5===void 0||$5>0){let j5=Math.max(0,G-t);G5=$5===void 0?s.slice(j5):s.slice(j5,j5+$5)}}let p=[...J5,...G5.map((s)=>({entity:s,type:"group"}))],c=t+r,l=Z?.listByTargets?await Z.listByTargets(p.map(({entity:s,type:$5})=>({targetType:$5,target:s.id}))):void 0,B5=await Promise.all(p.map(async({entity:s,type:$5})=>E5(s,$5,await O5(J,Z,$,$5,s.id,Q,l))));return{resources:B5,total:c,count:B5.length}}async function _1(J,Z,$,X,Q){let[G,F,B]=await Promise.all([J.groups.get(X),J.roles.get(X),J.permissions.get(X)]);if(G)return E5(G,"group",await O5(J,Z,$,"group",X,Q));if(F)return E5(F,"role",await O5(J,Z,$,"role",X,Q));if(B)return E5(B,"permission",await O5(J,Z,$,"permission",X,Q));let W=G1(await $?.entitlement?.(X));if(W)return E5(W,"group",await O5(J,Z,$,"group",X,Q));return}async function Z9(J,Z,$){let X=Q1(Z),G={...(X==="role"?await J.roles.get($):X==="permission"?await J.permissions.get($):await J.groups.get($))??{},...B4(Z,$)},F=X==="role"?J.roles.set(G):X==="permission"?J.permissions.set(G):J.groups.set(G);return await F.ready(),F}async function F4(J,Z){await Promise.all([J.groups.delete(Z),J.roles.delete(Z),J.permissions.delete(Z)])}function u9(){return crypto.randomUUID()}function n5(J,Z){let $=J;if(typeof $.validate==="function")return $.validate(Z);return Promise.resolve(J["~standard"].validate(Z))}function H4(J){if(!J)return;try{return new URL(J).pathname}catch{return J.startsWith("/")?J:`/${J}`}}function f5(J){let Z=H4(J);return Z?z1(Z):void 0}function V4(J,Z){let $=f5(J);if($?.endsWith("/Users"))return $.slice(0,-6);let X=f5(Z);if(X?.endsWith("/Groups"))return X.slice(0,-7);return}function y5(J,Z){return new URL(Z,J.url).toString()}function I(J,Z,$,X){let{multiValued:Q=!1,...G}=X??{};return{name:J,type:Z,description:$,multiValued:Q,...G}}function N4(J,Z){return{schemas:[a2],documentationUri:Z?.documentationUri,patch:{supported:!0},bulk:{supported:!1},filter:{supported:!0,maxResults:1000},changePassword:{supported:!1},sort:{supported:!1},etag:{supported:!1},authenticationSchemes:[{type:"oauthbearertoken",name:"OAuth Bearer Token",description:"Use an ionite workload bearer token for IAM discovery and provisioning requests.",primary:!0}],meta:{resourceType:"ServiceProviderConfig",location:y5(J.request,`${J.basePath}/ServiceProviderConfig`)}}}function M4(J){let Z=[];if(J.supportsUsers)Z.push({schemas:[f9],id:"User",name:"User",description:"User Account",endpoint:J.usersUrl,schema:P1,schemaExtensions:[{schema:h5,required:!1},{schema:I5,required:!1}],meta:{resourceType:"ResourceType",location:y5(J.request,`${J.basePath}/ResourceTypes/User`)}});if(J.supportsGroups)Z.push({schemas:[f9],id:"Group",name:"Group",description:"Group",endpoint:J.groupsUrl,schema:O1,schemaExtensions:[{schema:Y5,required:!1}],meta:{resourceType:"ResourceType",location:y5(J.request,`${J.basePath}/ResourceTypes/Group`)}});return Z}function D4(J){let Z=[];if(J.supportsUsers)Z.push({schemas:[Z1],id:P1,name:"User",description:"User Account",meta:{resourceType:"Schema",location:y5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(P1)}`)},attributes:[I("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),I("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),I("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),I("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[I("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),I("familyName","string","The family name of the User.",{multiValued:!1}),I("givenName","string","The given name of the User.",{multiValued:!1}),I("middleName","string","The middle name(s) of the User.",{multiValued:!1}),I("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),I("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),I("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),I("nickName","string","The casual way to address the user.",{multiValued:!1}),I("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),I("title","string","The user title, such as Vice President.",{multiValued:!1}),I("userType","string","The relationship between the organization and the User.",{multiValued:!1}),I("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),I("locale","string","Default location for localizing values.",{multiValued:!1}),I("timezone","string","The User time zone.",{multiValued:!1}),I("active","boolean","The User administrative status.",{multiValued:!1}),I("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[I("value","string","Email address value.",{multiValued:!1,required:!0}),I("display","string","Display label for the email.",{multiValued:!1}),I("type","string","Email type such as work or home.",{multiValued:!1}),I("primary","boolean","Primary email indicator.",{multiValued:!1})]}),I("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[I("value","string","Phone number value.",{multiValued:!1,required:!0}),I("display","string","Display label for the phone number.",{multiValued:!1}),I("type","string","Phone number type.",{multiValued:!1}),I("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),I("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[I("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),I("display","string","Display label for the photo.",{multiValued:!1}),I("type","string","Photo type.",{multiValued:!1}),I("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),I("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[I("formatted","string","Formatted mailing address.",{multiValued:!1}),I("streetAddress","string","Full street address component.",{multiValued:!1}),I("locality","string","City or locality.",{multiValued:!1}),I("region","string","State or region.",{multiValued:!1}),I("postalCode","string","Postal code.",{multiValued:!1}),I("country","string","Country.",{multiValued:!1}),I("type","string","Address type.",{multiValued:!1}),I("primary","boolean","Primary address indicator.",{multiValued:!1})]}),I("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[I("value","string","Group identifier.",{multiValued:!1,required:!0}),I("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),I("display","string","Display name of the group.",{multiValued:!1}),I("type","string","Relationship type.",{multiValued:!1})]}),I("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[I("value","string","Entitlement value.",{multiValued:!1,required:!0}),I("display","string","Display value.",{multiValued:!1}),I("type","string","Entitlement type.",{multiValued:!1}),I("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),I("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[I("value","string","Role value.",{multiValued:!1,required:!0}),I("display","string","Display value.",{multiValued:!1}),I("type","string","Role type.",{multiValued:!1}),I("primary","boolean","Primary role indicator.",{multiValued:!1})]}),I("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[I("value","string","Certificate value.",{multiValued:!1,required:!0}),I("display","string","Display value.",{multiValued:!1}),I("type","string","Certificate type.",{multiValued:!1}),I("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),Z.push({schemas:[Z1],id:h5,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:y5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(h5)}`)},attributes:[I("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),I("costCenter","string","Name of a cost center.",{multiValued:!1}),I("organization","string","Name of an organization.",{multiValued:!1}),I("division","string","Name of a division.",{multiValued:!1}),I("department","string","Name of a department.",{multiValued:!1}),I("manager","complex","The User manager.",{multiValued:!1,subAttributes:[I("value","string","Identifier of the manager User resource.",{multiValued:!1}),I("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),I("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),Z.push({schemas:[Z1],id:I5,name:"IoniteUser",description:"ionite User extension carrying the Enterprise Controlled ID (ECID) identity correlator and the account purpose (accountClass). See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:y5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(I5)}`)},attributes:[I("ecid","string","Enterprise Controlled ID formatted as 'ecid:<realm>:<opaque>' (realm = the minting authority's id). Correlates multiple accounts to one identity.",{multiValued:!1,caseExact:!0}),I("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1})]}),Z.push({schemas:[Z1],id:Y5,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:y5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(Y5)}`)},attributes:[I("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),I("requestable","boolean","Whether this catalog entry should be requestable access in IAM tooling.",{multiValued:!1,required:!1}),I("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),I("assignableSubjectTypes","string","AppDev-owned hard ceiling of principal kinds (user, workload) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),I("recommendedSubjectTypes","string","AppDev advisory default principal kinds (subset of assignableSubjectTypes). Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]})]});if(J.supportsGroups)Z.push({schemas:[Z1],id:O1,name:"Group",description:"Group",meta:{resourceType:"Schema",location:y5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(O1)}`)},attributes:[I("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),I("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),I("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),I("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[I("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),I("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group"]}),I("display","string","Display name of the member.",{multiValued:!1}),I("type","string","Member type.",{multiValued:!1})]})]});return Z}function _4(J,Z,$,X,Q,G,F,B,W,L,f,u,t,J5){let r={authz:X,accessStore:Q,accessIndex:G,catalogStore:F,codeCatalog:B,resources:W,log:Z,iamDelta:u,onAccessMutation:t};if(!L&&!f)return;let p={...L,...f},c=p.users?.enabled!==!1,l=p.groups?.enabled!==!1;if(Boolean(p.url||p.userStore||F||B)&&!$)Z.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function s(){if(!$)throw Z.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"}),Error("IAM requires workload identity for SCIM push/pull operations");return $}async function $5(x){let U=s(),h=x.headers.get("Authorization");if(!h?.startsWith("Bearer "))return!1;try{let n=h.substring(7);return(await U.validateToken(n)).valid}catch{return!1}}async function j5(){let x=s(),U=typeof x.getServerToken==="function"?await x.getServerToken():await x.getToken();return new Headers({"Content-Type":Y1,Accept:Y1,Authorization:`Bearer ${U}`})}async function q5(x,U,h,n){if(!p.url)throw Error("IAM URL not configured for outgoing requests");let e=`${p.url}${U}`;try{let i=await j5(),V=await fetch(e,{method:x,headers:i,body:h?JSON.stringify(h):void 0}),A=await V.json();if(!V.ok)return{success:!1,error:A,status:V.status};let K=await n["~standard"].validate(A);if(K.issues)return Z.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:K.issues}),{success:!1,error:{schemas:[Q9],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${K.issues.map((H)=>H.message).join("; ")}`},status:400};return{success:!0,data:K.value,status:V.status}}catch(i){return{success:!1,error:{schemas:[Q9],status:"500",detail:i instanceof Error?i.message:"Unknown error occurred"},status:500}}}function t5(){return p.url}function g5(x,U){let h=f5(U?.usersUrl??p.usersUrl??"/api/iam/Users")??"/api/iam/Users",n=f5(U?.groupsUrl??p.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",e=f5(U?.discovery?.basePath??p.discovery?.basePath)??V4(h,n);if(!e)return;return{request:x,basePath:e,usersUrl:h,groupsUrl:n,supportsUsers:c&&Boolean(p.userStore),supportsGroups:l&&Boolean(F||B)}}async function m5(x){let U=N4(x,p.discovery);return await p.discovery?.buildServiceProviderConfig?.(x,U)??U}async function C5(x){let U=M4(x);return await p.discovery?.buildResourceTypes?.(x,U)??U}async function T5(x){let U=D4(x);return await p.discovery?.buildSchemas?.(x,U)??U}async function p5(x,U){let h=g5(x,U);if(!h)return;let n=z1(new URL(x.url).pathname),{basePath:e}=h;if(n!==e&&!n.startsWith(`${e}/`))return;let i=z1(n.slice(e.length)||"/");if(!(i==="/ServiceProviderConfig"||i==="/ResourceTypes"||i.startsWith("/ResourceTypes/")||i==="/Schemas"||i.startsWith("/Schemas/")))return;if(x.method!=="GET")return k(405,"Method not allowed");if(!await $5(x))return k(401,"Authorization required");if(i==="/ServiceProviderConfig")return H5(await m5(h));if(i==="/ResourceTypes")return d5(await C5(h));if(i.startsWith("/ResourceTypes/")){let K=decodeURIComponent(i.slice(15)),H=(await C5(h)).find((N)=>N.id===K||N.name===K);return H?H5(H):k(404,"Resource not found")}if(i==="/Schemas")return d5(await T5(h));if(i.startsWith("/Schemas/")){let K=decodeURIComponent(i.slice(9)),H=(await T5(h)).find((N)=>N.id===K);return H?H5(H):k(404,"Resource not found")}return}let N5,u5;if(p.url)u5=async(U,h)=>{let n={...U,schemas:U.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return q5("POST","/Users",n,J.user)},N5={createGroup:async(U,h)=>{let n={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:U,externalId:h?.externalId,members:h?.members};return q5("POST","/Groups",n,J.group)}};let S5;if(F||B){let x=G9(B,F),U=async(M)=>{if(!W?.entitlement)return;let[_,D,E]=await Promise.all([x.groups.get(M),x.roles.get(M),x.permissions.get(M)]);if(_||D||E)return;return G1(await W.entitlement(M))},h=(M,_)=>k(403,`Entitlement "${M}" is derived from the application's resource data (ResourceProvider.entitlements); its definition cannot be ${_} through SCIM. Member add/remove is allowed; the definition changes only when the application's resources or derivation logic change.`,"mutability"),n=(M)=>{if(!B)return;let _=B.groups.get(M);if(_)return{entity:_,type:"group"};let D=B.roles.get(M);if(D)return{entity:D,type:"role"};let E=B.permissions.get(M);if(E)return{entity:E,type:"permission"};return},e=(M,_)=>k(403,`Entitlement "${M}" is declared in application code (authz.catalog); its definition cannot be ${_} through SCIM. Member add/remove is allowed; the definition changes only when the application code changes.`,"mutability"),i=(M)=>M.path==="members"||Boolean(M.path?.startsWith("members[")),V=async(M,_)=>{if(!await $5(M))return k(401,"Authorization required");let E=new URL(M.url),P=_?.basePath??"/Groups",w=E.pathname;if(w.startsWith(P))w=w.substring(P.length);let R=w.match(/^\/([^/]+)$/)?.[1],v=M.method;try{if(R)switch(v){case"GET":return await K(R);case"PUT":return await N(M,R);case"PATCH":return await z(M,R);case"DELETE":return await j(R);default:return k(405,"Method not allowed")}else if(w===""||w==="/")switch(v){case"GET":return await A(M);case"POST":return await H(M);default:return k(405,"Method not allowed")}return k(404,"Resource not found")}catch(y){if(y instanceof a5)return h9(y);if($9(y))return k(409,y.message,"uniqueness");return Z.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},y),k(500,y instanceof Error?y.message:"Internal server error")}},A=async(M)=>{let _=new URL(M.url),D=_.searchParams.get("startIndex"),E=_.searchParams.get("count"),P=D!=null?parseInt(D,10):void 0,w=E!=null?parseInt(E,10):void 0,q=P!=null&&!Number.isNaN(P)?Math.max(0,P-1):0,R=w!=null&&!Number.isNaN(w)?w:void 0,v=_.searchParams.get("filter"),y=p9(v);if(y!==void 0){let T=await G4(x,Q,W,y,J5),b=T?[T]:[];return d5(b,{totalResults:b.length,startIndex:1,itemsPerPage:b.length})}let Y=W4(v),O=await L4(x,Q,W,{start:q,limit:R,filter:Y},J5);return d5(O.resources,{totalResults:O.total,startIndex:q+1,itemsPerPage:O.count})},K=async(M)=>{let _=await _1(x,Q,W,M,J5);if(!_)return k(404,`Group ${M} not found`,"invalidValue");return H5(_)},H=async(M)=>{let _=await M.json(),D=await n5(J.group,_);if(D.issues)return Z.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:D.issues}),k(400,`Request validation failed: ${D.issues.map((Y)=>Y.message).join("; ")}`,"invalidValue");let E=D.value;if(!E.displayName)return k(400,"displayName is required","invalidValue");if(!F)return k(501,"Group creation is not supported: this application declares its catalog in code (authz.catalog) and wires no AccessCatalogStore for SCIM-authored definitions.","invalidValue");if(E.externalId){let Y=E.externalId,O=B&&(B.groups.getByExternalId(Y)??B.roles.getByExternalId(Y)??B.permissions.getByExternalId(Y)),T=!O&&W?.entitlements?(await H9(W)).find((S)=>S.externalId===Y):void 0,b=O||T;if(b)throw new L9(`externalId "${Y}" is already used by ${O?"code-declared":"resource-derived"} entitlement "${b.id}"`,"unique_violation","externalId")}let P=Q1(E),w=u9(),q=s1(E),R=X1(new Map,$1(E.members,P,w,q)),v;await k5(r,async()=>{v=await Z9(x,E,w)},R,()=>J9(X,v,P));let y=await O5(x,Q,W,P,w);return H5(E5(v,P,y),201)},N=async(M,_)=>{let D=await M.json(),E=await n5(J.group,D);if(E.issues)return Z.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:E.issues}),k(400,`Request validation failed: ${E.issues.map((C)=>C.message).join("; ")}`,"invalidValue");let P=E.value,w=Q1(P);if(!await _1(x,Q,W,_))return k(404,`Group ${_} not found`,"invalidValue");let R=n(_),v=R?void 0:await U(_),y=R??(v?{entity:v,type:"group"}:void 0);if(y){if($4(P,y.entity,y.type))return R?e(_,"replaced"):h(_,"replaced");let C=j1(y.entity),g=Q?(await Q.listByTarget(y.type,_)).items:[],d=X1(m9(g),$1(P.members,y.type,_,C));await k5(r,async()=>{},d);let a=await O5(x,Q,W,y.type,_);return H5(E5(y.entity,y.type,a))}let Y=s1(P),O=Q?(await Q.listByTarget(w,_)).items:[],T=X1(m9(O),$1(P.members,w,_,Y)),b;await k5(r,async()=>{b=await Z9(x,P,_)},T,()=>J9(X,b,w));let S=await O5(x,Q,W,w,_);return H5(E5(b,w,S))},z=async(M,_)=>{let D=await _1(x,Q,W,_);if(!D)return k(404,`Group ${_} not found`,"invalidValue");let E=n(_),P=E?void 0:await U(_),w=E??(P?{entity:P,type:"group"}:void 0),q=await M.json();if(w&&(q.Operations??[]).some((S)=>!i(S)))return E?e(_,"patched"):h(_,"patched");let R={...D};for(let S of q.Operations??[])if(S.op==="replace"&&S.path&&S.value!==void 0){if(S.path==="displayName")R.displayName=S.value;else if(S.path===`${Y5}.requestable`)R[Y5]={...R[Y5],requestable:Boolean(S.value)};else if(S.path===`${Y5}.description`)R[Y5]={...R[Y5],description:String(S.value)}}else if(S.op==="add"&&S.path==="members"&&S.value!==void 0){let C=S.value;R.members=[...R.members??[],...C]}else if(S.op==="remove"&&S.path?.startsWith("members[")){let C=S.path.match(/members\[value eq "([^"]+)"\]/);if(C)R.members=(R.members??[]).filter((g)=>g.value!==C[1])}let v=await n5(J.group,R);if(v.issues)return Z.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:v.issues}),k(400,`Request validation failed: ${v.issues.map((S)=>S.message).join("; ")}`,"invalidValue");let y=Q1(R),Y=w?j1(w.entity):s1(R),O=X1($1(D.members,y,_,Y),$1(R.members,y,_,Y)),T;await k5(r,async()=>{if(!w)T=await Z9(x,R,_)},O,w?void 0:()=>J9(X,T,y));let b=await O5(x,Q,W,y,_);return H5(E5(w?.entity??T,y,b))},j=async(M)=>{let _=await _1(x,Q,W,M);if(!_)return k(404,`Group ${M} not found`,"invalidValue");if(n(M))return e(M,"deleted");if(await U(M))return h(M,"deleted");let D=Q1(_);if(Q){let E=await Q.listByTarget(D,M),P=[];for(let w of E.items)await E1(r,w,P);await K9(r,P)}return await F4(x,M),new Response(null,{status:204})};S5={handler:V}}let L5;if(p.userStore){let{userStore:x,inboundUsers:U}=p,h=(Y)=>Y?.find((O)=>O.primary)?.value||Y?.[0]?.value,n=(Y)=>{if(Y.scimName)return Y.scimName;if(!Y.name)return;let[O,...T]=Y.name.split(" ");return{givenName:O,familyName:T.join(" ")||void 0}},e=(Y)=>Object.keys(Y.scimSchemaExtensions??{}).filter((O)=>O.startsWith("urn:")&&Y.scimSchemaExtensions?.[O]!==void 0),i=(Y)=>{let O={};if(Y.ecid!==void 0)O.ecid=Y.ecid;if(Y.accountClass!==void 0)O.accountClass=Y.accountClass;return O.ecid!==void 0||O.accountClass!==void 0?O:void 0},V=(Y)=>{let O=new Set([P1]);if(Y.scimEnterprise!==void 0)O.add(h5);if(i(Y)!==void 0)O.add(I5);for(let T of e(Y))O.add(T);return Array.from(O)},A=(Y)=>{let O={};if(Y.scimEnterprise!==void 0)O[h5]=Y.scimEnterprise;let T=i(Y);if(T!==void 0)O[I5]=T;for(let[b,S]of Object.entries(Y.scimSchemaExtensions??{}))if(b.startsWith("urn:")&&b!==I5&&S!==void 0)O[b]=S;return O},K=(Y)=>{let O=Y.userName||Y.email||Y.id||"",T=Y.emails??(Y.email?[{value:Y.email,primary:!0}]:[]);return{schemas:V(Y),id:Y.id,externalId:Y.externalId,userName:O,displayName:Y.displayName??Y.name??O,name:n(Y),nickName:Y.nickName,profileUrl:Y.avatar,title:Y.title,userType:Y.userType,preferredLanguage:Y.preferredLanguage,locale:Y.locale,timezone:Y.timezone,active:Y.active??!0,emails:T,phoneNumbers:Y.phoneNumbers,ims:Y.ims,photos:Y.photos,addresses:Y.addresses,groups:Y.groups,entitlements:Y.entitlements,roles:Y.roles,x509Certificates:Y.x509Certificates,meta:{resourceType:"User",created:(Y.createdAt??Y.updatedAt??new Date).toISOString(),lastModified:(Y.updatedAt??Y.createdAt??new Date).toISOString()},...A(Y)}},H=async(Y)=>{if(U?.mapBaseUserToScim)return await U.mapBaseUserToScim(Y);return K(Y)},N=async(Y,O)=>{if(U?.mapValidatedScimToBaseUser)return await U.mapValidatedScimToBaseUser(Y,O);let T=new Date,b=h(Y.emails),S=Y.name?.formatted||[Y.name?.givenName,Y.name?.middleName,Y.name?.familyName].filter(Boolean).join(" ").trim()||Y.displayName,C=Y.id||O.existing?.id||u9(),g=Y.userName||b||O.existing?.userName||C,d=S||Y.displayName||O.existing?.name||g,a=Object.fromEntries(Object.entries(Y).filter(([P5,v5])=>P5.startsWith("urn:")&&P5!==h5&&P5!==I5&&v5!==void 0)),Z5=Y[I5],i5=Z5?.ecid!==void 0&&Z5.ecid!==null?A1(Z5.ecid):O.existing?.ecid,z5=Z5?.accountClass??O.existing?.accountClass,o=O.existing?.sso;return{...O.existing??{},id:C,userName:g,name:d,email:b||O.existing?.email||g,avatar:Y.profileUrl,sso:{...o??{},profile:{...o?.profile??{},sub:C,iss:o?.profile.iss??"iam-provisioned",aud:o?.profile.aud??"iam-provisioned",exp:o?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:o?.profile.iat??Math.floor(Date.now()/1000),email:b||O.existing?.email||g,email_verified:!0,name:d,preferred_username:g},tenant:o?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:o?.scope??"openid profile email",tokenType:o?.tokenType??"Bearer",expires:o?.expires??new Date(Date.now()+3600000)},externalId:Y.externalId,ecid:i5,accountClass:z5,displayName:Y.displayName,scimName:Y.name,emails:Y.emails,nickName:Y.nickName,title:Y.title,preferredLanguage:Y.preferredLanguage,locale:Y.locale,timezone:Y.timezone,active:Y.active,phoneNumbers:Y.phoneNumbers,ims:Y.ims,photos:Y.photos,addresses:Y.addresses,groups:Y.groups,entitlements:Y.entitlements,roles:Y.roles,x509Certificates:Y.x509Certificates,scimEnterprise:Y[h5],scimSchemaExtensions:Object.keys(a).length>0?a:void 0,createdAt:O.existing?.createdAt??(Y.meta?.created?new Date(Y.meta.created):T),updatedAt:Y.meta?.lastModified?new Date(Y.meta.lastModified):T,userType:Y.userType}},z=(Y,O,T)=>{Y[O]=T},j=(Y,O,T)=>{let b=Y[O];if(Array.isArray(b)){Y[O]=[...b,...Array.isArray(T)?T:[T]];return}if(b&&typeof b==="object"&&!Array.isArray(b)&&T&&typeof T==="object"&&!Array.isArray(T)){Y[O]={...b,...T};return}Y[O]=T},M=(Y,O,T)=>{let b=O.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),S=b?[b[1],...b[2]?.split(":")??[]]:O.split("."),C=Y;for(let d of S.slice(0,-1)){let a=C[d];if(a===void 0){if(!T)return null;C[d]={}}else if(a===null||typeof a!=="object"||Array.isArray(a)){if(!T)return null;C[d]={}}C=C[d]}let g=S.at(-1);if(!g)return null;return{parent:C,key:g}},_=(Y,O)=>{let T=O.op.toLowerCase();if(!O.path){if(T!=="remove"&&O.value&&typeof O.value==="object"&&!Array.isArray(O.value))Object.assign(Y,O.value);return}let b=O.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(b&&T==="remove"){let[,C,g]=b,d=Y[C];if(Array.isArray(d))Y[C]=d.filter((a)=>!(a&&typeof a==="object"&&("value"in a)&&a.value===g));return}let S=M(Y,O.path,T!=="remove");if(!S)return;if(T==="remove"){delete S.parent[S.key];return}if(T==="add"){j(S.parent,S.key,O.value);return}z(S.parent,S.key,O.value)},D=async(Y,O)=>{if(!await $5(Y))return k(401,"Authorization required");let b=new URL(Y.url),S=O?.basePath??"/Users",C=b.pathname;if(C.startsWith(S))C=C.substring(S.length);let d=C.match(/^\/([^/]+)$/)?.[1],a=Y.method;try{if(d)switch(a){case"GET":return await P(d);case"PUT":return await R(Y,d);case"PATCH":return await v(Y,d);case"DELETE":return await y(d);default:return k(405,"Method not allowed")}else if(C===""||C==="/")switch(a){case"GET":return await E(Y);case"POST":return await q(Y);default:return k(405,"Method not allowed")}return k(404,"Resource not found")}catch(Z5){if(Z5 instanceof a5)return h9(Z5);if($9(Z5))return k(409,Z5.message,"uniqueness");return Z.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},Z5),k(500,Z5 instanceof Error?Z5.message:"Internal server error")}},E=async(Y)=>{let O=new URL(Y.url),T=O.searchParams.get("startIndex"),b=O.searchParams.get("count"),S=T!=null?parseInt(T,10):void 0,C=b!=null?parseInt(b,10):void 0,g=S!=null&&!Number.isNaN(S)?Math.max(0,S-1):0,d=C!=null&&!Number.isNaN(C)?C:void 0,a=p9(O.searchParams.get("filter"));if(a!==void 0){let z5=await x.lookup({externalId:a}),o=z5?[await H(z5)]:[];return d5(o,{totalResults:o.length,startIndex:1,itemsPerPage:o.length})}let Z5=await x.list({start:g,limit:d}),i5=await Promise.all(Z5.items.map((z5)=>H(z5)));return d5(i5,{totalResults:Z5.total,startIndex:g+1,itemsPerPage:Z5.count})},P=async(Y)=>{let O=await x.get(Y);if(!O)return k(404,`User ${Y} not found`,"invalidValue");return H5(await H(O))},w=async(Y,O)=>{let T=r.accessIndex;if(!T?.setSubjectDisabled||!O.id)return;let b=Y?Y.active??!0:!0,S=O.active??!0;if(Y&&b===S)return;if(!Y&&S)return;await T.setSubjectDisabled(O.id,"user",!S)},q=async(Y)=>{let O=await Y.json(),T=await n5(J.user,O);if(T.issues)return Z.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:T.issues}),k(400,`Request validation failed: ${T.issues.map((C)=>C.message).join("; ")}`,"invalidValue");let b=T.value;if(!b.userName&&!b.emails?.[0]?.value)return k(400,"userName or email is required","invalidValue");let S=await N(b,{mode:"create"});return await k5(r,async()=>{await x.upsert(S),await w(void 0,S)},r1(void 0,S),async()=>{await e1(X,S)}),H5(await H(S),201)},R=async(Y,O)=>{let T=await x.get(O);if(!T)return k(404,`User ${O} not found`,"invalidValue");let b=await Y.json(),S=await n5(J.user,b);if(S.issues)return Z.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:S.issues}),k(400,`Request validation failed: ${S.issues.map((d)=>d.message).join("; ")}`,"invalidValue");let C=S.value,g=await N({...C,id:O},{existing:T,mode:"replace"});return g.createdAt=T.createdAt,g.updatedAt=new Date,await k5(r,async()=>{await x.upsert(g),await w(T,g)},r1(T,g),async()=>{await e1(X,g)}),H5(await H(g))},v=async(Y,O)=>{let T=await x.get(O);if(!T)return k(404,`User ${O} not found`,"invalidValue");let S=(await Y.json()).Operations??[],g={...await H(T)};for(let Z5 of S)_(g,Z5);let d=await n5(J.user,g);if(d.issues)return Z.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:d.issues}),k(400,`Request validation failed: ${d.issues.map((Z5)=>Z5.message).join("; ")}`,"invalidValue");let a=await N(d.value,{existing:T,mode:"patch"});return a.updatedAt=new Date,await k5(r,async()=>{await x.upsert(a),await w(T,a)},r1(T,a),async()=>{await e1(X,a)}),H5(await H(a))},y=async(Y)=>{if(!await x.get(Y))return k(404,`User ${Y} not found`,"invalidValue");if(Q){let T=await Q.listBySubject(Y,"user"),b=[];for(let S of T.items)await E1(r,S,b);await K9(r,b)}if(await x.delete(Y),await r.accessIndex?.setSubjectDisabled?.(Y,"user",!1),r.authz.oaa.isReady())await F9(r,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>r.authz.oaa.deleteUser(Y),{id:Y,kind:"user"});return new Response(null,{status:204})};L5={handler:D}}async function M5(x,U){s();let h=new URL(x.url).pathname,n=f5(U?.usersUrl??p.usersUrl??"/api/iam/Users")??"/api/iam/Users",e=f5(U?.groupsUrl??p.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",i=await p5(x,U);if(i)return i;let V=(A)=>h===A||h.startsWith(`${A}/`);if(V(n)){if(!c)return k(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!L5)return k(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return L5.handler(x,{basePath:n})}if(V(e)){if(!l)return k(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!S5)return k(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return S5.handler(x,{basePath:e})}return k(404,"Resource not found")}return{...p,createUser:u5,getBaseUrl:t5,groups_outbound:N5,groups_inbound:S5,users_inbound:L5,handler:M5,delta:u}}function V9(J,Z){let $=new TextEncoder().encode(J),X=typeof Z==="string"?new TextEncoder().encode(Z):Z,Q=new Uint8Array($.length+1+X.length);return Q.set($,0),Q[$.length]=46,Q.set(X,$.length+1),Q}function z4(J){let Z=J.replace(/-/g,"+").replace(/_/g,"/"),$=Z.length%4===0?"":"=".repeat(4-Z.length%4),X=atob(Z+$),Q=new Uint8Array(X.length);for(let G=0;G<X.length;G++)Q[G]=X.charCodeAt(G);return Q}function P4(J){let Z="";for(let $ of J)Z+=String.fromCharCode($);return btoa(Z).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function c9(J){let Z=JSON.parse(J);if(!Z||typeof Z!=="object"||!Array.isArray(Z.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return Z}function O4(J){return JSON.stringify(J)}async function E4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x},{name:"Ed25519"},!0,["verify"])}async function j4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x,d:J.d},{name:"Ed25519"},!0,["sign"])}async function A4(J){let $=(typeof J.jwks==="string"?c9(J.jwks):J.jwks).keys.find((X)=>X.kid===J.kid&&X.kty==="OKP"&&X.crv==="Ed25519");if(!$?.x)return!1;try{let X=await E4($),Q=V9(J.requestId,J.rawBody),G=z4(J.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},X,G,Q)}catch{return!1}}async function w4(J){let Z=await j4(J.privateKeyJwk),$=V9(J.requestId,J.rawBody),X=await crypto.subtle.sign({name:"Ed25519"},Z,$);return P4(new Uint8Array(X))}async function I4(J){let Z=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),$=await crypto.subtle.exportKey("jwk",Z.privateKey),Q=(await crypto.subtle.exportKey("jwk",Z.publicKey)).x,G=$.d;if(!Q||!G)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:Q,d:G,kid:J,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:Q,kid:J,alg:"EdDSA",use:"sig"}]}}}var L1={jwksTtlSeconds:{min:60,max:86400,default:600},jwksMaxEntries:{min:16,max:4096,default:256},sessionReadTtlSeconds:{min:1,max:300,default:30},sessionReadMaxEntries:{min:16,max:65536,default:1024}};function I1(J,Z){if(typeof J!=="number"||!Number.isFinite(J))return Z.default;let $=Math.floor(J);if($<Z.min)return Z.min;if($>Z.max)return Z.max;return $}function d9(J){return{ttlMs:I1(J?.ttlSeconds,L1.jwksTtlSeconds)*1000,maxEntries:I1(J?.maxEntries,L1.jwksMaxEntries)}}function n9(J){let Z=J?.read;return{read:{enabled:Z?.enabled===!0,ttlMs:I1(Z?.ttlSeconds,L1.sessionReadTtlSeconds)*1000,maxEntries:I1(Z?.maxEntries,L1.sessionReadMaxEntries)}}}function T4(J){return{jwks:d9(J?.jwks),session:n9(J?.session)}}function S4(J){let Z={};if(!J)return Z;let $=J.split(";");for(let X of $){let Q=X.trim();if(!Q)continue;let G=Q.indexOf("=");if(G===-1)continue;Z[Q.slice(0,G).trim()]=Q.slice(G+1).trim()}return Z}function a9(J){if(!J.expiresAt)return!1;let Z=J.expiresAt instanceof Date?J.expiresAt:new Date(J.expiresAt);return!Number.isNaN(Z.getTime())&&Date.now()>Z.getTime()}function R4(J){if(!J||typeof J!=="object"||Array.isArray(J))return;let{access_token:Z,id_token:$,refresh_token:X,tokens:Q,...G}=J;return G}function _5(J,Z){let $=J[Z];return typeof $==="string"?$:""}function x4(J,Z){let $=J.exp;if(typeof $==="number")return new Date($*1000);if(typeof $==="string"&&$.trim()){let X=Number($);if(!Number.isNaN(X))return new Date(X*1000)}if(Z instanceof Date)return Z;if(Z){let X=new Date(Z);if(!Number.isNaN(X.getTime()))return X}return new Date}function y4(J){let Z=J.claims;if(!Z?.sub||typeof Z.sub!=="string")return;let $=x4(Z,J.expiresAt);if(J.authType==="sso")return{id:Z.sub,userName:_5(Z,"preferred_username"),name:_5(Z,"name"),email:_5(Z,"email"),avatar:_5(Z,"picture")||void 0,sso:{profile:Z,tenant:{id:_5(Z,"idp")||_5(Z,"iss"),name:_5(Z,"iss")},tokenType:"Bearer",expires:$}};return{id:Z.sub,userName:_5(Z,"preferred_username"),name:_5(Z,"name"),email:_5(Z,"email"),avatar:_5(Z,"picture")||void 0,userType:"customer",ciam:{profile:Z,scope:"openid profile email",tokenType:"Bearer",expires:$}}}function b4(J){if(J.authType!=="sso"&&J.authType!=="ciam")return;if(a9(J))return;return{sid:J.sid,authType:J.authType,tenantId:typeof J.tenantId==="string"?J.tenantId:void 0,sub:J.sub,expiresAt:J.expiresAt,createdAt:J.createdAt,claims:R4(J.claims)}}function q4(J,Z){if(!J.endsWith(".session"))return!1;if(!Z||Z.length===0)return!0;return Z.some(($)=>J===`${$}.session`)}function C4(J){if(J===void 0)return;let Z=(Array.isArray(J)?J:[J]).map(($)=>$.trim()).filter(($)=>$.length>0);return Z.length>0?Z:void 0}async function t9(J,Z,$){return(await i9(J,Z,$)).map(b4).filter((Q)=>Boolean(Q))}async function i9(J,Z,$){let X=S4(J.headers.get("cookie")),Q=C4($?.cookiesPrefix),G=[],F=new Set;for(let[B,W]of Object.entries(X)){if(!q4(B,Q)||!W)continue;if(F.has(W))continue;F.add(W);let L=await Z.get(W);if(!L)continue;if(L.authType!=="sso"&&L.authType!=="ciam")continue;if(a9(L))continue;G.push(L)}return G}async function v4(J,Z,$){return(await t9(J,Z,$)).map(y4).filter((Q)=>Boolean(Q))}var U4="@ionite/core",k4=c5(D1(U4));async function f4(J,Z){let $=await R5({idToken:J,jwksUri:Z.jwksUri,issuer:Z.issuer,audience:Z.audience}),X=await k4.validate($);if(X.issues)throw Error(`ID token claims validation failed: ${X.issues.map((F)=>F.message).join("; ")}`);let Q=X.value;if(Q===void 0)throw Error("ID token claims missing");return o9(Q)}function K5(J){return Date.now()-J}function N9(J){if(J instanceof Error)return{"error.name":J.name,"error.message":J.message};return{"error.name":typeof J,"error.message":String(J)}}function T1(J,Z){if(!J)return{};try{let $=new URL(J);return{[`${Z}.origin`]:$.origin,[`${Z}.path`]:$.pathname}}catch{return{[`${Z}.path`]:J.startsWith("/")?J:`/${J}`}}}function S1(J,Z=5){if(!Array.isArray(J))return[String(J)];return J.slice(0,Z).map(($)=>{if(!$||typeof $!=="object")return String($);let X=$,Q=Array.isArray(X.path)?X.path.join("."):String(X.path??""),G=typeof X.message==="string"?X.message:String(X.message??"validation failed");return Q?`${Q}: ${G}`:G})}function h4(J){if(!J||typeof J!=="object")return{};let Z=J;return{oidc_error:typeof Z.error==="string"?Z.error:void 0,oidc_error_description:typeof Z.error_description==="string"?Z.error_description:void 0,oidc_error_uri:typeof Z.error_uri==="string"?Z.error_uri:void 0}}function g4(J,Z={}){let $=typeof J==="string"?J:J?.headers.get("cookie")??void 0;if(!$)return[];let Q=`${Z.cookiePrefix??"ion.sso"}.`,G=new Set;for(let F of Object.keys(p4($))){if(!F.startsWith(Q))continue;let B=F.slice(Q.length),W=B.lastIndexOf(".");if(W<=0)continue;let L=B.slice(0,W).trim();if(L)G.add(L)}return Array.from(G)}function m4(J,Z,$,X,Q){if(!$&&!X)return;let G=new WeakMap,F=new Map,B={...$,...X},W=!!(B.authority&&B.tokenUrl&&B.authorizationUrl&&B.clientId&&B.redirectUri&&B.scope),L={...B,authority:W?m(B.authority,"Missing 'authority' from SSO Config"):B.authority,tokenUrl:W?m(B.tokenUrl,"Missing 'tokenUrl' from SSO Config"):B.tokenUrl,authorizationUrl:W?m(B.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):B.authorizationUrl,clientId:W?m(B.clientId,"Missing 'clientId' from SSO Config"):B.clientId,redirectUri:W?m(B.redirectUri,"Missing 'redirectUri' from SSO Config"):B.redirectUri,scope:W?m(B.scope,"Missing 'scope' from SSO Config"):B.scope,responseType:B.responseType??"code",cookiesSecure:B.cookiesSecure!==void 0?B.cookiesSecure:!0,cookiesSameSite:B.cookiesSameSite!==void 0?B.cookiesSameSite:"Strict",cookiesPrefix:B.cookiesPrefix??(B.clientId?`ion.sso.${B.clientId}`:"ion.sso"),cookiesPath:B.cookiesPath??"/"},f=Math.min(600,Math.max(0,Math.floor(Number(L.rotationGraceSeconds??60))||0))*1000;function u(){let V=[];if(!L.authority)V.push("authority");if(!L.tokenUrl)V.push("tokenUrl");if(!L.authorizationUrl)V.push("authorizationUrl");if(!L.clientId)V.push("clientId");if(!L.redirectUri)V.push("redirectUri");if(!L.scope)V.push("scope");if(V.length>0)throw Error(`Missing OIDC configuration fields: ${V.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing ionite.`)}async function t(V){if(!L)throw Error("ionite SSO Manager not initialized");let A=G.get(V);if(A)return A;let K=J5(V);return G.set(V,K),K}async function J5(V){try{let{tokens:A,session:K,refreshedUser:H}=await M5(V);if(!A)return{status:"unauthenticated"};if(H)return{status:"authenticated",value:H};if(K?.claims)return{status:"authenticated",value:$5(K.claims,A,N5(K.expiresAt))};return{status:"unauthenticated"}}catch(A){if(r9(A))return{status:"unauthenticated"};return Z.error("Error parsing user from cookies",{"ion.operation":"cookie.parse","ion.outcome":"degraded"},A),{status:"degraded",error:A instanceof Error?A:void 0}}}async function r(V){let A=await t(V);return A.status==="authenticated"?A.value:void 0}async function G5(V){if(!L)throw Error("ionite SSO Manager not initialized");u();let A=m(L.redirectUri,"Missing 'redirectUri' from SSO Config"),K=m(L.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),H=m(L.clientId,"Missing 'clientId' from SSO Config"),N=m(L.scope,"Missing 'scope' from SSO Config"),z=L.cookiesSecure?V.url.replace(/^http:\/\//,"https://"):V.url,j=D5(),M=D5(64),_=D5(),D=A;try{new URL(D)}catch{if(z)try{let R=new URL(z),v=D.startsWith("//")?D.slice(1):D.startsWith("/")?D:`/${D}`;D=new URL(v,R.origin).toString()}catch{try{let R=new URL(K),v=D.startsWith("//")?D.slice(1):D.startsWith("/")?D:`/${D}`;D=new URL(v,R.origin).toString()}catch{throw Error(`Invalid redirectUri: "${A}". It must be a valid absolute URL.`)}}}let E=new URL(K);E.searchParams.append("client_id",H),E.searchParams.append("redirect_uri",D),E.searchParams.append("response_type","code"),E.searchParams.append("scope",N),E.searchParams.append("state",j),E.searchParams.append("nonce",_);let P=await J1(M);E.searchParams.append("code_challenge",P),E.searchParams.append("code_challenge_method","S256");let w=await L.beforeLogin?.({request:V}),q=w===void 0?{state:j,codeVerifier:M,nonce:_}:{state:j,codeVerifier:M,nonce:_,context:w};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:E.toString(),"Set-Cookie":U(e(j),q,L.loginStateTtl??600,"Lax")}})}async function p(V){if(!L)throw Error("ionite SSO Manager not initialized");let A;try{A=await r(V)}catch{A=void 0}let K=await L.beforeLogout?.({request:V,user:A}),H=n("session",V),N;try{N=await M5(V);let P=N.tokens?.refresh_token??n("refresh",V);if(P)await g5(P)}catch(P){Z.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},P)}if(L.sessionStore)try{let P=N?.sid??H;if(P)await L.sessionStore.delete(P)}catch(P){Z.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},P)}let z=[["Set-Cookie",h("session")]],j=await L.afterLogout?.({request:V,context:K}),M=x5(j,"/",V.url);if(M.response){let P=new Headers(M.response.headers);for(let[,w]of z)P.append("Set-Cookie",w);return new Response(M.response.body,{status:M.response.status,statusText:M.response.statusText,headers:P})}let _=M.location??"/",D=V.headers.get("accept");if(D?.includes("application/json")||D?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:_}),{status:200,headers:[["Content-Type","application/json"],...z]});return new Response("Logged out",{status:302,headers:[["Location",_],...z]})}async function c(V){if(!L)throw Error("ionite SSO Manager not initialized");if(!L.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!V.headers.get("content-type")?.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let K=await V.text(),N=new URLSearchParams(K).get("logout_token");if(!N)return new Response("Missing logout_token parameter",{status:400});let z=m(L.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),j=m(L.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),M=L.jwksUri||`${z}/protocol/openid-connect/certs`,_=await d1({logoutToken:N,jwksUri:M,issuer:z,audience:j,log:Z}),D=typeof _.sid==="string"?_.sid:void 0;if(!D)return Z.warn("Back-Channel Logout: logout_token missing sid claim",{"ion.operation":"backchannel_logout","ion.outcome":"failure"}),new Response("Invalid logout_token: missing sid claim",{status:400});return await L.sessionStore.delete(D),Z.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:D}),new Response("OK",{status:200})}catch(A){return Z.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},A),new Response("Internal Server Error",{status:500})}}async function l(V){if(!L)throw Error("ionite SSO Manager not initialized");let A=Date.now(),K=new URL(V.url),H=new URLSearchParams(K.search);Z.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":V.method,"url.path":K.pathname,hasCode:H.has("code"),hasState:H.has("state"),hasError:H.has("error"),...T1(H.get("iss")??void 0,"oidc.issuer")});let N=Object.fromEntries(H.entries()),z=await J.callbackParams.validate(N);if(z.issues)return Z.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":S1(z.issues)}),s9(z.issues,"OIDC callback parameters validation failed");let{code:j,state:M}=z.value,_;try{let D=m(M,'OIDC "state" was not present in the callback parameters'),E=n(e(D),V,!0),{codeVerifier:P,state:w,nonce:q,context:R}=E??{};_=R,Z.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(E),hasCodeVerifier:Boolean(P),hasStateVerifier:Boolean(w),hasNonce:Boolean(q),hasContext:R!==void 0});let v=m(P,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');m(w,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let y=m(q,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),Y=m(j,'OIDC "code" was not present in the callback parameters');if(M!==w)throw Z.warn("SSO callback state verification failed",{"ion.event":"ion.sso.callback.state_verification_failed","ion.operation":"sign_in.callback","ion.outcome":"failure"}),Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');Z.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let O=L.cookiesSecure?V.url.replace(/^http:\/\//,"https://"):V.url,T=await q5(Y,v,O),{tokenExpiresAt:b,sessionExpiresAt:S}=B5(T);T.expires=b.toISOString();let C=Date.now();Z.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let g=await s(T,y,S);Z.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":K5(C),"user.id":g.id});let d,a;{let o=T5("SSO requires sessionStore configuration for opaque session cookies."),P5=typeof g.sso.profile.sid==="string"?g.sso.profile.sid:void 0,v5=P5||D5(32),F5=g.id;if(Z.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(v5),hasIdpSid:Boolean(P5),hasSub:Boolean(F5),"user.id":F5}),!F5)throw Error("Session creation failed: missing sub in ID token claims");let x1=Date.now(),F1={sid:v5,sub:F5,idpSid:P5,authType:"sso",tenantId:L.tenantId,tokens:T,claims:g.sso.profile,expiresAt:S,createdAt:new Date};await p5(o,F1),a=F1,d=["Set-Cookie",U("session",v5,S)],Z.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":K5(x1),"user.id":F5})}if(L.userStore)try{let o=g.id;if(o){let P5=new Date,v5=Date.now();Z.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":o});let F5=await L.userStore.get(o);if(Z.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":K5(v5),"user.id":o,found:Boolean(F5)}),F5||L.enableJitUserProvisioning){let x1=Date.now(),F1={...F5??{},...g,id:o,tenantId:F5?.tenantId,createdAt:F5?.createdAt??P5,updatedAt:P5};await L.userStore.upsert(F1),Z.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":K5(x1),"user.id":o,existing:Boolean(F5),jitProvisioning:Boolean(L.enableJitUserProvisioning)})}else Z.warn("JIT user provisioning disabled: user not found in store and will not be created",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped","user.id":o})}else Z.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(o){Z.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...N9(o)})}Z.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":K5(A),"user.id":g.id});let Z5=[["Set-Cookie",h(e(D))],...d?[d]:[]],i5=await L.afterLogin?.({ok:!0,request:V,user:g,session:a,context:_}),z5=x5(i5,"/",V.url);if(z5.response)return U5(z5.response,Z5.map(([,o])=>o));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",z5.location],...Z5]})}catch(D){Z.error("Error during sign-in callback",{"ion.event":"ion.sso.sign_in.callback_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","duration.ms":K5(A),...N9(D)});let E=M?[["Set-Cookie",h(e(M))]]:[],P=await L.afterLogin?.({ok:!1,request:V,error:D,context:_}),w=x5(P,"/",V.url);if(w.response)return U5(w.response,E.map(([,q])=>q));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",w.location],...E]})}}function B5(V){let A=Date.now(),K=Number(V.expires_in??3600)||3600,H=new Date(A+K*1000),N;if(V.refresh_expires_in!=null&&Number.isFinite(Number(V.refresh_expires_in)))N=Number(V.refresh_expires_in);else if(V.refresh_token)N=86400;else N=K;return{tokenExpiresAt:H,sessionExpiresAt:new Date(A+N*1000)}}async function s(V,A,K){if(!L)throw Error("ionite SSO Manager not initialized");let H=Date.now(),N=await C5(V.id_token,A);return Z.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":K5(H),"user.id":N.sub,hasEmail:Boolean(N.email),hasName:Boolean(N.name)}),$5(N,V,K)}function $5(V,A,K){let H=K??B5(A).sessionExpiresAt,N=V.ecid!==void 0&&V.ecid!==null?A1(V.ecid):void 0;return{id:V.sub,userName:V.preferred_username||"",name:V.name||"",email:V.email||"",emails:[{value:V.email||"",primary:!0}],...N?{ecid:N}:{},avatar:V.picture,sso:{profile:{...V},tenant:{id:V.idp||V.iss||"",name:V.iss||""},scope:A.scope,tokenType:A.token_type,sessionState:A.session_state,expires:H}}}async function j5(V){if(!L.userStore)return V;let A=await L.userStore.lookup(V);if(!A)return V;return{...V,...A,id:V.id,sso:V.sso}}async function q5(V,A,K){if(!L)throw Error("ionite SSO Manager not initialized");u();let H=m(L.tokenUrl,"Missing 'tokenUrl' from SSO Config"),N=m(L.redirectUri,"Missing 'redirectUri' from SSO Config"),z=m(L.clientId,"Missing 'clientId' from SSO Config"),j=N;try{new URL(j)}catch{if(K)try{let _=new URL(K),D=j.startsWith("//")?j.slice(1):j.startsWith("/")?j:`/${j}`;j=new URL(D,_.origin).toString()}catch{try{let _=new URL(H),D=j.startsWith("//")?j.slice(1):j.startsWith("/")?j:`/${j}`;j=new URL(D,_.origin).toString()}catch{throw Error(`Invalid redirectUri: "${N}". It must be a valid absolute URL.`)}}}let M=new URLSearchParams;if(M.append("grant_type","authorization_code"),M.append("code",V),M.append("redirect_uri",j),M.append("client_id",z),L.clientSecret)M.append("client_secret",L.clientSecret);M.append("code_verifier",A);try{let _=Date.now();Z.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...T1(H,"oidc.token_url"),...T1(j,"oidc.redirect_uri"),hasClientSecret:Boolean(L.clientSecret)});let D=await fetch(H,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:M.toString()});Z.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":D.status,"duration.ms":K5(_)}),Z.debug("SSO token exchange response body read started",{"ion.event":"ion.sso.token.response_body_read_started","ion.module":"sso","ion.operation":"token.exchange"});let E=await D.json();if(Z.debug("SSO token exchange response body read completed",{"ion.event":"ion.sso.token.response_body_read_completed","ion.module":"sso","ion.operation":"token.exchange","duration.ms":K5(_)}),!D.ok){Z.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":D.status,"duration.ms":K5(_),...h4(E)});let w=E;throw Error(`Token exchange failed: ${w.error||D.statusText} - ${w.error_description||""}`.trim())}let P=await J.tokenResponse.validate(E);if(P.issues)throw Z.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":K5(_),"validation.issues":S1(P.issues)}),Error(`Token response validation failed: ${P.issues}`);return Z.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":K5(_),tokenType:P.value.token_type,hasAccessToken:Boolean(P.value.access_token),hasIdToken:Boolean(P.value.id_token),hasRefreshToken:Boolean(P.value.refresh_token),expiresIn:P.value.expires_in}),P.value}catch(_){throw Z.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...N9(_)}),_}}async function t5(V){return g1(async()=>{if(!L)throw Error("ionite SSO Manager not initialized");u();let A=m(L.tokenUrl,"Missing 'tokenUrl' from SSO Config"),K=m(L.clientId,"Missing 'clientId' from SSO Config"),H=new URLSearchParams;H.append("grant_type","refresh_token"),H.append("refresh_token",V),H.append("client_id",K);let N=await fetch(A,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:H.toString()}),z=await N.json();if(!N.ok){Z.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:z});let M=z;throw Error(`Token refresh failed: ${M.error||N.statusText} - ${M.error_description||""}`.trim())}let j=await J.tokenResponse.validate(z);if(j.issues)throw Z.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":S1(j.issues)}),Error(`Token refresh response validation failed: ${j.issues}`);return j.value},void 0,void 0,void 0,Z)}async function g5(V){try{if(!L)throw Error("ionite SSO Manager not initialized");if(!L.revocationEndpoint)return;let A=m(L.clientId,"Missing 'clientId' from SSO Config"),K=new URLSearchParams;K.append("token",V),K.append("token_type_hint","refresh_token"),K.append("client_id",A);let H=await fetch(L.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:K.toString()});if(!H.ok)Z.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:H.status,statusText:H.statusText});else Z.info("Token revoked successfully",{"ion.module":"sso"})}catch(A){Z.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},A)}}async function m5(){if(!L)throw Error("ionite SSO Manager not initialized");let V=L.authority;if(!L.jwksUri&&!V)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let A=L.jwksUri||`${V}/protocol/openid-connect/certs`;return r5(A,Z)}async function C5(V,A){let K=Date.now(),H=m(L.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),N=m(L.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),z=L.jwksUri||`${H}/protocol/openid-connect/certs`;Z.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...T1(z,"oidc.jwks_uri")});let j;try{j=await R5({idToken:V,jwksUri:z,issuer:H,audience:N,expectedNonce:A,log:Z})}catch(_){throw Z.error("SSO ID token verification failed",{"ion.event":"ion.sso.id_token.verify_failed","ion.module":"sso","ion.operation":"id_token.verify","ion.outcome":"failure","duration.ms":K5(K)},_),_}Z.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":K5(K)});let M=await J.idTokenClaims.validate(j);if(M.issues)throw Z.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":K5(K),"validation.issues":S1(M.issues)}),Error(`ID token claims validation failed: ${M.issues}`);return Z.debug("SSO ID token claims validated",{"ion.event":"ion.sso.id_token.claims_validated","ion.module":"sso","ion.operation":"id_token.validate","ion.outcome":"success","duration.ms":K5(K),"user.id":M.value.sub,hasIssuer:Boolean(M.value.iss),hasAudience:Boolean(M.value.aud)}),M.value}function T5(V="SSO sessionStore is required for opaque session cookies."){if(!L.sessionStore)throw Error(V);return L.sessionStore}async function p5(V,A){try{await V.create(A)}catch(K){if(!await V.get(A.sid))throw K;await V.update(A.sid,A)}}function N5(V){if(!V)return;if(V instanceof Date)return V;let A=new Date(V);return Number.isNaN(A.getTime())?void 0:A}function u5(V){let A=V.tokens;if(!A?.access_token||!A.id_token||!A.token_type)return;return A}async function S5(V,A=!1){let K=T5(),H=n("session",V);if(!H)return{tokens:void 0,refreshHeaders:[]};let N=await K.get(H);if(N&&L.tenantId&&N.tenantId&&N.tenantId!==L.tenantId)return{tokens:void 0,refreshHeaders:[["Set-Cookie",h("session")]],sid:H};if(N?.authType!=="sso")return{tokens:void 0,refreshHeaders:[["Set-Cookie",h("session")]],sid:H};let z=u5(N);if(!z)return{tokens:void 0,refreshHeaders:[["Set-Cookie",h("session")]],sid:H};let j=N5(N.expiresAt);if(j?Date.now()>j.getTime():!1)return await K.delete(H),{tokens:void 0,sid:H,refreshHeaders:[["Set-Cookie",h("session")]]};let _=N5(z.expires),D=_?Date.now()>_.getTime():!0;if((A||D)&&z.refresh_token)return L5(H,N,z);return{tokens:z,sid:H,session:N,refreshHeaders:[]}}function L5(V,A,K){let H=F.get(V);if(H)return H;let N=T5(),z=(async()=>{let j=await t5(K.refresh_token),{tokenExpiresAt:M,sessionExpiresAt:_}=B5(j);j.expires=M.toISOString();let D=await s(j,void 0,_),E=D.sso.profile,P=D5(32),w={...A,sid:P,tokens:j,claims:E,expiresAt:_,createdAt:new Date};await p5(N,w);try{if(f<=0)await N.delete(V);else{let{refresh_token:q,...R}=K;await N.update(V,{tokens:R,expiresAt:new Date(Date.now()+f)})}}catch(q){Z.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},q)}return{tokens:j,sid:P,session:w,refreshedUser:D,refreshHeaders:[["Set-Cookie",U("session",P,_)]]}})();return F.set(V,z),z.finally(()=>{F.delete(V)})}async function M5(V,A=!1){return S5(V,A)}async function x(V){let{tokens:A}=await M5(V);if(!A)return;return A.access_token}function U(V,A,K,H=L.cookiesSameSite??"Strict"){if(!L)throw Error("ionite SSO Manager not initialized");if(V=`${L.cookiesPrefix}.${V}`,typeof A!=="string")A=btoa(JSON.stringify(A));let N;if(K instanceof Date)N=`Expires=${K.toUTCString()}`;else if(typeof K==="number")N=`Max-Age=${K}`;else throw Error("Invalid expires type",K);if(A.length>4000)throw Error(`Error setting cookie: ${V}. Cookie length is: ${A.length}`);return`${V}=${A}; ${N}; Path=${L.cookiesPath}; HttpOnly;${L.cookiesSecure?" Secure;":""} SameSite=${H};`}function h(V){if(!L)throw Error("ionite SSO Manager not initialized");return`${L.cookiesPrefix}.${V}=; Max-Age=0; Path=${L.cookiesPath}; HttpOnly;${L.cookiesSecure?" Secure;":""} SameSite=${L.cookiesSameSite};`}function n(V,A,K=!1){if(!L)throw Error("ionite SSO Manager not initialized");let H=A.headers.get("cookie");if(!H)return null;let N=`${L.cookiesPrefix}.${V}`,z=H.split(";").find((D)=>D.trim().startsWith(`${N}=`));if(!z)return null;let j=z.indexOf("="),M=z.slice(j+1).trim();if(!K)return M;let _=atob(M);return JSON.parse(_)}function e(V){return`state_${V}`}async function i(V,A){if(!L)throw Error("ionite SSO Manager not initialized");let{loginUrl:K,userUrl:H,tokenUrl:N,refreshUrl:z,logoutUrl:j,logoutBackChannelUrl:M,jwksUrl:_,redirectUri:D}={...L,...A},E=new URL(V.url).pathname;if(D){let P;try{P=new URL(D).pathname}catch{try{let w=new URL(V.url),q=D.startsWith("//")?D.slice(1):D;P=new URL(q,w.origin).pathname}catch{P=D.startsWith("/")?D:`/${D}`}}if(P===E)return l(V)}if(K===E)return G5(V);if(H===E)try{let{tokens:P,session:w,refreshedUser:q,refreshHeaders:R}=await M5(V);if(!P)return new Response("User not logged in",{status:401,headers:R});let v=q??(w?.claims?$5(w.claims,P,N5(w.expiresAt)):void 0);if(!v)return new Response("User not logged in",{status:401,headers:R});let y=await j5(v);return new Response(JSON.stringify(y),{headers:[["Content-Type","application/json"],...R]})}catch(P){if(r9(P))return new Response("User not logged in",{status:401});return Z.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},P),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:{"Content-Type":"application/json"}})}if(N===E){let{tokens:P,refreshHeaders:w}=await M5(V);if(!P)return new Response("User not logged in",{status:401,headers:w});return new Response(JSON.stringify({token:P.access_token,expires:P.expires}),{headers:[["Content-Type","application/json"],...w]})}if(z===E){let{tokens:P,refreshHeaders:w}=await M5(V,!0);if(!P)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:w})}if(j===E)return p(V);if(M===E)return c(V);if(_===E){let P=await m5();return new Response(JSON.stringify(P),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...L,getUser:r,resolveUser:t,getJwt:x,initiateLogin:G5,logout:p,logoutBackChannel:c,callbackHandler:l,handler:i}}function p4(J){let Z={},$=J.split(";");for(let X of $){let Q=X.trim();if(!Q)continue;let G=Q.indexOf("=");if(G===-1)continue;let F=Q.slice(0,G).trim(),B=Q.slice(G+1).trim();Z[F]=B}return Z}function r9(J){if(!(J instanceof Error))return!1;return["Public key not found","Invalid JWT","Invalid JWT signature","ID token expired","ID token issuer mismatch","ID token audience mismatch","ID token nonce mismatch","ID token missing exp","invalid_grant"].some((Z)=>J.message.includes(Z))}function e9(J){return J=J??"SSO Unavailable",new Response(JSON.stringify({error:J}),{status:503,statusText:J,headers:{"Content-Type":"application/json"}})}var R1="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function u4(J,Z){return m(Z,R1),Z.sso?.getUser(J)}async function l4(J,Z){return m(Z,R1),await Z.sso?.resolveUser(J)??{status:"unauthenticated"}}async function c4(J,Z){m(Z,R1);let $=Z.sso;if(!$)return e9();return $.initiateLogin(J)}async function d4(J,Z){m(Z,R1);let $=Z.sso;if(!$)return e9();return $.callbackHandler(J)}export{U5 as withSetCookies,G1 as withDefaultExternalId,f4 as verifyUser,d1 as verifyLogoutToken,A4 as verifyLfvSignature,R5 as verifyIdToken,O4 as stringifyLfvJwks,m4 as sso,w4 as signLfvPayload,z2 as setJwksRetry,_2 as setJwksClock,y2 as setDiscoveryClock,t4 as sendTenantWebhook,i1 as sameOriginRedirectRules,l4 as resolveUser,n9 as resolveSessionCacheConfig,o1 as resolveRedirect,C1 as resolveProviderBranding,d9 as resolveJwksCacheConfig,j2 as resolveJwkForKid,d2 as resolveCustomer,V1 as resolveCiamProvider,m2 as resolveCapturedRedirect,T4 as resolveCacheConfig,x5 as resolveAfterRedirect,W9 as reconcileSubjectAccess,J1 as pkceChallengeFromVerifier,c9 as parseLfvJwks,v1 as orderedEnabledProviders,e5 as normalizeOidcIssuer,g4 as listSsoClientIdsFromCookies,v9 as isRedirectAllowed,c4 as initiateLogin,_4 as iam,V2 as hasScope,G2 as hasRole,W2 as hasPermission,L2 as hasGroup,N2 as hasAnyScope,F2 as hasAny,M2 as hasAllScope,H2 as hasAll,B2 as has,p1 as getVerificationKeyForKid,u4 as getUser,A2 as getPublicKeyFromJwks,w2 as getPublicKeyForKid,q1 as getProviderPreset,r5 as getJwks,v4 as getDiscoveredSessionUsers,c2 as getCustomer,m1 as getCachedVerificationKey,I4 as generateLfvEd25519KeyPair,t1 as generateAppleClientSecret,a1 as fetchUserInfo,B9 as expandRoot,c1 as exchangeAuthorizationCode,t9 as discoverSessions,i9 as discoverSessionRecords,n1 as discoverOidcEndpoints,h2 as defaultRedirectPolicies,D2 as configureJwksCache,n4 as collectReferencedDefinitions,E2 as clearJwksCache,b2 as clearDiscoveryCache,l2 as ciam,g2 as captureRedirect,d4 as callback,V9 as buildLfvSigningInput,l1 as buildAuthorizationUrl,b9 as blockDangerousUrls,R9 as assertTrustedIdTokenClaims,C9 as allowSameOrigin,q9 as allowRelativePaths,k2 as allowOrigins,f2 as allowHosts,a4 as InMemoryTenantStore,Y9 as CatalogAdjacencyCache,P9 as CIAM_PROVIDER_PRESETS,L1 as CACHE_BOUNDS};
1
+ import{A as s9,E as P1,I as o9,K as L9,L as $9,O as a4,P as t4,Q as B5,R as X9,T as I5,a as D9,d as l9,e as M5,f as W1,g as G1,h as Y9,i as B9,j as W9,k as n4,o as G9,u as A1,v as U9,w as k9,x as D1,y as n5,z as p}from"./shared/core-f0gk15rd.js";var J2="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",M9=["user","customer","workload"],Z2={user:async(J,Z)=>Z.sso?.getUser(J),customer:async(J,Z)=>Z.ciam?.getCustomer(J),workload:async(J,Z)=>{let $=await Z.workload?.getWorkloadIdentity?.(J);if(!$)return;let X=$.clientId??$.workloadId??$.claims.sub;return X?{...$,id:X}:void 0}};function $2(J){if(J==="any")return M9;let Z=Array.isArray(J)?J:[J];return M9.filter(($)=>Z.includes($))}function X2(J){let Z=J.headers.get("cookie");if(!Z)return[];return Z.split(";").map(($)=>$.slice(0,$.indexOf("=")===-1?$.length:$.indexOf("=")).trim()).filter(Boolean)}function Q2(J,Z){let $=J.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,X=X2(J),Q=new Set;for(let H of X){if(H.startsWith("ion.sso"))Q.add("user");if(H.startsWith("ion.ciam"))Q.add("customer")}let L=X.length>0&&!Q.has("user")&&!Q.has("customer");return Z.filter((H)=>{if(H==="workload")return $;if(X.length===0)return!1;return Q.has(H)||L})}function X5(J){return typeof J==="string"?J:J.id}function _9(J){let{subject:Z,subjectType:$}=J,X;if($==="user")X=Z.sso?.scope;else if($==="customer")X=Z.ciam?.scope;else if($==="workload")X=Z.scope;return new Set((X??"").split(/\s+/).filter(Boolean))}function b1(J,Z,$){let X=_9(J),Q=Z.filter((H)=>X.has(H));return{allow:$==="any"?Q.length>0:Z.length>0&&Q.length===Z.length,metadata:{reason:"scope",wantedScopes:Z,matchedScopes:Q}}}function d5(J,Z){return($)=>{if(J.length===0)return;let X=_9($),Q=J.filter((H)=>X.has(H));return(Z==="any"?Q.length>0:Q.length===J.length)?Q:void 0}}function H1(J,Z,$){return(X)=>{if(Z.length===0||X.subjectType!=="workload")return;let Q=D9(J.config?.authz,X.subject);if(!Q)return;let L=Z.filter((B)=>Q.has(B));return($==="any"?L.length>0:L.length===Z.length)?L:void 0}}function K2(J,Z){if(J.subjectType==="workload"){let $=J.subject.scopesAsEntitlements;if(typeof $==="boolean")return $}return Z.config?.authz?.scopesAsEntitlements===!0}function y1(J,Z,$,X,Q){return{allow:$==="ok",subject:Z?.subject,subjectType:Z?.subjectType,reason:$,decision:X,response(){if($==="ok")return new Response(null,{status:204});if($==="unauthenticated")return J.log.warn("authz.denied",{reason:$,...Q()}),Response.json({error:"Unauthorized"},{status:401});if($==="not_configured")return J.log.warn("authz.denied",{reason:$,subject:Z?.subject?.id,subjectType:Z?.subjectType,...Q()}),Response.json({error:"not_configured"},{status:503});return J.log.warn("authz.denied",{reason:$,subject:Z?.subject?.id,subjectType:Z?.subjectType,...Q()}),Response.json({error:"Forbidden"},{status:403})}}}function Y2(J,Z,$){return new Promise((X)=>{let Q=[],L=J.length,H=!1,B=()=>{if(L-=1,L===0&&!H)H=!0,X({outcomes:Q})};for(let W of J)Z(W).then((F)=>{if(Q.push({principal:W,decision:F}),!H&&F.allow){H=!0,X({matched:{principal:W,decision:F},outcomes:Q});return}B()},(F)=>{$?.(W,F),Q.push({principal:W,decision:{allow:!1,metadata:{reason:"error"}}}),B()})})}async function A5(J,Z,$,X,Q,L,H){p(Z,J2);let B=Q2(J,$2($)),F=(await Promise.all(B.map(async(q)=>{let c=await Z2[q](J,Z);return c?.id?{subject:c,subjectType:q,subjectId:c.id}:void 0}))).filter((q)=>q!==void 0);if(F.length===0)return y1(Z,void 0,"unauthenticated",void 0,Q);let g=async(q)=>{let c=Z.authz.accessIndex;if(!c?.isSubjectDisabled)return!1;return c.isSubjectDisabled(q.subjectId,q.subjectType)},u=async(q)=>{if(H){let c=H(q);if(c&&c.length>0){if(await g(q))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:c}}}}if(L&&K2(q,Z)){let c=L(q);if(c&&c.length>0){if(await g(q))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:c}}}}return X(q)},{matched:t,outcomes:o}=await Y2(F,u,(q,c)=>{Z.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:q.subjectId,subjectType:q.subjectType,error:c instanceof Error?c.message:String(c),...Q()})});if(t){if(t.decision.metadata?.reason==="scope")Z.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:t.principal.subjectId,subjectType:t.principal.subjectType,matchedScopes:t.decision.metadata.matchedScopes,...Q()});return y1(Z,t.principal,"ok",t.decision,Q)}let F5=o.length>0&&o.every((q)=>{let c=q.decision.metadata?.reason;return c==="access_index_not_configured"||c==="error"}),i=o[0],H5=F5?"not_configured":"forbidden";return y1(Z,i?.principal,H5,i?.decision,Q)}async function B2(J,Z,$,X,Q,L="any"){return A5(J,Z,L,(H)=>Z.authz.has(H.subjectId,$,X,Q,H.subjectType),()=>({targetType:$,target:X5(X),resource:Q?X5(Q):void 0}),Q?void 0:d5([X5(X)],"any"),$==="permission"&&!Q?H1(Z,[X5(X)],"any"):void 0)}async function W2(J,Z,$,X,Q="any"){return A5(J,Z,Q,(L)=>Z.authz.hasPermission(L.subjectId,$,X,L.subjectType),()=>({targetType:"permission",target:X5($),resource:X?X5(X):void 0}),X?void 0:d5([X5($)],"any"),X?void 0:H1(Z,[X5($)],"any"))}async function G2(J,Z,$,X,Q="any"){return A5(J,Z,Q,(L)=>Z.authz.hasRole(L.subjectId,$,X,L.subjectType),()=>({targetType:"role",target:X5($),resource:X?X5(X):void 0}),X?void 0:d5([X5($)],"any"))}async function L2(J,Z,$,X,Q="any"){return A5(J,Z,Q,(L)=>Z.authz.hasGroup(L.subjectId,$,X,L.subjectType),()=>({targetType:"group",target:X5($),resource:X?X5(X):void 0}),X?void 0:d5([X5($)],"any"))}async function F2(J,Z,$,X="any"){let Q=$.filter((H)=>!H.resource).map((H)=>X5(H.target)),L=$.filter((H)=>!H.resource&&H.targetType==="permission").map((H)=>X5(H.target));return A5(J,Z,X,(H)=>Z.authz.hasAny(H.subjectId,$,H.subjectType),()=>({targets:$.map((H)=>`${H.targetType}:${X5(H.target)}`)}),Q.length>0?d5(Q,"any"):void 0,L.length>0?H1(Z,L,"any"):void 0)}async function H2(J,Z,$,X="any"){let Q=$.length>0&&$.every((B)=>!B.resource),L=$.length>0&&$.every((B)=>!B.resource&&B.targetType==="permission"),H=$.map((B)=>X5(B.target));return A5(J,Z,X,(B)=>Z.authz.hasAll(B.subjectId,$,B.subjectType),()=>({targets:$.map((B)=>`${B.targetType}:${X5(B.target)}`)}),Q?d5(H,"all"):void 0,L?H1(Z,H,"all"):void 0)}async function V2(J,Z,$,X="any"){return A5(J,Z,X,(Q)=>Promise.resolve(b1(Q,[$],"any")),()=>({scope:$}))}async function N2(J,Z,$,X="any"){return A5(J,Z,X,(Q)=>Promise.resolve(b1(Q,$,"any")),()=>({scopes:$}))}async function M2(J,Z,$,X="any"){return A5(J,Z,X,(Q)=>Promise.resolve(b1(Q,$,"all")),()=>({scopes:$}))}function K5(J){return typeof J==="string"&&J.length>0?J:void 0}function P9(J){let Z=K5(J.email);return{sub:String(J.sub??""),email:Z,name:K5(J.name),userName:K5(J.preferred_username)??Z,avatar:K5(J.picture)}}var z9={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:P9},google:{flow:"id_token",authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",jwksUri:"https://www.googleapis.com/oauth2/v3/certs",scope:"openid email profile",branding:{displayName:"Google",iconUrl:"https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg",colors:{light:"#ffffff",dark:"#131314",secondary:"#4285F4"},url:"https://accounts.google.com"},mapClaims:P9},microsoft:{flow:"id_token",authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",jwksUri:"https://login.microsoftonline.com/common/discovery/v2.0/keys",scope:"openid email profile",branding:{displayName:"Microsoft",colors:{light:"#ffffff",dark:"#2f2f2f",secondary:"#0067b8"},url:"https://login.microsoftonline.com"},mapClaims:(J)=>{let Z=K5(J.email)??K5(J.preferred_username);return{sub:String(J.sub??J.oid??""),email:Z,name:K5(J.name),userName:K5(J.preferred_username)??Z,avatar:K5(J.picture)}}},apple:{flow:"id_token",authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",jwksUri:"https://appleid.apple.com/auth/keys",scope:"openid email name",extraAuthParams:{response_mode:"form_post"},branding:{displayName:"Apple",colors:{light:"#000000",dark:"#ffffff"},url:"https://appleid.apple.com"},mapClaims:(J)=>{let Z=K5(J.email);return{sub:String(J.sub??""),email:Z,name:K5(J.name),userName:Z}}},github:{flow:"userinfo",authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",scope:"read:user user:email",branding:{displayName:"GitHub",colors:{light:"#24292f",dark:"#ffffff"},url:"https://github.com"},mapClaims:(J)=>({sub:String(J.id??J.node_id??""),email:K5(J.email),name:K5(J.name)??K5(J.login),userName:K5(J.login),avatar:K5(J.avatar_url)})}};function q1(J){if(J==="magic-link")return;return z9[J]}function V1(J,Z){if(Z.type==="magic-link")return;let $=q1(Z.type);if(!$)return;return{name:J,type:Z.type,flow:$.flow,authorizationUrl:Z.authorizationUrl??$.authorizationUrl,tokenUrl:Z.tokenUrl??$.tokenUrl,jwksUri:Z.jwksUri??$.jwksUri,userInfoUrl:Z.userInfoUrl??$.userInfoUrl,scope:Z.scope??$.scope,clientId:Z.clientId,clientSecret:Z.clientSecret,extraAuthParams:$.extraAuthParams,branding:{...$.branding,...Z.branding},mapClaims:$.mapClaims,config:Z}}function C1(J){return{...q1(J.type)?.branding??{displayName:J.type},...J.branding}}function v1(J){if(!J)return[];return Object.entries(J).filter(([,Z])=>Z.enabled!==!1).map(([Z,$],X)=>({name:Z,config:$,index:X})).sort((Z,$)=>{let X=Z.config.order??Number.MAX_SAFE_INTEGER,Q=$.config.order??Number.MAX_SAFE_INTEGER;if(X!==Q)return X-Q;return Z.index-$.index}).map(({name:Z,config:$})=>({name:Z,config:$}))}var E9=600000,k1=256,L5=new Map;function D2(J){if(typeof J?.ttlMs==="number"&&Number.isFinite(J.ttlMs))E9=Math.min(Math.max(J.ttlMs,60000),86400000);if(typeof J?.maxEntries==="number"&&Number.isFinite(J.maxEntries)){k1=Math.max(1,Math.floor(J.maxEntries));while(L5.size>k1){let Z=L5.keys().next().value;if(Z===void 0)break;L5.delete(Z)}}}function O9(J,Z){L5.delete(J),L5.set(J,Z);while(L5.size>k1){let $=L5.keys().next().value;if($===void 0)break;L5.delete($)}}var o5=new Map,f1=()=>Date.now();function _2(J){f1=J??(()=>Date.now())}var h1={};function P2(J){h1=J??{}}function z2(J){if(!J)return;if(/\bno-store\b/i.test(J))return 60000;let Z=/max-age\s*=\s*(\d+)/i.exec(J);if(!Z)return;let $=Number(Z[1]);return Number.isFinite($)?$*1000:void 0}function O2(J){let $=z2(J)??E9;return Math.min(Math.max($,60000),86400000)}async function g1(J,Z=3,$=1000,X=30000,Q){let L=Error("Placeholder Error");for(let H=0;H<=Z;H++)try{return await J()}catch(B){if(L=B instanceof Error?B:Error(String(B)),B instanceof Error&&B.message.includes("400"))throw B;if(H===Z)throw L;let W=Math.min($*2**H,X),F=Math.random()*0.1*W;await new Promise((g)=>setTimeout(g,W+F)),Q?.warn(`Retry attempt ${H+1} after ${W+F}ms delay`)}throw L}async function r5(J,Z,$){let X=L5.get(J);if(!$?.forceRefresh&&X&&X.expiresAt>f1())return O9(J,X),X.jwks;let Q=o5.get(J);if(Q)return Q;let L=(async()=>{try{return await g1(async()=>{let H=await fetch(J);if(!H.ok)throw Error("Failed to fetch JWKS");let B=await H.json(),W=O2(H.headers.get("cache-control"));return O9(J,{jwks:B,expiresAt:f1()+W,importedKeys:new Map}),B},h1.maxRetries,h1.baseDelayMs,void 0,Z)}catch(H){let B=L5.get(J);if(B)return Z?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),B.jwks;throw H}finally{o5.delete(J)}})();return o5.set(J,L),L}function E2(J){if(J){L5.delete(J),o5.delete(J);return}L5.clear(),o5.clear()}async function j2(J,Z,$){return(await j9(J,Z,$)).jwk}async function j9(J,Z,$){if(!Z?.trim())throw Error("JWT header missing kid");await r5(J,$);let X=L5.get(J),Q=X?.jwks.keys.find((L)=>L.kid===Z);if(!Q)await r5(J,$,{forceRefresh:!0}),X=L5.get(J),Q=X?.jwks.keys.find((L)=>L.kid===Z);if(!X||!Q)throw Error("Public key not found");return{jwk:Q,entry:X}}async function m1(J,Z,$,X,Q){let{jwk:L,entry:H}=await j9(J,Z,Q),B=`${Z}\x00${$}`,W=H.importedKeys.get(B);if(W)return W;let F=X(L);return F.catch(()=>{if(H.importedKeys.get(B)===F)H.importedKeys.delete(B)}),H.importedKeys.set(B,F),F}async function A2(J,Z){let $=J.keys.find((X)=>X.kid===Z);if(!$)throw Error("Public key not found");return A9($)}function A9(J){return crypto.subtle.importKey("jwk",{kty:J.kty,n:J.n,e:J.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function w2(J,Z,$){return m1(J,Z,"rs256",A9,$)}var U1={RS256:{kty:"RSA",importParams:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},verifyParams:{name:"RSASSA-PKCS1-v1_5"}},ES256:{kty:"EC",crv:"P-256",importParams:{name:"ECDSA",namedCurve:"P-256"},verifyParams:{name:"ECDSA",hash:"SHA-256"}}};async function p1(J,Z,$,X){if(typeof $!=="string"||!($ in U1))throw Error(`Unsupported JWT alg "${String($)}" (allowed: ${Object.keys(U1).join(", ")})`);let Q=U1[$];return{key:await m1(J,Z,`oidc:${$}`,(H)=>{if(H.kty!==Q.kty)throw Error(`JWK type "${H.kty}" does not match token alg "${$}"`);if(Q.kty==="EC"){let B=H;if(B.crv!==Q.crv)throw Error(`JWK curve "${String(B.crv)}" does not match token alg "${$}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:B.crv,x:B.x,y:B.y},Q.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:H.kty,n:H.n,e:H.e},Q.importParams,!1,["verify"])},X),algorithm:Q.verifyParams}}function _5(J=32){let Z=new Uint8Array(J);return crypto.getRandomValues(Z),Array.from(Z,($)=>$.toString(16).padStart(2,"0")).join("").substring(0,J)}function N1(J){let Z="";return J.forEach(($)=>{Z+=String.fromCharCode($)}),btoa(Z).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function T9(J){let Z=J.replace(/-/g,"+").replace(/_/g,"/"),$=Z.padEnd(Z.length+(4-Z.length%4)%4,"="),X=atob($),Q=new Uint8Array(X.length);for(let L=0;L<X.length;L++)Q[L]=X.charCodeAt(L);return Q}function w9(J){let Z=new TextDecoder().decode(T9(J));return JSON.parse(Z)}async function J1(J){let Z=new TextEncoder().encode(J),$=await crypto.subtle.digest("SHA-256",Z);return N1(new Uint8Array($))}function l1(J){let Z=new URL(J.authorizationUrl);if(Z.searchParams.set("client_id",J.clientId),Z.searchParams.set("redirect_uri",J.redirectUri),Z.searchParams.set("response_type","code"),Z.searchParams.set("scope",J.scope),Z.searchParams.set("state",J.state),J.codeChallenge)Z.searchParams.set("code_challenge",J.codeChallenge),Z.searchParams.set("code_challenge_method","S256");if(J.nonce)Z.searchParams.set("nonce",J.nonce);for(let[$,X]of Object.entries(J.extraParams??{}))Z.searchParams.set($,X);return Z.toString()}async function c1(J){let Z=new URLSearchParams;if(Z.append("grant_type","authorization_code"),Z.append("code",J.code),Z.append("redirect_uri",J.redirectUri),Z.append("client_id",J.clientId),J.clientSecret)Z.append("client_secret",J.clientSecret);if(J.codeVerifier)Z.append("code_verifier",J.codeVerifier);let $=await fetch(J.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Z.toString()}),X=await $.json();if(!$.ok){let Q=X;throw J.log?.error("OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":$.status,oidc_error:Q.error}),Error(`Token exchange failed: ${Q.error||$.statusText} - ${Q.error_description||""}`.trim())}if(typeof X.access_token!=="string")throw Error("Token exchange response missing access_token");return X}var S9=60;function e5(J){return J.trim().replace(/\/$/,"")}function R9(J){let{claims:Z,audience:$}=J,X=e5(J.issuer),Q=J.nowSec??Math.floor(Date.now()/1000),L=J.clockSkewSec??S9,H=Z.iss;if(typeof H!=="string"||e5(H)!==X)throw Error("ID token issuer mismatch");let B=Z.aud,W=Array.isArray(B)?B.includes($):typeof B==="string"&&B===$,F=typeof Z.azp==="string"&&Z.azp===$;if(!W&&!F)throw Error("ID token audience mismatch");if(typeof Z.exp!=="number")throw Error("ID token missing exp");if(Z.exp<Q-L)throw Error("ID token expired");if(J.expectedNonce!==void 0){if(Z.nonce!==J.expectedNonce)throw Error("ID token nonce mismatch")}}async function x9(J,Z,$){let X=J.split(".");if(X.length!==3)throw Error("Invalid JWT");let Q=w9(X[0]),L=w9(X[1]),H=T9(X[2]),{key:B,algorithm:W}=await p1(Z,Q.kid,Q.alg,$),F=new TextEncoder().encode(`${X[0]}.${X[1]}`);if(!await crypto.subtle.verify(W,B,H,F))throw Error("Invalid JWT signature");return{header:Q,payload:L}}async function S5(J){let{payload:Z}=await x9(J.idToken,J.jwksUri,J.log);return R9({claims:Z,issuer:J.issuer,audience:J.audience,clockSkewSec:J.clockSkewSec,expectedNonce:J.expectedNonce}),Z}var I2="http://schemas.openid.net/event/backchannel-logout";async function d1(J){let{payload:Z}=await x9(J.logoutToken,J.jwksUri,J.log),$=e5(J.issuer),X=Z.iss;if(typeof X!=="string"||e5(X)!==$)throw Error("Logout token issuer mismatch");let Q=Z.aud,L=Array.isArray(Q)?Q.includes(J.audience):typeof Q==="string"&&Q===J.audience,H=typeof Z.azp==="string"&&Z.azp===J.audience;if(!L&&!H)throw Error("Logout token audience mismatch");if(Z.nonce!=null)throw Error("Logout token must not contain a nonce");let B=Z.events;if(!(typeof B==="object"&&B!==null&&!Array.isArray(B)&&Object.hasOwn(B,I2)))throw Error("Logout token missing back-channel logout event");let F=typeof Z.sid==="string"&&Z.sid.length>0,g=typeof Z.sub==="string"&&Z.sub.length>0;if(!F&&!g)throw Error("Logout token missing sid and sub");if(typeof Z.exp==="number"){let u=Math.floor(Date.now()/1000),t=J.clockSkewSec??S9;if(Z.exp<u-t)throw Error("Logout token expired")}return Z}var T2=3600000,S2=60000,R2=86400000,x2=256,w5=new Map,s5=new Map;function I9(J,Z){w5.delete(J),w5.set(J,Z);while(w5.size>x2){let $=w5.keys().next().value;if($===void 0)break;w5.delete($)}}var u1=()=>Date.now();function y2(J){u1=J??(()=>Date.now())}function b2(J){if(J){w5.delete(J),s5.delete(J);return}w5.clear(),s5.clear()}function q2(J){let Z=J?/max-age\s*=\s*(\d+)/i.exec(J):null,$=Z?Number(Z[1]):Number.NaN,X=Number.isFinite($)?$*1000:T2;return Math.min(Math.max(X,S2),R2)}async function n1(J){let Z=w5.get(J);if(Z&&Z.expiresAt>u1())return I9(J,Z),Z.endpoints;let $=s5.get(J);if($)return $;let X=(async()=>{try{let Q=J.replace(/\/$/,""),L=await fetch(`${Q}/.well-known/openid-configuration`,{headers:{Accept:"application/json"}});if(!L.ok)throw Error(`OIDC discovery failed for ${J} with status ${L.status}`);let H=await L.json(),B={authorizationUrl:typeof H.authorization_endpoint==="string"?H.authorization_endpoint:void 0,tokenUrl:typeof H.token_endpoint==="string"?H.token_endpoint:void 0,jwksUri:typeof H.jwks_uri==="string"?H.jwks_uri:void 0,userInfoUrl:typeof H.userinfo_endpoint==="string"?H.userinfo_endpoint:void 0};return I9(J,{endpoints:B,expiresAt:u1()+q2(L.headers.get("cache-control"))}),B}catch(Q){let L=w5.get(J);if(L)return L.endpoints;throw Q}finally{s5.delete(J)}})();return s5.set(J,X),X}async function a1(J,Z){let $=await fetch(J,{headers:{Authorization:`Bearer ${Z}`,Accept:"application/json","User-Agent":"ionite-ciam"}});if(!$.ok)throw Error(`UserInfo request failed with status ${$.status}`);return await $.json()}function C2(J){let Z=J.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),$=atob(Z),X=new Uint8Array($.length);for(let Q=0;Q<$.length;Q++)X[Q]=$.charCodeAt(Q);return X}async function t1(J){let Z=Math.floor(Date.now()/1000),$={alg:"ES256",kid:J.keyId,typ:"JWT"},X={iss:J.teamId,iat:Z,exp:Z+(J.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:J.clientId},Q=N1(new TextEncoder().encode(JSON.stringify($))),L=N1(new TextEncoder().encode(JSON.stringify(X))),H=`${Q}.${L}`,B=await crypto.subtle.importKey("pkcs8",C2(J.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),W=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},B,new TextEncoder().encode(H));return`${H}.${N1(new Uint8Array(W))}`}function v2(J){for(let Z=0;Z<J.length;Z++){let $=J.charCodeAt(Z);if($<=31||$===127)return!0}return!1}function U2(J,Z){let $=null;try{$=new URL(J,Z)}catch{$=null}let X="";try{X=new URL(Z).origin}catch{X=""}return{candidate:J,url:$,requestOrigin:X}}function y9(J,Z,$){let X=U2(J,$),Q=!1;for(let L of Z){let H=L(X);if(H==="deny")return!1;if(H==="allow")Q=!0}return Q}function b9(){return({candidate:J,url:Z})=>{if(v2(J))return"deny";if(J.includes("\\"))return"deny";if(J.startsWith("//"))return"deny";if(!Z)return"deny";if(Z.protocol!=="http:"&&Z.protocol!=="https:")return"deny";if(Z.username||Z.password)return"deny";return"abstain"}}function q9(){return({candidate:J})=>J.startsWith("/")&&!J.startsWith("//")&&!J.startsWith("/\\")?"allow":"abstain"}function C9(){return({url:J,requestOrigin:Z})=>J&&Z&&J.origin===Z?"allow":"abstain"}function k2(...J){let Z=new Set(J.map(($)=>{try{return new URL($).origin}catch{return $}}));return({url:$})=>$&&Z.has($.origin)?"allow":"abstain"}function f2(...J){let Z=J.map(($)=>$.toLowerCase());return({url:$})=>{if(!$)return"abstain";let X=$.hostname.toLowerCase();for(let Q of Z)if(Q.startsWith(".")){if(X===Q.slice(1)||X.endsWith(Q))return"allow"}else if(X===Q)return"allow";return"abstain"}}function i1(){return[b9(),q9(),C9()]}function v9(J,Z,$){if(!J)return!1;return y9(J,Z,$)}function o1(J,Z){if(!J)return Z.fallback;return y9(J,Z.rules,Z.requestUrl)?J:Z.fallback}var h2={rules:i1(),fallback:"/"};function g2(J,Z,$="redirect"){let X=new URL(J.url).searchParams.get($)??void 0;return v9(X,Z.rules,J.url)?{redirect:X}:void 0}function m2(J,Z){let $=J.context;return o1($?.redirect,{rules:Z.rules,fallback:Z.fallback,requestUrl:J.request.url})}function R5(J,Z,$){if(J instanceof Response)return{response:J};if(typeof J==="string")return{location:o1(J,{rules:i1(),fallback:Z,requestUrl:$})};return{location:Z}}function C5(J,Z){if(Z.length===0)return J;let $=new Headers(J.headers);for(let X of Z)$.append("Set-Cookie",X);return new Response(J.body,{status:J.status,statusText:J.statusText,headers:$})}var M1="ciam",p2="id_token",u2="access_token";function l2(J,Z,$,X,Q,L){if(!$&&!X)return;let H=new WeakMap,B={...$,...X},W={...B,magicLinkTtl:B.magicLinkTtl??3600,sessionTtl:B.sessionTtl??86400,cookiesSecure:B.cookiesSecure!==void 0?B.cookiesSecure:!0,cookiesSameSite:B.cookiesSameSite!==void 0?B.cookiesSameSite:"Strict",cookiesPrefix:B.cookiesPrefix??(B.ciamId?`ion.ciam.${B.ciamId}`:"ion.ciam"),cookiesPath:B.cookiesPath??"/"};function F(){if(!W.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return W.sessionStore}function g(){F()}let u=J.callbackParams??n5(U9("ionite.ciam")),t=J.idTokenClaims??n5(D1("ionite.ciam")),o=J.tokenResponse??n5(k9("ionite.ciam"));function F5(K=32){let N=new Uint8Array(K);return crypto.getRandomValues(N),Array.from(N,(V)=>V.toString(16).padStart(2,"0")).join("").substring(0,K)}function i(K,N,V,D=W.cookiesSameSite??"Strict"){if(!W)throw Error("ionite CIAM Manager not initialized");if(K=`${W.cookiesPrefix}.${K}`,typeof N!=="string")N=btoa(JSON.stringify(N));let E;if(V instanceof Date)E=`Expires=${V.toUTCString()}`;else if(typeof V==="number")E=`Max-Age=${V}`;else throw Error("Invalid expires type",V);if(N.length>4000)throw Error(`Error setting cookie: ${K}. Cookie length is: ${N.length}`);return`${K}=${N}; ${E}; Path=${W.cookiesPath}; HttpOnly;${W.cookiesSecure?" Secure;":""} SameSite=${D};`}function H5(K){if(!W)throw Error("ionite CIAM Manager not initialized");return`${W.cookiesPrefix}.${K}=; Max-Age=0; Path=${W.cookiesPath}; HttpOnly;${W.cookiesSecure?" Secure;":""} SameSite=${W.cookiesSameSite};`}function q(K,N,V=!1){if(!W)throw Error("ionite CIAM Manager not initialized");let D=N.headers.get("cookie");if(!D)return null;let E=`${W.cookiesPrefix}.${K}`,A=D.split(";").find((j)=>j.trim().startsWith(`${E}=`));if(!A)return null;let _=A.indexOf("="),M=A.substring(_+1).trim();if(!V)return M;try{let j=atob(M);return JSON.parse(j)}catch(j){return Z.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:E},j),null}}function c(K){return`cstate_${K}`}async function Q5(K,N,V,D){let E=await W.afterLogin?.({...N,request:K,context:V}),A=R5(E,"/",K.url);if(A.response)return C5(A.response,D.map(([,_])=>_));return new Response(N.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",A.location],...D]})}function r(K,N){return["Set-Cookie",i("session",K,N)]}function $5(K){if(!K)return;if(K instanceof Date)return K;let N=new Date(K);return Number.isNaN(N.getTime())?void 0:N}async function D5(K){let N=q("session",K);if(!N)return;let V=await F().get(N);if(V&&W.tenantId&&V.tenantId&&V.tenantId!==W.tenantId)return;if(V?.authType!=="ciam")return;let D=$5(V.expiresAt);if(D&&Date.now()>D.getTime()){await F().delete(N);return}return V}async function f5(K){if(!W)throw Error("ionite CIAM Manager not initialized");g();let N=H.get(K);if(N)return N;let V=h5(K);return H.set(K,V),V}async function h5(K){try{let N=await D5(K);if(!N?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:z5(N.claims)}}catch(N){return Z.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},N),{status:"degraded",error:N instanceof Error?N:void 0}}}async function g5(K){let N=await f5(K);return N.status==="authenticated"?N.value:void 0}async function m5(K){if(!W)throw Error("ionite CIAM Manager not initialized");g();let N;try{N=await g5(K)}catch{N=void 0}let V=await W.beforeLogout?.({request:K,user:N});try{let P=q("session",K);if(P)await F().delete(P)}catch(P){Z.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},P)}let D=[["Set-Cookie",H5("session")]],E=await W.afterLogout?.({request:K,context:V}),A=R5(E,"/",K.url);if(A.response)return C5(A.response,D.map(([,P])=>P));let _=A.location??"/",M=K.headers.get("accept");if(M?.includes("application/json")||M?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:_}),{status:200,headers:[["Content-Type","application/json"],...D]});return new Response("Logged out",{status:302,headers:[["Location",_],...D]})}function p5(K){return K.id||K.email||`ciam-${K.userName}`}function T5(K,N,V){return{sub:p5(K),iss:M1,aud:M1,typ:p2,exp:Math.floor(V.getTime()/1000),iat:Math.floor(Date.now()/1000),email:K.email,name:K.name,preferred_username:K.userName,picture:K.avatar,sid:N}}function b5(K,N,V){return{sub:K,iss:M1,aud:M1,typ:u2,exp:Math.floor(V.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:N,scope:"openid profile email"}}function z5(K){let N=K.exp?new Date(K.exp*1000):new Date;return{id:K.sub,userName:K.preferred_username??"",name:K.name??"",email:K.email??"",avatar:K.picture,userType:"customer",ciam:{profile:K,scope:"openid profile email",tokenType:"Bearer",expires:N}}}async function u5(K){if(!W)throw Error("ionite 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(K))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let V,D;try{if(!K.headers.get("content-type")?.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let b=await K.text(),C=JSON.parse(b);D=typeof C?.redirect==="string"&&C.redirect.length>0?C.redirect:void 0;let U={userName:C.userName,name:C.name,email:C.email,avatar:C.avatar},Y=await J.customer.validate(U);if(Y.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}});V=Y.value}catch(v){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let A=new URL(K.url).searchParams.get("ttl"),_=A?parseInt(A,10):W.magicLinkTtl??3600;if(Number.isNaN(_)||_<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let M=F5(32),j=new Date(Date.now()+_*1000);if(!W.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await W.magicLinkStore.create(M,V,j)}catch(v){return Z.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},v),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let P=new URL(K.url),I=W.magicLinkLoginUrl||"/magic-link/login",T=new URL(I,P.origin);if(T.searchParams.set("token",M),D)T.searchParams.set("redirect",D);return new Response(JSON.stringify({magicLink:T.toString(),expiresAt:j.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function l5(K){if(!W)throw Error("ionite CIAM Manager not initialized");g();let V=new URL(K.url).searchParams.get("token");if(!V)return Q5(K,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!W.magicLinkStore)return Q5(K,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let D=await W.magicLinkStore.getAndDelete(V);if(!D)return Q5(K,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let E=new Date(Date.now()+(W.sessionTtl??86400)*1000),A=F5(32),_=p5(D.customer),M=T5(D.customer,A,E),j=b5(_,A,E),P=z5(M),I;try{let v={sid:A,sub:_,authType:"ciam",tenantId:W.tenantId,expiresAt:E,claims:M,accessClaims:j,createdAt:new Date};await F().create(v),I=v}catch(v){throw Z.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},v),v}if(W.customerStore)try{let v=P.id;if(v){let b=new Date,C=await W.customerStore.get(v);if(C||W.enableJitUserProvisioning){let U={...C??{},...P,id:v,tenantId:C?.tenantId,createdAt:C?.createdAt??b,updatedAt:b,userType:C?.userType??"customer"};await W.customerStore.upsert(U)}}}catch(v){Z.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},v)}let T=[r(A,E)];return Q5(K,{ok:!0,user:P,session:I},void 0,T)}function V5(K,N=200,V=[]){return new Response(JSON.stringify(K),{status:N,headers:[["Content-Type","application/json"],...V]})}function W5(K,N){try{return new URL(K).toString()}catch{let V=new URL(N).origin,D=W.cookiesSecure?V.replace(/^http:\/\//,"https://"):V;return new URL(K,D).toString()}}function c5(){let K=W.customerLoginUrl||"/auth/customer/login",N=K.includes("?")?"&":"?";return v1(W.providers).map(({name:V,config:D})=>{let E=C1(D);return{name:V,type:D.type,displayName:E.displayName,loginUrl:`${K}${N}provider=${encodeURIComponent(V)}`,iconUrl:E.iconUrl,colors:E.colors,url:E.url}})}async function x(K){if(!K)return{};let{authorizationUrl:N,tokenUrl:V,jwksUri:D,userInfoUrl:E}=K,A=K.config.authority;if(A&&(!N||!V||K.flow==="id_token"&&!D))try{let M=await n1(A);N=N??M.authorizationUrl,V=V??M.tokenUrl,D=D??M.jwksUri,E=E??M.userInfoUrl}catch(M){Z.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},M)}return{authorizationUrl:N,tokenUrl:V,jwksUri:D,userInfoUrl:E}}async function k(K){if(K.type==="apple"){let{teamId:N,keyId:V,privateKey:D,clientId:E}=K.config;if(N&&V&&D&&E)return t1({teamId:N,keyId:V,privateKey:D,clientId:E})}return K.clientSecret}async function m(K){F();let V=new URL(K.url).searchParams.get("provider");if(!V)return V5({error:"Missing required query parameter: provider"},400);let D=W.providers?.[V];if(!D||D.enabled===!1||D.type==="magic-link")return V5({error:`Unknown or disabled CIAM provider: ${V}`},404);let E=V1(V,D);if(!E?.clientId)return V5({error:`CIAM provider ${V} is not fully configured`},500);let A=await x(E);if(!A.authorizationUrl)return V5({error:`CIAM provider ${V} is missing an authorization endpoint`},500);let _=W.customerCallbackUrl||"/auth/customer/callback",M=W5(_,K.url),j=_5(),P=_5(64),I=_5(),T=E.flow==="id_token",v=T?await J1(P):void 0,b=await W.beforeLogin?.({request:K}),C=l1({authorizationUrl:A.authorizationUrl,clientId:E.clientId,redirectUri:M,scope:E.scope,state:j,codeChallenge:v,nonce:I,extraParams:E.extraAuthParams}),U={provider:V,state:j,codeVerifier:T?P:void 0,nonce:I,redirectUri:M,...b===void 0?{}:{context:b}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",C],["Set-Cookie",i(c(j),U,W.loginStateTtl??600,"Lax")]]})}async function d(K){if(K.method==="POST"){if((K.headers.get("content-type")??"").includes("application/x-www-form-urlencoded")){let V=await K.text();return Object.fromEntries(new URLSearchParams(V).entries())}}return Object.fromEntries(new URL(K.url).searchParams.entries())}async function s(K,N){let V=K.mapClaims(N);if(!V.sub)return{ok:!1};let D=`${K.name}:${V.sub}`,E={id:D,userName:V.userName||V.email||D,name:V.name||"",email:V.email||"",avatar:V.avatar,userType:"customer"},A=D;if(W.customerStore){let T=await W.customerStore.lookup(E)??await W.customerStore.get(D);if(A=T?.id??D,!T&&!W.enableJitUserProvisioning)return Z.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let v=new Date,b={...T??{},...E,id:A,tenantId:T?.tenantId,createdAt:T?.createdAt??v,updatedAt:v,userType:T?.userType??"customer"};await W.customerStore.upsert(b)}let _=new Date(Date.now()+(W.sessionTtl??86400)*1000),M=_5(32),j={sub:A,iss:K.name,aud:K.clientId,exp:Math.floor(_.getTime()/1000),iat:Math.floor(Date.now()/1000),email:V.email,name:V.name,preferred_username:V.userName??V.email,picture:V.avatar,sid:M},P={sid:M,sub:A,authType:"ciam",tenantId:W.tenantId,expiresAt:_,claims:j,accessClaims:{sub:A,sid:M,scope:K.scope},createdAt:new Date},I=F();try{await I.create(P)}catch(T){if(!await I.get(M))throw T;await I.update(M,P)}return{ok:!0,claims:j,sid:M,expires:_}}async function G(K){F();let N,V,D=(E)=>{let A=N?[["Set-Cookie",H5(N)]]:[];return Q5(K,{ok:!1,error:E},V,A)};try{let E=await d(K),A=await u.validate(E);if(A.issues||!A.value)return D(Error("Invalid CIAM callback parameters"));let{code:_,state:M}=A.value;if(!M)return D(Error("Missing CIAM callback state"));N=c(M);let j=q(N,K,!0);if(V=j?.context,!j?.provider||!j.state||j.state!==M)return Z.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),D(Error("CIAM callback state verification failed"));let P=W.providers?.[j.provider];if(!P)return D(Error("Unknown CIAM provider"));let I=V1(j.provider,P);if(!I?.clientId)return D(Error("CIAM provider not configured"));let T=await x(I);if(!T.tokenUrl)return D(Error("CIAM provider missing token endpoint"));let v=await k(I),b=await c1({tokenUrl:T.tokenUrl,clientId:I.clientId,clientSecret:v,redirectUri:j.redirectUri||W5(W.customerCallbackUrl||"/auth/customer/callback",K.url),code:_,codeVerifier:I.flow==="id_token"?j.codeVerifier:void 0,log:Z}),C;if(I.flow==="id_token"){let S=I.config.authority;if(!b.id_token||!T.jwksUri||!S)return D(Error("CIAM id_token flow misconfigured"));if(!j.nonce)return D(Error("CIAM callback state cookie missing nonce"));if((await o.validate(b)).issues)return Z.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),D(Error("CIAM token response validation failed"));C=await S5({idToken:b.id_token,jwksUri:T.jwksUri,issuer:S,audience:I.clientId,expectedNonce:j.nonce,log:Z});let R=await t.validate(C);if(!R.issues)C=R.value}else{if(!T.userInfoUrl)return D(Error("CIAM provider missing userinfo endpoint"));C=await a1(T.userInfoUrl,b.access_token);let S=I.config.authority;if(b.id_token&&T.jwksUri&&S){let y=await S5({idToken:b.id_token,jwksUri:T.jwksUri,issuer:S,audience:I.clientId,expectedNonce:j.nonce||void 0,log:Z}),R=typeof y.sub==="string"?y.sub:"";if(R){if(typeof C.sub==="string"&&C.sub.length>0&&C.sub!==R)return Z.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),D(Error("CIAM UserInfo sub mismatch"));C.sub=R}}if(typeof C.sub!=="string"||C.sub.length===0)return Z.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),D(Error("CIAM UserInfo response missing sub"))}let U=await s(I,C);if(!U.ok)return D(Error("Failed to persist CIAM customer"));let Y=z5(U.claims);Z.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:I.name});let z=[["Set-Cookie",H5(N)],r(U.sid,U.expires)];return Q5(K,{ok:!0,user:Y,session:void 0},V,z)}catch(E){return Z.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},E),D(E)}}async function O(K){if(!W)throw Error("ionite CIAM Manager not initialized");g();let N=W.magicLinkUrl||"/magic-link",V=W.magicLinkLoginUrl||"/magic-link/login",D=W.logoutUrl||"/auth/customer/logout",E=W.customerLoginUrl||"/auth/customer/login",A=W.customerCallbackUrl||"/auth/customer/callback",_=W.customerProvidersUrl||"/auth/customer/providers",M=new URL(K.url).pathname,j=(U)=>{if(!U)return;try{return new URL(U).pathname}catch{return U.startsWith("/")?U:`/${U}`}};if(j(N)===M&&K.method==="POST")return u5(K);if(j(V)===M&&K.method==="GET")return l5(K);if(j(D)===M&&K.method==="GET")return m5(K);if(j(_)===M&&K.method==="GET")return V5({providers:c5()});if(j(E)===M&&K.method==="GET")return m(K);if(j(A)===M&&(K.method==="GET"||K.method==="POST"))return G(K);return new Response("Not Found",{status:404})}return{...W,getCustomer:g5,resolveCustomer:f5,logout:m5,handler:O,listCustomerProviders:c5}}async function c2(J,Z){return p(Z,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),Z.ciam?.getCustomer(J)}async function d2(J,Z){return p(Z,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await Z.ciam?.resolveCustomer(J)??{status:"unauthenticated"}}var Y1="application/scim+json",n2="urn:ietf:params:scim:api:messages:2.0:ListResponse",Q9="urn:ietf:params:scim:api:messages:2.0:Error",z1="urn:ietf:params:scim:schemas:core:2.0:User",k5="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",O1="urn:ietf:params:scim:schemas:core:2.0:Group",a2="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",f9="urn:ietf:params:scim:schemas:core:2.0:ResourceType",Z1="urn:ietf:params:scim:schemas:core:2.0:Schema",t2="00000000000000000000000000000000";function i2(J){let Z={timestamp:new Date().toISOString()};if(J)Z.actor=J;try{let Q=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),L=Q?.traceId;if(L&&L!==t2){if(Z.traceId=L,Q?.spanId)Z.spanId=Q.spanId}}catch{}return Z}class B1 extends Error{constructor(J){super(J);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,B1.prototype)}}async function o2(J,Z,$,X,Q){let L=X.subjectType??"user";if(!X9.includes(L))throw new B1(`Cannot grant ${X.targetType} "${M5(X.target)}" to a "${L}" principal: only [${X9.join(", ")}] principals are assignable on this platform.`);let H=G9(Z,J);if(!H&&!Q)return;let B=M5(X.target),W;if(Q)W=await Q.getNode(X.targetType,B);else if(H){if(W=await(X.targetType==="group"?H.groups:X.targetType==="role"?H.roles:H.permissions).get(B),!W&&X.targetType==="group")W=await $?.entitlement?.(B)}let F=W?.assignableSubjectTypes;if(F&&F.length>0&&!F.includes(L))throw new B1(`Cannot grant ${X.targetType} "${B}" to a "${L}" principal: this entitlement restricts assignment to [${F.join(", ")}].`)}async function r2(J,Z,$,X){await o2(J.catalogStore,J.codeCatalog,J.resources,Z,X);let Q={...Z,status:Z.status??"active",provenance:Z.provenance??i2()};if(Q.id=W1(Q),await J.accessStore?.grant(Q),J.accessIndex&&(J.catalogStore||J.codeCatalog)){let L=await B9(Q,{catalog:J.catalogStore,code:J.codeCatalog,resources:J.resources,cache:X});await J.accessIndex.materialize(Q.id,L)}return $?.push({op:"add",change:Q}),Q}async function E1(J,Z,$){let X=Z.id??W1(Z);await J.accessStore?.revoke(Z),await J.accessIndex?.removeByRoot(X),$?.push({op:"delete",change:{...Z,id:X}})}async function K9(J,Z){let $=await s2(J,Z),X=await J4(J,Z);return{oaa:$,delta:X}}async function s2(J,Z){if(Z.length===0||!J.authz.oaa.isReady())return{status:"skipped"};return F9(J,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>J.authz.oaa.pushAccessChanges(Z),{count:Z.length})}async function F9(J,Z,$,X,Q){try{return await X(),{status:"ok"}}catch(L){return J.log?.warn($,{"ion.operation":Z,"ion.outcome":"degraded",...Q,error:y5(L)}),{status:"degraded",reason:y5(L)}}}var e2=6;async function J4(J,Z){let $=J.iamDelta;if(!$?.isReady()||Z.length===0)return{status:"skipped"};let X=new Map;for(let W of Z){let F=`${W.change.subjectType??"user"}:${M5(W.change.subject)}\x00${W.change.targetType}:${M5(W.change.target)}`;X.set(F,W)}let Q=[...X.values()],L=Q.map(({op:W,change:F})=>()=>W==="add"?$.onGrant(F):$.onRevoke(F)),B=(await Z4(L,e2)).filter((W)=>W.status==="rejected");if(B.length>0)return J.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:B.length,total:Q.length,error:y5(B[0]?.reason)}),{status:"degraded",reason:y5(B[0]?.reason)};return{status:"ok"}}async function Z4(J,Z){let $=Array(J.length),X=0,Q=async()=>{while(!0){let H=X++;if(H>=J.length)return;let B=J[H];if(!B)continue;try{$[H]={status:"fulfilled",value:await B()}}catch(W){$[H]={status:"rejected",reason:W}}}},L=Array.from({length:Math.min(Z,J.length)},Q);return await Promise.all(L),$}class w1 extends Error{constructor(J){super(J);this.name="DerivedRevokeError",Object.setPrototypeOf(this,w1.prototype)}}class i5 extends Error{summary;clientError;constructor(J,Z,$=!1){super(J);this.name="ScimMutationError",this.summary=Z,this.clientError=$,Object.setPrototypeOf(this,i5.prototype)}}function h(J,Z,$){return new Response(JSON.stringify({schemas:[Q9],status:String(J),scimType:$,detail:Z}),{status:J,headers:{"Content-Type":Y1}})}function a5(J,Z){let $=Z?.totalResults??J.length,X=Z?.startIndex??1,Q=Z?.itemsPerPage??J.length;return new Response(JSON.stringify({schemas:[n2],totalResults:$,startIndex:X,itemsPerPage:Q,Resources:J}),{status:200,headers:{"Content-Type":Y1}})}function N5(J,Z=200){return new Response(JSON.stringify(J),{status:Z,headers:{"Content-Type":Y1}})}function h9(J){return h(J.clientError?409:500,`${J.message}; authz mutation summary: ${JSON.stringify(J.summary)}`,J.clientError?"mutability":"invalidValue")}function K1(J){return W1(J)}function r1(J,Z){return X1(g9(J),g9(Z))}function g9(J){let Z=new Map;if(!J?.id)return Z;for(let $ of J.groups??[]){let X={subject:J.id,targetType:"group",target:$.value,metadata:$.display||$.type?{display:$.display,type:$.type}:void 0};Z.set(K1(X),X)}for(let $ of J.roles??[]){let X={subject:J.id,targetType:"role",target:$.value,metadata:$.display||$.type?{display:$.display,type:$.type,primary:$.primary}:void 0};Z.set(K1(X),X)}for(let $ of J.entitlements??[]){let X={subject:J.id,targetType:"permission",target:$.value,metadata:$.display||$.type?{display:$.display,type:$.type,primary:$.primary}:void 0};Z.set(K1(X),X)}return Z}function $1(J,Z,$,X){let Q=new Map,L=X&&X.length>0?X:void 0;for(let H of J??[]){let B={subject:H.value,targetType:Z,target:$,resources:L,metadata:H.display||H.type?{display:H.display,type:H.type}:void 0};Q.set(K1(B),B)}return Q}function s1(J){let Z=J[B5]?.resources;return Z&&Z.length>0?Z:void 0}function $4(J,Z,$){let X=J[B5];if(J.displayName!==void 0&&J.displayName!==(Z.displayName??Z.name))return!0;if(J.externalId!==void 0&&J.externalId!==Z.externalId)return!0;if(X?.type!==void 0&&X.type!==$)return!0;if(X?.requestable!==void 0&&Boolean(X.requestable)!==Boolean(Z.requestable))return!0;if(X?.description!==void 0&&X.description!==Z.description)return!0;if(X?.resources!==void 0){let Q=[...X.resources].sort().join(","),L=[...j1(Z)??[]].sort().join(",");if(Q!==L)return!0}return!1}function m9(J){let Z=new Map;for(let $ of J)Z.set(K1($),$);return Z}async function O5(J,Z,$,X,Q,L,H){let B=[],W=new Set,F=H?H.get(`${X}:${Q}`)??[]:Z?(await Z.listByTarget(X,Q)).items:[];for(let g of F){let u=M5(g.subject);if(W.has(u))continue;W.add(u);let t=g.metadata,o=g.subjectType==="workload"?"Workload":t?.type??"User";B.push({value:u,...t?.display?{display:t.display}:{},type:o})}for(let g of L??[]){if(g.targetType!==X||M5(g.target)!==Q)continue;let u=M5(g.subject);if(W.has(u))continue;W.add(u),B.push({value:u,type:"Workload"})}if(X==="group"){let g=await J.groups.get(Q)??await $?.entitlement?.(Q);for(let u of g?.groups??[]){let t=M5(u);if(!t||W.has(t))continue;W.add(t),B.push({value:t,type:"Group"})}}return B.length>0?B:void 0}function X1(J,Z){let $=[];for(let[X,Q]of Z)if(!J.has(X))$.push({action:"grant",change:Q});for(let[X,Q]of J)if(!Z.has(X))$.push({action:"revoke",change:Q});return $}async function e1(J,Z){if(J.oaa.isReady())await J.oaa.pushUser(Z)}async function v5(J,Z,$,X){let Q={metadataApplied:!1,access:[]},L=[],H=new Y9(J.catalogStore,J.resources,J.codeCatalog);try{try{await Z(),Q.metadataApplied=!0}catch(B){for(let W of $)Q.access.push({change:W.change,status:"rolled_back"});throw Q.metadataApplied=!1,new i5(`SCIM metadata write failed: ${y5(B)}`,Q,!1)}if(X)await F9(J,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",X);for(let B=0;B<$.length;B++){let W=$[B];try{if(W.action==="grant")await r2(J,W.change,L,H);else await Y4(J,W.change,L);Q.access.push({change:W.change,status:"applied"})}catch(F){Q.access.push({change:W.change,status:"failed",error:F});for(let u=B+1;u<$.length;u++)Q.access.push({change:$[u].change,status:"rolled_back"});let g=F instanceof w1||F instanceof B1;if(!g)await Q4(J,W.change,H);throw new i5(g?y5(F):`SCIM access mutation failed: ${y5(F)}`,Q,g)}}return Q}finally{await X4(J),Q.egress=await K9(J,L),K4(J,Q)}}function y5(J){return J instanceof Error?J.message:String(J)}async function X4(J){try{await J.settleAuthz?.()}catch{}}async function Q4(J,Z,$){if(!J.accessIndex||!J.catalogStore&&!J.codeCatalog||!J.accessStore)return;let X=M5(Z.subject);if(!X)return;let Q=Z.subjectType??"user";try{await W9(X,Q,{accessStore:J.accessStore,accessIndex:J.accessIndex,catalogStore:J.catalogStore,code:J.codeCatalog,resources:J.resources},$)}catch(L){J.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:X,subjectType:Q,error:y5(L)})}}function K4(J,Z){if(!J.onAccessMutation)return;try{J.onAccessMutation(Z)}catch{}}async function Y4(J,Z,$){if(J.accessStore){let X=Z.id??W1(Z);if(!await J.accessStore.get(X)){if((J.accessIndex?await J.accessIndex.has(Z.subject,Z.targetType,Z.target,Z.resources?.[0],Z.subjectType):{allow:!1}).allow)throw new w1(`Cannot revoke ${Z.targetType} "${M5(Z.target)}" for "${M5(Z.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await E1(J,Z,$);return}}await E1(J,Z,$)}function Q1(J){let Z=J[B5]?.type??"group";if(Z==="group"||Z==="role"||Z==="permission")return Z;throw Error(`Unsupported ionite SCIM Group authz type "${String(Z)}"`)}async function J9(J,Z,$){if(!J.oaa.isReady())return;if($==="role"){await J.oaa.pushRole(Z);return}if($==="permission"){await J.oaa.pushPermission(Z);return}await J.oaa.pushGroup(Z)}function j1(J){let Z=J.resources;if(!Z||Z.length===0)return;let $=Z.map((X)=>typeof X==="string"?X:X.id).filter(Boolean);return $.length>0?$:void 0}function E5(J,Z,$){return{schemas:[O1],id:J.id,externalId:J.externalId,displayName:J.displayName??J.name,members:$,[B5]:{type:Z,requestable:J.requestable,description:J.description,resources:Z==="group"?j1(J):void 0,assignableSubjectTypes:J.assignableSubjectTypes,recommendedSubjectTypes:J.recommendedSubjectTypes}}}function B4(J,Z){let $=J[B5],X={id:Z,name:J.displayName,displayName:J.displayName,description:$?.description??J.displayName,externalId:J.externalId,requestable:$?.requestable};if($?.resources!==void 0)X.resources=$.resources;return X}function W4(J){if(!J)return;let Z=J.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!Z)return;return{requestable:Z[1]?.toLowerCase()==="true"}}function p9(J){if(!J)return;let Z=J.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return Z?Z[1]:void 0}async function H9(J,Z){if(!J?.entitlements)return[];let $=J.entitlements.bind(J),X=[];for await(let Q of l9((L,H)=>J.list({start:L,limit:H})))for(let L of $(Q)){if(Z?.requestable!==void 0&&Boolean(L.requestable)!==Z.requestable)continue;X.push(G1(L))}return X}async function G4(J,Z,$,X,Q){let L=[{store:J.groups,type:"group"},{store:J.roles,type:"role"},{store:J.permissions,type:"permission"}],H;if(L.every(({store:W})=>typeof W.getByExternalId==="function"))H=(await Promise.all(L.map(async({store:F,type:g})=>{let u=await F.getByExternalId?.(X);return u?{entity:u,type:g}:void 0}))).filter((F)=>F!==void 0);else{let W={start:0},[F,g,u]=await Promise.all([J.groups.list(W),J.roles.list(W),J.permissions.list(W)]);H=[...F.items.map((o)=>({entity:o,type:"group"})),...g.items.map((o)=>({entity:o,type:"role"})),...u.items.map((o)=>({entity:o,type:"permission"}))].filter(({entity:o})=>o.externalId===X)}if($?.entitlements){let W=await H9($);for(let F of W)if(F.externalId===X)H.push({entity:F,type:"group"})}if(H.length>1)throw new L9(`Ambiguous externalId "${X}": ${H.length} entitlements share it (${H.map((W)=>`${W.type}:${W.entity.id}`).join(", ")})`,"unique_violation","externalId");let B=H[0];if(!B)return;return E5(B.entity,B.type,await O5(J,Z,$,B.type,B.entity.id,Q))}async function L4(J,Z,$,X,Q){let L=Math.max(0,X.start),H=X.limit!=null?L+X.limit:void 0,B={start:0,limit:H,filter:X.filter},[W,F,g]=await Promise.all([J.groups.list(B),J.roles.list(B),J.permissions.list(B)]),u=[...W.items.map((r)=>({entity:r,type:"group"})),...F.items.map((r)=>({entity:r,type:"role"})),...g.items.map((r)=>({entity:r,type:"permission"}))],t=W.total+F.total+g.total,o=u.slice(L,H),F5=0,i=[];if($?.entitlements){let r=await H9($,X.filter);F5=r.length;let $5=X.limit!=null?X.limit-o.length:void 0;if($5===void 0||$5>0){let D5=Math.max(0,L-t);i=$5===void 0?r.slice(D5):r.slice(D5,D5+$5)}}let H5=[...o,...i.map((r)=>({entity:r,type:"group"}))],q=t+F5,c=Z?.listByTargets?await Z.listByTargets(H5.map(({entity:r,type:$5})=>({targetType:$5,target:r.id}))):void 0,Q5=await Promise.all(H5.map(async({entity:r,type:$5})=>E5(r,$5,await O5(J,Z,$,$5,r.id,Q,c))));return{resources:Q5,total:q,count:Q5.length}}async function _1(J,Z,$,X,Q){let[L,H,B]=await Promise.all([J.groups.get(X),J.roles.get(X),J.permissions.get(X)]);if(L)return E5(L,"group",await O5(J,Z,$,"group",X,Q));if(H)return E5(H,"role",await O5(J,Z,$,"role",X,Q));if(B)return E5(B,"permission",await O5(J,Z,$,"permission",X,Q));let W=G1(await $?.entitlement?.(X));if(W)return E5(W,"group",await O5(J,Z,$,"group",X,Q));return}async function Z9(J,Z,$){let X=Q1(Z),L={...(X==="role"?await J.roles.get($):X==="permission"?await J.permissions.get($):await J.groups.get($))??{},...B4(Z,$)},H=X==="role"?J.roles.set(L):X==="permission"?J.permissions.set(L):J.groups.set(L);return await H.ready(),H}async function F4(J,Z){await Promise.all([J.groups.delete(Z),J.roles.delete(Z),J.permissions.delete(Z)])}function u9(){return crypto.randomUUID()}function t5(J,Z){let $=J;if(typeof $.validate==="function")return $.validate(Z);return Promise.resolve(J["~standard"].validate(Z))}function H4(J){if(!J)return;try{return new URL(J).pathname}catch{return J.startsWith("/")?J:`/${J}`}}function U5(J){let Z=H4(J);return Z?P1(Z):void 0}function V4(J,Z){let $=U5(J);if($?.endsWith("/Users"))return $.slice(0,-6);let X=U5(Z);if(X?.endsWith("/Groups"))return X.slice(0,-7);return}function x5(J,Z){return new URL(Z,J.url).toString()}function w(J,Z,$,X){let{multiValued:Q=!1,...L}=X??{};return{name:J,type:Z,description:$,multiValued:Q,...L}}function N4(J,Z){return{schemas:[a2],documentationUri:Z?.documentationUri,patch:{supported:!0},bulk:{supported:!1},filter:{supported:!0,maxResults:1000},changePassword:{supported:!1},sort:{supported:!1},etag:{supported:!1},authenticationSchemes:[{type:"oauthbearertoken",name:"OAuth Bearer Token",description:"Use an ionite workload bearer token for IAM discovery and provisioning requests.",primary:!0}],meta:{resourceType:"ServiceProviderConfig",location:x5(J.request,`${J.basePath}/ServiceProviderConfig`)}}}function M4(J){let Z=[];if(J.supportsUsers)Z.push({schemas:[f9],id:"User",name:"User",description:"User Account",endpoint:J.usersUrl,schema:z1,schemaExtensions:[{schema:k5,required:!1},{schema:I5,required:!1}],meta:{resourceType:"ResourceType",location:x5(J.request,`${J.basePath}/ResourceTypes/User`)}});if(J.supportsGroups)Z.push({schemas:[f9],id:"Group",name:"Group",description:"Group",endpoint:J.groupsUrl,schema:O1,schemaExtensions:[{schema:B5,required:!1}],meta:{resourceType:"ResourceType",location:x5(J.request,`${J.basePath}/ResourceTypes/Group`)}});return Z}function D4(J){let Z=[];if(J.supportsUsers)Z.push({schemas:[Z1],id:z1,name:"User",description:"User Account",meta:{resourceType:"Schema",location:x5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(z1)}`)},attributes:[w("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),w("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),w("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),w("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[w("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),w("familyName","string","The family name of the User.",{multiValued:!1}),w("givenName","string","The given name of the User.",{multiValued:!1}),w("middleName","string","The middle name(s) of the User.",{multiValued:!1}),w("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),w("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),w("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),w("nickName","string","The casual way to address the user.",{multiValued:!1}),w("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),w("title","string","The user title, such as Vice President.",{multiValued:!1}),w("userType","string","The relationship between the organization and the User.",{multiValued:!1}),w("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),w("locale","string","Default location for localizing values.",{multiValued:!1}),w("timezone","string","The User time zone.",{multiValued:!1}),w("active","boolean","The User administrative status.",{multiValued:!1}),w("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[w("value","string","Email address value.",{multiValued:!1,required:!0}),w("display","string","Display label for the email.",{multiValued:!1}),w("type","string","Email type such as work or home.",{multiValued:!1}),w("primary","boolean","Primary email indicator.",{multiValued:!1})]}),w("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[w("value","string","Phone number value.",{multiValued:!1,required:!0}),w("display","string","Display label for the phone number.",{multiValued:!1}),w("type","string","Phone number type.",{multiValued:!1}),w("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),w("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[w("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),w("display","string","Display label for the photo.",{multiValued:!1}),w("type","string","Photo type.",{multiValued:!1}),w("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),w("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[w("formatted","string","Formatted mailing address.",{multiValued:!1}),w("streetAddress","string","Full street address component.",{multiValued:!1}),w("locality","string","City or locality.",{multiValued:!1}),w("region","string","State or region.",{multiValued:!1}),w("postalCode","string","Postal code.",{multiValued:!1}),w("country","string","Country.",{multiValued:!1}),w("type","string","Address type.",{multiValued:!1}),w("primary","boolean","Primary address indicator.",{multiValued:!1})]}),w("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[w("value","string","Group identifier.",{multiValued:!1,required:!0}),w("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),w("display","string","Display name of the group.",{multiValued:!1}),w("type","string","Relationship type.",{multiValued:!1})]}),w("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[w("value","string","Entitlement value.",{multiValued:!1,required:!0}),w("display","string","Display value.",{multiValued:!1}),w("type","string","Entitlement type.",{multiValued:!1}),w("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),w("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[w("value","string","Role value.",{multiValued:!1,required:!0}),w("display","string","Display value.",{multiValued:!1}),w("type","string","Role type.",{multiValued:!1}),w("primary","boolean","Primary role indicator.",{multiValued:!1})]}),w("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[w("value","string","Certificate value.",{multiValued:!1,required:!0}),w("display","string","Display value.",{multiValued:!1}),w("type","string","Certificate type.",{multiValued:!1}),w("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),Z.push({schemas:[Z1],id:k5,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:x5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(k5)}`)},attributes:[w("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),w("costCenter","string","Name of a cost center.",{multiValued:!1}),w("organization","string","Name of an organization.",{multiValued:!1}),w("division","string","Name of a division.",{multiValued:!1}),w("department","string","Name of a department.",{multiValued:!1}),w("manager","complex","The User manager.",{multiValued:!1,subAttributes:[w("value","string","Identifier of the manager User resource.",{multiValued:!1}),w("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),w("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),Z.push({schemas:[Z1],id:I5,name:"IoniteUser",description:"ionite User extension carrying the Enterprise Controlled ID (ECID) identity correlator and the account purpose (accountClass). See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:x5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(I5)}`)},attributes:[w("ecid","string","Enterprise Controlled ID formatted as 'ecid:<realm>:<opaque>' (realm = the minting authority's id). Correlates multiple accounts to one identity.",{multiValued:!1,caseExact:!0}),w("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1})]}),Z.push({schemas:[Z1],id:B5,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:x5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(B5)}`)},attributes:[w("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),w("requestable","boolean","Whether this catalog entry should be requestable access in IAM tooling.",{multiValued:!1,required:!1}),w("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),w("assignableSubjectTypes","string","AppDev-owned hard ceiling of principal kinds (user, workload) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),w("recommendedSubjectTypes","string","AppDev advisory default principal kinds (subset of assignableSubjectTypes). Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]})]});if(J.supportsGroups)Z.push({schemas:[Z1],id:O1,name:"Group",description:"Group",meta:{resourceType:"Schema",location:x5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(O1)}`)},attributes:[w("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),w("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),w("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),w("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[w("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),w("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group"]}),w("display","string","Display name of the member.",{multiValued:!1}),w("type","string","Member type.",{multiValued:!1})]})]});return Z}function _4(J,Z,$,X,Q,L,H,B,W,F,g,u,t,o,F5){let i={authz:X,settleAuthz:F5,accessStore:Q,accessIndex:L,catalogStore:H,codeCatalog:B,resources:W,log:Z,iamDelta:u,onAccessMutation:t};if(!F&&!g)return;let q={...F,...g},c=q.users?.enabled!==!1,Q5=q.groups?.enabled!==!1;if(Boolean(q.url||q.userStore||H||B)&&!$)Z.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function $5(){if(!$)throw Z.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"}),Error("IAM requires workload identity for SCIM push/pull operations");return $}async function D5(x){let k=$5(),m=x.headers.get("Authorization");if(!m?.startsWith("Bearer "))return!1;try{let d=m.substring(7);return(await k.validateToken(d)).valid}catch{return!1}}async function f5(){let x=$5(),k=typeof x.getServerToken==="function"?await x.getServerToken():await x.getToken();return new Headers({"Content-Type":Y1,Accept:Y1,Authorization:`Bearer ${k}`})}async function h5(x,k,m,d){if(!q.url)throw Error("IAM URL not configured for outgoing requests");let s=`${q.url}${k}`;try{let G=await f5(),O=await fetch(s,{method:x,headers:G,body:m?JSON.stringify(m):void 0}),K=await O.json();if(!O.ok)return{success:!1,error:K,status:O.status};let N=await d["~standard"].validate(K);if(N.issues)return Z.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:N.issues}),{success:!1,error:{schemas:[Q9],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${N.issues.map((V)=>V.message).join("; ")}`},status:400};return{success:!0,data:N.value,status:O.status}}catch(G){return{success:!1,error:{schemas:[Q9],status:"500",detail:G instanceof Error?G.message:"Unknown error occurred"},status:500}}}function g5(){return q.url}function m5(x,k){let m=U5(k?.usersUrl??q.usersUrl??"/api/iam/Users")??"/api/iam/Users",d=U5(k?.groupsUrl??q.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",s=U5(k?.discovery?.basePath??q.discovery?.basePath)??V4(m,d);if(!s)return;return{request:x,basePath:s,usersUrl:m,groupsUrl:d,supportsUsers:c&&Boolean(q.userStore),supportsGroups:Q5&&Boolean(H||B)}}async function p5(x){let k=N4(x,q.discovery);return await q.discovery?.buildServiceProviderConfig?.(x,k)??k}async function T5(x){let k=M4(x);return await q.discovery?.buildResourceTypes?.(x,k)??k}async function b5(x){let k=D4(x);return await q.discovery?.buildSchemas?.(x,k)??k}async function z5(x,k){let m=m5(x,k);if(!m)return;let d=P1(new URL(x.url).pathname),{basePath:s}=m;if(d!==s&&!d.startsWith(`${s}/`))return;let G=P1(d.slice(s.length)||"/");if(!(G==="/ServiceProviderConfig"||G==="/ResourceTypes"||G.startsWith("/ResourceTypes/")||G==="/Schemas"||G.startsWith("/Schemas/")))return;if(x.method!=="GET")return h(405,"Method not allowed");if(!await D5(x))return h(401,"Authorization required");if(G==="/ServiceProviderConfig")return N5(await p5(m));if(G==="/ResourceTypes")return a5(await T5(m));if(G.startsWith("/ResourceTypes/")){let N=decodeURIComponent(G.slice(15)),V=(await T5(m)).find((D)=>D.id===N||D.name===N);return V?N5(V):h(404,"Resource not found")}if(G==="/Schemas")return a5(await b5(m));if(G.startsWith("/Schemas/")){let N=decodeURIComponent(G.slice(9)),V=(await b5(m)).find((D)=>D.id===N);return V?N5(V):h(404,"Resource not found")}return}let u5,l5;if(q.url)l5=async(k,m)=>{let d={...k,schemas:k.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return h5("POST","/Users",d,J.user)},u5={createGroup:async(k,m)=>{let d={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:k,externalId:m?.externalId,members:m?.members};return h5("POST","/Groups",d,J.group)}};let V5;if(H||B){let x=G9(B,H),k=async(_)=>{if(!W?.entitlement)return;let[M,j,P]=await Promise.all([x.groups.get(_),x.roles.get(_),x.permissions.get(_)]);if(M||j||P)return;return G1(await W.entitlement(_))},m=(_,M)=>h(403,`Entitlement "${_}" is derived from the application's resource data (ResourceProvider.entitlements); its definition cannot be ${M} through SCIM. Member add/remove is allowed; the definition changes only when the application's resources or derivation logic change.`,"mutability"),d=(_)=>{if(!B)return;let M=B.groups.get(_);if(M)return{entity:M,type:"group"};let j=B.roles.get(_);if(j)return{entity:j,type:"role"};let P=B.permissions.get(_);if(P)return{entity:P,type:"permission"};return},s=(_,M)=>h(403,`Entitlement "${_}" is declared in application code (authz.catalog); its definition cannot be ${M} through SCIM. Member add/remove is allowed; the definition changes only when the application code changes.`,"mutability"),G=(_)=>_.path==="members"||Boolean(_.path?.startsWith("members[")),O=async(_,M)=>{if(!await D5(_))return h(401,"Authorization required");let P=new URL(_.url),I=M?.basePath??"/Groups",T=P.pathname;if(T.startsWith(I))T=T.substring(I.length);let b=T.match(/^\/([^/]+)$/)?.[1],C=_.method;try{if(b)switch(C){case"GET":return await N(b);case"PUT":return await D(_,b);case"PATCH":return await E(_,b);case"DELETE":return await A(b);default:return h(405,"Method not allowed")}else if(T===""||T==="/")switch(C){case"GET":return await K(_);case"POST":return await V(_);default:return h(405,"Method not allowed")}return h(404,"Resource not found")}catch(U){if(U instanceof i5)return h9(U);if($9(U))return h(409,U.message,"uniqueness");return Z.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},U),h(500,U instanceof Error?U.message:"Internal server error")}},K=async(_)=>{let M=new URL(_.url),j=M.searchParams.get("startIndex"),P=M.searchParams.get("count"),I=j!=null?parseInt(j,10):void 0,T=P!=null?parseInt(P,10):void 0,v=I!=null&&!Number.isNaN(I)?Math.max(0,I-1):0,b=T!=null&&!Number.isNaN(T)?T:void 0,C=M.searchParams.get("filter"),U=p9(C);if(U!==void 0){let S=await G4(x,Q,W,U,o),y=S?[S]:[];return a5(y,{totalResults:y.length,startIndex:1,itemsPerPage:y.length})}let Y=W4(C),z=await L4(x,Q,W,{start:v,limit:b,filter:Y},o);return a5(z.resources,{totalResults:z.total,startIndex:v+1,itemsPerPage:z.count})},N=async(_)=>{let M=await _1(x,Q,W,_,o);if(!M)return h(404,`Group ${_} not found`,"invalidValue");return N5(M)},V=async(_)=>{let M=await _.json(),j=await t5(J.group,M);if(j.issues)return Z.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:j.issues}),h(400,`Request validation failed: ${j.issues.map((Y)=>Y.message).join("; ")}`,"invalidValue");let P=j.value;if(!P.displayName)return h(400,"displayName is required","invalidValue");if(!H)return h(501,"Group creation is not supported: this application declares its catalog in code (authz.catalog) and wires no AccessCatalogStore for SCIM-authored definitions.","invalidValue");if(P.externalId){let Y=P.externalId,z=B&&(B.groups.getByExternalId(Y)??B.roles.getByExternalId(Y)??B.permissions.getByExternalId(Y)),S=!z&&W?.entitlements?(await H9(W)).find((R)=>R.externalId===Y):void 0,y=z||S;if(y)throw new L9(`externalId "${Y}" is already used by ${z?"code-declared":"resource-derived"} entitlement "${y.id}"`,"unique_violation","externalId")}let I=Q1(P),T=u9(),v=s1(P),b=X1(new Map,$1(P.members,I,T,v)),C;await v5(i,async()=>{C=await Z9(x,P,T)},b,()=>J9(X,C,I));let U=await O5(x,Q,W,I,T);return N5(E5(C,I,U),201)},D=async(_,M)=>{let j=await _.json(),P=await t5(J.group,j);if(P.issues)return Z.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:P.issues}),h(400,`Request validation failed: ${P.issues.map((f)=>f.message).join("; ")}`,"invalidValue");let I=P.value,T=Q1(I);if(!await _1(x,Q,W,M))return h(404,`Group ${M} not found`,"invalidValue");let b=d(M),C=b?void 0:await k(M),U=b??(C?{entity:C,type:"group"}:void 0);if(U){if($4(I,U.entity,U.type))return b?s(M,"replaced"):m(M,"replaced");let f=j1(U.entity),l=Q?(await Q.listByTarget(U.type,M)).items:[],n=X1(m9(l),$1(I.members,U.type,M,f));await v5(i,async()=>{},n);let a=await O5(x,Q,W,U.type,M);return N5(E5(U.entity,U.type,a))}let Y=s1(I),z=Q?(await Q.listByTarget(T,M)).items:[],S=X1(m9(z),$1(I.members,T,M,Y)),y;await v5(i,async()=>{y=await Z9(x,I,M)},S,()=>J9(X,y,T));let R=await O5(x,Q,W,T,M);return N5(E5(y,T,R))},E=async(_,M)=>{let j=await _1(x,Q,W,M);if(!j)return h(404,`Group ${M} not found`,"invalidValue");let P=d(M),I=P?void 0:await k(M),T=P??(I?{entity:I,type:"group"}:void 0),v=await _.json();if(T&&(v.Operations??[]).some((R)=>!G(R)))return P?s(M,"patched"):m(M,"patched");let b={...j};for(let R of v.Operations??[])if(R.op==="replace"&&R.path&&R.value!==void 0){if(R.path==="displayName")b.displayName=R.value;else if(R.path===`${B5}.requestable`)b[B5]={...b[B5],requestable:Boolean(R.value)};else if(R.path===`${B5}.description`)b[B5]={...b[B5],description:String(R.value)}}else if(R.op==="add"&&R.path==="members"&&R.value!==void 0){let f=R.value;b.members=[...b.members??[],...f]}else if(R.op==="remove"&&R.path?.startsWith("members[")){let f=R.path.match(/members\[value eq "([^"]+)"\]/);if(f)b.members=(b.members??[]).filter((l)=>l.value!==f[1])}let C=await t5(J.group,b);if(C.issues)return Z.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:C.issues}),h(400,`Request validation failed: ${C.issues.map((R)=>R.message).join("; ")}`,"invalidValue");let U=Q1(b),Y=T?j1(T.entity):s1(b),z=X1($1(j.members,U,M,Y),$1(b.members,U,M,Y)),S;await v5(i,async()=>{if(!T)S=await Z9(x,b,M)},z,T?void 0:()=>J9(X,S,U));let y=await O5(x,Q,W,U,M);return N5(E5(T?.entity??S,U,y))},A=async(_)=>{let M=await _1(x,Q,W,_);if(!M)return h(404,`Group ${_} not found`,"invalidValue");if(d(_))return s(_,"deleted");if(await k(_))return m(_,"deleted");let j=Q1(M);if(Q){let P=await Q.listByTarget(j,_),I=[];for(let T of P.items)await E1(i,T,I);await K9(i,I)}return await F4(x,_),new Response(null,{status:204})};V5={handler:O}}let W5;if(q.userStore){let{userStore:x,inboundUsers:k}=q,m=(Y)=>Y?.find((z)=>z.primary)?.value||Y?.[0]?.value,d=(Y)=>{if(Y.scimName)return Y.scimName;if(!Y.name)return;let[z,...S]=Y.name.split(" ");return{givenName:z,familyName:S.join(" ")||void 0}},s=(Y)=>Object.keys(Y.scimSchemaExtensions??{}).filter((z)=>z.startsWith("urn:")&&Y.scimSchemaExtensions?.[z]!==void 0),G=(Y)=>{let z={};if(Y.ecid!==void 0)z.ecid=Y.ecid;if(Y.accountClass!==void 0)z.accountClass=Y.accountClass;return z.ecid!==void 0||z.accountClass!==void 0?z:void 0},O=(Y)=>{let z=new Set([z1]);if(Y.scimEnterprise!==void 0)z.add(k5);if(G(Y)!==void 0)z.add(I5);for(let S of s(Y))z.add(S);return Array.from(z)},K=(Y)=>{let z={};if(Y.scimEnterprise!==void 0)z[k5]=Y.scimEnterprise;let S=G(Y);if(S!==void 0)z[I5]=S;for(let[y,R]of Object.entries(Y.scimSchemaExtensions??{}))if(y.startsWith("urn:")&&y!==I5&&R!==void 0)z[y]=R;return z},N=(Y)=>{let z=Y.userName||Y.email||Y.id||"",S=Y.emails??(Y.email?[{value:Y.email,primary:!0}]:[]);return{schemas:O(Y),id:Y.id,externalId:Y.externalId,userName:z,displayName:Y.displayName??Y.name??z,name:d(Y),nickName:Y.nickName,profileUrl:Y.avatar,title:Y.title,userType:Y.userType,preferredLanguage:Y.preferredLanguage,locale:Y.locale,timezone:Y.timezone,active:Y.active??!0,emails:S,phoneNumbers:Y.phoneNumbers,ims:Y.ims,photos:Y.photos,addresses:Y.addresses,groups:Y.groups,entitlements:Y.entitlements,roles:Y.roles,x509Certificates:Y.x509Certificates,meta:{resourceType:"User",created:(Y.createdAt??Y.updatedAt??new Date).toISOString(),lastModified:(Y.updatedAt??Y.createdAt??new Date).toISOString()},...K(Y)}},V=async(Y)=>{if(k?.mapBaseUserToScim)return await k.mapBaseUserToScim(Y);return N(Y)},D=async(Y,z)=>{if(k?.mapValidatedScimToBaseUser)return await k.mapValidatedScimToBaseUser(Y,z);let S=new Date,y=m(Y.emails),R=Y.name?.formatted||[Y.name?.givenName,Y.name?.middleName,Y.name?.familyName].filter(Boolean).join(" ").trim()||Y.displayName,f=Y.id||z.existing?.id||u9(),l=Y.userName||y||z.existing?.userName||f,n=R||Y.displayName||z.existing?.name||l,a=Object.fromEntries(Object.entries(Y).filter(([j5,G5])=>j5.startsWith("urn:")&&j5!==k5&&j5!==I5&&G5!==void 0)),e=Y[I5],q5=e?.ecid!==void 0&&e.ecid!==null?A1(e.ecid):z.existing?.ecid,Z5=e?.accountClass??z.existing?.accountClass,J5=z.existing?.sso;return{...z.existing??{},id:f,userName:l,name:n,email:y||z.existing?.email||l,avatar:Y.profileUrl,sso:{...J5??{},profile:{...J5?.profile??{},sub:f,iss:J5?.profile.iss??"iam-provisioned",aud:J5?.profile.aud??"iam-provisioned",exp:J5?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:J5?.profile.iat??Math.floor(Date.now()/1000),email:y||z.existing?.email||l,email_verified:!0,name:n,preferred_username:l},tenant:J5?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:J5?.scope??"openid profile email",tokenType:J5?.tokenType??"Bearer",expires:J5?.expires??new Date(Date.now()+3600000)},externalId:Y.externalId,ecid:q5,accountClass:Z5,displayName:Y.displayName,scimName:Y.name,emails:Y.emails,nickName:Y.nickName,title:Y.title,preferredLanguage:Y.preferredLanguage,locale:Y.locale,timezone:Y.timezone,active:Y.active,phoneNumbers:Y.phoneNumbers,ims:Y.ims,photos:Y.photos,addresses:Y.addresses,groups:Y.groups,entitlements:Y.entitlements,roles:Y.roles,x509Certificates:Y.x509Certificates,scimEnterprise:Y[k5],scimSchemaExtensions:Object.keys(a).length>0?a:void 0,createdAt:z.existing?.createdAt??(Y.meta?.created?new Date(Y.meta.created):S),updatedAt:Y.meta?.lastModified?new Date(Y.meta.lastModified):S,userType:Y.userType}},E=(Y,z,S)=>{Y[z]=S},A=(Y,z,S)=>{let y=Y[z];if(Array.isArray(y)){Y[z]=[...y,...Array.isArray(S)?S:[S]];return}if(y&&typeof y==="object"&&!Array.isArray(y)&&S&&typeof S==="object"&&!Array.isArray(S)){Y[z]={...y,...S};return}Y[z]=S},_=(Y,z,S)=>{let y=z.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),R=y?[y[1],...y[2]?.split(":")??[]]:z.split("."),f=Y;for(let n of R.slice(0,-1)){let a=f[n];if(a===void 0){if(!S)return null;f[n]={}}else if(a===null||typeof a!=="object"||Array.isArray(a)){if(!S)return null;f[n]={}}f=f[n]}let l=R.at(-1);if(!l)return null;return{parent:f,key:l}},M=(Y,z)=>{let S=z.op.toLowerCase();if(!z.path){if(S!=="remove"&&z.value&&typeof z.value==="object"&&!Array.isArray(z.value))Object.assign(Y,z.value);return}let y=z.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(y&&S==="remove"){let[,f,l]=y,n=Y[f];if(Array.isArray(n))Y[f]=n.filter((a)=>!(a&&typeof a==="object"&&("value"in a)&&a.value===l));return}let R=_(Y,z.path,S!=="remove");if(!R)return;if(S==="remove"){delete R.parent[R.key];return}if(S==="add"){A(R.parent,R.key,z.value);return}E(R.parent,R.key,z.value)},j=async(Y,z)=>{if(!await D5(Y))return h(401,"Authorization required");let y=new URL(Y.url),R=z?.basePath??"/Users",f=y.pathname;if(f.startsWith(R))f=f.substring(R.length);let n=f.match(/^\/([^/]+)$/)?.[1],a=Y.method;try{if(n)switch(a){case"GET":return await I(n);case"PUT":return await b(Y,n);case"PATCH":return await C(Y,n);case"DELETE":return await U(n);default:return h(405,"Method not allowed")}else if(f===""||f==="/")switch(a){case"GET":return await P(Y);case"POST":return await v(Y);default:return h(405,"Method not allowed")}return h(404,"Resource not found")}catch(e){if(e instanceof i5)return h9(e);if($9(e))return h(409,e.message,"uniqueness");return Z.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},e),h(500,e instanceof Error?e.message:"Internal server error")}},P=async(Y)=>{let z=new URL(Y.url),S=z.searchParams.get("startIndex"),y=z.searchParams.get("count"),R=S!=null?parseInt(S,10):void 0,f=y!=null?parseInt(y,10):void 0,l=R!=null&&!Number.isNaN(R)?Math.max(0,R-1):0,n=f!=null&&!Number.isNaN(f)?f:void 0,a=p9(z.searchParams.get("filter"));if(a!==void 0){let Z5=await x.lookup({externalId:a}),J5=Z5?[await V(Z5)]:[];return a5(J5,{totalResults:J5.length,startIndex:1,itemsPerPage:J5.length})}let e=await x.list({start:l,limit:n}),q5=await Promise.all(e.items.map((Z5)=>V(Z5)));return a5(q5,{totalResults:e.total,startIndex:l+1,itemsPerPage:e.count})},I=async(Y)=>{let z=await x.get(Y);if(!z)return h(404,`User ${Y} not found`,"invalidValue");return N5(await V(z))},T=async(Y,z)=>{let S=i.accessIndex;if(!S?.setSubjectDisabled||!z.id)return;let y=Y?Y.active??!0:!0,R=z.active??!0;if(Y&&y===R)return;if(!Y&&R)return;await S.setSubjectDisabled(z.id,"user",!R)},v=async(Y)=>{let z=await Y.json(),S=await t5(J.user,z);if(S.issues)return Z.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:S.issues}),h(400,`Request validation failed: ${S.issues.map((f)=>f.message).join("; ")}`,"invalidValue");let y=S.value;if(!y.userName&&!y.emails?.[0]?.value)return h(400,"userName or email is required","invalidValue");let R=await D(y,{mode:"create"});return await v5(i,async()=>{await x.upsert(R),await T(void 0,R)},r1(void 0,R),async()=>{await e1(X,R)}),N5(await V(R),201)},b=async(Y,z)=>{let S=await x.get(z);if(!S)return h(404,`User ${z} not found`,"invalidValue");let y=await Y.json(),R=await t5(J.user,y);if(R.issues)return Z.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:R.issues}),h(400,`Request validation failed: ${R.issues.map((n)=>n.message).join("; ")}`,"invalidValue");let f=R.value,l=await D({...f,id:z},{existing:S,mode:"replace"});return l.createdAt=S.createdAt,l.updatedAt=new Date,await v5(i,async()=>{await x.upsert(l),await T(S,l)},r1(S,l),async()=>{await e1(X,l)}),N5(await V(l))},C=async(Y,z)=>{let S=await x.get(z);if(!S)return h(404,`User ${z} not found`,"invalidValue");let R=(await Y.json()).Operations??[],l={...await V(S)};for(let e of R)M(l,e);let n=await t5(J.user,l);if(n.issues)return Z.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:n.issues}),h(400,`Request validation failed: ${n.issues.map((e)=>e.message).join("; ")}`,"invalidValue");let a=await D(n.value,{existing:S,mode:"patch"});return a.updatedAt=new Date,await v5(i,async()=>{await x.upsert(a),await T(S,a)},r1(S,a),async()=>{await e1(X,a)}),N5(await V(a))},U=async(Y)=>{if(!await x.get(Y))return h(404,`User ${Y} not found`,"invalidValue");if(Q){let S=await Q.listBySubject(Y,"user"),y=[];for(let R of S.items)await E1(i,R,y);await K9(i,y)}if(await x.delete(Y),await i.accessIndex?.setSubjectDisabled?.(Y,"user",!1),i.authz.oaa.isReady())await F9(i,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>i.authz.oaa.deleteUser(Y),{id:Y,kind:"user"});return new Response(null,{status:204})};W5={handler:j}}async function c5(x,k){$5();let m=new URL(x.url).pathname,d=U5(k?.usersUrl??q.usersUrl??"/api/iam/Users")??"/api/iam/Users",s=U5(k?.groupsUrl??q.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",G=await z5(x,k);if(G)return G;let O=(K)=>m===K||m.startsWith(`${K}/`);if(O(d)){if(!c)return h(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!W5)return h(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return W5.handler(x,{basePath:d})}if(O(s)){if(!Q5)return h(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!V5)return h(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return V5.handler(x,{basePath:s})}return h(404,"Resource not found")}return{...q,createUser:l5,getBaseUrl:g5,groups_outbound:u5,groups_inbound:V5,users_inbound:W5,handler:c5,delta:u}}function V9(J,Z){let $=new TextEncoder().encode(J),X=typeof Z==="string"?new TextEncoder().encode(Z):Z,Q=new Uint8Array($.length+1+X.length);return Q.set($,0),Q[$.length]=46,Q.set(X,$.length+1),Q}function P4(J){let Z=J.replace(/-/g,"+").replace(/_/g,"/"),$=Z.length%4===0?"":"=".repeat(4-Z.length%4),X=atob(Z+$),Q=new Uint8Array(X.length);for(let L=0;L<X.length;L++)Q[L]=X.charCodeAt(L);return Q}function z4(J){let Z="";for(let $ of J)Z+=String.fromCharCode($);return btoa(Z).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function c9(J){let Z=JSON.parse(J);if(!Z||typeof Z!=="object"||!Array.isArray(Z.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return Z}function O4(J){return JSON.stringify(J)}async function E4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x},{name:"Ed25519"},!0,["verify"])}async function j4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x,d:J.d},{name:"Ed25519"},!0,["sign"])}async function A4(J){let $=(typeof J.jwks==="string"?c9(J.jwks):J.jwks).keys.find((X)=>X.kid===J.kid&&X.kty==="OKP"&&X.crv==="Ed25519");if(!$?.x)return!1;try{let X=await E4($),Q=V9(J.requestId,J.rawBody),L=P4(J.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},X,L,Q)}catch{return!1}}async function w4(J){let Z=await j4(J.privateKeyJwk),$=V9(J.requestId,J.rawBody),X=await crypto.subtle.sign({name:"Ed25519"},Z,$);return z4(new Uint8Array(X))}async function I4(J){let Z=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),$=await crypto.subtle.exportKey("jwk",Z.privateKey),Q=(await crypto.subtle.exportKey("jwk",Z.publicKey)).x,L=$.d;if(!Q||!L)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:Q,d:L,kid:J,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:Q,kid:J,alg:"EdDSA",use:"sig"}]}}}var L1={jwksTtlSeconds:{min:60,max:86400,default:600},jwksMaxEntries:{min:16,max:4096,default:256},sessionReadTtlSeconds:{min:1,max:300,default:30},sessionReadMaxEntries:{min:16,max:65536,default:1024}};function I1(J,Z){if(typeof J!=="number"||!Number.isFinite(J))return Z.default;let $=Math.floor(J);if($<Z.min)return Z.min;if($>Z.max)return Z.max;return $}function d9(J){return{ttlMs:I1(J?.ttlSeconds,L1.jwksTtlSeconds)*1000,maxEntries:I1(J?.maxEntries,L1.jwksMaxEntries)}}function n9(J){let Z=J?.read;return{read:{enabled:Z?.enabled===!0,ttlMs:I1(Z?.ttlSeconds,L1.sessionReadTtlSeconds)*1000,maxEntries:I1(Z?.maxEntries,L1.sessionReadMaxEntries)}}}function T4(J){return{jwks:d9(J?.jwks),session:n9(J?.session)}}function S4(J){let Z={};if(!J)return Z;let $=J.split(";");for(let X of $){let Q=X.trim();if(!Q)continue;let L=Q.indexOf("=");if(L===-1)continue;Z[Q.slice(0,L).trim()]=Q.slice(L+1).trim()}return Z}function a9(J){if(!J.expiresAt)return!1;let Z=J.expiresAt instanceof Date?J.expiresAt:new Date(J.expiresAt);return!Number.isNaN(Z.getTime())&&Date.now()>Z.getTime()}function R4(J){if(!J||typeof J!=="object"||Array.isArray(J))return;let{access_token:Z,id_token:$,refresh_token:X,tokens:Q,...L}=J;return L}function P5(J,Z){let $=J[Z];return typeof $==="string"?$:""}function x4(J,Z){let $=J.exp;if(typeof $==="number")return new Date($*1000);if(typeof $==="string"&&$.trim()){let X=Number($);if(!Number.isNaN(X))return new Date(X*1000)}if(Z instanceof Date)return Z;if(Z){let X=new Date(Z);if(!Number.isNaN(X.getTime()))return X}return new Date}function y4(J){let Z=J.claims;if(!Z?.sub||typeof Z.sub!=="string")return;let $=x4(Z,J.expiresAt);if(J.authType==="sso")return{id:Z.sub,userName:P5(Z,"preferred_username"),name:P5(Z,"name"),email:P5(Z,"email"),avatar:P5(Z,"picture")||void 0,sso:{profile:Z,tenant:{id:P5(Z,"idp")||P5(Z,"iss"),name:P5(Z,"iss")},tokenType:"Bearer",expires:$}};return{id:Z.sub,userName:P5(Z,"preferred_username"),name:P5(Z,"name"),email:P5(Z,"email"),avatar:P5(Z,"picture")||void 0,userType:"customer",ciam:{profile:Z,scope:"openid profile email",tokenType:"Bearer",expires:$}}}function b4(J){if(J.authType!=="sso"&&J.authType!=="ciam")return;if(a9(J))return;return{sid:J.sid,authType:J.authType,tenantId:typeof J.tenantId==="string"?J.tenantId:void 0,sub:J.sub,expiresAt:J.expiresAt,createdAt:J.createdAt,claims:R4(J.claims)}}function q4(J,Z){if(!J.endsWith(".session"))return!1;if(!Z||Z.length===0)return!0;return Z.some(($)=>J===`${$}.session`)}function C4(J){if(J===void 0)return;let Z=(Array.isArray(J)?J:[J]).map(($)=>$.trim()).filter(($)=>$.length>0);return Z.length>0?Z:void 0}async function t9(J,Z,$){return(await i9(J,Z,$)).map(b4).filter((Q)=>Boolean(Q))}async function i9(J,Z,$){let X=S4(J.headers.get("cookie")),Q=C4($?.cookiesPrefix),L=[],H=new Set;for(let[B,W]of Object.entries(X)){if(!q4(B,Q)||!W)continue;if(H.has(W))continue;H.add(W);let F=await Z.get(W);if(!F)continue;if(F.authType!=="sso"&&F.authType!=="ciam")continue;if(a9(F))continue;L.push(F)}return L}async function v4(J,Z,$){return(await t9(J,Z,$)).map(y4).filter((Q)=>Boolean(Q))}var U4="@ionite/core",k4=n5(D1(U4));async function f4(J,Z){let $=await S5({idToken:J,jwksUri:Z.jwksUri,issuer:Z.issuer,audience:Z.audience}),X=await k4.validate($);if(X.issues)throw Error(`ID token claims validation failed: ${X.issues.map((H)=>H.message).join("; ")}`);let Q=X.value;if(Q===void 0)throw Error("ID token claims missing");return o9(Q)}function Y5(J){return Date.now()-J}function N9(J){if(J instanceof Error)return{"error.name":J.name,"error.message":J.message};return{"error.name":typeof J,"error.message":String(J)}}function T1(J,Z){if(!J)return{};try{let $=new URL(J);return{[`${Z}.origin`]:$.origin,[`${Z}.path`]:$.pathname}}catch{return{[`${Z}.path`]:J.startsWith("/")?J:`/${J}`}}}function S1(J,Z=5){if(!Array.isArray(J))return[String(J)];return J.slice(0,Z).map(($)=>{if(!$||typeof $!=="object")return String($);let X=$,Q=Array.isArray(X.path)?X.path.join("."):String(X.path??""),L=typeof X.message==="string"?X.message:String(X.message??"validation failed");return Q?`${Q}: ${L}`:L})}function h4(J){if(!J||typeof J!=="object")return{};let Z=J;return{oidc_error:typeof Z.error==="string"?Z.error:void 0,oidc_error_description:typeof Z.error_description==="string"?Z.error_description:void 0,oidc_error_uri:typeof Z.error_uri==="string"?Z.error_uri:void 0}}function g4(J,Z={}){let $=typeof J==="string"?J:J?.headers.get("cookie")??void 0;if(!$)return[];let Q=`${Z.cookiePrefix??"ion.sso"}.`,L=new Set;for(let H of Object.keys(p4($))){if(!H.startsWith(Q))continue;let B=H.slice(Q.length),W=B.lastIndexOf(".");if(W<=0)continue;let F=B.slice(0,W).trim();if(F)L.add(F)}return Array.from(L)}function m4(J,Z,$,X,Q){if(!$&&!X)return;let L=new WeakMap,H=new Map,B={...$,...X},W=!!(B.authority&&B.tokenUrl&&B.authorizationUrl&&B.clientId&&B.redirectUri&&B.scope),F={...B,authority:W?p(B.authority,"Missing 'authority' from SSO Config"):B.authority,tokenUrl:W?p(B.tokenUrl,"Missing 'tokenUrl' from SSO Config"):B.tokenUrl,authorizationUrl:W?p(B.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):B.authorizationUrl,clientId:W?p(B.clientId,"Missing 'clientId' from SSO Config"):B.clientId,redirectUri:W?p(B.redirectUri,"Missing 'redirectUri' from SSO Config"):B.redirectUri,scope:W?p(B.scope,"Missing 'scope' from SSO Config"):B.scope,responseType:B.responseType??"code",cookiesSecure:B.cookiesSecure!==void 0?B.cookiesSecure:!0,cookiesSameSite:B.cookiesSameSite!==void 0?B.cookiesSameSite:"Strict",cookiesPrefix:B.cookiesPrefix??(B.clientId?`ion.sso.${B.clientId}`:"ion.sso"),cookiesPath:B.cookiesPath??"/"},g=Math.min(600,Math.max(0,Math.floor(Number(F.rotationGraceSeconds??60))||0))*1000;function u(){let G=[];if(!F.authority)G.push("authority");if(!F.tokenUrl)G.push("tokenUrl");if(!F.authorizationUrl)G.push("authorizationUrl");if(!F.clientId)G.push("clientId");if(!F.redirectUri)G.push("redirectUri");if(!F.scope)G.push("scope");if(G.length>0)throw Error(`Missing OIDC configuration fields: ${G.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing ionite.`)}async function t(G){if(!F)throw Error("ionite SSO Manager not initialized");let O=L.get(G);if(O)return O;let K=o(G);return L.set(G,K),K}async function o(G){try{let{tokens:O,session:K,refreshedUser:N}=await W5(G);if(!O)return{status:"unauthenticated"};if(N)return{status:"authenticated",value:N};if(K?.claims)return{status:"authenticated",value:$5(K.claims,O,z5(K.expiresAt))};return{status:"unauthenticated"}}catch(O){if(r9(O))return{status:"unauthenticated"};return Z.error("Error parsing user from cookies",{"ion.operation":"cookie.parse","ion.outcome":"degraded"},O),{status:"degraded",error:O instanceof Error?O:void 0}}}async function F5(G){let O=await t(G);return O.status==="authenticated"?O.value:void 0}async function i(G){if(!F)throw Error("ionite SSO Manager not initialized");u();let O=p(F.redirectUri,"Missing 'redirectUri' from SSO Config"),K=p(F.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),N=p(F.clientId,"Missing 'clientId' from SSO Config"),V=p(F.scope,"Missing 'scope' from SSO Config"),D=F.cookiesSecure?G.url.replace(/^http:\/\//,"https://"):G.url,E=_5(),A=_5(64),_=_5(),M=O;try{new URL(M)}catch{if(D)try{let v=new URL(D),b=M.startsWith("//")?M.slice(1):M.startsWith("/")?M:`/${M}`;M=new URL(b,v.origin).toString()}catch{try{let v=new URL(K),b=M.startsWith("//")?M.slice(1):M.startsWith("/")?M:`/${M}`;M=new URL(b,v.origin).toString()}catch{throw Error(`Invalid redirectUri: "${O}". It must be a valid absolute URL.`)}}}let j=new URL(K);j.searchParams.append("client_id",N),j.searchParams.append("redirect_uri",M),j.searchParams.append("response_type","code"),j.searchParams.append("scope",V),j.searchParams.append("state",E),j.searchParams.append("nonce",_);let P=await J1(A);j.searchParams.append("code_challenge",P),j.searchParams.append("code_challenge_method","S256");let I=await F.beforeLogin?.({request:G}),T=I===void 0?{state:E,codeVerifier:A,nonce:_}:{state:E,codeVerifier:A,nonce:_,context:I};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:j.toString(),"Set-Cookie":x(d(E),T,F.loginStateTtl??600,"Lax")}})}async function H5(G){if(!F)throw Error("ionite SSO Manager not initialized");let O;try{O=await F5(G)}catch{O=void 0}let K=await F.beforeLogout?.({request:G,user:O}),N=m("session",G),V;try{V=await W5(G);let P=V.tokens?.refresh_token??m("refresh",G);if(P)await g5(P)}catch(P){Z.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},P)}if(F.sessionStore)try{let P=V?.sid??N;if(P)await F.sessionStore.delete(P)}catch(P){Z.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},P)}let D=[["Set-Cookie",k("session")]],E=await F.afterLogout?.({request:G,context:K}),A=R5(E,"/",G.url);if(A.response){let P=new Headers(A.response.headers);for(let[,I]of D)P.append("Set-Cookie",I);return new Response(A.response.body,{status:A.response.status,statusText:A.response.statusText,headers:P})}let _=A.location??"/",M=G.headers.get("accept");if(M?.includes("application/json")||M?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:_}),{status:200,headers:[["Content-Type","application/json"],...D]});return new Response("Logged out",{status:302,headers:[["Location",_],...D]})}async function q(G){if(!F)throw Error("ionite SSO Manager not initialized");if(!F.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!G.headers.get("content-type")?.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let K=await G.text(),V=new URLSearchParams(K).get("logout_token");if(!V)return new Response("Missing logout_token parameter",{status:400});let D=p(F.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),E=p(F.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),A=F.jwksUri||`${D}/protocol/openid-connect/certs`,_=await d1({logoutToken:V,jwksUri:A,issuer:D,audience:E,log:Z}),M=typeof _.sid==="string"?_.sid:void 0;if(!M)return Z.warn("Back-Channel Logout: logout_token missing sid claim",{"ion.operation":"backchannel_logout","ion.outcome":"failure"}),new Response("Invalid logout_token: missing sid claim",{status:400});return await F.sessionStore.delete(M),Z.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:M}),new Response("OK",{status:200})}catch(O){return Z.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},O),new Response("Internal Server Error",{status:500})}}async function c(G){if(!F)throw Error("ionite SSO Manager not initialized");let O=Date.now(),K=new URL(G.url),N=new URLSearchParams(K.search);Z.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":G.method,"url.path":K.pathname,hasCode:N.has("code"),hasState:N.has("state"),hasError:N.has("error"),...T1(N.get("iss")??void 0,"oidc.issuer")});let V=Object.fromEntries(N.entries()),D=await J.callbackParams.validate(V);if(D.issues)return Z.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":S1(D.issues)}),s9(D.issues,"OIDC callback parameters validation failed");let{code:E,state:A}=D.value,_;try{let M=p(A,'OIDC "state" was not present in the callback parameters'),j=m(d(M),G,!0),{codeVerifier:P,state:I,nonce:T,context:v}=j??{};_=v,Z.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(j),hasCodeVerifier:Boolean(P),hasStateVerifier:Boolean(I),hasNonce:Boolean(T),hasContext:v!==void 0});let b=p(P,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');p(I,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let C=p(T,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),U=p(E,'OIDC "code" was not present in the callback parameters');if(A!==I)throw Z.warn("SSO callback state verification failed",{"ion.event":"ion.sso.callback.state_verification_failed","ion.operation":"sign_in.callback","ion.outcome":"failure"}),Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');Z.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let Y=F.cookiesSecure?G.url.replace(/^http:\/\//,"https://"):G.url,z=await f5(U,b,Y),{tokenExpiresAt:S,sessionExpiresAt:y}=Q5(z);z.expires=S.toISOString();let R=Date.now();Z.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let f=await r(z,C,y);Z.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Y5(R),"user.id":f.id});let l,n;{let Z5=T5("SSO requires sessionStore configuration for opaque session cookies."),J5=typeof f.sso.profile.sid==="string"?f.sso.profile.sid:void 0,j5=J5||_5(32),G5=f.id;if(Z.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(j5),hasIdpSid:Boolean(J5),hasSub:Boolean(G5),"user.id":G5}),!G5)throw Error("Session creation failed: missing sub in ID token claims");let x1=Date.now(),F1={sid:j5,sub:G5,idpSid:J5,authType:"sso",tenantId:F.tenantId,tokens:z,claims:f.sso.profile,expiresAt:y,createdAt:new Date};await b5(Z5,F1),n=F1,l=["Set-Cookie",x("session",j5,y)],Z.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":Y5(x1),"user.id":G5})}if(F.userStore)try{let Z5=f.id;if(Z5){let J5=new Date,j5=Date.now();Z.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":Z5});let G5=await F.userStore.get(Z5);if(Z.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":Y5(j5),"user.id":Z5,found:Boolean(G5)}),G5||F.enableJitUserProvisioning){let x1=Date.now(),F1={...G5??{},...f,id:Z5,tenantId:G5?.tenantId,createdAt:G5?.createdAt??J5,updatedAt:J5};await F.userStore.upsert(F1),Z.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":Y5(x1),"user.id":Z5,existing:Boolean(G5),jitProvisioning:Boolean(F.enableJitUserProvisioning)})}else Z.warn("JIT user provisioning disabled: user not found in store and will not be created",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped","user.id":Z5})}else Z.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(Z5){Z.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...N9(Z5)})}Z.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":Y5(O),"user.id":f.id});let a=[["Set-Cookie",k(d(M))],...l?[l]:[]],e=await F.afterLogin?.({ok:!0,request:G,user:f,session:n,context:_}),q5=R5(e,"/",G.url);if(q5.response)return C5(q5.response,a.map(([,Z5])=>Z5));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",q5.location],...a]})}catch(M){Z.error("Error during sign-in callback",{"ion.event":"ion.sso.sign_in.callback_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","duration.ms":Y5(O),...N9(M)});let j=A?[["Set-Cookie",k(d(A))]]:[],P=await F.afterLogin?.({ok:!1,request:G,error:M,context:_}),I=R5(P,"/",G.url);if(I.response)return C5(I.response,j.map(([,T])=>T));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",I.location],...j]})}}function Q5(G){let O=Date.now(),K=Number(G.expires_in??3600)||3600,N=new Date(O+K*1000),V;if(G.refresh_expires_in!=null&&Number.isFinite(Number(G.refresh_expires_in)))V=Number(G.refresh_expires_in);else if(G.refresh_token)V=86400;else V=K;return{tokenExpiresAt:N,sessionExpiresAt:new Date(O+V*1000)}}async function r(G,O,K){if(!F)throw Error("ionite SSO Manager not initialized");let N=Date.now(),V=await p5(G.id_token,O);return Z.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Y5(N),"user.id":V.sub,hasEmail:Boolean(V.email),hasName:Boolean(V.name)}),$5(V,G,K)}function $5(G,O,K){let N=K??Q5(O).sessionExpiresAt,V=G.ecid!==void 0&&G.ecid!==null?A1(G.ecid):void 0;return{id:G.sub,userName:G.preferred_username||"",name:G.name||"",email:G.email||"",emails:[{value:G.email||"",primary:!0}],...V?{ecid:V}:{},avatar:G.picture,sso:{profile:{...G},tenant:{id:G.idp||G.iss||"",name:G.iss||""},scope:O.scope,tokenType:O.token_type,sessionState:O.session_state,expires:N}}}async function D5(G){if(!F.userStore)return G;let O=await F.userStore.lookup(G);if(!O)return G;return{...G,...O,id:G.id,sso:G.sso}}async function f5(G,O,K){if(!F)throw Error("ionite SSO Manager not initialized");u();let N=p(F.tokenUrl,"Missing 'tokenUrl' from SSO Config"),V=p(F.redirectUri,"Missing 'redirectUri' from SSO Config"),D=p(F.clientId,"Missing 'clientId' from SSO Config"),E=V;try{new URL(E)}catch{if(K)try{let _=new URL(K),M=E.startsWith("//")?E.slice(1):E.startsWith("/")?E:`/${E}`;E=new URL(M,_.origin).toString()}catch{try{let _=new URL(N),M=E.startsWith("//")?E.slice(1):E.startsWith("/")?E:`/${E}`;E=new URL(M,_.origin).toString()}catch{throw Error(`Invalid redirectUri: "${V}". It must be a valid absolute URL.`)}}}let A=new URLSearchParams;if(A.append("grant_type","authorization_code"),A.append("code",G),A.append("redirect_uri",E),A.append("client_id",D),F.clientSecret)A.append("client_secret",F.clientSecret);A.append("code_verifier",O);try{let _=Date.now();Z.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...T1(N,"oidc.token_url"),...T1(E,"oidc.redirect_uri"),hasClientSecret:Boolean(F.clientSecret)});let M=await fetch(N,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:A.toString()});Z.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":M.status,"duration.ms":Y5(_)}),Z.debug("SSO token exchange response body read started",{"ion.event":"ion.sso.token.response_body_read_started","ion.module":"sso","ion.operation":"token.exchange"});let j=await M.json();if(Z.debug("SSO token exchange response body read completed",{"ion.event":"ion.sso.token.response_body_read_completed","ion.module":"sso","ion.operation":"token.exchange","duration.ms":Y5(_)}),!M.ok){Z.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":M.status,"duration.ms":Y5(_),...h4(j)});let I=j;throw Error(`Token exchange failed: ${I.error||M.statusText} - ${I.error_description||""}`.trim())}let P=await J.tokenResponse.validate(j);if(P.issues)throw Z.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":Y5(_),"validation.issues":S1(P.issues)}),Error(`Token response validation failed: ${P.issues}`);return Z.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":Y5(_),tokenType:P.value.token_type,hasAccessToken:Boolean(P.value.access_token),hasIdToken:Boolean(P.value.id_token),hasRefreshToken:Boolean(P.value.refresh_token),expiresIn:P.value.expires_in}),P.value}catch(_){throw Z.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...N9(_)}),_}}async function h5(G){return g1(async()=>{if(!F)throw Error("ionite SSO Manager not initialized");u();let O=p(F.tokenUrl,"Missing 'tokenUrl' from SSO Config"),K=p(F.clientId,"Missing 'clientId' from SSO Config"),N=new URLSearchParams;N.append("grant_type","refresh_token"),N.append("refresh_token",G),N.append("client_id",K);let V=await fetch(O,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:N.toString()}),D=await V.json();if(!V.ok){Z.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:D});let A=D;throw Error(`Token refresh failed: ${A.error||V.statusText} - ${A.error_description||""}`.trim())}let E=await J.tokenResponse.validate(D);if(E.issues)throw Z.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":S1(E.issues)}),Error(`Token refresh response validation failed: ${E.issues}`);return E.value},void 0,void 0,void 0,Z)}async function g5(G){try{if(!F)throw Error("ionite SSO Manager not initialized");if(!F.revocationEndpoint)return;let O=p(F.clientId,"Missing 'clientId' from SSO Config"),K=new URLSearchParams;K.append("token",G),K.append("token_type_hint","refresh_token"),K.append("client_id",O);let N=await fetch(F.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:K.toString()});if(!N.ok)Z.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:N.status,statusText:N.statusText});else Z.info("Token revoked successfully",{"ion.module":"sso"})}catch(O){Z.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},O)}}async function m5(){if(!F)throw Error("ionite SSO Manager not initialized");let G=F.authority;if(!F.jwksUri&&!G)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let O=F.jwksUri||`${G}/protocol/openid-connect/certs`;return r5(O,Z)}async function p5(G,O){let K=Date.now(),N=p(F.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),V=p(F.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),D=F.jwksUri||`${N}/protocol/openid-connect/certs`;Z.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...T1(D,"oidc.jwks_uri")});let E;try{E=await S5({idToken:G,jwksUri:D,issuer:N,audience:V,expectedNonce:O,log:Z})}catch(_){throw Z.error("SSO ID token verification failed",{"ion.event":"ion.sso.id_token.verify_failed","ion.module":"sso","ion.operation":"id_token.verify","ion.outcome":"failure","duration.ms":Y5(K)},_),_}Z.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":Y5(K)});let A=await J.idTokenClaims.validate(E);if(A.issues)throw Z.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":Y5(K),"validation.issues":S1(A.issues)}),Error(`ID token claims validation failed: ${A.issues}`);return Z.debug("SSO ID token claims validated",{"ion.event":"ion.sso.id_token.claims_validated","ion.module":"sso","ion.operation":"id_token.validate","ion.outcome":"success","duration.ms":Y5(K),"user.id":A.value.sub,hasIssuer:Boolean(A.value.iss),hasAudience:Boolean(A.value.aud)}),A.value}function T5(G="SSO sessionStore is required for opaque session cookies."){if(!F.sessionStore)throw Error(G);return F.sessionStore}async function b5(G,O){try{await G.create(O)}catch(K){if(!await G.get(O.sid))throw K;await G.update(O.sid,O)}}function z5(G){if(!G)return;if(G instanceof Date)return G;let O=new Date(G);return Number.isNaN(O.getTime())?void 0:O}function u5(G){let O=G.tokens;if(!O?.access_token||!O.id_token||!O.token_type)return;return O}async function l5(G,O=!1){let K=T5(),N=m("session",G);if(!N)return{tokens:void 0,refreshHeaders:[]};let V=await K.get(N);if(V&&F.tenantId&&V.tenantId&&V.tenantId!==F.tenantId)return{tokens:void 0,refreshHeaders:[["Set-Cookie",k("session")]],sid:N};if(V?.authType!=="sso")return{tokens:void 0,refreshHeaders:[["Set-Cookie",k("session")]],sid:N};let D=u5(V);if(!D)return{tokens:void 0,refreshHeaders:[["Set-Cookie",k("session")]],sid:N};let E=z5(V.expiresAt);if(E?Date.now()>E.getTime():!1)return await K.delete(N),{tokens:void 0,sid:N,refreshHeaders:[["Set-Cookie",k("session")]]};let _=z5(D.expires),M=_?Date.now()>_.getTime():!0;if((O||M)&&D.refresh_token)return V5(N,V,D);return{tokens:D,sid:N,session:V,refreshHeaders:[]}}function V5(G,O,K){let N=H.get(G);if(N)return N;let V=T5(),D=(async()=>{let E=await h5(K.refresh_token),{tokenExpiresAt:A,sessionExpiresAt:_}=Q5(E);E.expires=A.toISOString();let M=await r(E,void 0,_),j=M.sso.profile,P=_5(32),I={...O,sid:P,tokens:E,claims:j,expiresAt:_,createdAt:new Date};await b5(V,I);try{if(g<=0)await V.delete(G);else{let{refresh_token:T,...v}=K;await V.update(G,{tokens:v,expiresAt:new Date(Date.now()+g)})}}catch(T){Z.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},T)}return{tokens:E,sid:P,session:I,refreshedUser:M,refreshHeaders:[["Set-Cookie",x("session",P,_)]]}})();return H.set(G,D),D.finally(()=>{H.delete(G)})}async function W5(G,O=!1){return l5(G,O)}async function c5(G){let{tokens:O}=await W5(G);if(!O)return;return O.access_token}function x(G,O,K,N=F.cookiesSameSite??"Strict"){if(!F)throw Error("ionite SSO Manager not initialized");if(G=`${F.cookiesPrefix}.${G}`,typeof O!=="string")O=btoa(JSON.stringify(O));let V;if(K instanceof Date)V=`Expires=${K.toUTCString()}`;else if(typeof K==="number")V=`Max-Age=${K}`;else throw Error("Invalid expires type",K);if(O.length>4000)throw Error(`Error setting cookie: ${G}. Cookie length is: ${O.length}`);return`${G}=${O}; ${V}; Path=${F.cookiesPath}; HttpOnly;${F.cookiesSecure?" Secure;":""} SameSite=${N};`}function k(G){if(!F)throw Error("ionite SSO Manager not initialized");return`${F.cookiesPrefix}.${G}=; Max-Age=0; Path=${F.cookiesPath}; HttpOnly;${F.cookiesSecure?" Secure;":""} SameSite=${F.cookiesSameSite};`}function m(G,O,K=!1){if(!F)throw Error("ionite SSO Manager not initialized");let N=O.headers.get("cookie");if(!N)return null;let V=`${F.cookiesPrefix}.${G}`,D=N.split(";").find((M)=>M.trim().startsWith(`${V}=`));if(!D)return null;let E=D.indexOf("="),A=D.slice(E+1).trim();if(!K)return A;let _=atob(A);return JSON.parse(_)}function d(G){return`state_${G}`}async function s(G,O){if(!F)throw Error("ionite SSO Manager not initialized");let{loginUrl:K,userUrl:N,tokenUrl:V,refreshUrl:D,logoutUrl:E,logoutBackChannelUrl:A,jwksUrl:_,redirectUri:M}={...F,...O},j=new URL(G.url).pathname;if(M){let P;try{P=new URL(M).pathname}catch{try{let I=new URL(G.url),T=M.startsWith("//")?M.slice(1):M;P=new URL(T,I.origin).pathname}catch{P=M.startsWith("/")?M:`/${M}`}}if(P===j)return c(G)}if(K===j)return i(G);if(N===j)try{let{tokens:P,session:I,refreshedUser:T,refreshHeaders:v}=await W5(G);if(!P)return new Response("User not logged in",{status:401,headers:v});let b=T??(I?.claims?$5(I.claims,P,z5(I.expiresAt)):void 0);if(!b)return new Response("User not logged in",{status:401,headers:v});let C=await D5(b);return new Response(JSON.stringify(C),{headers:[["Content-Type","application/json"],...v]})}catch(P){if(r9(P))return new Response("User not logged in",{status:401});return Z.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},P),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:{"Content-Type":"application/json"}})}if(V===j){let{tokens:P,refreshHeaders:I}=await W5(G);if(!P)return new Response("User not logged in",{status:401,headers:I});return new Response(JSON.stringify({token:P.access_token,expires:P.expires}),{headers:[["Content-Type","application/json"],...I]})}if(D===j){let{tokens:P,refreshHeaders:I}=await W5(G,!0);if(!P)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:I})}if(E===j)return H5(G);if(A===j)return q(G);if(_===j){let P=await m5();return new Response(JSON.stringify(P),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...F,getUser:F5,resolveUser:t,getJwt:c5,initiateLogin:i,logout:H5,logoutBackChannel:q,callbackHandler:c,handler:s}}function p4(J){let Z={},$=J.split(";");for(let X of $){let Q=X.trim();if(!Q)continue;let L=Q.indexOf("=");if(L===-1)continue;let H=Q.slice(0,L).trim(),B=Q.slice(L+1).trim();Z[H]=B}return Z}function r9(J){if(!(J instanceof Error))return!1;return["Public key not found","Invalid JWT","Invalid JWT signature","ID token expired","ID token issuer mismatch","ID token audience mismatch","ID token nonce mismatch","ID token missing exp","invalid_grant"].some((Z)=>J.message.includes(Z))}function e9(J){return J=J??"SSO Unavailable",new Response(JSON.stringify({error:J}),{status:503,statusText:J,headers:{"Content-Type":"application/json"}})}var R1="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function u4(J,Z){return p(Z,R1),Z.sso?.getUser(J)}async function l4(J,Z){return p(Z,R1),await Z.sso?.resolveUser(J)??{status:"unauthenticated"}}async function c4(J,Z){p(Z,R1);let $=Z.sso;if(!$)return e9();return $.initiateLogin(J)}async function d4(J,Z){p(Z,R1);let $=Z.sso;if(!$)return e9();return $.callbackHandler(J)}export{C5 as withSetCookies,G1 as withDefaultExternalId,f4 as verifyUser,d1 as verifyLogoutToken,A4 as verifyLfvSignature,S5 as verifyIdToken,O4 as stringifyLfvJwks,m4 as sso,w4 as signLfvPayload,P2 as setJwksRetry,_2 as setJwksClock,y2 as setDiscoveryClock,t4 as sendTenantWebhook,i1 as sameOriginRedirectRules,l4 as resolveUser,n9 as resolveSessionCacheConfig,o1 as resolveRedirect,C1 as resolveProviderBranding,d9 as resolveJwksCacheConfig,j2 as resolveJwkForKid,d2 as resolveCustomer,V1 as resolveCiamProvider,m2 as resolveCapturedRedirect,T4 as resolveCacheConfig,R5 as resolveAfterRedirect,W9 as reconcileSubjectAccess,J1 as pkceChallengeFromVerifier,c9 as parseLfvJwks,v1 as orderedEnabledProviders,e5 as normalizeOidcIssuer,g4 as listSsoClientIdsFromCookies,v9 as isRedirectAllowed,c4 as initiateLogin,_4 as iam,V2 as hasScope,G2 as hasRole,W2 as hasPermission,L2 as hasGroup,N2 as hasAnyScope,F2 as hasAny,M2 as hasAllScope,H2 as hasAll,B2 as has,p1 as getVerificationKeyForKid,u4 as getUser,A2 as getPublicKeyFromJwks,w2 as getPublicKeyForKid,q1 as getProviderPreset,r5 as getJwks,v4 as getDiscoveredSessionUsers,c2 as getCustomer,m1 as getCachedVerificationKey,I4 as generateLfvEd25519KeyPair,t1 as generateAppleClientSecret,a1 as fetchUserInfo,B9 as expandRoot,c1 as exchangeAuthorizationCode,t9 as discoverSessions,i9 as discoverSessionRecords,n1 as discoverOidcEndpoints,h2 as defaultRedirectPolicies,D2 as configureJwksCache,n4 as collectReferencedDefinitions,E2 as clearJwksCache,b2 as clearDiscoveryCache,l2 as ciam,g2 as captureRedirect,d4 as callback,V9 as buildLfvSigningInput,l1 as buildAuthorizationUrl,b9 as blockDangerousUrls,R9 as assertTrustedIdTokenClaims,C9 as allowSameOrigin,q9 as allowRelativePaths,k2 as allowOrigins,f2 as allowHosts,a4 as InMemoryTenantStore,Y9 as CatalogAdjacencyCache,z9 as CIAM_PROVIDER_PRESETS,L1 as CACHE_BOUNDS};
@@ -1,4 +1,4 @@
1
- function f(H){if(H===void 0||H===null)return[];return Array.isArray(H)?H:[H]}function y(H){if(typeof H!=="string")return;return H.endsWith("/")?H.slice(0,-1):H}function a(H,Z){if(y(Z.issuer)!==y(H.claims?.iss))return!1;let X=f(Z.audience);if(X.length===0)return!1;let $=f(H.claims?.aud),Q=typeof H.claims?.azp==="string"?H.claims.azp:void 0;if(!(X.some((L)=>$.includes(L))||(Q?X.includes(Q):!1)))return!1;let Y=H.clientId??H.workloadId??H.claims?.sub;return Z.clientId===Y}function RH(H,Z){let X=H?.trustedProvisioningClients;if(!X?.length)return;let $=new Set;for(let Q of X){if(!a(Z,Q))continue;for(let G of Q.permissions??[])$.add(G)}return $.size>0?$:void 0}function OH(H){let Z=H?.trustedProvisioningClients;if(!Z?.length)return[];let X=[];for(let $ of Z)for(let Q of $.permissions??[])X.push({subject:$.clientId,subjectType:"workload",targetType:"permission",target:Q,status:"active",provenance:{source:"eci-trusted",actor:$.clientId}});return X}function R(H,Z,X,$){let Q=Z.length,G=$??H,Y=G>0?Math.floor(X/G)+1:1,L=G>0?Math.ceil(H/G):0;return{total:H,count:Q,items:Z,size:G,page:Y,pages:L}}async function*b(H,Z,X=1000){let $=0;while(!0){let Q=await H($,X);if(Q.items.length===0)break;for(let G of Q.items)yield(Z?await Z(G):G)??G;if(Q.items.length<X||$+Q.items.length>=Q.total)break;$+=X}}function z(H){if(typeof H==="string")return H.trim();if(H&&typeof H==="object"){let Z=H;for(let X of["id","value","name","displayName"]){let $=Z[X];if(typeof $==="string"&&$.trim())return $.trim()}}return""}function g(H){let Z=z(H.subject),X=z(H.target);if(!Z)throw Error("Access change subject must resolve to a non-empty id.");if(!H.targetType)throw Error("Access change targetType is required.");if(!X)throw Error("Access change target must resolve to a non-empty id.");let $=(H.resources??[]).map((Y)=>Y.trim()).filter(Boolean),Q=!H.applyToApplication&&$.length>0?[...$].sort().join(","):"app";return`${H.subjectType??"user"}:${Z}:${H.targetType}:${X}:${Q}`}function s(H){let Z=(H.resources??[]).map((X)=>X.trim()).filter(Boolean);if(H.applyToApplication||Z.length===0)return[void 0];return Z}function EH(H){if(!H)return;return H.externalId===void 0?{...H,externalId:H.id}:H}async function m(H,Z,X,$,Q){if($==="resource")return X?.get(Q);if(Z){let G=$==="group"?Z.groups.get(Q):$==="role"?Z.roles.get(Q):Z.permissions.get(Q);if(G)return G}if(H){let Y=await($==="group"?H.groups:$==="role"?H.roles:H.permissions).get(Q);if(Y)return Y}if($==="group")return X?.entitlement?.(Q);return}class e{catalog;resources;code;nodes=new Map;subResources=new Map;children=new Map;constructor(H,Z,X){this.catalog=H;this.resources=Z;this.code=X}getNode(H,Z){let X=`${H}:${Z}`,$=this.nodes.get(X);if(!$)$=m(this.catalog,this.code,this.resources,H,Z),this.nodes.set(X,$);return $}resourceChildren(H){let Z=this.children.get(H);if(!Z)Z=v(H,this.view()),this.children.set(H,Z);return Z}resourceAndSubResourceIds(H){let Z=this.subResources.get(H);if(!Z)Z=p(H,this.view()),this.subResources.set(H,Z);return Z}view(){return{catalog:this.catalog,code:this.code,resources:this.resources,cache:this}}invalidate(H){this.clear()}clear(){this.nodes.clear(),this.subResources.clear(),this.children.clear()}}async function O(H,Z,X){if(H.cache)return H.cache.getNode(Z,X);return m(H.catalog,H.code,H.resources,Z,X)}async function h(H,Z){if(typeof H!=="string")return H;return O(Z,"resource",H)}async function v(H,Z){if(Z.resources?.children)return Z.resources.children(H);let X=await h(H,Z),$=[];for(let Q of X?.resources??[]){let G=await h(Q,Z);if(G)$.push(G);else if(typeof Q==="string"&&Q.trim())$.push({id:Q.trim()})}return $}async function c(H,Z){if(Z.cache)return Z.cache.resourceChildren(H);return v(H,Z)}async function p(H,Z){let X=[],$=new Set,Q=async(G)=>{if(!G||$.has(G))return;$.add(G),X.push(G);for(let Y of await c(G,Z))await Q(z(Y))};return await Q(z(H)),X}async function HH(H,Z){let X=H.id??g(H),$=z(H.subject);if(!$)throw Error("Access change subject must resolve to a non-empty id.");let Q=H.subjectType??"user",G=s(H),Y=[],L=new Set,D=new Set,J=(B,M,U)=>{if(!M)return;let F=`${B}:${M}:${U??""}`;if(L.has(F))return;L.add(F),Y.push({subject:$,subjectType:Q,targetType:B,target:M,resource:U,rootId:X})},q=async(B,M,U)=>{for(let F of G)if(B==="permission"&&U?.applyToSubResources&&F){let V=Z.cache?await Z.cache.resourceAndSubResourceIds(F):await p(F,Z);for(let A of V)J("permission",M,A)}else J(B,M,F)},W=async(B,M)=>{let U=z(M);if(!U)return;let F=`${B}:${U}`;if(D.has(F))return;if(D.add(F),B==="group"){let A=typeof M==="string"?await O(Z,"group",U):M;await q("group",U,void 0);for(let K of A?.groups??[])await W("group",K);for(let K of A?.roles??[])await W("role",K);for(let K of A?.permissions??[])await W("permission",K);return}if(B==="role"){let A=typeof M==="string"?await O(Z,"role",U):M;await q("role",U,void 0);for(let K of A?.permissions??[])await W("permission",K);return}let V=typeof M==="string"?await O(Z,"permission",U):M;await q("permission",U,V)};return await W(H.targetType,H.target),Y}async function TH(H,Z,X,$){let{accessStore:Q,accessIndex:G,catalogStore:Y,code:L,resources:D}=X;if(!G||!Y&&!L)return 0;if(await G.clear(H,Z),!Q)return 0;let J={catalog:Y,code:L,resources:D,cache:$},q=0;for await(let W of b((B,M)=>Q.listBySubject(H,Z,{start:B,limit:M}))){let B=W.id??g(W),M=await HH({...W,id:B},J);await G.materialize(B,M),q+=1}return q}async function kH(H,Z,X){let $=new Map,Q=new Map,G=new Map,Y=new Map,L=new Set,D=(W,B)=>O(X,W,B),J=async(W)=>{let B=z(W);if(!B||Y.has(B))return;let M=typeof W==="string"?await D("resource",B):W;if(!M)return;Y.set(B,M);let U=M.resources??(M.id?await c(M.id,X):[]);for(let F of U)await J(F)},q=async(W,B)=>{let M=z(B);if(!M)return;let U=`${W}:${M}`;if(L.has(U))return;if(L.add(U),W==="group"){let V=typeof B==="string"?await D("group",M):B;if(!V)return;$.set(M,V);for(let A of V.groups??[])await q("group",A);for(let A of V.roles??[])await q("role",A);for(let A of V.permissions??[])await q("permission",A);for(let A of V.resources??[])await J(A);return}if(W==="role"){let V=typeof B==="string"?await D("role",M):B;if(!V)return;Q.set(M,V);for(let A of V.permissions??[])await q("permission",A);return}let F=typeof B==="string"?await D("permission",M):B;if(!F)return;G.set(M,F)};if(L.add(`${Z}:${z(H)}`),Z==="group"){let W=H;for(let B of W.groups??[])await q("group",B);for(let B of W.roles??[])await q("role",B);for(let B of W.permissions??[])await q("permission",B);for(let B of W.resources??[])await J(B)}else{let W=H;for(let B of W.permissions??[])await q("permission",B)}return{groups:[...$.values()],roles:[...Q.values()],permissions:[...G.values()],resources:[...Y.values()]}}function XH(H){return typeof H.groups?.get==="function"}function PH(H){return XH(H)?H:$H(H)}class N extends Error{constructor(H){super(`defineCatalog: ${H}`);this.name="CodeCatalogError"}}function d(H){return typeof H==="string"?H:H.id}function ZH(H){for(let Z of Object.values(H))if(Array.isArray(Z))Object.freeze(Z);if(H.metadata)Object.freeze(H.metadata);Object.freeze(H)}function j(H,Z){let{assignableSubjectTypes:X,recommendedSubjectTypes:$}=Z;if(!$?.length)return;if(!X)return;for(let Q of $)if(!X.includes(Q))throw new N(`${H} "${Z.id}": recommendedSubjectTypes "${Q}" is not in assignableSubjectTypes.`)}function E(H){let Z=new Map(H.map((Q)=>[Q.id,Q])),X=new Map(H.map((Q)=>[Q.externalId,Q])),$=Object.freeze([...H]);return Object.freeze({get:(Q)=>Z.get(Q),getByExternalId:(Q)=>X.get(Q),list:()=>$})}function $H(H){let Z=H.groups??[],X=H.roles??[],$=H.permissions??[],Q=new Map,G=(W,B)=>{for(let M of B){if(!M.id)throw new N(`a ${W} is missing its required "id".`);let U=Q.get(M.id);if(U)throw new N(`duplicate id "${M.id}" (declared as both ${U} and ${W}).`);Q.set(M.id,W)}};G("group",Z),G("role",X),G("permission",$);let Y=new Map;for(let W of[...Z,...X,...$]){if(W.externalId===void 0)W.externalId=W.id;let B=W.externalId,M=Y.get(B);if(M!==void 0)throw new N(`duplicate externalId "${B}" (on "${M}" and "${W.id}").`);Y.set(B,W.id)}let L=(W,B,M,U)=>{let F=d(U),V=Q.get(F);if(V===void 0)throw new N(`${W} "${B}" references ${M} "${F}", which is not declared in the catalog.`);if(V!==M)throw new N(`${W} "${B}" references "${F}" as a ${M}, but it is a ${V}.`)};for(let W of X){j("role",W);for(let B of W.permissions??[])L("role",W.id,"permission",B)}for(let W of $)j("permission",W);for(let W of Z){j("group",W);for(let B of W.groups??[])L("group",W.id,"group",B);for(let B of W.roles??[])L("group",W.id,"role",B);for(let B of W.permissions??[])L("group",W.id,"permission",B)}let D=new Map(Z.map((W)=>[W.id,W])),J=new Map,q=(W,B)=>{let M=J.get(W);if(M==="done")return;if(M==="visiting")throw new N(`group composition cycle: ${[...B,W].join(" -> ")}.`);J.set(W,"visiting");for(let U of D.get(W)?.groups??[])q(d(U),[...B,W]);J.set(W,"done")};for(let W of Z)q(W.id,[]);for(let W of[...Z,...X,...$])ZH(W);return Object.freeze({groups:E(Z),roles:E(X),permissions:E($)})}function T(H,Z,X){let $=()=>{if(!X)throw Error(`Cannot write ${H} definitions: no AccessCatalogStore is wired (the code-declared catalog is read-only).`);return X},Q={async get(G){return Z.get(G)??await X?.get(G)},set(G){return $().set(G)},async delete(G){await $().delete(G)},async list(G){let Y=Math.max(0,G?.start??0),L=G?.limit,D=G?.filter?.requestable,J=Z.list().filter((F)=>D===void 0||Boolean(F.requestable)===D),q=L!=null?J.slice(Y,Y+L):J.slice(Y);if(!X)return R(J.length,q,Y,L);let W=Math.max(0,Y-J.length),B=L!=null?L-q.length:void 0,M=await X.list({start:W,limit:B!=null?Math.max(1,B):void 0,filter:G?.filter}),U=(B!=null?M.items.slice(0,B):M.items).filter((F)=>!Z.get(F.id));return R(J.length+M.total,[...q,...U],Y,L)}};if(!X||typeof X.getByExternalId==="function")Q.getByExternalId=async(G)=>Z.getByExternalId(G)??await X?.getByExternalId?.(G);return Q}function SH(H,Z){if(!H)return Z;return{groups:T("group",H.groups,Z?.groups),roles:T("role",H.roles,Z?.roles),permissions:T("permission",H.permissions,Z?.permissions),afterChange:Z?.afterChange?.bind(Z)}}var yH="ecid",n=/^ecid:([A-Za-z0-9._-]+):([A-Za-z0-9_-]+)$/,QH=/^[A-Za-z0-9._-]+$/,YH=/^[A-Za-z0-9_-]+$/;class x extends Error{constructor(H){super(H);this.name="EcidFormatError"}}function GH(H){return typeof H==="string"&&n.test(H)}function bH(H,Z){if(!H||!QH.test(H))throw new x(`Invalid ECID realm ${JSON.stringify(H)}: must be non-empty and match [A-Za-z0-9._-].`);if(!Z||!YH.test(Z))throw new x(`Invalid ECID opaque ${JSON.stringify(Z)}: must be non-empty and match [A-Za-z0-9_-].`);return`ecid:${H}:${Z}`}function hH(H){let Z=typeof H==="string"?H.match(n):null;if(!Z)throw new x(`Invalid ECID ${JSON.stringify(H)}: expected "ecid:<realm>:<opaque>".`);return{realm:Z[1],opaque:Z[2]}}function gH(H){if(!GH(H))throw new x(`Invalid ECID ${JSON.stringify(H)}: expected "ecid:<realm>:<opaque>".`);return H}function vH(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={};if("code"in X)if(typeof X.code==="string")Q.code=X.code;else $.push({message:"code must be a string",path:["code"]});else if(!("error"in X))$.push({message:"code is required",path:["code"]});if("state"in X)if(typeof X.state==="string"||X.state===void 0)Q.state=X.state;else $.push({message:"state must be a string",path:["state"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)Q.session_state=X.session_state;else $.push({message:"session_state must be a string",path:["session_state"]});if("error"in X){if(typeof X.error==="string")Q.error=X.error;else $.push({message:"error must be a string",path:["error"]});if("error_description"in X)if(typeof X.error_description==="string"||X.error_description===void 0)Q.error_description=X.error_description;else $.push({message:"error_description must be a string",path:["error_description"]});if("error_uri"in X)if(typeof X.error_uri==="string"||X.error_uri===void 0)Q.error_uri=X.error_uri;else $.push({message:"error_uri must be a string",path:["error_uri"]})}if("iss"in X)if(typeof X.iss==="string"||X.iss===void 0)Q.iss=X.iss;else $.push({message:"iss must be a string",path:["iss"]});if($.length>0)return{issues:$};return{value:Q}}}}}function cH(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={};if("access_token"in X)if(typeof X.access_token==="string")Q.access_token=X.access_token;else $.push({message:"access_token must be a string",path:["access_token"]});else $.push({message:"access_token is required",path:["access_token"]});if("id_token"in X)if(typeof X.id_token==="string")Q.id_token=X.id_token;else $.push({message:"id_token must be a string",path:["id_token"]});else $.push({message:"id_token is required",path:["id_token"]});if("token_type"in X)if(typeof X.token_type==="string")Q.token_type=X.token_type;else $.push({message:"token_type must be a string",path:["token_type"]});else $.push({message:"token_type is required",path:["token_type"]});if("refresh_token"in X)if(typeof X.refresh_token==="string"||X.refresh_token===void 0)Q.refresh_token=X.refresh_token;else $.push({message:"refresh_token must be a string",path:["refresh_token"]});if("scope"in X)if(typeof X.scope==="string"||X.scope===void 0)Q.scope=X.scope;else $.push({message:"scope must be a string",path:["scope"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)Q.session_state=X.session_state;else $.push({message:"session_state must be a string",path:["session_state"]});if("expires"in X)if(typeof X.expires==="string"||X.expires===void 0)Q.expires=X.expires;else $.push({message:"expires must be a string",path:["expires"]});if("expires_in"in X)if(typeof X.expires_in==="number"||X.expires_in===void 0)Q.expires_in=X.expires_in;else $.push({message:"expires_in must be a number",path:["expires_in"]});if("refresh_expires_in"in X)if(typeof X.refresh_expires_in==="number"||X.refresh_expires_in===void 0)Q.refresh_expires_in=X.refresh_expires_in;else $.push({message:"refresh_expires_in must be a number",path:["refresh_expires_in"]});if($.length>0)return{issues:$};return{value:Q}}}}}function l(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={...X},G=["iss","sub"];for(let J of G)if(typeof X[J]!=="string")$.push({message:`${J} is required and must be a string`,path:[J]});let Y=X.aud;if(!(typeof Y==="string"||Array.isArray(Y)&&Y.length>0&&Y.every((J)=>typeof J==="string")))$.push({message:"aud is required and must be a string or a non-empty array of strings",path:["aud"]});if(typeof X.exp!=="number")$.push({message:"exp is required and must be a number",path:["exp"]});let D=["sid","name","email","preferred_username","picture"];for(let J of D)if(J in X&&X[J]!==void 0){if(typeof X[J]!=="string")$.push({message:`${J} must be a string`,path:[J]})}if("iat"in X&&X.iat!==void 0&&typeof X.iat!=="number")$.push({message:"iat must be a number",path:["iat"]});if($.length>0)return{issues:$};return{value:Q}}}}}function o(H){let Z=H["~standard"];return Object.assign(H,{validate(X){return Promise.resolve(Z.validate(X))}})}function dH(H,Z="Assertion failed. Required value is null or undefined."){if(H===void 0||H===null)throw Error(Z);return H}function nH(H,Z){return Response.json({error:"validation_failed",message:Z,issues:H},{status:400,headers:{"Content-Type":"application/json"}})}function lH(H,Z,X=[]){let $={...H,...Z};for(let Q of X)$[Q]=H?.[Q]??Z?.[Q];return $}function LH(H){let Z="",X=0,$=H.length;while(X<$){let Q=H[X];if(Q==='"'||Q==="'"){let G=Q;Z+=Q,X++;while(X<$){let Y=H[X];if(Y==="\\"){if(Z+=Y,X+1<$)Z+=H[X+1],X+=2;else X++;continue}if(Y===G){Z+=Y,X++;break}Z+=Y,X++}continue}if(Q==="/"&&X+1<$){let G=H[X+1];if(G==="/"){X+=2;while(X<$&&H[X]!==`
1
+ function f(H){if(H===void 0||H===null)return[];return Array.isArray(H)?H:[H]}function y(H){if(typeof H!=="string")return;return H.endsWith("/")?H.slice(0,-1):H}function a(H,Z){if(y(Z.issuer)!==y(H.claims?.iss))return!1;let X=f(Z.audience);if(X.length===0)return!1;let $=f(H.claims?.aud),Q=typeof H.claims?.azp==="string"?H.claims.azp:void 0;if(!(X.some((L)=>$.includes(L))||(Q?X.includes(Q):!1)))return!1;let Y=H.clientId??H.workloadId??H.claims?.sub;return Z.clientId===Y}function RH(H,Z){let X=H?.trustedProvisioningClients;if(!X?.length)return;let $=new Set;for(let Q of X){if(!a(Z,Q))continue;for(let G of Q.permissions??[])$.add(G)}return $.size>0?$:void 0}function OH(H){let Z=H?.trustedProvisioningClients;if(!Z?.length)return[];let X=[];for(let $ of Z)for(let Q of $.permissions??[])X.push({subject:$.clientId,subjectType:"workload",targetType:"permission",target:Q,status:"active",provenance:{source:"eci-trusted",actor:$.clientId}});return X}function R(H,Z,X,$){let Q=Z.length,G=$??H,Y=G>0?Math.floor(X/G)+1:1,L=G>0?Math.ceil(H/G):0;return{total:H,count:Q,items:Z,size:G,page:Y,pages:L}}async function*b(H,Z,X=1000){let $=0;while(!0){let Q=await H($,X);if(Q.items.length===0)break;for(let G of Q.items)yield(Z?await Z(G):G)??G;if(Q.items.length<X||$+Q.items.length>=Q.total)break;$+=X}}function z(H){if(typeof H==="string")return H.trim();if(H&&typeof H==="object"){let Z=H;for(let X of["id","value","name","displayName"]){let $=Z[X];if(typeof $==="string"&&$.trim())return $.trim()}}return""}function g(H){let Z=z(H.subject),X=z(H.target);if(!Z)throw Error("Access change subject must resolve to a non-empty id.");if(!H.targetType)throw Error("Access change targetType is required.");if(!X)throw Error("Access change target must resolve to a non-empty id.");let $=(H.resources??[]).map((Y)=>Y.trim()).filter(Boolean),Q=!H.applyToApplication&&$.length>0?[...$].sort().join(","):"app";return`${H.subjectType??"user"}:${Z}:${H.targetType}:${X}:${Q}`}function s(H){let Z=(H.resources??[]).map((X)=>X.trim()).filter(Boolean);if(H.applyToApplication||Z.length===0)return[void 0];return Z}function TH(H){if(!H)return;return H.externalId===void 0?{...H,externalId:H.id}:H}async function m(H,Z,X,$,Q){if($==="resource")return X?.get(Q);if(Z){let G=$==="group"?Z.groups.get(Q):$==="role"?Z.roles.get(Q):Z.permissions.get(Q);if(G)return G}if(H){let Y=await($==="group"?H.groups:$==="role"?H.roles:H.permissions).get(Q);if(Y)return Y}if($==="group")return X?.entitlement?.(Q);return}class e{catalog;resources;code;nodes=new Map;subResources=new Map;children=new Map;constructor(H,Z,X){this.catalog=H;this.resources=Z;this.code=X}getNode(H,Z){let X=`${H}:${Z}`,$=this.nodes.get(X);if(!$)$=m(this.catalog,this.code,this.resources,H,Z),this.nodes.set(X,$);return $}resourceChildren(H){let Z=this.children.get(H);if(!Z)Z=v(H,this.view()),this.children.set(H,Z);return Z}resourceAndSubResourceIds(H){let Z=this.subResources.get(H);if(!Z)Z=p(H,this.view()),this.subResources.set(H,Z);return Z}view(){return{catalog:this.catalog,code:this.code,resources:this.resources,cache:this}}invalidate(H){this.clear()}clear(){this.nodes.clear(),this.subResources.clear(),this.children.clear()}}async function O(H,Z,X){if(H.cache)return H.cache.getNode(Z,X);return m(H.catalog,H.code,H.resources,Z,X)}async function h(H,Z){if(typeof H!=="string")return H;return O(Z,"resource",H)}async function v(H,Z){if(Z.resources?.children)return Z.resources.children(H);let X=await h(H,Z),$=[];for(let Q of X?.resources??[]){let G=await h(Q,Z);if(G)$.push(G);else if(typeof Q==="string"&&Q.trim())$.push({id:Q.trim()})}return $}async function c(H,Z){if(Z.cache)return Z.cache.resourceChildren(H);return v(H,Z)}async function p(H,Z){let X=[],$=new Set,Q=async(G)=>{if(!G||$.has(G))return;$.add(G),X.push(G);for(let Y of await c(G,Z))await Q(z(Y))};return await Q(z(H)),X}async function HH(H,Z){let X=H.id??g(H),$=z(H.subject);if(!$)throw Error("Access change subject must resolve to a non-empty id.");let Q=H.subjectType??"user",G=s(H),Y=[],L=new Set,D=new Set,J=(B,M,U)=>{if(!M)return;let F=`${B}:${M}:${U??""}`;if(L.has(F))return;L.add(F),Y.push({subject:$,subjectType:Q,targetType:B,target:M,resource:U,rootId:X})},q=async(B,M,U)=>{for(let F of G)if(B==="permission"&&U?.applyToSubResources&&F){let V=Z.cache?await Z.cache.resourceAndSubResourceIds(F):await p(F,Z);for(let A of V)J("permission",M,A)}else J(B,M,F)},W=async(B,M)=>{let U=z(M);if(!U)return;let F=`${B}:${U}`;if(D.has(F))return;if(D.add(F),B==="group"){let A=typeof M==="string"?await O(Z,"group",U):M;await q("group",U,void 0);for(let K of A?.groups??[])await W("group",K);for(let K of A?.roles??[])await W("role",K);for(let K of A?.permissions??[])await W("permission",K);return}if(B==="role"){let A=typeof M==="string"?await O(Z,"role",U):M;await q("role",U,void 0);for(let K of A?.permissions??[])await W("permission",K);return}let V=typeof M==="string"?await O(Z,"permission",U):M;await q("permission",U,V)};return await W(H.targetType,H.target),Y}async function jH(H,Z,X,$){let{accessStore:Q,accessIndex:G,catalogStore:Y,code:L,resources:D}=X;if(!G||!Y&&!L)return 0;if(!Q)return await G.replaceSubject(H,Z,[]),0;let J={catalog:Y,code:L,resources:D,cache:$},q=[],W=0;for await(let B of b((M,U)=>Q.listBySubject(H,Z,{start:M,limit:U}))){let M=B.id??g(B),U=await HH({...B,id:M},J);q.push(...U),W+=1}return await G.replaceSubject(H,Z,q),W}async function kH(H,Z,X){let $=new Map,Q=new Map,G=new Map,Y=new Map,L=new Set,D=(W,B)=>O(X,W,B),J=async(W)=>{let B=z(W);if(!B||Y.has(B))return;let M=typeof W==="string"?await D("resource",B):W;if(!M)return;Y.set(B,M);let U=M.resources??(M.id?await c(M.id,X):[]);for(let F of U)await J(F)},q=async(W,B)=>{let M=z(B);if(!M)return;let U=`${W}:${M}`;if(L.has(U))return;if(L.add(U),W==="group"){let V=typeof B==="string"?await D("group",M):B;if(!V)return;$.set(M,V);for(let A of V.groups??[])await q("group",A);for(let A of V.roles??[])await q("role",A);for(let A of V.permissions??[])await q("permission",A);for(let A of V.resources??[])await J(A);return}if(W==="role"){let V=typeof B==="string"?await D("role",M):B;if(!V)return;Q.set(M,V);for(let A of V.permissions??[])await q("permission",A);return}let F=typeof B==="string"?await D("permission",M):B;if(!F)return;G.set(M,F)};if(L.add(`${Z}:${z(H)}`),Z==="group"){let W=H;for(let B of W.groups??[])await q("group",B);for(let B of W.roles??[])await q("role",B);for(let B of W.permissions??[])await q("permission",B);for(let B of W.resources??[])await J(B)}else{let W=H;for(let B of W.permissions??[])await q("permission",B)}return{groups:[...$.values()],roles:[...Q.values()],permissions:[...G.values()],resources:[...Y.values()]}}function XH(H){return typeof H.groups?.get==="function"}function PH(H){return XH(H)?H:$H(H)}class N extends Error{constructor(H){super(`defineCatalog: ${H}`);this.name="CodeCatalogError"}}function d(H){return typeof H==="string"?H:H.id}function ZH(H){for(let Z of Object.values(H))if(Array.isArray(Z))Object.freeze(Z);if(H.metadata)Object.freeze(H.metadata);Object.freeze(H)}function E(H,Z){let{assignableSubjectTypes:X,recommendedSubjectTypes:$}=Z;if(!$?.length)return;if(!X)return;for(let Q of $)if(!X.includes(Q))throw new N(`${H} "${Z.id}": recommendedSubjectTypes "${Q}" is not in assignableSubjectTypes.`)}function T(H){let Z=new Map(H.map((Q)=>[Q.id,Q])),X=new Map(H.map((Q)=>[Q.externalId,Q])),$=Object.freeze([...H]);return Object.freeze({get:(Q)=>Z.get(Q),getByExternalId:(Q)=>X.get(Q),list:()=>$})}function $H(H){let Z=H.groups??[],X=H.roles??[],$=H.permissions??[],Q=new Map,G=(W,B)=>{for(let M of B){if(!M.id)throw new N(`a ${W} is missing its required "id".`);let U=Q.get(M.id);if(U)throw new N(`duplicate id "${M.id}" (declared as both ${U} and ${W}).`);Q.set(M.id,W)}};G("group",Z),G("role",X),G("permission",$);let Y=new Map;for(let W of[...Z,...X,...$]){if(W.externalId===void 0)W.externalId=W.id;let B=W.externalId,M=Y.get(B);if(M!==void 0)throw new N(`duplicate externalId "${B}" (on "${M}" and "${W.id}").`);Y.set(B,W.id)}let L=(W,B,M,U)=>{let F=d(U),V=Q.get(F);if(V===void 0)throw new N(`${W} "${B}" references ${M} "${F}", which is not declared in the catalog.`);if(V!==M)throw new N(`${W} "${B}" references "${F}" as a ${M}, but it is a ${V}.`)};for(let W of X){E("role",W);for(let B of W.permissions??[])L("role",W.id,"permission",B)}for(let W of $)E("permission",W);for(let W of Z){E("group",W);for(let B of W.groups??[])L("group",W.id,"group",B);for(let B of W.roles??[])L("group",W.id,"role",B);for(let B of W.permissions??[])L("group",W.id,"permission",B)}let D=new Map(Z.map((W)=>[W.id,W])),J=new Map,q=(W,B)=>{let M=J.get(W);if(M==="done")return;if(M==="visiting")throw new N(`group composition cycle: ${[...B,W].join(" -> ")}.`);J.set(W,"visiting");for(let U of D.get(W)?.groups??[])q(d(U),[...B,W]);J.set(W,"done")};for(let W of Z)q(W.id,[]);for(let W of[...Z,...X,...$])ZH(W);return Object.freeze({groups:T(Z),roles:T(X),permissions:T($)})}function j(H,Z,X){let $=()=>{if(!X)throw Error(`Cannot write ${H} definitions: no AccessCatalogStore is wired (the code-declared catalog is read-only).`);return X},Q={async get(G){return Z.get(G)??await X?.get(G)},set(G){return $().set(G)},async delete(G){await $().delete(G)},async list(G){let Y=Math.max(0,G?.start??0),L=G?.limit,D=G?.filter?.requestable,J=Z.list().filter((F)=>D===void 0||Boolean(F.requestable)===D),q=L!=null?J.slice(Y,Y+L):J.slice(Y);if(!X)return R(J.length,q,Y,L);let W=Math.max(0,Y-J.length),B=L!=null?L-q.length:void 0,M=await X.list({start:W,limit:B!=null?Math.max(1,B):void 0,filter:G?.filter}),U=(B!=null?M.items.slice(0,B):M.items).filter((F)=>!Z.get(F.id));return R(J.length+M.total,[...q,...U],Y,L)}};if(!X||typeof X.getByExternalId==="function")Q.getByExternalId=async(G)=>Z.getByExternalId(G)??await X?.getByExternalId?.(G);return Q}function SH(H,Z){if(!H)return Z;return{groups:j("group",H.groups,Z?.groups),roles:j("role",H.roles,Z?.roles),permissions:j("permission",H.permissions,Z?.permissions),afterChange:Z?.afterChange?.bind(Z)}}var yH="ecid",n=/^ecid:([A-Za-z0-9._-]+):([A-Za-z0-9_-]+)$/,QH=/^[A-Za-z0-9._-]+$/,YH=/^[A-Za-z0-9_-]+$/;class x extends Error{constructor(H){super(H);this.name="EcidFormatError"}}function GH(H){return typeof H==="string"&&n.test(H)}function bH(H,Z){if(!H||!QH.test(H))throw new x(`Invalid ECID realm ${JSON.stringify(H)}: must be non-empty and match [A-Za-z0-9._-].`);if(!Z||!YH.test(Z))throw new x(`Invalid ECID opaque ${JSON.stringify(Z)}: must be non-empty and match [A-Za-z0-9_-].`);return`ecid:${H}:${Z}`}function hH(H){let Z=typeof H==="string"?H.match(n):null;if(!Z)throw new x(`Invalid ECID ${JSON.stringify(H)}: expected "ecid:<realm>:<opaque>".`);return{realm:Z[1],opaque:Z[2]}}function gH(H){if(!GH(H))throw new x(`Invalid ECID ${JSON.stringify(H)}: expected "ecid:<realm>:<opaque>".`);return H}function vH(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={};if("code"in X)if(typeof X.code==="string")Q.code=X.code;else $.push({message:"code must be a string",path:["code"]});else if(!("error"in X))$.push({message:"code is required",path:["code"]});if("state"in X)if(typeof X.state==="string"||X.state===void 0)Q.state=X.state;else $.push({message:"state must be a string",path:["state"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)Q.session_state=X.session_state;else $.push({message:"session_state must be a string",path:["session_state"]});if("error"in X){if(typeof X.error==="string")Q.error=X.error;else $.push({message:"error must be a string",path:["error"]});if("error_description"in X)if(typeof X.error_description==="string"||X.error_description===void 0)Q.error_description=X.error_description;else $.push({message:"error_description must be a string",path:["error_description"]});if("error_uri"in X)if(typeof X.error_uri==="string"||X.error_uri===void 0)Q.error_uri=X.error_uri;else $.push({message:"error_uri must be a string",path:["error_uri"]})}if("iss"in X)if(typeof X.iss==="string"||X.iss===void 0)Q.iss=X.iss;else $.push({message:"iss must be a string",path:["iss"]});if($.length>0)return{issues:$};return{value:Q}}}}}function cH(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={};if("access_token"in X)if(typeof X.access_token==="string")Q.access_token=X.access_token;else $.push({message:"access_token must be a string",path:["access_token"]});else $.push({message:"access_token is required",path:["access_token"]});if("id_token"in X)if(typeof X.id_token==="string")Q.id_token=X.id_token;else $.push({message:"id_token must be a string",path:["id_token"]});else $.push({message:"id_token is required",path:["id_token"]});if("token_type"in X)if(typeof X.token_type==="string")Q.token_type=X.token_type;else $.push({message:"token_type must be a string",path:["token_type"]});else $.push({message:"token_type is required",path:["token_type"]});if("refresh_token"in X)if(typeof X.refresh_token==="string"||X.refresh_token===void 0)Q.refresh_token=X.refresh_token;else $.push({message:"refresh_token must be a string",path:["refresh_token"]});if("scope"in X)if(typeof X.scope==="string"||X.scope===void 0)Q.scope=X.scope;else $.push({message:"scope must be a string",path:["scope"]});if("session_state"in X)if(typeof X.session_state==="string"||X.session_state===void 0)Q.session_state=X.session_state;else $.push({message:"session_state must be a string",path:["session_state"]});if("expires"in X)if(typeof X.expires==="string"||X.expires===void 0)Q.expires=X.expires;else $.push({message:"expires must be a string",path:["expires"]});if("expires_in"in X)if(typeof X.expires_in==="number"||X.expires_in===void 0)Q.expires_in=X.expires_in;else $.push({message:"expires_in must be a number",path:["expires_in"]});if("refresh_expires_in"in X)if(typeof X.refresh_expires_in==="number"||X.refresh_expires_in===void 0)Q.refresh_expires_in=X.refresh_expires_in;else $.push({message:"refresh_expires_in must be a number",path:["refresh_expires_in"]});if($.length>0)return{issues:$};return{value:Q}}}}}function l(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={...X},G=["iss","sub"];for(let J of G)if(typeof X[J]!=="string")$.push({message:`${J} is required and must be a string`,path:[J]});let Y=X.aud;if(!(typeof Y==="string"||Array.isArray(Y)&&Y.length>0&&Y.every((J)=>typeof J==="string")))$.push({message:"aud is required and must be a string or a non-empty array of strings",path:["aud"]});if(typeof X.exp!=="number")$.push({message:"exp is required and must be a number",path:["exp"]});let D=["sid","name","email","preferred_username","picture"];for(let J of D)if(J in X&&X[J]!==void 0){if(typeof X[J]!=="string")$.push({message:`${J} must be a string`,path:[J]})}if("iat"in X&&X.iat!==void 0&&typeof X.iat!=="number")$.push({message:"iat must be a number",path:["iat"]});if($.length>0)return{issues:$};return{value:Q}}}}}function o(H){let Z=H["~standard"];return Object.assign(H,{validate(X){return Promise.resolve(Z.validate(X))}})}function dH(H,Z="Assertion failed. Required value is null or undefined."){if(H===void 0||H===null)throw Error(Z);return H}function nH(H,Z){return Response.json({error:"validation_failed",message:Z,issues:H},{status:400,headers:{"Content-Type":"application/json"}})}function lH(H,Z,X=[]){let $={...H,...Z};for(let Q of X)$[Q]=H?.[Q]??Z?.[Q];return $}function LH(H){let Z="",X=0,$=H.length;while(X<$){let Q=H[X];if(Q==='"'||Q==="'"){let G=Q;Z+=Q,X++;while(X<$){let Y=H[X];if(Y==="\\"){if(Z+=Y,X+1<$)Z+=H[X+1],X+=2;else X++;continue}if(Y===G){Z+=Y,X++;break}Z+=Y,X++}continue}if(Q==="/"&&X+1<$){let G=H[X+1];if(G==="/"){X+=2;while(X<$&&H[X]!==`
2
2
  `)X++;if(X<$)Z+=`
3
3
  `;X++;continue}if(G==="*"){X+=2;while(X+1<$&&!(H[X]==="*"&&H[X+1]==="/"))X++;X+=2;continue}}Z+=Q,X++}return Z}function uH(H){let Z=LH(H);return JSON.parse(Z)}function oH(H){return H==="/"?H:H.replace(/\/+$/,"")}function k(H){if(H===null||typeof H!=="object"||Array.isArray(H))return!1;let Z=Object.getPrototypeOf(H);return Z===Object.prototype||Z===null}function I(H){return Object.keys(H).filter((Z)=>H[Z]!==void 0).sort()}function u(H,Z){if(Object.is(H,Z))return!0;if(H===null||Z===null)return H===Z;if(Array.isArray(H)||Array.isArray(Z)){if(!Array.isArray(H)||!Array.isArray(Z)||H.length!==Z.length)return!1;for(let Q=0;Q<H.length;Q+=1)if(!u(H[Q],Z[Q]))return!1;return!0}if(!k(H)||!k(Z))return!1;let X=I(H),$=I(Z);if(X.length!==$.length)return!1;for(let Q=0;Q<X.length;Q+=1)if(X[Q]!==$[Q])return!1;for(let Q of X)if(!u(H[Q],Z[Q]))return!1;return!0}function w(H,Z){if(H===null||H===void 0){Z.push("n");return}if(Array.isArray(H)){Z.push("[");for(let X of H)w(X,Z);Z.push("]");return}if(k(H)){Z.push("{");for(let X of I(H))Z.push(JSON.stringify(X),":"),w(H[X],Z);Z.push("}");return}Z.push(JSON.stringify(H))}function rH(H){let Z=[];w(H,Z);let X=Z.join(""),$=2166136261;for(let Q=0;Q<X.length;Q+=1)$^=X.charCodeAt(Q),$=$*16777619%9007199254740992;return`${X.length.toString(36)}:${$.toString(36)}`}async function tH(H,Z=async(Y)=>Y.status===200,X=1000,$=1e4,Q,G){let Y=Date.now(),L=`Awaiting Ping (${H})`;return new Promise((D,J)=>{let q=null,W=null,B=null,M=!1,U=()=>{if(q)clearTimeout(q);if(W)clearInterval(W);if(B)clearTimeout(B);q=null,W=null,B=null},F=(K)=>{if(M)return;M=!0,U(),K()},V=Math.max(X,1e4),A=async()=>{try{let K=await fetch(H,{signal:AbortSignal.timeout(V)});if(K.ok){if(await Z(K)){F(D);return}L=`Response test failed: ${K.status}: ${K.statusText} - ${H}`}else try{let S=await K.json();L=`Response error: ${K.status}: ${K.statusText} - ${H}: ${JSON.stringify(S)}`}catch(S){L=`Response error: ${K.status}: ${K.statusText} - ${H}`}}catch(K){L=`${K instanceof Error?K.message:String(K)} - ${H}`}if(!M)q=setTimeout(()=>void A(),X)};if($>0)W=setInterval(()=>{G?.warn(`${L}: ${Date.now()-Y}ms`)},$);if(Q)B=setTimeout(()=>{F(()=>J(Error(`Timeout: ${Q}ms: ${L}`)))},Q);A()})}var WH="@ionite/core",BH=o(l(WH));function MH(H){let Z=H.exp!=null?new Date(H.exp*1000):new Date,X=H.iss??"";return{id:H.sub??"",userName:H.preferred_username??"",name:H.name??"",email:H.email??"",avatar:H.picture,sso:{profile:{...H,iss:H.iss??X,aud:H.aud},tenant:{id:H.idp??X,name:X},tokenType:"Bearer",expires:Z}}}function _H(H){let Z=H.replace(/-/g,"+").replace(/_/g,"/");return atob(Z)}async function eH(H){let Z=H.split(".");if(Z.length!==3)throw Error("Invalid JWT");let X=_H(Z[1]),$=JSON.parse(X),Q=await BH.validate($);if(Q.issues)throw Error(`ID token claims validation failed: ${Q.issues.map((G)=>G.message).join("; ")}`);if(Q.value)return MH(Q.value);throw Error("ID token claims validation failed")}class P extends Error{code="conflict";kind;field;constructor(H,Z,X){super(H);this.name="StoreConflictError",this.kind=Z,this.field=X,Object.setPrototypeOf(this,P.prototype)}}function XX(H){return H instanceof P||typeof H==="object"&&H!=null&&H.code==="conflict"}class r extends Error{status;statusText;constructor(H,Z={}){super(H,{cause:Z.cause});this.name="IoniteError",this.status=Z.status,this.statusText=Z.statusText,Object.setPrototypeOf(this,r.prototype)}}function QX(H){if(typeof H!=="object"||H==null)return!1;let Z=H.type;return Z==="vault"||Z==="aws"||Z==="azure"||Z==="gcp"}class t{tenants=new Map;async get(H){return this.tenants.get(H)}async list(H){let Z=Array.from(this.tenants.values()),X=Math.max(0,H?.start??0),$=H?.limit,Q=Z.length,G=$!=null?X+$:void 0,Y=Z.slice(X,G);return R(Q,Y,X,$)}async upsert(H){return this.tenants.set(H.id,H),H}async delete(H){let Z=this.tenants.has(H);return this.tenants.delete(H),Z?1:0}}class JH{store;ionCache;constructor(H={}){this.ionCache=H.ionCache,this.store=new t}async get(H){return this.store.get(H)}async list(H){return this.store.list(H)}async upsert(H){let Z=await this.store.upsert(H);return this.ionCache?.delete(H.id),Z}async delete(H){let Z=await this.store.delete(H);return this.ionCache?.delete(H),Z}async getIon(H){if(!this.ionCache)throw Error(`${this.constructor.name}.getIon() requires an app-owned ionCache. Pass { ionCache } (an lru-cache instance whose fetchMethod builds the tenant Ionite and whose dispose `+"closes it) — the SDK does not cache tenant runtimes. See the multi-tenant docs.");return this.ionCache.fetch(H)}}function DH(H,Z,X){return(async()=>{try{let $=await fetch(H,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Z)});if(!$.ok)X.error("Failed to send webhook update",{"ion.operation":"webhook.update","ion.outcome":"failure",status:$.status,statusText:$.statusText})}catch($){X.error("Failed to send webhook update",{"ion.operation":"webhook.update","ion.outcome":"failure"},$)}})()}async function YX(H,Z,X){return DH(H,Z,X)}var LX="urn:ionite:params:scim:schemas:extension:authz:2.0:Group",i=["user","workload"];function WX(H){let{assignableSubjectTypes:Z,recommendedSubjectTypes:X}=H,$=H.id?` for "${H.id}"`:"";if(Z){let Q=Z.filter((G)=>!i.includes(G));if(Q.length>0)throw Error(`assignableSubjectTypes${$} contains values outside the platform ceiling [${i.join(", ")}]: ${Q.join(", ")}`)}if(X&&Z){let Q=X.filter((G)=>!Z.includes(G));if(Q.length>0)throw Error(`recommendedSubjectTypes${$} must be a subset of assignableSubjectTypes; offending values: ${Q.join(", ")}`)}}var MX="urn:ionite:scim:schemas:extension:ion:2.0:User";function _(H,Z,X,$,Q){if(H===void 0||H===null){if(X)$.push({message:`${Z} is required`,path:Q});return}if(typeof H!=="string"){$.push({message:`${Z} must be a string`,path:Q});return}return H}function C(H,Z,X,$){if(H===void 0||H===null)return;if(typeof H!=="boolean"){X.push({message:`${Z} must be a boolean`,path:$});return}return H}function UH(H,Z,X){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){Z.push({message:"name must be an object",path:X});return}let $=H,Q={};return Q.formatted=_($.formatted,"formatted",!1,Z,[...X,"formatted"]),Q.familyName=_($.familyName,"familyName",!1,Z,[...X,"familyName"]),Q.givenName=_($.givenName,"givenName",!1,Z,[...X,"givenName"]),Q.middleName=_($.middleName,"middleName",!1,Z,[...X,"middleName"]),Q.honorificPrefix=_($.honorificPrefix,"honorificPrefix",!1,Z,[...X,"honorificPrefix"]),Q.honorificSuffix=_($.honorificSuffix,"honorificSuffix",!1,Z,[...X,"honorificSuffix"]),Q}function qH(H,Z,X){if(H===void 0||H===null)return;if(!Array.isArray(H)){Z.push({message:"emails must be an array",path:X});return}let $=[];for(let Q=0;Q<H.length;Q++){let G=H[Q],Y=[...X,Q];if(typeof G!=="object"||G===null){Z.push({message:"email must be an object",path:Y});continue}let L=G,D=_(L.value,"value",!0,Z,[...Y,"value"]);if(D)$.push({value:D,display:_(L.display,"display",!1,Z,[...Y,"display"]),type:_(L.type,"type",!1,Z,[...Y,"type"]),primary:C(L.primary,"primary",Z,[...Y,"primary"])})}return $.length>0?$:void 0}function FH(H,Z,X){if(H===void 0||H===null)return;if(!Array.isArray(H)){Z.push({message:"phoneNumbers must be an array",path:X});return}let $=[];for(let Q=0;Q<H.length;Q++){let G=H[Q],Y=[...X,Q];if(typeof G!=="object"||G===null){Z.push({message:"phoneNumber must be an object",path:Y});continue}let L=G,D=_(L.value,"value",!0,Z,[...Y,"value"]);if(D)$.push({value:D,display:_(L.display,"display",!1,Z,[...Y,"display"]),type:_(L.type,"type",!1,Z,[...Y,"type"]),primary:C(L.primary,"primary",Z,[...Y,"primary"])})}return $.length>0?$:void 0}function KH(H,Z,X){if(H===void 0||H===null)return;if(!Array.isArray(H)){Z.push({message:"addresses must be an array",path:X});return}let $=[];for(let Q=0;Q<H.length;Q++){let G=H[Q],Y=[...X,Q];if(typeof G!=="object"||G===null){Z.push({message:"address must be an object",path:Y});continue}let L=G;$.push({formatted:_(L.formatted,"formatted",!1,Z,[...Y,"formatted"]),streetAddress:_(L.streetAddress,"streetAddress",!1,Z,[...Y,"streetAddress"]),locality:_(L.locality,"locality",!1,Z,[...Y,"locality"]),region:_(L.region,"region",!1,Z,[...Y,"region"]),postalCode:_(L.postalCode,"postalCode",!1,Z,[...Y,"postalCode"]),country:_(L.country,"country",!1,Z,[...Y,"country"]),type:_(L.type,"type",!1,Z,[...Y,"type"]),primary:C(L.primary,"primary",Z,[...Y,"primary"])})}return $.length>0?$:void 0}function VH(H,Z,X){if(H===void 0||H===null)return;if(!Array.isArray(H)){Z.push({message:"groups must be an array",path:X});return}let $=[];for(let Q=0;Q<H.length;Q++){let G=H[Q],Y=[...X,Q];if(typeof G!=="object"||G===null){Z.push({message:"group must be an object",path:Y});continue}let L=G,D=_(L.value,"value",!0,Z,[...Y,"value"]);if(D)$.push({value:D,$ref:_(L.$ref,"$ref",!1,Z,[...Y,"$ref"]),display:_(L.display,"display",!1,Z,[...Y,"display"]),type:_(L.type,"type",!1,Z,[...Y,"type"])})}return $.length>0?$:void 0}function AH(H,Z,X){if(H===void 0||H===null)return;if(!Array.isArray(H)){Z.push({message:"roles must be an array",path:X});return}let $=[];for(let Q=0;Q<H.length;Q++){let G=H[Q],Y=[...X,Q];if(typeof G!=="object"||G===null){Z.push({message:"role must be an object",path:Y});continue}let L=G,D=_(L.value,"value",!0,Z,[...Y,"value"]);if(D)$.push({value:D,display:_(L.display,"display",!1,Z,[...Y,"display"]),type:_(L.type,"type",!1,Z,[...Y,"type"]),primary:C(L.primary,"primary",Z,[...Y,"primary"])})}return $.length>0?$:void 0}function zH(H,Z,X){if(H===void 0||H===null)return;if(typeof H!=="object"||H===null){Z.push({message:"Enterprise User extension must be an object",path:X});return}let $=H,Q={};if(Q.employeeNumber=_($.employeeNumber,"employeeNumber",!1,Z,[...X,"employeeNumber"]),Q.costCenter=_($.costCenter,"costCenter",!1,Z,[...X,"costCenter"]),Q.organization=_($.organization,"organization",!1,Z,[...X,"organization"]),Q.division=_($.division,"division",!1,Z,[...X,"division"]),Q.department=_($.department,"department",!1,Z,[...X,"department"]),$.manager!==void 0&&$.manager!==null)if(typeof $.manager!=="object"||$.manager===null)Z.push({message:"manager must be an object",path:[...X,"manager"]});else{let G=$.manager;Q.manager={value:_(G.value,"value",!1,Z,[...X,"manager","value"]),$ref:_(G.$ref,"$ref",!1,Z,[...X,"manager","$ref"]),displayName:_(G.displayName,"displayName",!1,Z,[...X,"manager","displayName"])}}return Q}function _X(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={},G=_(X.userName,"userName",!0,$,["userName"]);if(!G)return{issues:$};if(Q.userName=G,Q.id=_(X.id,"id",!1,$,["id"]),Q.externalId=_(X.externalId,"externalId",!1,$,["externalId"]),Q.displayName=_(X.displayName,"displayName",!1,$,["displayName"]),Q.nickName=_(X.nickName,"nickName",!1,$,["nickName"]),Q.profileUrl=_(X.profileUrl,"profileUrl",!1,$,["profileUrl"]),Q.title=_(X.title,"title",!1,$,["title"]),Q.userType=_(X.userType,"userType",!1,$,["userType"]),Q.preferredLanguage=_(X.preferredLanguage,"preferredLanguage",!1,$,["preferredLanguage"]),Q.locale=_(X.locale,"locale",!1,$,["locale"]),Q.timezone=_(X.timezone,"timezone",!1,$,["timezone"]),X.password!==void 0)$.push({message:"password is not supported: the SDK does not accept credentials via SCIM",path:["password"]});Q.active=C(X.active,"active",$,["active"]),Q.name=UH(X.name,$,["name"]),Q.emails=qH(X.emails,$,["emails"]),Q.phoneNumbers=FH(X.phoneNumbers,$,["phoneNumbers"]),Q.addresses=KH(X.addresses,$,["addresses"]),Q.groups=VH(X.groups,$,["groups"]),Q.roles=AH(X.roles,$,["roles"]);let Y="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User";if(X[Y]!==void 0)Q[Y]=zH(X[Y],$,[Y]);if(X.schemas!==void 0)if(Array.isArray(X.schemas))Q.schemas=X.schemas.filter((L)=>typeof L==="string");else $.push({message:"schemas must be an array",path:["schemas"]});if(X.meta!==void 0)if(typeof X.meta==="object"&&X.meta!==null){let L=X.meta;Q.meta={resourceType:typeof L.resourceType==="string"?L.resourceType:void 0,created:typeof L.created==="string"?L.created:void 0,lastModified:typeof L.lastModified==="string"?L.lastModified:void 0,location:typeof L.location==="string"?L.location:void 0,version:typeof L.version==="string"?L.version:void 0}}else $.push({message:"meta must be an object",path:["meta"]});if($.length>0)return{issues:$};return{value:Q}}}}}function NH(H,Z,X){if(H===void 0||H===null)return;if(!Array.isArray(H)){Z.push({message:"members must be an array",path:X});return}let $=[];for(let Q=0;Q<H.length;Q++){let G=H[Q],Y=[...X,Q];if(typeof G!=="object"||G===null){Z.push({message:"member must be an object",path:Y});continue}let L=G,D=_(L.value,"value",!0,Z,[...Y,"value"]);if(D){let J=_(L.type,"type",!1,Z,[...Y,"type"]);$.push({value:D,$ref:_(L.$ref,"$ref",!1,Z,[...Y,"$ref"]),display:_(L.display,"display",!1,Z,[...Y,"display"]),type:J==="User"||J==="Group"?J:void 0})}}return $.length>0?$:void 0}function JX(H){return{"~standard":{version:1,vendor:H,validate:(Z)=>{if(typeof Z!=="object"||Z===null)return{issues:[{message:"Expected an object"}]};let X=Z,$=[],Q={},G=_(X.displayName,"displayName",!0,$,["displayName"]);if(!G)return{issues:$};if(Q.displayName=G,Q.id=_(X.id,"id",!1,$,["id"]),Q.externalId=_(X.externalId,"externalId",!1,$,["externalId"]),Q.members=NH(X.members,$,["members"]),X.schemas!==void 0)if(Array.isArray(X.schemas))Q.schemas=X.schemas.filter((Y)=>typeof Y==="string");else $.push({message:"schemas must be an array",path:["schemas"]});if(X.meta!==void 0)if(typeof X.meta==="object"&&X.meta!==null){let Y=X.meta;Q.meta={resourceType:typeof Y.resourceType==="string"?Y.resourceType:void 0,created:typeof Y.created==="string"?Y.created:void 0,lastModified:typeof Y.lastModified==="string"?Y.lastModified:void 0,location:typeof Y.location==="string"?Y.location:void 0,version:typeof Y.version==="string"?Y.version:void 0}}else $.push({message:"meta must be an object",path:["meta"]});if($.length>0)return{issues:$};return{value:Q}}}}}
4
- export{RH as a,OH as b,R as c,b as d,z as e,g as f,EH as g,e as h,HH as i,TH as j,kH as k,XH as l,PH as m,$H as n,SH as o,yH as p,x as q,GH as r,bH as s,hH as t,gH as u,vH as v,cH as w,l as x,o as y,dH as z,nH as A,lH as B,LH as C,uH as D,oH as E,u as F,rH as G,tH as H,MH as I,eH as J,P as K,XX as L,r as M,QX as N,JH as O,YX as P,LX as Q,i as R,WX as S,MX as T,_X as U,JX as V};
4
+ export{RH as a,OH as b,R as c,b as d,z as e,g as f,TH as g,e as h,HH as i,jH as j,kH as k,XH as l,PH as m,$H as n,SH as o,yH as p,x as q,GH as r,bH as s,hH as t,gH as u,vH as v,cH as w,l as x,o as y,dH as z,nH as A,lH as B,LH as C,uH as D,oH as E,u as F,rH as G,tH as H,MH as I,eH as J,P as K,XX as L,r as M,QX as N,JH as O,YX as P,LX as Q,i as R,WX as S,MX as T,_X as U,JX as V};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ionite/core",
3
- "version": "0.0.23-beta.20260803.1",
3
+ "version": "0.0.23-beta.20260809.2",
4
4
  "description": "ionite Core (client-safe main entry; server handlers under ./server)",
5
5
  "private": false,
6
6
  "author": "ionite",