@frontmcp/auth 1.10.16 → 1.11.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/browser/authorities/authorities.context.mjs +115 -0
  2. package/browser/authorities/authorities.engine.mjs +272 -0
  3. package/browser/authorities/authorities.errors.mjs +59 -0
  4. package/browser/authorities/authorities.evaluator.mjs +225 -0
  5. package/browser/authorities/authorities.metadata-augment.mjs +18 -0
  6. package/browser/authorities/authorities.registry.mjs +112 -0
  7. package/browser/authorities/authorities.schema.mjs +92 -0
  8. package/browser/authorities/authorities.scope-mapping.mjs +30 -0
  9. package/browser/authorities/authorities.validation.mjs +208 -0
  10. package/browser/authorities/index.mjs +43 -0
  11. package/browser/authorization/authorization.class.mjs +252 -0
  12. package/browser/authorization/authorization.types.mjs +64 -0
  13. package/browser/authorization/dcr-client.registry.mjs +222 -0
  14. package/browser/authorization/index.mjs +41 -0
  15. package/browser/authorization/orchestrated.accessor.mjs +86 -0
  16. package/browser/authorization/orchestrated.authorization.mjs +289 -0
  17. package/browser/authorization/public.authorization.mjs +124 -0
  18. package/browser/authorization/transparent.authorization.mjs +130 -0
  19. package/browser/cimd/cimd-redis.cache.mjs +231 -0
  20. package/browser/cimd/cimd.cache.mjs +215 -0
  21. package/browser/cimd/cimd.errors.mjs +142 -0
  22. package/browser/cimd/cimd.logger.mjs +15 -0
  23. package/browser/cimd/cimd.service.mjs +376 -0
  24. package/browser/cimd/cimd.types.mjs +228 -0
  25. package/browser/cimd/cimd.validator.mjs +217 -0
  26. package/browser/cimd/index.mjs +63 -0
  27. package/browser/common/auth-logger.interface.mjs +14 -0
  28. package/browser/common/index.mjs +6 -0
  29. package/browser/common/jwt.types.mjs +38 -0
  30. package/browser/common/session-user.types.mjs +0 -0
  31. package/browser/common/session.types.mjs +58 -0
  32. package/browser/common/zod-utils.mjs +0 -0
  33. package/browser/consent/consent.types.mjs +94 -0
  34. package/browser/consent/index.mjs +17 -0
  35. package/browser/context/frontmcp-auth-context.factory.mjs +29 -0
  36. package/browser/context/frontmcp-auth-context.impl.mjs +112 -0
  37. package/browser/context/index.mjs +7 -0
  38. package/browser/detection/auth-provider-detection.mjs +176 -0
  39. package/browser/detection/index.mjs +19 -0
  40. package/browser/errors/auth-internal.error.mjs +42 -0
  41. package/browser/errors/auth-internal.errors.mjs +150 -0
  42. package/browser/errors/index.mjs +53 -0
  43. package/browser/fetch/fetch-credential-middleware.mjs +91 -0
  44. package/browser/fetch/index.mjs +19 -0
  45. package/browser/index.mjs +573 -0
  46. package/browser/jwks/index.mjs +9 -0
  47. package/browser/jwks/jose.loader.mjs +28 -0
  48. package/browser/jwks/jwks.service.mjs +521 -0
  49. package/browser/jwks/jwks.utils.mjs +33 -0
  50. package/browser/options/app-auth.schema.mjs +18 -0
  51. package/browser/options/index.mjs +89 -0
  52. package/browser/options/orchestrated.schema.mjs +128 -0
  53. package/browser/options/public.schema.mjs +39 -0
  54. package/browser/options/schema.mjs +16 -0
  55. package/browser/options/shared.schemas.mjs +506 -0
  56. package/browser/options/static.schema.mjs +41 -0
  57. package/browser/options/transparent.schema.mjs +43 -0
  58. package/browser/options/utils.mjs +47 -0
  59. package/browser/people/index.mjs +15 -0
  60. package/browser/people/loopback-token.auth.mjs +115 -0
  61. package/browser/people/people-auth.options.mjs +37 -0
  62. package/browser/session/authorization-vault.mjs +279 -0
  63. package/browser/session/authorization.store.mjs +336 -0
  64. package/browser/session/consent.store.mjs +34 -0
  65. package/browser/session/credential-resume-link.mjs +43 -0
  66. package/browser/session/credentials-accessor.impl.mjs +54 -0
  67. package/browser/session/credentials-accessor.mjs +5 -0
  68. package/browser/session/encrypted-authorization-vault.mjs +405 -0
  69. package/browser/session/federated-auth.session.mjs +176 -0
  70. package/browser/session/incremental-auth-ticket.mjs +42 -0
  71. package/browser/session/index.mjs +266 -0
  72. package/browser/session/orchestrated-token.crypto.mjs +47 -0
  73. package/browser/session/orchestrated-token.store.mjs +286 -0
  74. package/browser/session/pending-login.mjs +37 -0
  75. package/browser/session/redis-session.store.mjs +255 -0
  76. package/browser/session/secure-store-accessor.impl.mjs +78 -0
  77. package/browser/session/secure-store-accessor.mjs +5 -0
  78. package/browser/session/secure-store-backends.mjs +111 -0
  79. package/browser/session/secure-store.factory.mjs +77 -0
  80. package/browser/session/session-credential-vault.factory.mjs +18 -0
  81. package/browser/session/session-credential-vault.mjs +243 -0
  82. package/browser/session/session-crypto.mjs +39 -0
  83. package/browser/session/session-rate-limiter.mjs +126 -0
  84. package/browser/session/session.transport.mjs +16 -0
  85. package/browser/session/signin-binding.mjs +30 -0
  86. package/browser/session/storage/in-memory-authorization-vault.mjs +28 -0
  87. package/browser/session/storage/index.mjs +14 -0
  88. package/browser/session/storage/storage-authorization-vault.mjs +301 -0
  89. package/browser/session/storage/storage-token-store.mjs +83 -0
  90. package/browser/session/storage-authorization.store.mjs +134 -0
  91. package/browser/session/storage-consent.store.mjs +33 -0
  92. package/browser/session/storage-federated-auth.session.mjs +55 -0
  93. package/browser/session/storage-orchestrated-token.store.mjs +197 -0
  94. package/browser/session/token-storage.factory.mjs +58 -0
  95. package/browser/session/token.refresh.mjs +36 -0
  96. package/browser/session/token.vault.mjs +61 -0
  97. package/browser/session/transport-session.types.mjs +108 -0
  98. package/browser/session/utils/auth-token.utils.mjs +58 -0
  99. package/browser/session/utils/index.mjs +23 -0
  100. package/browser/session/utils/session-crypto.utils.mjs +49 -0
  101. package/browser/session/utils/tiny-ttl-cache.mjs +46 -0
  102. package/browser/session/vault-encryption.mjs +187 -0
  103. package/browser/session/vercel-kv-session.store.mjs +230 -0
  104. package/browser/shared-server/index.mjs +17 -0
  105. package/browser/shared-server/shared-server-identity.mjs +55 -0
  106. package/browser/ui/base-layout.mjs +184 -0
  107. package/browser/ui/index.mjs +51 -0
  108. package/browser/ui/local-login.helper.mjs +46 -0
  109. package/browser/ui/templates.mjs +482 -0
  110. package/browser/utils/audience.validator.mjs +110 -0
  111. package/browser/utils/authorization-id.utils.mjs +10 -0
  112. package/browser/utils/index.mjs +45 -0
  113. package/browser/utils/redirect-uri.utils.mjs +22 -0
  114. package/browser/utils/scope-grant.utils.mjs +36 -0
  115. package/browser/utils/token-scopes.utils.mjs +12 -0
  116. package/browser/utils/www-authenticate.utils.mjs +164 -0
  117. package/browser/vault/auth-providers.accessor.impl.mjs +236 -0
  118. package/browser/vault/auth-providers.accessor.mjs +5 -0
  119. package/browser/vault/auth-providers.registry.mjs +140 -0
  120. package/browser/vault/auth-providers.types.mjs +47 -0
  121. package/browser/vault/auth-providers.vault.mjs +206 -0
  122. package/browser/vault/credential-cache.mjs +187 -0
  123. package/browser/vault/credential-helpers.mjs +15 -0
  124. package/browser/vault/credential-loaders/eager-loader.mjs +91 -0
  125. package/browser/vault/credential-loaders/lazy-loader.mjs +120 -0
  126. package/browser/vault/index.mjs +35 -0
  127. package/cimd/cimd.types.d.ts +1 -1
  128. package/cimd/cimd.types.d.ts.map +1 -1
  129. package/common/jwt.types.d.ts +1 -1
  130. package/common/jwt.types.d.ts.map +1 -1
  131. package/common/session.types.d.ts +9 -1
  132. package/common/session.types.d.ts.map +1 -1
  133. package/consent/consent.types.d.ts +1 -1
  134. package/consent/consent.types.d.ts.map +1 -1
  135. package/detection/auth-provider-detection.d.ts +1 -1
  136. package/detection/auth-provider-detection.d.ts.map +1 -1
  137. package/errors/auth-internal.errors.d.ts +6 -0
  138. package/errors/auth-internal.errors.d.ts.map +1 -1
  139. package/errors/index.d.ts +1 -1
  140. package/errors/index.d.ts.map +1 -1
  141. package/esm/index.mjs +2 -2
  142. package/esm/package.json +21 -5
  143. package/index.d.ts +5 -1
  144. package/index.d.ts.map +1 -1
  145. package/index.js +2 -2
  146. package/options/app-auth.schema.d.ts +19 -1
  147. package/options/app-auth.schema.d.ts.map +1 -1
  148. package/options/orchestrated.schema.d.ts +37 -1
  149. package/options/orchestrated.schema.d.ts.map +1 -1
  150. package/options/public.schema.d.ts +1 -1
  151. package/options/public.schema.d.ts.map +1 -1
  152. package/options/schema.d.ts +19 -1
  153. package/options/schema.d.ts.map +1 -1
  154. package/options/shared.schemas.d.ts +10 -14
  155. package/options/shared.schemas.d.ts.map +1 -1
  156. package/options/static.schema.d.ts +1 -1
  157. package/options/static.schema.d.ts.map +1 -1
  158. package/options/transparent.schema.d.ts +1 -1
  159. package/options/transparent.schema.d.ts.map +1 -1
  160. package/package.json +21 -5
  161. package/people/index.d.ts +3 -0
  162. package/people/index.d.ts.map +1 -0
  163. package/people/loopback-token.auth.d.ts +75 -0
  164. package/people/loopback-token.auth.d.ts.map +1 -0
  165. package/people/people-auth.options.d.ts +36 -0
  166. package/people/people-auth.options.d.ts.map +1 -0
  167. package/session/authorization-vault.d.ts +1 -1
  168. package/session/authorization-vault.d.ts.map +1 -1
  169. package/session/encrypted-authorization-vault.d.ts +1 -1
  170. package/session/encrypted-authorization-vault.d.ts.map +1 -1
  171. package/session/secure-store.factory.d.ts.map +1 -1
  172. package/shared-server/index.d.ts +3 -0
  173. package/shared-server/index.d.ts.map +1 -0
  174. package/shared-server/shared-server-identity.d.ts +26 -0
  175. package/shared-server/shared-server-identity.d.ts.map +1 -0
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf;var __hasOwnProp=Object.prototype.hasOwnProperty;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:true}):target,mod));var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var cimd_redis_cache_exports={};__export(cimd_redis_cache_exports,{RedisCimdCache:()=>RedisCimdCache});var import_utils43,import_utils44,RedisCimdCache;var init_cimd_redis_cache=__esm({"libs/auth/src/cimd/cimd-redis.cache.ts"(){"use strict";import_utils43=require("@frontmcp/utils");import_utils44=require("@frontmcp/utils");init_cimd_cache();RedisCimdCache=class{redis;keyPrefix;config;constructor(config){if(!config.redis){throw new Error("Redis configuration is required for RedisCimdCache")}this.config={defaultTtlMs:config.defaultTtlMs??36e5,maxTtlMs:config.maxTtlMs??864e5,minTtlMs:config.minTtlMs??6e4};this.keyPrefix=config.redis.keyPrefix??"cimd:";const redisOptions={};if(config.redis.url){redisOptions.url=config.redis.url}else if(config.redis.host){redisOptions.config={host:config.redis.host,port:config.redis.port,password:config.redis.password,db:config.redis.db,tls:config.redis.tls}}this.redis=new import_utils43.RedisStorageAdapter(redisOptions)}async connect(){await this.redis.connect()}cacheKey(clientId){const hash=(0,import_utils44.sha256Hex)(clientId);return`${this.keyPrefix}${hash}`}async get(clientId){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return void 0}try{const entry=JSON.parse(data);if(entry.expiresAt<Date.now()){return void 0}return entry}catch{await this.redis.delete(key);return void 0}}async getStale(clientId){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return void 0}try{return JSON.parse(data)}catch{return void 0}}async set(clientId,document,headers){const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);const now=Date.now();const entry={document,expiresAt:now+ttlMs,etag,lastModified,cachedAt:now};const key=this.cacheKey(clientId);const value=JSON.stringify(entry);const redisTtlSeconds=Math.ceil((ttlMs+this.config.maxTtlMs*2)/1e3);await this.redis.set(key,value,{ttlSeconds:redisTtlSeconds})}async revalidate(clientId,headers){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return false}try{const existing=JSON.parse(data);const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);existing.expiresAt=Date.now()+ttlMs;if(etag)existing.etag=etag;if(lastModified)existing.lastModified=lastModified;const value=JSON.stringify(existing);const redisTtlSeconds=Math.ceil((ttlMs+this.config.maxTtlMs*2)/1e3);await this.redis.set(key,value,{ttlSeconds:redisTtlSeconds});return true}catch{return false}}async delete(clientId){const key=this.cacheKey(clientId);return this.redis.delete(key)}async getConditionalHeaders(clientId){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return void 0}try{const entry=JSON.parse(data);const headers={};if(entry.etag){headers["If-None-Match"]=entry.etag}if(entry.lastModified){headers["If-Modified-Since"]=entry.lastModified}return Object.keys(headers).length>0?headers:void 0}catch{return void 0}}async clear(){const keys=await this.redis.keys(`${this.keyPrefix}*`);if(keys.length>0){await this.redis.mdelete(keys)}}async size(){const keys=await this.redis.keys(`${this.keyPrefix}*`);return keys.length}async cleanup(){const now=Date.now();let removed=0;const keys=await this.redis.keys(`${this.keyPrefix}*`);for(const key of keys){const data=await this.redis.get(key);if(!data)continue;try{const entry=JSON.parse(data);if(entry.expiresAt+this.config.maxTtlMs*2<now){await this.redis.delete(key);removed++}}catch{await this.redis.delete(key);removed++}}return removed}async close(){await this.redis.disconnect()}}}});function extractCacheHeaders(headers){return{"cache-control":headers.get("cache-control")??void 0,expires:headers.get("expires")??void 0,etag:headers.get("etag")??void 0,"last-modified":headers.get("last-modified")??void 0,age:headers.get("age")??void 0}}function parseCacheHeaders(headers,config){let ttlMs=config.defaultTtlMs;if(headers["cache-control"]){const cacheControl=parseCacheControlHeader(headers["cache-control"]);if(cacheControl["no-store"]||cacheControl["no-cache"]){ttlMs=config.minTtlMs}else if(typeof cacheControl["max-age"]==="number"){let maxAgeSecs=cacheControl["max-age"];if(headers.age){const ageSeconds=parseInt(headers.age,10);if(!isNaN(ageSeconds)){maxAgeSecs=Math.max(0,maxAgeSecs-ageSeconds)}}ttlMs=maxAgeSecs*1e3}if(typeof cacheControl["s-maxage"]==="number"){let sMaxAgeSecs=cacheControl["s-maxage"];if(headers.age){const ageSeconds=parseInt(headers.age,10);if(!isNaN(ageSeconds)){sMaxAgeSecs=Math.max(0,sMaxAgeSecs-ageSeconds)}}ttlMs=sMaxAgeSecs*1e3}}else if(headers.expires){const expiresDate=new Date(headers.expires);if(!isNaN(expiresDate.getTime())){ttlMs=Math.max(0,expiresDate.getTime()-Date.now())}}ttlMs=Math.max(config.minTtlMs,Math.min(config.maxTtlMs,ttlMs));return{ttlMs,etag:headers.etag,lastModified:headers["last-modified"]}}function parseCacheControlHeader(value){const result={};const directives=value.toLowerCase().split(",").map(d=>d.trim());for(const directive of directives){const[key,val]=directive.split("=").map(s=>s.trim());if(val!==void 0){const numVal=parseInt(val,10);if(!isNaN(numVal)){result[key]=numVal}}else{result[key]=true}}return result}async function createCimdCache(config){const cacheType=config?.type??"memory";if(cacheType==="redis"){if(!config?.redis){throw new Error('Redis configuration is required when cache type is "redis"')}const{RedisCimdCache:RedisCimdCache2}=await Promise.resolve().then(()=>(init_cimd_redis_cache(),cimd_redis_cache_exports));const cache=new RedisCimdCache2(config);await cache.connect();return cache}return new InMemoryCimdCache(config)}var InMemoryCimdCache;var init_cimd_cache=__esm({"libs/auth/src/cimd/cimd.cache.ts"(){"use strict";InMemoryCimdCache=class{cache=new Map;config;constructor(config){this.config={defaultTtlMs:config?.defaultTtlMs??36e5,maxTtlMs:config?.maxTtlMs??864e5,minTtlMs:config?.minTtlMs??6e4}}async get(clientId){const entry=this.cache.get(clientId);if(!entry){return void 0}if(entry.expiresAt<Date.now()){return void 0}return entry}async getStale(clientId){return this.cache.get(clientId)}async set(clientId,document,headers){const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);const now=Date.now();const entry={document,expiresAt:now+ttlMs,etag,lastModified,cachedAt:now};this.cache.set(clientId,entry)}async revalidate(clientId,headers){const existing=this.cache.get(clientId);if(!existing){return false}const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);existing.expiresAt=Date.now()+ttlMs;if(etag)existing.etag=etag;if(lastModified)existing.lastModified=lastModified;return true}async delete(clientId){return this.cache.delete(clientId)}async getConditionalHeaders(clientId){const entry=this.cache.get(clientId);if(!entry){return void 0}const headers={};if(entry.etag){headers["If-None-Match"]=entry.etag}if(entry.lastModified){headers["If-Modified-Since"]=entry.lastModified}return Object.keys(headers).length>0?headers:void 0}async clear(){this.cache.clear()}async size(){return this.cache.size}async cleanup(){const now=Date.now();let removed=0;for(const[clientId,entry]of this.cache){if(entry.expiresAt+this.config.maxTtlMs*2<now){this.cache.delete(clientId);removed++}}return removed}}}});var index_exports={};__export(index_exports,{AUTH_PROVIDERS_ACCESSOR:()=>AUTH_PROVIDERS_ACCESSOR,AUTH_PROVIDERS_REGISTRY:()=>AUTH_PROVIDERS_REGISTRY,AUTH_PROVIDERS_VAULT:()=>AUTH_PROVIDERS_VAULT,AppAuthState:()=>AppAuthState,AudienceValidator:()=>AudienceValidator,AuthInternalError:()=>AuthInternalError,AuthInvalidInputError:()=>AuthInvalidInputError,AuthProvidersAccessorImpl:()=>AuthProvidersAccessorImpl,AuthProvidersNotConfiguredError:()=>AuthProvidersNotConfiguredError,AuthProvidersRegistry:()=>AuthProvidersRegistry,AuthProvidersVault:()=>AuthProvidersVault,AuthoritiesContextBuilder:()=>AuthoritiesContextBuilder,AuthoritiesEngine:()=>AuthoritiesEngine,AuthoritiesEvaluatorRegistry:()=>AuthoritiesEvaluatorRegistry,AuthoritiesProfileRegistry:()=>AuthoritiesProfileRegistry,AuthorityDeniedError:()=>AuthorityDeniedError,AuthorizationBase:()=>AuthorizationBase,BUILT_IN_AUTH_PAGE_CSP:()=>BUILT_IN_AUTH_PAGE_CSP,CDN:()=>CDN,CREDENTIALS_ACCESSOR:()=>CREDENTIALS_ACCESSOR,CimdClientIdMismatchError:()=>CimdClientIdMismatchError,CimdDisabledError:()=>CimdDisabledError,CimdError:()=>CimdError,CimdFetchError:()=>CimdFetchError,CimdResponseTooLargeError:()=>CimdResponseTooLargeError,CimdSecurityError:()=>CimdSecurityError,CimdService:()=>CimdService,CimdValidationError:()=>CimdValidationError,CredentialCache:()=>CredentialCache,CredentialProviderAlreadyRegisteredError:()=>CredentialProviderAlreadyRegisteredError,CredentialStorageError:()=>CredentialStorageError,CredentialsAccessorImpl:()=>CredentialsAccessorImpl,DEFAULT_ALLOWED_SCOPES:()=>DEFAULT_ALLOWED_SCOPES,DEFAULT_INCREMENTAL_TICKET_TTL_MS:()=>DEFAULT_INCREMENTAL_TICKET_TTL_MS,DEFAULT_RESUME_TTL_MS:()=>DEFAULT_RESUME_TTL_MS,DEFAULT_THEME:()=>DEFAULT_THEME,DcrClientRegistry:()=>DcrClientRegistry,EagerCredentialLoader:()=>EagerCredentialLoader,ElicitationSecretRequiredError:()=>ElicitationSecretRequiredError,EncryptedRedisVault:()=>EncryptedRedisVault,EncryptedStorageError:()=>import_utils26.EncryptedStorageError,EncryptedStorageSecureStoreBackend:()=>EncryptedStorageSecureStoreBackend,EncryptedTypedStorage:()=>import_utils26.EncryptedTypedStorage,EncryptionContextNotSetError:()=>EncryptionContextNotSetError,EncryptionKeyNotConfiguredError:()=>EncryptionKeyNotConfiguredError,FetchCredentialMiddleware:()=>FetchCredentialMiddleware,FrontMcpAuthContextImpl:()=>FrontMcpAuthContextImpl,InMemoryAuthorizationStore:()=>InMemoryAuthorizationStore,InMemoryAuthorizationVault:()=>InMemoryAuthorizationVault,InMemoryCimdCache:()=>InMemoryCimdCache,InMemoryConsentStore:()=>InMemoryConsentStore,InMemoryFederatedAuthSessionStore:()=>InMemoryFederatedAuthSessionStore,InMemoryOrchestratedTokenStore:()=>InMemoryOrchestratedTokenStore,InMemoryStoreRequiredError:()=>InMemoryStoreRequiredError,InvalidClientIdUrlError:()=>InvalidClientIdUrlError,JwksService:()=>JwksService,JwtSecretRequiredError:()=>JwtSecretRequiredError,JwtSecretWeakError:()=>JwtSecretWeakError,LazyCredentialLoader:()=>LazyCredentialLoader,NoProviderIdError:()=>NoProviderIdError,NullOrchestratedAuthAccessor:()=>NullOrchestratedAuthAccessor,ORCHESTRATED_AUTH_ACCESSOR:()=>ORCHESTRATED_AUTH_ACCESSOR,OrchestratedAuthAccessorAdapter:()=>OrchestratedAuthAccessorAdapter,OrchestratedAuthNotAvailableError:()=>OrchestratedAuthNotAvailableError,OrchestratedAuthorization:()=>OrchestratedAuthorization,OrchestratorJwksNotAvailableError:()=>OrchestratorJwksNotAvailableError,PublicAuthorization:()=>PublicAuthorization,RedirectUriMismatchError:()=>RedirectUriMismatchError,RedisAuthorizationStore:()=>RedisAuthorizationStore,RedisSessionStore:()=>RedisSessionStore,SECURE_STORE_ACCESSOR:()=>SECURE_STORE_ACCESSOR,SIGNIN_BINDING_COOKIE_PREFIX:()=>SIGNIN_BINDING_COOKIE_PREFIX,SIGNIN_BINDING_MAX_AGE_SECONDS:()=>SIGNIN_BINDING_MAX_AGE_SECONDS,SIGNIN_BINDING_SECURE_COOKIE_PREFIX:()=>SIGNIN_BINDING_SECURE_COOKIE_PREFIX,ScopeDeniedError:()=>ScopeDeniedError,SecureStoreAccessorImpl:()=>SecureStoreAccessorImpl,SessionCredentialVault:()=>SessionCredentialVault,SessionIdEmptyError:()=>SessionIdEmptyError,SessionRateLimiter:()=>SessionRateLimiter,SessionSecretRequiredError:()=>SessionSecretRequiredError,StorageAuthorizationStore:()=>StorageAuthorizationStore,StorageAuthorizationVault:()=>StorageAuthorizationVault,StorageConsentStore:()=>StorageConsentStore,StorageFederatedAuthSessionStore:()=>StorageFederatedAuthSessionStore,StorageOrchestratedTokenStore:()=>StorageOrchestratedTokenStore,StorageTokenStore:()=>StorageTokenStore,TinyTtlCache:()=>TinyTtlCache,TokenLeakDetectedError:()=>TokenLeakDetectedError,TokenNotAvailableError:()=>TokenNotAvailableError,TokenStoreRequiredError:()=>TokenStoreRequiredError,TokenVault:()=>TokenVault,TransparentAuthorization:()=>TransparentAuthorization,TransportIdGenerator:()=>TransportIdGenerator,TypedStorage:()=>import_utils25.TypedStorage,VaultEncryption:()=>VaultEncryption,VaultLoadError:()=>VaultLoadError,VaultNotFoundError:()=>VaultNotFoundError,VercelKvSessionStore:()=>VercelKvSessionStore,abacConditionSchema:()=>abacConditionSchema,abacOperatorSchema:()=>abacOperatorSchema,abacPolicySchema:()=>abacPolicySchema,advertisedScopes:()=>advertisedScopes,aiPlatformTypeSchema:()=>aiPlatformTypeSchema,allowsPublicAccess:()=>allowsPublicAccess,anonymousCallerClaims:()=>anonymousCallerClaims,apiKeyCredentialSchema:()=>apiKeyCredentialSchema,appAuthOptionsSchema:()=>appAuthOptionsSchema,appAuthStateSchema:()=>appAuthStateSchema,appAuthorizationRecordSchema:()=>appAuthorizationRecordSchema,appCredentialSchema:()=>appCredentialSchema,appRequiresOrchestration:()=>appRequiresOrchestration,authLayout:()=>authLayout,authModeSchema:()=>authModeSchema,authOptionsSchema:()=>authOptionsSchema,authProviderDetectionResultSchema:()=>authProviderDetectionResultSchema,authProviderMappingSchema:()=>authProviderMappingSchema,authProvidersVaultOptionsSchema:()=>authProvidersVaultOptionsSchema,authUserSchema:()=>authUserSchema,authenticateFnSchema:()=>authenticateFnSchema,authoritiesClaimsMappingSchema:()=>authoritiesClaimsMappingSchema,authoritiesConfigSchema:()=>authoritiesConfigSchema,authoritiesMetadataSchema:()=>authoritiesMetadataSchema,authoritiesPolicySchema:()=>authoritiesPolicySchema,authorizationCodeRecordSchema:()=>authorizationCodeRecordSchema,authorizationVaultEntrySchema:()=>authorizationVaultEntrySchema,authorizedPromptSchema:()=>authorizedPromptSchema,authorizedToolSchema:()=>authorizedToolSchema,baseLayout:()=>baseLayout,basicApplier:()=>basicApplier,basicAuthCredentialSchema:()=>basicAuthCredentialSchema,bearerApplier:()=>bearerApplier,bearerCredentialSchema:()=>bearerCredentialSchema,buildAuthContext:()=>buildAuthContext,buildCodeRecord:()=>buildCodeRecord,buildConnectPage:()=>buildConnectPage,buildConnectSuccessPage:()=>buildConnectSuccessPage,buildConsentPage:()=>buildConsentPage,buildCredentialResumeUrl:()=>buildCredentialResumeUrl,buildErrorPage:()=>buildErrorPage,buildFederatedLoginPage:()=>buildFederatedLoginPage,buildIncrementalAuthPage:()=>buildIncrementalAuthPage,buildInsufficientScopeHeader:()=>buildInsufficientScopeHeader,buildInvalidRequestHeader:()=>buildInvalidRequestHeader,buildInvalidTokenHeader:()=>buildInvalidTokenHeader,buildLoginPage:()=>buildLoginPage,buildPendingRecord:()=>buildPendingRecord,buildPrmUrl:()=>buildPrmUrl,buildRefreshTokenRecord:()=>buildRefreshTokenRecord,buildToolConsentPage:()=>buildToolConsentPage,buildUnauthorizedHeader:()=>buildUnauthorizedHeader,buildWwwAuthenticate:()=>buildWwwAuthenticate,builtInAuthPageHeaders:()=>builtInAuthPageHeaders,centeredCardLayout:()=>centeredCardLayout,checkSsrfProtection:()=>checkSsrfProtection,cimdCacheConfigSchema:()=>cimdCacheConfigSchema,cimdConfigSchema:()=>cimdConfigSchema,cimdNetworkConfigSchema:()=>cimdNetworkConfigSchema,cimdSecurityConfigSchema:()=>cimdSecurityConfigSchema,clientMetadataDocumentSchema:()=>clientMetadataDocumentSchema,completeCurrentProvider:()=>completeCurrentProvider,consentConfigSchema:()=>consentConfigSchema,consentRecordKey:()=>consentRecordKey,consentSelectionSchema:()=>consentSelectionSchema,consentStateSchema:()=>consentStateSchema,consentToolItemSchema:()=>consentToolItemSchema,createAudienceValidator:()=>createAudienceValidator,createEncryptedVault:()=>createEncryptedVault,createFederatedAuthSession:()=>createFederatedAuthSession,createLayout:()=>createLayout,createSecureStore:()=>createSecureStore,createSessionCredentialVault:()=>createSessionCredentialVault,createSigninBinding:()=>createSigninBinding,createTokenStorageAdapter:()=>createTokenStorageAdapter,credentialProviderConfigSchema:()=>credentialProviderConfigSchema,credentialSchema:()=>credentialSchema,credentialScopeSchema:()=>credentialScopeSchema,credentialTypeSchema:()=>credentialTypeSchema,customCredentialSchema:()=>customCredentialSchema,decodeJwtPayloadSafe:()=>decodeJwtPayloadSafe,decryptAesGcm:()=>import_utils36.decryptAesGcm,decryptSessionJson:()=>decryptSessionJson,decryptValue:()=>import_utils36.decryptValue,defaultSessionRateLimiter:()=>defaultSessionRateLimiter,deriveAuthorizationId:()=>deriveAuthorizationId,deriveExpectedAudience:()=>deriveExpectedAudience,deriveProviderId:()=>deriveProviderId,deriveTypedUser:()=>deriveTypedUser,detectAuthProviders:()=>detectAuthProviders,detectedAuthProviderSchema:()=>detectedAuthProviderSchema,encryptAesGcm:()=>import_utils36.encryptAesGcm,encryptJson:()=>encryptJson,encryptValue:()=>import_utils36.encryptValue,encryptedBlobSchema:()=>encryptedBlobSchema,encryptedDataSchema:()=>encryptedDataSchema,encryptedVaultEntrySchema:()=>encryptedVaultEntrySchema,escapeHtml:()=>import_utils4.escapeHtml,extraWideLayout:()=>extraWideLayout,extractBearerToken:()=>extractBearerToken,extractCacheHeaders:()=>extractCacheHeaders,extractCredentialExpiry:()=>extractCredentialExpiry,federatedAuthConfigSchema:()=>federatedAuthConfigSchema,federatedLoginStateSchema:()=>federatedLoginStateSchema,federatedProviderItemSchema:()=>federatedProviderItemSchema,federatedSelectionSchema:()=>federatedSelectionSchema,findAuthoritiesProfileProblems:()=>findAuthoritiesProfileProblems,findAuthoritiesRuleProblems:()=>findAuthoritiesRuleProblems,flatRemoteProviderFields:()=>flatRemoteProviderFields,fromSessionRecord:()=>fromSessionRecord,generateAuthorizationCode:()=>generateAuthorizationCode,generatePkceChallenge:()=>generatePkceChallenge,generateRefreshTokenValue:()=>generateRefreshTokenValue,getCredentialOptionsSchema:()=>getCredentialOptionsSchema,getKey:()=>getKey,getNextProvider:()=>getNextProvider,getProviderApps:()=>getProviderApps,getProviderScopes:()=>getProviderScopes,getTokenSignatureFingerprint:()=>getTokenSignatureFingerprint,grantScopes:()=>grantScopes,hasOnlyLocalhostRedirectUris:()=>hasOnlyLocalhostRedirectUris,headerApplier:()=>headerApplier,hkdfSha256:()=>import_utils36.hkdfSha256,incrementalAuthConfigSchema:()=>incrementalAuthConfigSchema,isAnonymousSubject:()=>isAnonymousSubject,isCimdClientId:()=>isCimdClientId,isFrontMcpCredentials:()=>isFrontMcpCredentials,isJwt:()=>isJwt,isLocalMode:()=>isLocalMode,isLoopbackRedirectUri:()=>isLoopbackRedirectUri,isOrchestratedLocal:()=>isOrchestratedLocal,isOrchestratedMode:()=>isOrchestratedMode,isOrchestratedRemote:()=>isOrchestratedRemote,isPersistentTokenStorage:()=>isPersistentTokenStorage,isPublicMode:()=>isPublicMode,isRedisTokenStorage:()=>isRedisTokenStorage,isRemoteMode:()=>isRemoteMode,isSessionComplete:()=>isSessionComplete,isSignedSession:()=>import_utils18.isSignedData,isSoonExpiring:()=>isSoonExpiring,isSoonExpiringProvider:()=>isSoonExpiringProvider,isSqliteTokenStorage:()=>isSqliteTokenStorage,isStaticMode:()=>isStaticMode,isTransparentMode:()=>isTransparentMode,jsonWebKeySetSchema:()=>jsonWebKeySetSchema,jwkParametersSchema:()=>jwkParametersSchema,jwkSchema:()=>jwkSchema,legacySseTransportStateSchema:()=>legacySseTransportStateSchema,llmSafeAuthContextSchema:()=>llmSafeAuthContextSchema,loadingStrategySchema:()=>loadingStrategySchema,localAuthSchema:()=>localAuthSchema,localDcrClientSchema:()=>localDcrClientSchema,localDcrConfigSchema:()=>localDcrConfigSchema,localSigningConfigSchema:()=>localSigningConfigSchema,loginConfigSchema:()=>loginConfigSchema,mtlsCredentialSchema:()=>mtlsCredentialSchema,noopLogger:()=>noopLogger,normalizeIssuer:()=>normalizeIssuer,oauthCredentialSchema:()=>oauthCredentialSchema,openPendingLogin:()=>openPendingLogin,orchestratedLocalSchema:()=>orchestratedLocalSchema,orchestratedRemoteSchema:()=>orchestratedRemoteSchema,parseAuthOptions:()=>parseAuthOptions,parseCacheHeaders:()=>parseCacheHeaders,parseWwwAuthenticate:()=>parseWwwAuthenticate,pendingIncrementalAuthSchema:()=>pendingIncrementalAuthSchema,pkceChallengeSchema:()=>pkceChallengeSchema,pkceOAuthCredentialSchema:()=>pkceOAuthCredentialSchema,privateKeyCredentialSchema:()=>privateKeyCredentialSchema,progressiveAuthStateSchema:()=>progressiveAuthStateSchema,providerConfigSchema:()=>providerConfigSchema,providerHeadersCredentials:()=>providerHeadersCredentials,publicAccessConfigSchema:()=>publicAccessConfigSchema,publicAuthOptionsSchema:()=>publicAuthOptionsSchema,queryApplier:()=>queryApplier,rbacPermissionsPolicySchema:()=>rbacPermissionsPolicySchema,rbacRolesPolicySchema:()=>rbacRolesPolicySchema,rebacPolicySchema:()=>rebacPolicySchema,redisConfigSchema:()=>redisConfigSchema,redisVaultEntrySchema:()=>redisVaultEntrySchema,remoteAuthSchema:()=>remoteAuthSchema,remoteProviderConfigSchema:()=>remoteProviderConfigSchema,renderLocalLoginPage:()=>renderLocalLoginPage,renderToHtml:()=>renderToHtml,resetCachedKey:()=>resetCachedKey,resolveRequiredScopes:()=>resolveRequiredScopes,resourceIdRefSchema:()=>resourceIdRefSchema,resourceScopesFor:()=>resourceScopesFor,safeDecrypt:()=>safeDecrypt,scopesFromClaims:()=>scopesFromClaims,sealPendingLogin:()=>sealPendingLogin,secureStoreConfigSchema:()=>secureStoreConfigSchema,secureStoreCustomBackendSchema:()=>secureStoreCustomBackendSchema,secureStoreEncryptionSchema:()=>secureStoreEncryptionSchema,secureStoreScopeSchema:()=>secureStoreScopeSchema,serviceAccountCredentialSchema:()=>serviceAccountCredentialSchema,sessionIdPayloadSchema:()=>sessionIdPayloadSchema,sessionJwtPayloadSchema:()=>sessionJwtPayloadSchema,signCredentialResumeToken:()=>signCredentialResumeToken,signIncrementalAuthTicket:()=>signIncrementalAuthTicket,signSession:()=>signSession,signinBindingCookieName:()=>signinBindingCookieName,signinBindingMatches:()=>signinBindingMatches,skippedAppBehaviorSchema:()=>skippedAppBehaviorSchema,sseTransportStateSchema:()=>sseTransportStateSchema,sshKeyCredentialSchema:()=>sshKeyCredentialSchema,startNextProvider:()=>startNextProvider,statefulHttpTransportStateSchema:()=>statefulHttpTransportStateSchema,statelessHttpTransportStateSchema:()=>statelessHttpTransportStateSchema,staticAuthOptionsSchema:()=>staticAuthOptionsSchema,storedSessionSchema:()=>storedSessionSchema,streamableHttpTransportStateSchema:()=>streamableHttpTransportStateSchema,toEpochSeconds:()=>toEpochSeconds,toLoginExtraFields:()=>toLoginExtraFields,toSessionRecord:()=>toSessionRecord,tokenRefreshConfigSchema:()=>tokenRefreshConfigSchema,tokenStorageConfigSchema:()=>tokenStorageConfigSchema,tokenStorageSqliteSchema:()=>tokenStorageSqliteSchema,transparentAuthOptionsSchema:()=>transparentAuthOptionsSchema,transportProtocolSchema:()=>transportProtocolSchema,transportSessionSchema:()=>transportSessionSchema,transportStateSchema:()=>transportStateSchema,trimSlash:()=>trimSlash,tryJwtExp:()=>tryJwtExp,upstreamProviderSchema:()=>upstreamProviderSchema,userClaimSchema:()=>userClaimSchema,validateAudience:()=>validateAudience,validateClientIdUrl:()=>validateClientIdUrl,vaultConsentRecordSchema:()=>vaultConsentRecordSchema,vaultFederatedRecordSchema:()=>vaultFederatedRecordSchema,verifyCredentialResumeToken:()=>verifyCredentialResumeToken,verifyIncrementalAuthTicket:()=>verifyIncrementalAuthTicket,verifyOrParseSession:()=>verifyOrParseSession,verifyPkce:()=>verifyPkce,verifySession:()=>verifySession,wideLayout:()=>wideLayout,withoutSecretFieldValues:()=>withoutSecretFieldValues});module.exports=__toCommonJS(index_exports);var import_utils2=require("@frontmcp/utils");var import_utils=require("@frontmcp/utils");var CimdError=class extends Error{code;statusCode;clientIdUrl;constructor(message,code,statusCode,clientIdUrl){super(message);this.name=this.constructor.name;this.code=code;this.statusCode=statusCode;this.clientIdUrl=clientIdUrl;if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}getPublicMessage(){return this.message}};var InvalidClientIdUrlError=class extends CimdError{reason;constructor(clientIdUrl,reason){super(`Invalid CIMD client_id URL: ${reason}`,"INVALID_CLIENT_ID_URL",400,clientIdUrl);this.reason=reason}getPublicMessage(){return`Invalid client_id URL: ${this.reason}`}};var CimdFetchError=class extends CimdError{httpStatus;originalError;constructor(clientIdUrl,message,options){super(`Failed to fetch CIMD document from ${clientIdUrl}: ${message}`,"CIMD_FETCH_ERROR",502,clientIdUrl);this.httpStatus=options?.httpStatus;this.originalError=options?.originalError}getPublicMessage(){if(this.httpStatus){return`Failed to fetch client metadata: HTTP ${this.httpStatus}`}return"Failed to fetch client metadata document"}};var CimdValidationError=class extends CimdError{validationErrors;constructor(clientIdUrl,errors){super(`CIMD document validation failed: ${errors.join("; ")}`,"CIMD_VALIDATION_ERROR",400,clientIdUrl);this.validationErrors=errors}getPublicMessage(){return`Client metadata document validation failed: ${this.validationErrors.join("; ")}`}};var CimdClientIdMismatchError=class extends CimdError{documentClientId;constructor(urlClientId,documentClientId){super(`CIMD client_id mismatch: URL is "${urlClientId}" but document contains "${documentClientId}"`,"CIMD_CLIENT_ID_MISMATCH",400,urlClientId);this.documentClientId=documentClientId}getPublicMessage(){return"Client ID in metadata document does not match the request"}};var CimdSecurityError=class extends CimdError{securityReason;constructor(clientIdUrl,reason){super(`CIMD security check failed for ${clientIdUrl}: ${reason}`,"CIMD_SECURITY_ERROR",403,clientIdUrl);this.securityReason=reason}getPublicMessage(){return"Client ID URL is not allowed by security policy"}};var RedirectUriMismatchError=class extends CimdError{requestedRedirectUri;allowedRedirectUris;constructor(clientIdUrl,requestedRedirectUri,allowedRedirectUris){super(`Redirect URI "${requestedRedirectUri}" is not registered for client "${clientIdUrl}"`,"REDIRECT_URI_MISMATCH",400,clientIdUrl);this.requestedRedirectUri=requestedRedirectUri;this.allowedRedirectUris=allowedRedirectUris}getPublicMessage(){return"The redirect_uri is not registered for this client"}};var CimdResponseTooLargeError=class extends CimdError{maxBytes;actualBytes;constructor(clientIdUrl,maxBytes,actualBytes){super(`CIMD response from ${clientIdUrl} exceeds maximum size of ${maxBytes} bytes${actualBytes?` (received ${actualBytes} bytes)`:""}`,"CIMD_RESPONSE_TOO_LARGE",502,clientIdUrl);this.maxBytes=maxBytes;this.actualBytes=actualBytes}getPublicMessage(){return"Client metadata document is too large"}};var CimdDisabledError=class extends CimdError{constructor(){super("CIMD (Client ID Metadata Documents) is disabled on this server","CIMD_DISABLED",400)}};function isCimdClientId(clientId,allowInsecure=false){if(!clientId||typeof clientId!=="string"){return false}try{const url=new URL(clientId);if(url.protocol==="https:"){}else if(url.protocol==="http:"&&allowInsecure&&isLocalhostHost(url.hostname)){}else{return false}if(!url.pathname||url.pathname==="/"){return false}return true}catch{return false}}function isLocalhostHost(hostname){const lower=hostname.toLowerCase();return lower==="localhost"||lower==="127.0.0.1"||lower==="[::1]"||lower.endsWith(".localhost")}function validateClientIdUrl(clientId,securityConfig){if(!clientId||typeof clientId!=="string"){throw new InvalidClientIdUrlError(clientId||"","client_id must be a non-empty string")}let url;try{url=new URL(clientId)}catch{throw new InvalidClientIdUrlError(clientId,"Invalid URL format")}const allowInsecure=securityConfig?.allowInsecureForTesting??false;if(url.protocol==="https:"){}else if(url.protocol==="http:"&&allowInsecure&&isLocalhostHost(url.hostname)){}else{throw new InvalidClientIdUrlError(clientId,`CIMD requires HTTPS, got ${url.protocol.replace(":","")}`)}if(!url.pathname||url.pathname==="/"){throw new InvalidClientIdUrlError(clientId,"CIMD client_id URL must have a path component (e.g., /oauth/client-metadata.json)")}const config={blockPrivateIPs:securityConfig?.blockPrivateIPs??true,allowedDomains:securityConfig?.allowedDomains,blockedDomains:securityConfig?.blockedDomains};if(config.allowedDomains?.length){if(!isDomainInList(url.hostname,config.allowedDomains)){throw new CimdSecurityError(clientId,`Domain "${url.hostname}" is not in the allowed domains list`)}}if(config.blockedDomains?.length){if(isDomainInList(url.hostname,config.blockedDomains)){throw new CimdSecurityError(clientId,`Domain "${url.hostname}" is blocked`)}}if(config.blockPrivateIPs&&!allowInsecure){const ssrfCheck=checkSsrfProtection(url.hostname);if(!ssrfCheck.allowed){throw new CimdSecurityError(clientId,ssrfCheck.reason)}}return url}function checkSsrfProtection(hostname){const lowercaseHostname=hostname.toLowerCase();if(lowercaseHostname==="localhost"||lowercaseHostname==="localhost.localdomain"||lowercaseHostname.endsWith(".localhost")){return{allowed:false,reason:"Localhost addresses are not allowed"}}if(isIpAddress(hostname)){const ipCheck=checkIpAddress(hostname);if(!ipCheck.allowed){return ipCheck}}return{allowed:true,reason:""}}async function resolveAndCheckHostname(hostname){const literal=checkSsrfProtection(hostname);if(!literal.allowed)return literal;if(isIpAddress(hostname))return{allowed:true,reason:""};let dns;try{dns=require("node:dns")}catch{return{allowed:true,reason:""}}let addresses;try{const result=await dns.promises.lookup(hostname,{all:true,verbatim:true});addresses=Array.isArray(result)?result:[result]}catch{return{allowed:false,reason:`DNS resolution failed for "${hostname}"; refusing to fetch an unvalidated host`}}if(addresses.length===0){return{allowed:false,reason:`Host "${hostname}" resolved to no addresses`}}for(const{address}of addresses){if(!address)continue;const ipCheck=checkIpAddress(address);if(!ipCheck.allowed){return{allowed:false,reason:`Host "${hostname}" resolves to a blocked address (${address}): ${ipCheck.reason}`}}}return{allowed:true,reason:""}}async function assertHostNotSsrf(hostname,clientId){const check=await resolveAndCheckHostname(hostname);if(!check.allowed){throw new CimdSecurityError(clientId,check.reason)}}function isIpAddress(hostname){const ipv4Pattern=/^(\d{1,3}\.){3}\d{1,3}$/;if(ipv4Pattern.test(hostname)){return true}const cleanHostname=hostname.replace(/^\[|\]$/g,"");if(cleanHostname.includes(":")){return true}return false}var BLOCKED_RANGE_REASONS=new Map([["0.0.0.0/8","Current network addresses (0.x.x.x) are not allowed"],["10.0.0.0/8","Private IP addresses (10.x.x.x) are not allowed"],["100.64.0.0/10","Carrier-grade NAT addresses (100.64-127.x.x) are not allowed"],["127.0.0.0/8","Loopback addresses (127.x.x.x) are not allowed"],["169.254.0.0/16","Link-local addresses (169.254.x.x) are not allowed"],["172.16.0.0/12","Private IP addresses (172.16-31.x.x) are not allowed"],["192.0.0.0/24","IETF protocol-assignment addresses (192.0.0.0/24) are not allowed"],["192.168.0.0/16","Private IP addresses (192.168.x.x) are not allowed"],["224.0.0.0/4","Multicast addresses are not allowed"],["255.255.255.255/32","Broadcast address is not allowed"],["::/128","IPv6 unspecified address (::) is not allowed"],["::1/128","IPv6 loopback address (::1) is not allowed"],["fc00::/7","IPv6 unique local addresses (fc00::/7) are not allowed"],["fe80::/10","IPv6 link-local addresses (fe80::/10) are not allowed"]]);function checkIpAddress(ip){const classification=(0,import_utils.classifyIpAddress)(ip);if(!classification){const bareIp=ip.replace(/^\[|\]$/g,"");return{allowed:false,reason:bareIp.includes(":")?`Malformed IPv6 address: ${bareIp}`:"Invalid IPv4 address"}}if(classification.range==="public"){return{allowed:true,reason:""}}return{allowed:false,reason:BLOCKED_RANGE_REASONS.get(classification.cidr)??`Addresses in the ${classification.range} range (${classification.cidr}) are not allowed`}}function isDomainInList(hostname,domainList){const lowerHostname=hostname.toLowerCase();for(const domain of domainList){const lowerDomain=domain.toLowerCase();if(lowerHostname===lowerDomain){return true}if(lowerHostname.endsWith("."+lowerDomain)){return true}if(lowerDomain.startsWith("*.")){const baseDomain=lowerDomain.slice(2);if(lowerHostname===baseDomain||lowerHostname.endsWith("."+baseDomain)){return true}}}return false}function hasOnlyLocalhostRedirectUris(redirectUris){if(!redirectUris.length){return false}return redirectUris.every(uri=>{try{const url=new URL(uri);const hostname=url.hostname.toLowerCase();return hostname==="localhost"||hostname==="127.0.0.1"||hostname==="[::1]"||hostname.endsWith(".localhost")}catch{return false}})}var noopAuthLogger={info(){},warn(){},error(){},debug(){}};var jose;function loadJose(){jose??=import("jose").catch(importError=>{try{return require("jose")}catch{throw importError}}).catch(error=>{jose=void 0;throw error});return jose}function trimSlash(s){const str=s??"";let end=str.length;while(end>0&&str[end-1]==="/"){end--}return str.slice(0,end)}function normalizeIssuer(u){return trimSlash(String(u??""))}function decodeJwtPayloadSafe(token){if(!token)return void 0;const parts=token.split(".");if(parts.length<2)return void 0;try{const b64=parts[1].replace(/-/g,"+").replace(/_/g,"/");const json=typeof Buffer!=="undefined"?Buffer.from(b64,"base64").toString("utf8"):atob(b64);const obj=JSON.parse(json);return obj&&typeof obj==="object"&&!Array.isArray(obj)?obj:void 0}catch{return void 0}}var TRANSPARENT_JWT_ALGS=["RS256","RS384","RS512","PS256","PS384","PS512","ES256","ES384","ES512","EdDSA"];var MAX_JWKS_FETCH_BYTES=1048576;var MAX_JWKS_FETCH_HOPS=3;var UNKNOWN_KID_REFETCH_COOLDOWN_MS=6e4;var MISSING_EXP_ERROR='missing required "exp" claim';function isMissingExpError(error){if(typeof error!=="object"||error===null)return false;const{code,claim,reason}=error;return code==="ERR_JWT_CLAIM_VALIDATION_FAILED"&&claim==="exp"&&reason==="missing"}var WEAK_KEY_WARNING=`
1
+ "use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf;var __hasOwnProp=Object.prototype.hasOwnProperty;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:true}):target,mod));var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var cimd_redis_cache_exports={};__export(cimd_redis_cache_exports,{RedisCimdCache:()=>RedisCimdCache});var import_utils16,import_utils17,RedisCimdCache;var init_cimd_redis_cache=__esm({"libs/auth/src/cimd/cimd-redis.cache.ts"(){"use strict";import_utils16=require("@frontmcp/utils");import_utils17=require("@frontmcp/utils");init_cimd_cache();RedisCimdCache=class{redis;keyPrefix;config;constructor(config){if(!config.redis){throw new Error("Redis configuration is required for RedisCimdCache")}this.config={defaultTtlMs:config.defaultTtlMs??36e5,maxTtlMs:config.maxTtlMs??864e5,minTtlMs:config.minTtlMs??6e4};this.keyPrefix=config.redis.keyPrefix??"cimd:";const redisOptions={};if(config.redis.url){redisOptions.url=config.redis.url}else if(config.redis.host){redisOptions.config={host:config.redis.host,port:config.redis.port,password:config.redis.password,db:config.redis.db,tls:config.redis.tls}}this.redis=new import_utils16.RedisStorageAdapter(redisOptions)}async connect(){await this.redis.connect()}cacheKey(clientId){const hash=(0,import_utils17.sha256Hex)(clientId);return`${this.keyPrefix}${hash}`}async get(clientId){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return void 0}try{const entry=JSON.parse(data);if(entry.expiresAt<Date.now()){return void 0}return entry}catch{await this.redis.delete(key);return void 0}}async getStale(clientId){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return void 0}try{return JSON.parse(data)}catch{return void 0}}async set(clientId,document,headers){const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);const now=Date.now();const entry={document,expiresAt:now+ttlMs,etag,lastModified,cachedAt:now};const key=this.cacheKey(clientId);const value=JSON.stringify(entry);const redisTtlSeconds=Math.ceil((ttlMs+this.config.maxTtlMs*2)/1e3);await this.redis.set(key,value,{ttlSeconds:redisTtlSeconds})}async revalidate(clientId,headers){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return false}try{const existing=JSON.parse(data);const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);existing.expiresAt=Date.now()+ttlMs;if(etag)existing.etag=etag;if(lastModified)existing.lastModified=lastModified;const value=JSON.stringify(existing);const redisTtlSeconds=Math.ceil((ttlMs+this.config.maxTtlMs*2)/1e3);await this.redis.set(key,value,{ttlSeconds:redisTtlSeconds});return true}catch{return false}}async delete(clientId){const key=this.cacheKey(clientId);return this.redis.delete(key)}async getConditionalHeaders(clientId){const key=this.cacheKey(clientId);const data=await this.redis.get(key);if(!data){return void 0}try{const entry=JSON.parse(data);const headers={};if(entry.etag){headers["If-None-Match"]=entry.etag}if(entry.lastModified){headers["If-Modified-Since"]=entry.lastModified}return Object.keys(headers).length>0?headers:void 0}catch{return void 0}}async clear(){const keys=await this.redis.keys(`${this.keyPrefix}*`);if(keys.length>0){await this.redis.mdelete(keys)}}async size(){const keys=await this.redis.keys(`${this.keyPrefix}*`);return keys.length}async cleanup(){const now=Date.now();let removed=0;const keys=await this.redis.keys(`${this.keyPrefix}*`);for(const key of keys){const data=await this.redis.get(key);if(!data)continue;try{const entry=JSON.parse(data);if(entry.expiresAt+this.config.maxTtlMs*2<now){await this.redis.delete(key);removed++}}catch{await this.redis.delete(key);removed++}}return removed}async close(){await this.redis.disconnect()}}}});function extractCacheHeaders(headers){return{"cache-control":headers.get("cache-control")??void 0,expires:headers.get("expires")??void 0,etag:headers.get("etag")??void 0,"last-modified":headers.get("last-modified")??void 0,age:headers.get("age")??void 0}}function parseCacheHeaders(headers,config){let ttlMs=config.defaultTtlMs;if(headers["cache-control"]){const cacheControl=parseCacheControlHeader(headers["cache-control"]);if(cacheControl["no-store"]||cacheControl["no-cache"]){ttlMs=config.minTtlMs}else if(typeof cacheControl["max-age"]==="number"){let maxAgeSecs=cacheControl["max-age"];if(headers.age){const ageSeconds=parseInt(headers.age,10);if(!isNaN(ageSeconds)){maxAgeSecs=Math.max(0,maxAgeSecs-ageSeconds)}}ttlMs=maxAgeSecs*1e3}if(typeof cacheControl["s-maxage"]==="number"){let sMaxAgeSecs=cacheControl["s-maxage"];if(headers.age){const ageSeconds=parseInt(headers.age,10);if(!isNaN(ageSeconds)){sMaxAgeSecs=Math.max(0,sMaxAgeSecs-ageSeconds)}}ttlMs=sMaxAgeSecs*1e3}}else if(headers.expires){const expiresDate=new Date(headers.expires);if(!isNaN(expiresDate.getTime())){ttlMs=Math.max(0,expiresDate.getTime()-Date.now())}}ttlMs=Math.max(config.minTtlMs,Math.min(config.maxTtlMs,ttlMs));return{ttlMs,etag:headers.etag,lastModified:headers["last-modified"]}}function parseCacheControlHeader(value){const result={};const directives=value.toLowerCase().split(",").map(d=>d.trim());for(const directive of directives){const[key,val]=directive.split("=").map(s=>s.trim());if(val!==void 0){const numVal=parseInt(val,10);if(!isNaN(numVal)){result[key]=numVal}}else{result[key]=true}}return result}async function createCimdCache(config){const cacheType=config?.type??"memory";if(cacheType==="redis"){if(!config?.redis){throw new Error('Redis configuration is required when cache type is "redis"')}const{RedisCimdCache:RedisCimdCache2}=await Promise.resolve().then(()=>(init_cimd_redis_cache(),cimd_redis_cache_exports));const cache=new RedisCimdCache2(config);await cache.connect();return cache}return new InMemoryCimdCache(config)}var InMemoryCimdCache;var init_cimd_cache=__esm({"libs/auth/src/cimd/cimd.cache.ts"(){"use strict";InMemoryCimdCache=class{cache=new Map;config;constructor(config){this.config={defaultTtlMs:config?.defaultTtlMs??36e5,maxTtlMs:config?.maxTtlMs??864e5,minTtlMs:config?.minTtlMs??6e4}}async get(clientId){const entry=this.cache.get(clientId);if(!entry){return void 0}if(entry.expiresAt<Date.now()){return void 0}return entry}async getStale(clientId){return this.cache.get(clientId)}async set(clientId,document,headers){const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);const now=Date.now();const entry={document,expiresAt:now+ttlMs,etag,lastModified,cachedAt:now};this.cache.set(clientId,entry)}async revalidate(clientId,headers){const existing=this.cache.get(clientId);if(!existing){return false}const cacheHeaders=extractCacheHeaders(headers);const{ttlMs,etag,lastModified}=parseCacheHeaders(cacheHeaders,this.config);existing.expiresAt=Date.now()+ttlMs;if(etag)existing.etag=etag;if(lastModified)existing.lastModified=lastModified;return true}async delete(clientId){return this.cache.delete(clientId)}async getConditionalHeaders(clientId){const entry=this.cache.get(clientId);if(!entry){return void 0}const headers={};if(entry.etag){headers["If-None-Match"]=entry.etag}if(entry.lastModified){headers["If-Modified-Since"]=entry.lastModified}return Object.keys(headers).length>0?headers:void 0}async clear(){this.cache.clear()}async size(){return this.cache.size}async cleanup(){const now=Date.now();let removed=0;for(const[clientId,entry]of this.cache){if(entry.expiresAt+this.config.maxTtlMs*2<now){this.cache.delete(clientId);removed++}}return removed}}}});var index_exports={};__export(index_exports,{AUTH_PROVIDERS_ACCESSOR:()=>AUTH_PROVIDERS_ACCESSOR,AUTH_PROVIDERS_REGISTRY:()=>AUTH_PROVIDERS_REGISTRY,AUTH_PROVIDERS_VAULT:()=>AUTH_PROVIDERS_VAULT,AppAuthState:()=>AppAuthState,AudienceValidator:()=>AudienceValidator,AuthInternalError:()=>AuthInternalError,AuthInvalidInputError:()=>AuthInvalidInputError,AuthProvidersAccessorImpl:()=>AuthProvidersAccessorImpl,AuthProvidersNotConfiguredError:()=>AuthProvidersNotConfiguredError,AuthProvidersRegistry:()=>AuthProvidersRegistry,AuthProvidersVault:()=>AuthProvidersVault,AuthoritiesContextBuilder:()=>AuthoritiesContextBuilder,AuthoritiesEngine:()=>AuthoritiesEngine,AuthoritiesEvaluatorRegistry:()=>AuthoritiesEvaluatorRegistry,AuthoritiesProfileRegistry:()=>AuthoritiesProfileRegistry,AuthorityDeniedError:()=>AuthorityDeniedError,AuthorizationBase:()=>AuthorizationBase,BUILT_IN_AUTH_PAGE_CSP:()=>BUILT_IN_AUTH_PAGE_CSP,CDN:()=>CDN,CREDENTIALS_ACCESSOR:()=>CREDENTIALS_ACCESSOR,CimdClientIdMismatchError:()=>CimdClientIdMismatchError,CimdDisabledError:()=>CimdDisabledError,CimdError:()=>CimdError,CimdFetchError:()=>CimdFetchError,CimdResponseTooLargeError:()=>CimdResponseTooLargeError,CimdSecurityError:()=>CimdSecurityError,CimdService:()=>CimdService,CimdValidationError:()=>CimdValidationError,CredentialCache:()=>CredentialCache,CredentialProviderAlreadyRegisteredError:()=>CredentialProviderAlreadyRegisteredError,CredentialStorageError:()=>CredentialStorageError,CredentialsAccessorImpl:()=>CredentialsAccessorImpl,DEFAULT_ALLOWED_SCOPES:()=>DEFAULT_ALLOWED_SCOPES,DEFAULT_INCREMENTAL_TICKET_TTL_MS:()=>DEFAULT_INCREMENTAL_TICKET_TTL_MS,DEFAULT_RESUME_TTL_MS:()=>DEFAULT_RESUME_TTL_MS,DEFAULT_THEME:()=>DEFAULT_THEME,DcrClientRegistry:()=>DcrClientRegistry,EagerCredentialLoader:()=>EagerCredentialLoader,ElicitationSecretRequiredError:()=>ElicitationSecretRequiredError,EncryptedRedisVault:()=>EncryptedRedisVault,EncryptedStorageError:()=>import_utils29.EncryptedStorageError,EncryptedStorageSecureStoreBackend:()=>EncryptedStorageSecureStoreBackend,EncryptedTypedStorage:()=>import_utils29.EncryptedTypedStorage,EncryptionContextNotSetError:()=>EncryptionContextNotSetError,EncryptionKeyNotConfiguredError:()=>EncryptionKeyNotConfiguredError,FetchCredentialMiddleware:()=>FetchCredentialMiddleware,FrontMcpAuthContextImpl:()=>FrontMcpAuthContextImpl,InMemoryAuthorizationStore:()=>InMemoryAuthorizationStore,InMemoryAuthorizationVault:()=>InMemoryAuthorizationVault,InMemoryCimdCache:()=>InMemoryCimdCache,InMemoryConsentStore:()=>InMemoryConsentStore,InMemoryFederatedAuthSessionStore:()=>InMemoryFederatedAuthSessionStore,InMemoryOrchestratedTokenStore:()=>InMemoryOrchestratedTokenStore,InMemoryStoreRequiredError:()=>InMemoryStoreRequiredError,InvalidClientIdUrlError:()=>InvalidClientIdUrlError,JwksService:()=>JwksService,JwtSecretRequiredError:()=>JwtSecretRequiredError,JwtSecretWeakError:()=>JwtSecretWeakError,LazyCredentialLoader:()=>LazyCredentialLoader,LoopbackTokenAuth:()=>LoopbackTokenAuth,NoProviderIdError:()=>NoProviderIdError,NullOrchestratedAuthAccessor:()=>NullOrchestratedAuthAccessor,ORCHESTRATED_AUTH_ACCESSOR:()=>ORCHESTRATED_AUTH_ACCESSOR,OrchestratedAuthAccessorAdapter:()=>OrchestratedAuthAccessorAdapter,OrchestratedAuthNotAvailableError:()=>OrchestratedAuthNotAvailableError,OrchestratedAuthorization:()=>OrchestratedAuthorization,OrchestratorJwksNotAvailableError:()=>OrchestratorJwksNotAvailableError,PEOPLE_SESSION_COOKIE:()=>PEOPLE_SESSION_COOKIE,PublicAuthorization:()=>PublicAuthorization,RedirectUriMismatchError:()=>RedirectUriMismatchError,RedisAuthorizationStore:()=>RedisAuthorizationStore,RedisSessionStore:()=>RedisSessionStore,SECURE_STORE_ACCESSOR:()=>SECURE_STORE_ACCESSOR,SIGNIN_BINDING_COOKIE_PREFIX:()=>SIGNIN_BINDING_COOKIE_PREFIX,SIGNIN_BINDING_MAX_AGE_SECONDS:()=>SIGNIN_BINDING_MAX_AGE_SECONDS,SIGNIN_BINDING_SECURE_COOKIE_PREFIX:()=>SIGNIN_BINDING_SECURE_COOKIE_PREFIX,ScopeDeniedError:()=>ScopeDeniedError,SecureStoreAccessorImpl:()=>SecureStoreAccessorImpl,SecureStoreConfigError:()=>SecureStoreConfigError,SessionCredentialVault:()=>SessionCredentialVault,SessionIdEmptyError:()=>SessionIdEmptyError,SessionRateLimiter:()=>SessionRateLimiter,SessionSecretRequiredError:()=>SessionSecretRequiredError,StorageAuthorizationStore:()=>StorageAuthorizationStore,StorageAuthorizationVault:()=>StorageAuthorizationVault,StorageConsentStore:()=>StorageConsentStore,StorageFederatedAuthSessionStore:()=>StorageFederatedAuthSessionStore,StorageOrchestratedTokenStore:()=>StorageOrchestratedTokenStore,StorageTokenStore:()=>StorageTokenStore,TinyTtlCache:()=>TinyTtlCache,TokenLeakDetectedError:()=>TokenLeakDetectedError,TokenNotAvailableError:()=>TokenNotAvailableError,TokenStoreRequiredError:()=>TokenStoreRequiredError,TokenVault:()=>TokenVault,TransparentAuthorization:()=>TransparentAuthorization,TransportIdGenerator:()=>TransportIdGenerator,TypedStorage:()=>import_utils28.TypedStorage,VaultEncryption:()=>VaultEncryption,VaultLoadError:()=>VaultLoadError,VaultNotFoundError:()=>VaultNotFoundError,VercelKvSessionStore:()=>VercelKvSessionStore,abacConditionSchema:()=>abacConditionSchema,abacOperatorSchema:()=>abacOperatorSchema,abacPolicySchema:()=>abacPolicySchema,advertisedScopes:()=>advertisedScopes,aiPlatformTypeSchema:()=>aiPlatformTypeSchema,allowsPublicAccess:()=>allowsPublicAccess,anonymousCallerClaims:()=>anonymousCallerClaims,apiKeyCredentialSchema:()=>apiKeyCredentialSchema,appAuthOptionsSchema:()=>appAuthOptionsSchema,appAuthStateSchema:()=>appAuthStateSchema,appAuthorizationRecordSchema:()=>appAuthorizationRecordSchema,appCredentialSchema:()=>appCredentialSchema,appRequiresOrchestration:()=>appRequiresOrchestration,authLayout:()=>authLayout,authModeSchema:()=>authModeSchema,authOptionsSchema:()=>authOptionsSchema,authProviderDetectionResultSchema:()=>authProviderDetectionResultSchema,authProviderMappingSchema:()=>authProviderMappingSchema,authProvidersVaultOptionsSchema:()=>authProvidersVaultOptionsSchema,authUserSchema:()=>authUserSchema,authenticateFnSchema:()=>authenticateFnSchema,authoritiesClaimsMappingSchema:()=>authoritiesClaimsMappingSchema,authoritiesConfigSchema:()=>authoritiesConfigSchema,authoritiesMetadataSchema:()=>authoritiesMetadataSchema,authoritiesPolicySchema:()=>authoritiesPolicySchema,authorizationCodeRecordSchema:()=>authorizationCodeRecordSchema,authorizationVaultEntrySchema:()=>authorizationVaultEntrySchema,authorizedPromptSchema:()=>authorizedPromptSchema,authorizedToolSchema:()=>authorizedToolSchema,baseLayout:()=>baseLayout,basicApplier:()=>basicApplier,basicAuthCredentialSchema:()=>basicAuthCredentialSchema,bearerApplier:()=>bearerApplier,bearerCredentialSchema:()=>bearerCredentialSchema,buildAuthContext:()=>buildAuthContext,buildCodeRecord:()=>buildCodeRecord,buildConnectPage:()=>buildConnectPage,buildConnectSuccessPage:()=>buildConnectSuccessPage,buildConsentPage:()=>buildConsentPage,buildCredentialResumeUrl:()=>buildCredentialResumeUrl,buildErrorPage:()=>buildErrorPage,buildFederatedLoginPage:()=>buildFederatedLoginPage,buildIncrementalAuthPage:()=>buildIncrementalAuthPage,buildInsufficientScopeHeader:()=>buildInsufficientScopeHeader,buildInvalidRequestHeader:()=>buildInvalidRequestHeader,buildInvalidTokenHeader:()=>buildInvalidTokenHeader,buildLoginPage:()=>buildLoginPage,buildPendingRecord:()=>buildPendingRecord,buildPrmUrl:()=>buildPrmUrl,buildRefreshTokenRecord:()=>buildRefreshTokenRecord,buildToolConsentPage:()=>buildToolConsentPage,buildUnauthorizedHeader:()=>buildUnauthorizedHeader,buildWwwAuthenticate:()=>buildWwwAuthenticate,builtInAuthPageHeaders:()=>builtInAuthPageHeaders,centeredCardLayout:()=>centeredCardLayout,checkSsrfProtection:()=>checkSsrfProtection,cimdCacheConfigSchema:()=>cimdCacheConfigSchema,cimdConfigSchema:()=>cimdConfigSchema,cimdNetworkConfigSchema:()=>cimdNetworkConfigSchema,cimdSecurityConfigSchema:()=>cimdSecurityConfigSchema,clientMetadataDocumentSchema:()=>clientMetadataDocumentSchema,completeCurrentProvider:()=>completeCurrentProvider,consentConfigSchema:()=>consentConfigSchema,consentRecordKey:()=>consentRecordKey,consentSelectionSchema:()=>consentSelectionSchema,consentStateSchema:()=>consentStateSchema,consentToolItemSchema:()=>consentToolItemSchema,createAudienceValidator:()=>createAudienceValidator,createEncryptedVault:()=>createEncryptedVault,createFederatedAuthSession:()=>createFederatedAuthSession,createLayout:()=>createLayout,createSecureStore:()=>createSecureStore,createSessionCredentialVault:()=>createSessionCredentialVault,createSharedServerNonce:()=>createSharedServerNonce,createSharedServerSecret:()=>createSharedServerSecret,createSigninBinding:()=>createSigninBinding,createTokenStorageAdapter:()=>createTokenStorageAdapter,credentialProviderConfigSchema:()=>credentialProviderConfigSchema,credentialSchema:()=>credentialSchema,credentialScopeSchema:()=>credentialScopeSchema,credentialTypeSchema:()=>credentialTypeSchema,customCredentialSchema:()=>customCredentialSchema,decodeJwtPayloadSafe:()=>decodeJwtPayloadSafe,decryptAesGcm:()=>import_utils39.decryptAesGcm,decryptSessionJson:()=>decryptSessionJson,decryptValue:()=>import_utils39.decryptValue,defaultSessionRateLimiter:()=>defaultSessionRateLimiter,deriveAuthorizationId:()=>deriveAuthorizationId,deriveExpectedAudience:()=>deriveExpectedAudience,deriveProviderId:()=>deriveProviderId,deriveSharedServerKeys:()=>deriveSharedServerKeys,deriveTypedUser:()=>deriveTypedUser,detectAuthProviders:()=>detectAuthProviders,detectedAuthProviderSchema:()=>detectedAuthProviderSchema,encryptAesGcm:()=>import_utils39.encryptAesGcm,encryptJson:()=>encryptJson,encryptValue:()=>import_utils39.encryptValue,encryptedBlobSchema:()=>encryptedBlobSchema,encryptedDataSchema:()=>encryptedDataSchema,encryptedVaultEntrySchema:()=>encryptedVaultEntrySchema,escapeHtml:()=>import_utils4.escapeHtml,extraWideLayout:()=>extraWideLayout,extractBearerToken:()=>extractBearerToken,extractCacheHeaders:()=>extractCacheHeaders,extractCredentialExpiry:()=>extractCredentialExpiry,federatedAuthConfigSchema:()=>federatedAuthConfigSchema,federatedLoginStateSchema:()=>federatedLoginStateSchema,federatedProviderItemSchema:()=>federatedProviderItemSchema,federatedSelectionSchema:()=>federatedSelectionSchema,findAuthoritiesProfileProblems:()=>findAuthoritiesProfileProblems,findAuthoritiesRuleProblems:()=>findAuthoritiesRuleProblems,flatRemoteProviderFields:()=>flatRemoteProviderFields,fromSessionRecord:()=>fromSessionRecord,generateAuthorizationCode:()=>generateAuthorizationCode,generatePkceChallenge:()=>generatePkceChallenge,generateRefreshTokenValue:()=>generateRefreshTokenValue,getCredentialOptionsSchema:()=>getCredentialOptionsSchema,getKey:()=>getKey,getNextProvider:()=>getNextProvider,getProviderApps:()=>getProviderApps,getProviderScopes:()=>getProviderScopes,getTokenSignatureFingerprint:()=>getTokenSignatureFingerprint,grantScopes:()=>grantScopes,hasOnlyLocalhostRedirectUris:()=>hasOnlyLocalhostRedirectUris,headerApplier:()=>headerApplier,hkdfSha256:()=>import_utils39.hkdfSha256,incrementalAuthConfigSchema:()=>incrementalAuthConfigSchema,isAnonymousSubject:()=>isAnonymousSubject,isCimdClientId:()=>isCimdClientId,isFrontMcpCredentials:()=>isFrontMcpCredentials,isJwt:()=>isJwt,isLocalMode:()=>isLocalMode,isLoopbackRedirectUri:()=>isLoopbackRedirectUri,isOrchestratedLocal:()=>isOrchestratedLocal,isOrchestratedMode:()=>isOrchestratedMode,isOrchestratedRemote:()=>isOrchestratedRemote,isPersistentTokenStorage:()=>isPersistentTokenStorage,isPublicMode:()=>isPublicMode,isRedisTokenStorage:()=>isRedisTokenStorage,isRemoteMode:()=>isRemoteMode,isSessionComplete:()=>isSessionComplete,isSharedServerNonce:()=>isSharedServerNonce,isSignedSession:()=>import_utils21.isSignedData,isSoonExpiring:()=>isSoonExpiring,isSoonExpiringProvider:()=>isSoonExpiringProvider,isSqliteTokenStorage:()=>isSqliteTokenStorage,isStaticMode:()=>isStaticMode,isTransparentMode:()=>isTransparentMode,jsonWebKeySetSchema:()=>jsonWebKeySetSchema,jwkParametersSchema:()=>jwkParametersSchema,jwkSchema:()=>jwkSchema,legacySseTransportStateSchema:()=>legacySseTransportStateSchema,llmSafeAuthContextSchema:()=>llmSafeAuthContextSchema,loadingStrategySchema:()=>loadingStrategySchema,localAuthSchema:()=>localAuthSchema,localDcrClientSchema:()=>localDcrClientSchema,localDcrConfigSchema:()=>localDcrConfigSchema,localSigningConfigSchema:()=>localSigningConfigSchema,loginConfigSchema:()=>loginConfigSchema,mtlsCredentialSchema:()=>mtlsCredentialSchema,noopLogger:()=>noopLogger,normalizeIssuer:()=>normalizeIssuer,oauthCredentialSchema:()=>oauthCredentialSchema,openPendingLogin:()=>openPendingLogin,orchestratedLocalSchema:()=>orchestratedLocalSchema,orchestratedRemoteSchema:()=>orchestratedRemoteSchema,parseAuthOptions:()=>parseAuthOptions,parseCacheHeaders:()=>parseCacheHeaders,parseWwwAuthenticate:()=>parseWwwAuthenticate,pendingIncrementalAuthSchema:()=>pendingIncrementalAuthSchema,peopleAuthOptionsSchema:()=>peopleAuthOptionsSchema,peopleSessionCookie:()=>peopleSessionCookie,pkceChallengeSchema:()=>pkceChallengeSchema,pkceOAuthCredentialSchema:()=>pkceOAuthCredentialSchema,privateKeyCredentialSchema:()=>privateKeyCredentialSchema,progressiveAuthStateSchema:()=>progressiveAuthStateSchema,proveSharedServerIdentity:()=>proveSharedServerIdentity,providerConfigSchema:()=>providerConfigSchema,providerHeadersCredentials:()=>providerHeadersCredentials,publicAccessConfigSchema:()=>publicAccessConfigSchema,publicAuthOptionsSchema:()=>publicAuthOptionsSchema,queryApplier:()=>queryApplier,rbacPermissionsPolicySchema:()=>rbacPermissionsPolicySchema,rbacRolesPolicySchema:()=>rbacRolesPolicySchema,rebacPolicySchema:()=>rebacPolicySchema,redisConfigSchema:()=>redisConfigSchema,redisVaultEntrySchema:()=>redisVaultEntrySchema,remoteAuthSchema:()=>remoteAuthSchema,remoteProviderConfigSchema:()=>remoteProviderConfigSchema,renderLocalLoginPage:()=>renderLocalLoginPage,renderToHtml:()=>renderToHtml,resetCachedKey:()=>resetCachedKey,resolveRequiredScopes:()=>resolveRequiredScopes,resourceIdRefSchema:()=>resourceIdRefSchema,resourceScopesFor:()=>resourceScopesFor,safeDecrypt:()=>safeDecrypt,scopesFromClaims:()=>scopesFromClaims,sealPendingLogin:()=>sealPendingLogin,secureStoreConfigSchema:()=>secureStoreConfigSchema,secureStoreCustomBackendSchema:()=>secureStoreCustomBackendSchema,secureStoreEncryptionSchema:()=>secureStoreEncryptionSchema,secureStoreScopeSchema:()=>secureStoreScopeSchema,serviceAccountCredentialSchema:()=>serviceAccountCredentialSchema,sessionIdPayloadSchema:()=>sessionIdPayloadSchema,sessionJwtPayloadSchema:()=>sessionJwtPayloadSchema,signCredentialResumeToken:()=>signCredentialResumeToken,signIncrementalAuthTicket:()=>signIncrementalAuthTicket,signSession:()=>signSession,signinBindingCookieName:()=>signinBindingCookieName,signinBindingMatches:()=>signinBindingMatches,skippedAppBehaviorSchema:()=>skippedAppBehaviorSchema,sseTransportStateSchema:()=>sseTransportStateSchema,sshKeyCredentialSchema:()=>sshKeyCredentialSchema,startNextProvider:()=>startNextProvider,statefulHttpTransportStateSchema:()=>statefulHttpTransportStateSchema,statelessHttpTransportStateSchema:()=>statelessHttpTransportStateSchema,staticAuthOptionsSchema:()=>staticAuthOptionsSchema,storedSessionSchema:()=>storedSessionSchema,streamableHttpTransportStateSchema:()=>streamableHttpTransportStateSchema,toEpochSeconds:()=>toEpochSeconds,toLoginExtraFields:()=>toLoginExtraFields,toSessionRecord:()=>toSessionRecord,tokenRefreshConfigSchema:()=>tokenRefreshConfigSchema,tokenStorageConfigSchema:()=>tokenStorageConfigSchema,tokenStorageSqliteSchema:()=>tokenStorageSqliteSchema,transparentAuthOptionsSchema:()=>transparentAuthOptionsSchema,transportProtocolSchema:()=>transportProtocolSchema,transportSessionSchema:()=>transportSessionSchema,transportStateSchema:()=>transportStateSchema,trimSlash:()=>trimSlash,tryJwtExp:()=>tryJwtExp,upstreamProviderSchema:()=>upstreamProviderSchema,userClaimSchema:()=>userClaimSchema,validateAudience:()=>validateAudience,validateClientIdUrl:()=>validateClientIdUrl,vaultConsentRecordSchema:()=>vaultConsentRecordSchema,vaultFederatedRecordSchema:()=>vaultFederatedRecordSchema,verifyCredentialResumeToken:()=>verifyCredentialResumeToken,verifyIncrementalAuthTicket:()=>verifyIncrementalAuthTicket,verifyOrParseSession:()=>verifyOrParseSession,verifyPkce:()=>verifyPkce,verifySession:()=>verifySession,verifySharedServerIdentity:()=>verifySharedServerIdentity,wideLayout:()=>wideLayout,withoutSecretFieldValues:()=>withoutSecretFieldValues});module.exports=__toCommonJS(index_exports);var import_utils2=require("@frontmcp/utils");var import_utils=require("@frontmcp/utils");var CimdError=class extends Error{code;statusCode;clientIdUrl;constructor(message,code,statusCode,clientIdUrl){super(message);this.name=this.constructor.name;this.code=code;this.statusCode=statusCode;this.clientIdUrl=clientIdUrl;if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}getPublicMessage(){return this.message}};var InvalidClientIdUrlError=class extends CimdError{reason;constructor(clientIdUrl,reason){super(`Invalid CIMD client_id URL: ${reason}`,"INVALID_CLIENT_ID_URL",400,clientIdUrl);this.reason=reason}getPublicMessage(){return`Invalid client_id URL: ${this.reason}`}};var CimdFetchError=class extends CimdError{httpStatus;originalError;constructor(clientIdUrl,message,options){super(`Failed to fetch CIMD document from ${clientIdUrl}: ${message}`,"CIMD_FETCH_ERROR",502,clientIdUrl);this.httpStatus=options?.httpStatus;this.originalError=options?.originalError}getPublicMessage(){if(this.httpStatus){return`Failed to fetch client metadata: HTTP ${this.httpStatus}`}return"Failed to fetch client metadata document"}};var CimdValidationError=class extends CimdError{validationErrors;constructor(clientIdUrl,errors){super(`CIMD document validation failed: ${errors.join("; ")}`,"CIMD_VALIDATION_ERROR",400,clientIdUrl);this.validationErrors=errors}getPublicMessage(){return`Client metadata document validation failed: ${this.validationErrors.join("; ")}`}};var CimdClientIdMismatchError=class extends CimdError{documentClientId;constructor(urlClientId,documentClientId){super(`CIMD client_id mismatch: URL is "${urlClientId}" but document contains "${documentClientId}"`,"CIMD_CLIENT_ID_MISMATCH",400,urlClientId);this.documentClientId=documentClientId}getPublicMessage(){return"Client ID in metadata document does not match the request"}};var CimdSecurityError=class extends CimdError{securityReason;constructor(clientIdUrl,reason){super(`CIMD security check failed for ${clientIdUrl}: ${reason}`,"CIMD_SECURITY_ERROR",403,clientIdUrl);this.securityReason=reason}getPublicMessage(){return"Client ID URL is not allowed by security policy"}};var RedirectUriMismatchError=class extends CimdError{requestedRedirectUri;allowedRedirectUris;constructor(clientIdUrl,requestedRedirectUri,allowedRedirectUris){super(`Redirect URI "${requestedRedirectUri}" is not registered for client "${clientIdUrl}"`,"REDIRECT_URI_MISMATCH",400,clientIdUrl);this.requestedRedirectUri=requestedRedirectUri;this.allowedRedirectUris=allowedRedirectUris}getPublicMessage(){return"The redirect_uri is not registered for this client"}};var CimdResponseTooLargeError=class extends CimdError{maxBytes;actualBytes;constructor(clientIdUrl,maxBytes,actualBytes){super(`CIMD response from ${clientIdUrl} exceeds maximum size of ${maxBytes} bytes${actualBytes?` (received ${actualBytes} bytes)`:""}`,"CIMD_RESPONSE_TOO_LARGE",502,clientIdUrl);this.maxBytes=maxBytes;this.actualBytes=actualBytes}getPublicMessage(){return"Client metadata document is too large"}};var CimdDisabledError=class extends CimdError{constructor(){super("CIMD (Client ID Metadata Documents) is disabled on this server","CIMD_DISABLED",400)}};function isCimdClientId(clientId,allowInsecure=false){if(!clientId||typeof clientId!=="string"){return false}try{const url=new URL(clientId);if(url.protocol==="https:"){}else if(url.protocol==="http:"&&allowInsecure&&isLocalhostHost(url.hostname)){}else{return false}if(!url.pathname||url.pathname==="/"){return false}return true}catch{return false}}function isLocalhostHost(hostname){const lower=hostname.toLowerCase();return lower==="localhost"||lower==="127.0.0.1"||lower==="[::1]"||lower.endsWith(".localhost")}function validateClientIdUrl(clientId,securityConfig){if(!clientId||typeof clientId!=="string"){throw new InvalidClientIdUrlError(clientId||"","client_id must be a non-empty string")}let url;try{url=new URL(clientId)}catch{throw new InvalidClientIdUrlError(clientId,"Invalid URL format")}const allowInsecure=securityConfig?.allowInsecureForTesting??false;if(url.protocol==="https:"){}else if(url.protocol==="http:"&&allowInsecure&&isLocalhostHost(url.hostname)){}else{throw new InvalidClientIdUrlError(clientId,`CIMD requires HTTPS, got ${url.protocol.replace(":","")}`)}if(!url.pathname||url.pathname==="/"){throw new InvalidClientIdUrlError(clientId,"CIMD client_id URL must have a path component (e.g., /oauth/client-metadata.json)")}const config={blockPrivateIPs:securityConfig?.blockPrivateIPs??true,allowedDomains:securityConfig?.allowedDomains,blockedDomains:securityConfig?.blockedDomains};if(config.allowedDomains?.length){if(!isDomainInList(url.hostname,config.allowedDomains)){throw new CimdSecurityError(clientId,`Domain "${url.hostname}" is not in the allowed domains list`)}}if(config.blockedDomains?.length){if(isDomainInList(url.hostname,config.blockedDomains)){throw new CimdSecurityError(clientId,`Domain "${url.hostname}" is blocked`)}}if(config.blockPrivateIPs&&!allowInsecure){const ssrfCheck=checkSsrfProtection(url.hostname);if(!ssrfCheck.allowed){throw new CimdSecurityError(clientId,ssrfCheck.reason)}}return url}function checkSsrfProtection(hostname){const lowercaseHostname=hostname.toLowerCase();if(lowercaseHostname==="localhost"||lowercaseHostname==="localhost.localdomain"||lowercaseHostname.endsWith(".localhost")){return{allowed:false,reason:"Localhost addresses are not allowed"}}if(isIpAddress(hostname)){const ipCheck=checkIpAddress(hostname);if(!ipCheck.allowed){return ipCheck}}return{allowed:true,reason:""}}async function resolveAndCheckHostname(hostname){const literal=checkSsrfProtection(hostname);if(!literal.allowed)return literal;if(isIpAddress(hostname))return{allowed:true,reason:""};let dns;try{dns=require("node:dns")}catch{return{allowed:true,reason:""}}let addresses;try{const result=await dns.promises.lookup(hostname,{all:true,verbatim:true});addresses=Array.isArray(result)?result:[result]}catch{return{allowed:false,reason:`DNS resolution failed for "${hostname}"; refusing to fetch an unvalidated host`}}if(addresses.length===0){return{allowed:false,reason:`Host "${hostname}" resolved to no addresses`}}for(const{address}of addresses){if(!address)continue;const ipCheck=checkIpAddress(address);if(!ipCheck.allowed){return{allowed:false,reason:`Host "${hostname}" resolves to a blocked address (${address}): ${ipCheck.reason}`}}}return{allowed:true,reason:""}}async function assertHostNotSsrf(hostname,clientId){const check=await resolveAndCheckHostname(hostname);if(!check.allowed){throw new CimdSecurityError(clientId,check.reason)}}function isIpAddress(hostname){const ipv4Pattern=/^(\d{1,3}\.){3}\d{1,3}$/;if(ipv4Pattern.test(hostname)){return true}const cleanHostname=hostname.replace(/^\[|\]$/g,"");if(cleanHostname.includes(":")){return true}return false}var BLOCKED_RANGE_REASONS=new Map([["0.0.0.0/8","Current network addresses (0.x.x.x) are not allowed"],["10.0.0.0/8","Private IP addresses (10.x.x.x) are not allowed"],["100.64.0.0/10","Carrier-grade NAT addresses (100.64-127.x.x) are not allowed"],["127.0.0.0/8","Loopback addresses (127.x.x.x) are not allowed"],["169.254.0.0/16","Link-local addresses (169.254.x.x) are not allowed"],["172.16.0.0/12","Private IP addresses (172.16-31.x.x) are not allowed"],["192.0.0.0/24","IETF protocol-assignment addresses (192.0.0.0/24) are not allowed"],["192.168.0.0/16","Private IP addresses (192.168.x.x) are not allowed"],["224.0.0.0/4","Multicast addresses are not allowed"],["255.255.255.255/32","Broadcast address is not allowed"],["::/128","IPv6 unspecified address (::) is not allowed"],["::1/128","IPv6 loopback address (::1) is not allowed"],["fc00::/7","IPv6 unique local addresses (fc00::/7) are not allowed"],["fe80::/10","IPv6 link-local addresses (fe80::/10) are not allowed"]]);function checkIpAddress(ip){const classification=(0,import_utils.classifyIpAddress)(ip);if(!classification){const bareIp=ip.replace(/^\[|\]$/g,"");return{allowed:false,reason:bareIp.includes(":")?`Malformed IPv6 address: ${bareIp}`:"Invalid IPv4 address"}}if(classification.range==="public"){return{allowed:true,reason:""}}return{allowed:false,reason:BLOCKED_RANGE_REASONS.get(classification.cidr)??`Addresses in the ${classification.range} range (${classification.cidr}) are not allowed`}}function isDomainInList(hostname,domainList){const lowerHostname=hostname.toLowerCase();for(const domain of domainList){const lowerDomain=domain.toLowerCase();if(lowerHostname===lowerDomain){return true}if(lowerHostname.endsWith("."+lowerDomain)){return true}if(lowerDomain.startsWith("*.")){const baseDomain=lowerDomain.slice(2);if(lowerHostname===baseDomain||lowerHostname.endsWith("."+baseDomain)){return true}}}return false}function hasOnlyLocalhostRedirectUris(redirectUris){if(!redirectUris.length){return false}return redirectUris.every(uri=>{try{const url=new URL(uri);const hostname=url.hostname.toLowerCase();return hostname==="localhost"||hostname==="127.0.0.1"||hostname==="[::1]"||hostname.endsWith(".localhost")}catch{return false}})}var noopAuthLogger={info(){},warn(){},error(){},debug(){}};var jose;function loadJose(){jose??=import("jose").catch(importError=>{try{return require("jose")}catch{throw importError}}).catch(error=>{jose=void 0;throw error});return jose}function trimSlash(s){const str=s??"";let end=str.length;while(end>0&&str[end-1]==="/"){end--}return str.slice(0,end)}function normalizeIssuer(u){return trimSlash(String(u??""))}function decodeJwtPayloadSafe(token){if(!token)return void 0;const parts=token.split(".");if(parts.length<2)return void 0;try{const b64=parts[1].replace(/-/g,"+").replace(/_/g,"/");const json=typeof Buffer!=="undefined"?Buffer.from(b64,"base64").toString("utf8"):atob(b64);const obj=JSON.parse(json);return obj&&typeof obj==="object"&&!Array.isArray(obj)?obj:void 0}catch{return void 0}}var TRANSPARENT_JWT_ALGS=["RS256","RS384","RS512","PS256","PS384","PS512","ES256","ES384","ES512","EdDSA"];var MAX_JWKS_FETCH_BYTES=1048576;var MAX_JWKS_FETCH_HOPS=3;var UNKNOWN_KID_REFETCH_COOLDOWN_MS=6e4;var MISSING_EXP_ERROR='missing required "exp" claim';function isMissingExpError(error){if(typeof error!=="object"||error===null)return false;const{code,claim,reason}=error;return code==="ERR_JWT_CLAIM_VALIDATION_FAILED"&&claim==="exp"&&reason==="missing"}var WEAK_KEY_WARNING=`
2
2
  \u26A0\uFE0F SECURITY WARNING: OAuth provider is using an RSA key smaller than 2048 bits.
3
3
  This is considered insecure and should be updated.
4
4
  Please contact your OAuth provider to upgrade their signing keys.
@@ -351,4 +351,4 @@ ${buildLoginFieldHtml(field)}
351
351
  <code class="px-2 py-1 bg-gray-100 rounded text-red-600 font-mono text-sm">${escapeHtml3(error)}</code>
352
352
  </p>
353
353
  <p class="text-gray-600">${escapeHtml3(description)}</p>
354
- </div>`;return centeredCardLayout(content,{title:"Error"})}function renderToHtml(html,_options){return html}function toLoginExtraFields(fields,values){if(!fields)return[];return Object.entries(fields).map(([name,def])=>({name,type:def.type,label:def.label,required:def.required,placeholder:def.placeholder,options:def.options,value:values?.[name]}))}function withoutSecretFieldValues(values,fields){if(!values)return void 0;const kept={};for(const[name,value]of Object.entries(values)){if(fields?.[name]?.type==="password")continue;kept[name]=value}return kept}function renderLocalLoginPage(login,ctx,submitted){const values=withoutSecretFieldValues(submitted,login?.fields);if(login?.render){return login.render({...ctx,values})}const extraFields=login?.fields?toLoginExtraFields(login.fields,values):void 0;return buildLoginPage({clientName:ctx.clientName,scope:ctx.scopes.join(" "),pendingAuthId:ctx.pendingAuthId,callbackPath:ctx.callbackPath,title:login?.title,subtitle:login?.subtitle,logoUri:login?.logoUri??ctx.logoUri,error:ctx.error,extraFields})}var import_lazy_zod=require("@frontmcp/lazy-zod");var import_utils5=require("@frontmcp/utils");var pkceChallengeSchema=import_lazy_zod.z.object({challenge:import_lazy_zod.z.string().min(43).max(128),method:import_lazy_zod.z.literal("S256")});var authorizationCodeRecordSchema=import_lazy_zod.z.object({code:import_lazy_zod.z.string().min(1),clientId:import_lazy_zod.z.string().min(1),redirectUri:import_lazy_zod.z.string().url(),scopes:import_lazy_zod.z.array(import_lazy_zod.z.string()),pkce:pkceChallengeSchema,userSub:import_lazy_zod.z.string().min(1),userEmail:import_lazy_zod.z.string().email().optional(),userName:import_lazy_zod.z.string().optional(),state:import_lazy_zod.z.string().optional(),createdAt:import_lazy_zod.z.number(),expiresAt:import_lazy_zod.z.number(),used:import_lazy_zod.z.boolean(),resource:import_lazy_zod.z.string().url().optional(),selectedToolIds:import_lazy_zod.z.array(import_lazy_zod.z.string()).optional(),selectedProviderIds:import_lazy_zod.z.array(import_lazy_zod.z.string()).optional(),skippedProviderIds:import_lazy_zod.z.array(import_lazy_zod.z.string()).optional(),consentEnabled:import_lazy_zod.z.boolean().optional(),federatedLoginUsed:import_lazy_zod.z.boolean().optional(),pendingAuthId:import_lazy_zod.z.string().optional(),authorizedAppIds:import_lazy_zod.z.array(import_lazy_zod.z.string()).optional(),customClaims:import_lazy_zod.z.record(import_lazy_zod.z.string(),import_lazy_zod.z.unknown()).optional()});var AUTH_CODE_TTL_MS=60*1e3;var PENDING_AUTH_TTL_MS=10*60*1e3;var REFRESH_TOKEN_TTL_MS=30*24*60*60*1e3;function generateAuthorizationCode(){return(0,import_utils5.randomUUID)().replace(/-/g,"")+(0,import_utils5.randomUUID)().replace(/-/g,"")}function generateRefreshTokenValue(){return(0,import_utils5.randomUUID)()+"-"+(0,import_utils5.randomUUID)()}function buildCodeRecord(params){const now=Date.now();return{code:generateAuthorizationCode(),clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,pkce:params.pkce,userSub:params.userSub,userEmail:params.userEmail,userName:params.userName,state:params.state,resource:params.resource,createdAt:now,expiresAt:now+AUTH_CODE_TTL_MS,used:false,selectedToolIds:params.selectedToolIds,selectedProviderIds:params.selectedProviderIds,skippedProviderIds:params.skippedProviderIds,consentEnabled:params.consentEnabled,federatedLoginUsed:params.federatedLoginUsed,pendingAuthId:params.pendingAuthId,authorizedAppIds:params.authorizedAppIds,customClaims:params.customClaims}}function buildPendingRecord(params){const now=Date.now();return{id:(0,import_utils5.randomUUID)(),clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,pkce:params.pkce,state:params.state,resource:params.resource,createdAt:now,expiresAt:now+PENDING_AUTH_TTL_MS,isIncremental:params.isIncremental,incrementalSub:params.incrementalSub,targetAppId:params.targetAppId,targetToolId:params.targetToolId,existingSessionId:params.existingSessionId,existingAuthorizationId:params.existingAuthorizationId,priorAuthorizedAppIds:params.priorAuthorizedAppIds,federatedLogin:params.federatedLogin,consent:params.consent,authUiCsrf:params.authUiCsrf,signinBinding:params.signinBinding}}function buildRefreshTokenRecord(params){const now=Date.now();return{token:generateRefreshTokenValue(),clientId:params.clientId,userSub:params.userSub,scopes:params.scopes,resource:params.resource,createdAt:now,expiresAt:now+REFRESH_TOKEN_TTL_MS,revoked:false,userEmail:params.userEmail,userName:params.userName,consentEnabled:params.consentEnabled,selectedToolIds:params.selectedToolIds,authorizedAppIds:params.authorizedAppIds,customClaims:params.customClaims,federatedLoginUsed:params.federatedLoginUsed,selectedProviderIds:params.selectedProviderIds,skippedProviderIds:params.skippedProviderIds,providerTokensId:params.providerTokensId}}function verifyPkce(codeVerifier,challenge){if(challenge.method!=="S256"){return false}const hash=(0,import_utils5.sha256Base64url)(codeVerifier);return hash===challenge.challenge}function generatePkceChallenge(codeVerifier){const challenge=(0,import_utils5.sha256Base64url)(codeVerifier);return{challenge,method:"S256"}}var InMemoryAuthorizationStore=class{codes=new Map;pending=new Map;refreshTokens=new Map;generateCode(){return generateAuthorizationCode()}generateRefreshToken(){return generateRefreshTokenValue()}async storeAuthorizationCode(record){this.codes.set(record.code,record)}async getAuthorizationCode(code){const record=this.codes.get(code);if(!record)return null;if(Date.now()>record.expiresAt){this.codes.delete(code);return null}return record}async markCodeUsed(code,issuedRefreshToken){const record=this.codes.get(code);if(record){record.used=true;if(issuedRefreshToken)record.issuedRefreshToken=issuedRefreshToken}}async deleteAuthorizationCode(code){this.codes.delete(code)}async storePendingAuthorization(record){this.pending.set(record.id,record)}async getPendingAuthorization(id){const record=this.pending.get(id);if(!record)return null;if(Date.now()>record.expiresAt){this.pending.delete(id);return null}return record}async deletePendingAuthorization(id){this.pending.delete(id)}async storeRefreshToken(record){this.refreshTokens.set(record.token,record)}async getRefreshToken(token){const record=this.refreshTokens.get(token);if(!record)return null;if(Date.now()>record.expiresAt||record.revoked){return null}return record}async revokeRefreshToken(token){const record=this.refreshTokens.get(token);if(record){record.revoked=true}}async rotateRefreshToken(oldToken,newRecord){await this.revokeRefreshToken(oldToken);newRecord.previousToken=oldToken;await this.storeRefreshToken(newRecord)}async cleanup(){const now=Date.now();for(const[code,record]of this.codes){if(now>record.expiresAt){this.codes.delete(code)}}for(const[id,record]of this.pending){if(now>record.expiresAt){this.pending.delete(id)}}for(const[token,record]of this.refreshTokens){if(now>record.expiresAt||record.revoked){this.refreshTokens.delete(token)}}}createCodeRecord(params){return buildCodeRecord(params)}createPendingRecord(params){return buildPendingRecord(params)}createRefreshTokenRecord(params){return buildRefreshTokenRecord(params)}};var RedisAuthorizationStore=class{constructor(redis,namespace="oauth:"){this.redis=redis;this.namespace=namespace}redis;namespace;key(type,id){return`${this.namespace}${type}:${id}`}generateCode(){return generateAuthorizationCode()}generateRefreshToken(){return generateRefreshTokenValue()}createCodeRecord(params){return buildCodeRecord(params)}createPendingRecord(params){return buildPendingRecord(params)}createRefreshTokenRecord(params){return buildRefreshTokenRecord(params)}async storeAuthorizationCode(record){const ttl=Math.max(Math.ceil((record.expiresAt-Date.now())/1e3),1);await this.redis.set(this.key("code",record.code),JSON.stringify(record),"EX",Math.max(ttl,1))}async getAuthorizationCode(code){const data=await this.redis.get(this.key("code",code));if(!data)return null;return JSON.parse(data)}async markCodeUsed(code,issuedRefreshToken){const record=await this.getAuthorizationCode(code);if(record){record.used=true;if(issuedRefreshToken)record.issuedRefreshToken=issuedRefreshToken;const ttl=Math.ceil((record.expiresAt-Date.now())/1e3);await this.redis.set(this.key("code",code),JSON.stringify(record),"EX",Math.max(ttl,1))}}async deleteAuthorizationCode(code){await this.redis.del(this.key("code",code))}async storePendingAuthorization(record){const ttl=Math.max(Math.ceil((record.expiresAt-Date.now())/1e3),1);await this.redis.set(this.key("pending",record.id),JSON.stringify(record),"EX",ttl)}async getPendingAuthorization(id){const data=await this.redis.get(this.key("pending",id));if(!data)return null;return JSON.parse(data)}async deletePendingAuthorization(id){await this.redis.del(this.key("pending",id))}async storeRefreshToken(record){const ttl=Math.ceil((record.expiresAt-Date.now())/1e3);await this.redis.set(this.key("refresh",record.token),JSON.stringify(record),"EX",ttl)}async getRefreshToken(token){const data=await this.redis.get(this.key("refresh",token));if(!data)return null;const record=JSON.parse(data);if(record.revoked)return null;return record}async revokeRefreshToken(token){const record=await this.getRefreshToken(token);if(record){record.revoked=true;const ttl=Math.ceil((record.expiresAt-Date.now())/1e3);await this.redis.set(this.key("refresh",token),JSON.stringify(record),"EX",Math.max(ttl,1))}}async rotateRefreshToken(oldToken,newRecord){await this.revokeRefreshToken(oldToken);newRecord.previousToken=oldToken;await this.storeRefreshToken(newRecord)}async cleanup(){}};var import_utils6=require("@frontmcp/utils");var SALT=new TextEncoder().encode("frontmcp-pending-login");function keyFor(secret,pendingAuthId){return(0,import_utils6.hkdfSha256)(secret,SALT,new TextEncoder().encode(`pending-login:${pendingAuthId}`),32)}function sealPendingLogin(secret,pendingAuthId,state){const iv=(0,import_utils6.randomBytes)(12);const{ciphertext,tag}=(0,import_utils6.encryptAesGcm)(keyFor(secret,pendingAuthId),new TextEncoder().encode(JSON.stringify(state)),iv);return[iv,tag,ciphertext].map(part=>(0,import_utils6.base64urlEncode)(part)).join(".")}function openPendingLogin(secret,pendingAuthId,sealed){try{const[iv,tag,ciphertext]=sealed.split(".").map(part=>(0,import_utils6.base64urlDecode)(part));if(!iv||!tag||!ciphertext)return void 0;const plaintext=(0,import_utils6.decryptAesGcm)(keyFor(secret,pendingAuthId),ciphertext,iv,tag);const state=JSON.parse(new TextDecoder().decode(plaintext));return typeof state?.sub==="string"&&state.sub.length>0?state:void 0}catch{return void 0}}var import_utils7=require("@frontmcp/utils");var SIGNIN_BINDING_COOKIE_PREFIX="frontmcp_signin_";var SIGNIN_BINDING_SECURE_COOKIE_PREFIX=`__Host-${SIGNIN_BINDING_COOKIE_PREFIX}`;var SIGNIN_BINDING_MAX_AGE_SECONDS=30*60;function signinBindingCookieName(pendingAuthId,options={}){const prefix=options.secure?SIGNIN_BINDING_SECURE_COOKIE_PREFIX:SIGNIN_BINDING_COOKIE_PREFIX;return`${prefix}${(0,import_utils7.sha256Hex)(`signin:${pendingAuthId}`).slice(0,16)}`}function createSigninBinding(pendingAuthId,options={}){const value=(0,import_utils7.base64urlEncode)((0,import_utils7.randomBytes)(32));return{cookieName:signinBindingCookieName(pendingAuthId,options),value,hash:(0,import_utils7.sha256Hex)(value)}}function signinBindingMatches(cookieHeader,pendingAuthId,expectedHash,options={}){if(!expectedHash)return false;const value=(0,import_utils7.getCookie)(cookieHeader,signinBindingCookieName(pendingAuthId,options));if(!value)return false;const encoder=new TextEncoder;const actual=encoder.encode((0,import_utils7.sha256Hex)(value));const expected=encoder.encode(expectedHash);return actual.length===expected.length&&(0,import_utils7.timingSafeEqual)(actual,expected)}var import_utils8=require("@frontmcp/utils");var StorageAuthorizationStore=class{codeStore;pendingStore;refreshStore;namespace;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"oauth";this.storageIsNamespaced=this.isNamespacedStorage(storage);const base=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.codeStore=new import_utils8.TypedStorage(base);this.pendingStore=new import_utils8.TypedStorage(base);this.refreshStore=new import_utils8.TypedStorage(base)}generateCode(){return generateAuthorizationCode()}generateRefreshToken(){return generateRefreshTokenValue()}createCodeRecord(params){return buildCodeRecord(params)}createPendingRecord(params){return buildPendingRecord(params)}createRefreshTokenRecord(params){return buildRefreshTokenRecord(params)}async storeAuthorizationCode(record){await this.codeStore.set(this.key("code",record.code),record,this.ttl(record.expiresAt))}async getAuthorizationCode(code){const record=await this.codeStore.get(this.key("code",code));if(!record)return null;if(Date.now()>record.expiresAt){await this.codeStore.delete(this.key("code",code));return null}return record}async markCodeUsed(code,issuedRefreshToken){const record=await this.getAuthorizationCode(code);if(record){record.used=true;if(issuedRefreshToken)record.issuedRefreshToken=issuedRefreshToken;await this.codeStore.set(this.key("code",code),record,this.ttl(record.expiresAt))}}async deleteAuthorizationCode(code){await this.codeStore.delete(this.key("code",code))}async storePendingAuthorization(record){await this.pendingStore.set(this.key("pending",record.id),record,this.ttl(record.expiresAt))}async getPendingAuthorization(id){const record=await this.pendingStore.get(this.key("pending",id));if(!record)return null;if(Date.now()>record.expiresAt){await this.pendingStore.delete(this.key("pending",id));return null}return record}async deletePendingAuthorization(id){await this.pendingStore.delete(this.key("pending",id))}async storeRefreshToken(record){await this.refreshStore.set(this.key("refresh",record.token),record,this.ttl(record.expiresAt))}async getRefreshToken(token){const record=await this.refreshStore.get(this.key("refresh",token));if(!record)return null;if(Date.now()>record.expiresAt||record.revoked){return null}return record}async revokeRefreshToken(token){const record=await this.refreshStore.get(this.key("refresh",token));if(record){record.revoked=true;await this.refreshStore.set(this.key("refresh",token),record,this.ttl(record.expiresAt))}}async rotateRefreshToken(oldToken,newRecord){await this.revokeRefreshToken(oldToken);newRecord.previousToken=oldToken;await this.storeRefreshToken(newRecord)}async cleanup(){}ttl(expiresAtMs){const ttl=Math.ceil((expiresAtMs-Date.now())/1e3);return{ttlSeconds:ttl>0?ttl:1}}key(type,id){const composite=`${type}:${id}`;return this.storageIsNamespaced?composite:`${this.namespace}:${composite}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_lazy_zod2=require("@frontmcp/lazy-zod");var credentialTypeSchema=import_lazy_zod2.z.enum(["oauth","api_key","basic","bearer","private_key","mtls","custom","ssh_key","service_account","oauth_pkce"]);var oauthCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("oauth"),accessToken:import_lazy_zod2.z.string(),refreshToken:import_lazy_zod2.z.string().optional(),tokenType:import_lazy_zod2.z.string().default("Bearer"),expiresAt:import_lazy_zod2.z.number().optional(),scopes:import_lazy_zod2.z.array(import_lazy_zod2.z.string()).default([]),idToken:import_lazy_zod2.z.string().optional()});var apiKeyCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("api_key"),key:import_lazy_zod2.z.string().min(1),headerName:import_lazy_zod2.z.string().default("X-API-Key"),headerPrefix:import_lazy_zod2.z.string().optional(),queryParam:import_lazy_zod2.z.string().optional()});var basicAuthCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("basic"),username:import_lazy_zod2.z.string().min(1),password:import_lazy_zod2.z.string(),encodedValue:import_lazy_zod2.z.string().optional()});var bearerCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("bearer"),token:import_lazy_zod2.z.string().min(1),expiresAt:import_lazy_zod2.z.number().optional()});var privateKeyCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("private_key"),format:import_lazy_zod2.z.enum(["pem","jwk","pkcs8","pkcs12"]),keyData:import_lazy_zod2.z.string(),keyId:import_lazy_zod2.z.string().optional(),algorithm:import_lazy_zod2.z.string().optional(),passphrase:import_lazy_zod2.z.string().optional(),certificate:import_lazy_zod2.z.string().optional()});var mtlsCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("mtls"),certificate:import_lazy_zod2.z.string(),privateKey:import_lazy_zod2.z.string(),passphrase:import_lazy_zod2.z.string().optional(),caCertificate:import_lazy_zod2.z.string().optional()});var customCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("custom"),customType:import_lazy_zod2.z.string().min(1),data:import_lazy_zod2.z.record(import_lazy_zod2.z.string(),import_lazy_zod2.z.unknown()),headers:import_lazy_zod2.z.record(import_lazy_zod2.z.string(),import_lazy_zod2.z.string()).optional()});var sshKeyCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("ssh_key"),privateKey:import_lazy_zod2.z.string().min(1),publicKey:import_lazy_zod2.z.string().optional(),passphrase:import_lazy_zod2.z.string().optional(),keyType:import_lazy_zod2.z.enum(["rsa","ed25519","ecdsa","dsa"]).default("ed25519"),fingerprint:import_lazy_zod2.z.string().optional(),username:import_lazy_zod2.z.string().optional()});var serviceAccountCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("service_account"),provider:import_lazy_zod2.z.enum(["gcp","aws","azure","custom"]),credentials:import_lazy_zod2.z.record(import_lazy_zod2.z.string(),import_lazy_zod2.z.unknown()),projectId:import_lazy_zod2.z.string().optional(),region:import_lazy_zod2.z.string().optional(),assumeRoleArn:import_lazy_zod2.z.string().optional(),externalId:import_lazy_zod2.z.string().optional(),serviceAccountId:import_lazy_zod2.z.string().optional(),expiresAt:import_lazy_zod2.z.number().optional()});var pkceOAuthCredentialSchema=import_lazy_zod2.z.object({type:import_lazy_zod2.z.literal("oauth_pkce"),accessToken:import_lazy_zod2.z.string(),refreshToken:import_lazy_zod2.z.string().optional(),tokenType:import_lazy_zod2.z.string().default("Bearer"),expiresAt:import_lazy_zod2.z.number().optional(),scopes:import_lazy_zod2.z.array(import_lazy_zod2.z.string()).default([]),idToken:import_lazy_zod2.z.string().optional(),issuer:import_lazy_zod2.z.string().optional()});var credentialSchema=import_lazy_zod2.z.discriminatedUnion("type",[oauthCredentialSchema,apiKeyCredentialSchema,basicAuthCredentialSchema,bearerCredentialSchema,privateKeyCredentialSchema,mtlsCredentialSchema,customCredentialSchema,sshKeyCredentialSchema,serviceAccountCredentialSchema,pkceOAuthCredentialSchema]);var appCredentialSchema=import_lazy_zod2.z.object({appId:import_lazy_zod2.z.string().min(1),providerId:import_lazy_zod2.z.string().min(1),credential:credentialSchema,acquiredAt:import_lazy_zod2.z.number(),lastUsedAt:import_lazy_zod2.z.number().optional(),expiresAt:import_lazy_zod2.z.number().optional(),isValid:import_lazy_zod2.z.boolean().default(true),invalidReason:import_lazy_zod2.z.string().optional(),userInfo:import_lazy_zod2.z.object({sub:import_lazy_zod2.z.string().optional(),email:import_lazy_zod2.z.string().optional(),name:import_lazy_zod2.z.string().optional()}).optional(),metadata:import_lazy_zod2.z.record(import_lazy_zod2.z.string(),import_lazy_zod2.z.unknown()).optional()});var vaultConsentRecordSchema=import_lazy_zod2.z.object({enabled:import_lazy_zod2.z.boolean(),selectedToolIds:import_lazy_zod2.z.array(import_lazy_zod2.z.string()),availableToolIds:import_lazy_zod2.z.array(import_lazy_zod2.z.string()),consentedAt:import_lazy_zod2.z.number(),version:import_lazy_zod2.z.string().default("1.0")});var vaultFederatedRecordSchema=import_lazy_zod2.z.object({selectedProviderIds:import_lazy_zod2.z.array(import_lazy_zod2.z.string()),skippedProviderIds:import_lazy_zod2.z.array(import_lazy_zod2.z.string()),primaryProviderId:import_lazy_zod2.z.string().optional(),completedAt:import_lazy_zod2.z.number()});var pendingIncrementalAuthSchema=import_lazy_zod2.z.object({id:import_lazy_zod2.z.string(),appId:import_lazy_zod2.z.string(),toolId:import_lazy_zod2.z.string().optional(),authUrl:import_lazy_zod2.z.string(),requiredScopes:import_lazy_zod2.z.array(import_lazy_zod2.z.string()).optional(),elicitId:import_lazy_zod2.z.string().optional(),createdAt:import_lazy_zod2.z.number(),expiresAt:import_lazy_zod2.z.number(),status:import_lazy_zod2.z.enum(["pending","completed","cancelled","expired"])});var authorizationVaultEntrySchema=import_lazy_zod2.z.object({id:import_lazy_zod2.z.string(),userSub:import_lazy_zod2.z.string(),userEmail:import_lazy_zod2.z.string().optional(),userName:import_lazy_zod2.z.string().optional(),clientId:import_lazy_zod2.z.string(),createdAt:import_lazy_zod2.z.number(),lastAccessAt:import_lazy_zod2.z.number(),appCredentials:import_lazy_zod2.z.record(import_lazy_zod2.z.string(),appCredentialSchema).default({}),consent:vaultConsentRecordSchema.optional(),federated:vaultFederatedRecordSchema.optional(),pendingAuths:import_lazy_zod2.z.array(pendingIncrementalAuthSchema),authorizedAppIds:import_lazy_zod2.z.array(import_lazy_zod2.z.string()),skippedAppIds:import_lazy_zod2.z.array(import_lazy_zod2.z.string())});var import_utils10=require("@frontmcp/utils");var import_lazy_zod3=require("@frontmcp/lazy-zod");var import_utils9=require("@frontmcp/utils");var encryptedDataSchema=import_lazy_zod3.z.object({v:import_lazy_zod3.z.literal(1),alg:import_lazy_zod3.z.literal("aes-256-gcm"),iv:import_lazy_zod3.z.string(),ct:import_lazy_zod3.z.string(),tag:import_lazy_zod3.z.string()});var VaultEncryption=class{pepper;hkdfInfo;constructor(config={}){this.pepper=new TextEncoder().encode(config.pepper??"");this.hkdfInfo=config.hkdfInfo??"frontmcp-vault-v1"}async deriveKey(claims){const ikmParts=[claims.jti,claims.vaultKey??"",claims.sub,claims.iat.toString(),new TextDecoder().decode(this.pepper)];const ikm=new TextEncoder().encode(ikmParts.join(""));const infoBytes=new TextEncoder().encode(this.hkdfInfo);const key=await(0,import_utils9.hkdfSha256)(ikm,new Uint8Array(0),infoBytes,32);return key}async deriveKeyFromToken(token,claims){const parts=token.split(".");const signature=parts[2]??"";const ikmParts=[claims.jti,claims.vaultKey??"",claims.sub,claims.iat.toString(),signature,new TextDecoder().decode(this.pepper)];const ikm=new TextEncoder().encode(ikmParts.join(""));const infoBytes=new TextEncoder().encode(this.hkdfInfo);const key=await(0,import_utils9.hkdfSha256)(ikm,new Uint8Array(0),infoBytes,32);return key}async encrypt(plaintext,key){if(key.length!==32){throw new Error("Encryption key must be 32 bytes")}const iv=(0,import_utils9.randomBytes)(12);const{ciphertext,tag}=await(0,import_utils9.encryptAesGcm)(key,new TextEncoder().encode(plaintext),iv);return{v:1,alg:"aes-256-gcm",iv:(0,import_utils9.base64urlEncode)(iv),ct:(0,import_utils9.base64urlEncode)(ciphertext),tag:(0,import_utils9.base64urlEncode)(tag)}}async decrypt(encrypted,key){if(key.length!==32){throw new Error("Encryption key must be 32 bytes")}const parsed=encryptedDataSchema.safeParse(encrypted);if(!parsed.success){throw new Error("Invalid encrypted data format")}const{iv,ct,tag}=parsed.data;const ivBuffer=(0,import_utils9.base64urlDecode)(iv);const ciphertext=(0,import_utils9.base64urlDecode)(ct);const tagBuffer=(0,import_utils9.base64urlDecode)(tag);try{const plaintext=await(0,import_utils9.decryptAesGcm)(key,ciphertext,ivBuffer,tagBuffer);return new TextDecoder().decode(plaintext)}catch(_error){throw new Error("Decryption failed: invalid key or corrupted data")}}async encryptObject(data,key){return this.encrypt(JSON.stringify(data),key)}async decryptObject(encrypted,key){const plaintext=await this.decrypt(encrypted,key);return JSON.parse(plaintext)}isEncrypted(data){return encryptedDataSchema.safeParse(data).success}};var encryptedVaultEntrySchema=import_lazy_zod3.z.object({id:import_lazy_zod3.z.string(),userSub:import_lazy_zod3.z.string(),userEmail:import_lazy_zod3.z.string().optional(),userName:import_lazy_zod3.z.string().optional(),clientId:import_lazy_zod3.z.string(),createdAt:import_lazy_zod3.z.number(),lastAccessAt:import_lazy_zod3.z.number(),encryptedData:encryptedDataSchema,authorizedAppIds:import_lazy_zod3.z.array(import_lazy_zod3.z.string()),skippedAppIds:import_lazy_zod3.z.array(import_lazy_zod3.z.string()),pendingAuthIds:import_lazy_zod3.z.array(import_lazy_zod3.z.string()).default([])});var DEFAULT_KEY_PREFIX="mcp:cred:";var DEFAULT_PENDING_TTL_MS=6e5;var SessionCredentialVault=class{storage;encryption;keyPrefix;ttlMs;pendingTtlMs;logger;keyCache=new Map;constructor(options){this.storage=options.storage;this.keyPrefix=options.keyPrefix??DEFAULT_KEY_PREFIX;this.ttlMs=options.ttlMs;this.pendingTtlMs=options.pendingTtlMs??DEFAULT_PENDING_TTL_MS;this.logger=options.logger??noopAuthLogger;const pepper=options.pepper??resolveVaultPepper(this.logger);this.encryption=new VaultEncryption({pepper,hkdfInfo:"frontmcp-session-credential-vault-v1"})}indexKey(sub){return`${this.keyPrefix}idx:${sub}`}keysKey(sub,vaultId){return`${this.keyPrefix}keys:${sub}:${vaultId}`}dataKey(sub,vaultId,key){return`${this.keyPrefix}data:${sub}:${vaultId}:${key}`}pendingKey(pendingId){return`${this.keyPrefix}pending:${pendingId}`}get credentialSetOpts(){return this.ttlMs?{ttlSeconds:Math.ceil(this.ttlMs/1e3)}:void 0}deriveKey(sub,vaultId){const cacheKey=`${sub}:${vaultId}`;const cached=this.keyCache.get(cacheKey);if(cached)return cached;const promise=this.encryption.deriveKey({jti:vaultId,vaultKey:vaultId,sub,iat:0});this.keyCache.set(cacheKey,promise);return promise}async getVaultId(sub){const raw=await this.storage.get(this.indexKey(sub));return raw??void 0}async rotateVault(sub){const vaultId=(0,import_utils10.randomUUID)();await this.storage.set(this.indexKey(sub),vaultId,this.credentialSetOpts);return vaultId}async store(sub,vaultId,key,value){const aesKey=await this.deriveKey(sub,vaultId);const enc=await this.encryption.encryptObject(this.normalize(value),aesKey);const record={enc};await this.storage.set(this.dataKey(sub,vaultId,key),JSON.stringify(record),this.credentialSetOpts);await this.addKeyToSet(sub,vaultId,key)}async get(sub,key){const vaultId=await this.getVaultId(sub);if(!vaultId)return void 0;const raw=await this.storage.get(this.dataKey(sub,vaultId,key));if(!raw)return void 0;try{const record=JSON.parse(raw);const aesKey=await this.deriveKey(sub,vaultId);return await this.encryption.decryptObject(record.enc,aesKey)}catch(err){this.logger.warn(`SessionCredentialVault: failed to read credential "${key}": ${errMsg(err)}`);return void 0}}async list(sub){const vaultId=await this.getVaultId(sub);if(!vaultId)return[];return this.readKeySet(sub,vaultId)}async remove(sub,key){const vaultId=await this.getVaultId(sub);if(!vaultId)return;await this.storage.delete(this.dataKey(sub,vaultId,key));const keys=await this.readKeySet(sub,vaultId);const next=keys.filter(k=>k!==key);if(next.length!==keys.length){await this.writeKeySet(sub,vaultId,next)}}async stage(pendingId,sub,credentials){const vaultId=await this.rotateVault(sub);const creds={};for(const cred of credentials){const aesKey=await this.deriveKey(sub,vaultId);const{key,...value}=cred;creds[key]={enc:await this.encryption.encryptObject(this.normalize(value),aesKey)}}const batch={sub,vaultId,creds};await this.storage.set(this.pendingKey(pendingId),JSON.stringify(batch),{ttlSeconds:Math.ceil(this.pendingTtlMs/1e3)});return vaultId}async commit(pendingId,sub){const raw=await this.storage.get(this.pendingKey(pendingId));if(!raw)return false;let batch;try{batch=JSON.parse(raw)}catch{await this.storage.delete(this.pendingKey(pendingId));return false}if(batch.sub!==sub){this.logger.warn("SessionCredentialVault: pending batch subject mismatch on commit; discarding");await this.storage.delete(this.pendingKey(pendingId));return false}await this.storage.set(this.indexKey(sub),batch.vaultId,this.credentialSetOpts);const keys=[];for(const[key,record]of Object.entries(batch.creds)){await this.storage.set(this.dataKey(sub,batch.vaultId,key),JSON.stringify(record),this.credentialSetOpts);keys.push(key)}await this.writeKeySet(sub,batch.vaultId,keys);await this.storage.delete(this.pendingKey(pendingId));return true}async readKeySet(sub,vaultId){const raw=await this.storage.get(this.keysKey(sub,vaultId));if(!raw)return[];try{const parsed=JSON.parse(raw);return Array.isArray(parsed)?parsed.filter(k=>typeof k==="string"):[]}catch{return[]}}async writeKeySet(sub,vaultId,keys){const unique=[...new Set(keys)];await this.storage.set(this.keysKey(sub,vaultId),JSON.stringify(unique),this.credentialSetOpts)}async addKeyToSet(sub,vaultId,key){const keys=await this.readKeySet(sub,vaultId);if(!keys.includes(key)){keys.push(key);await this.writeKeySet(sub,vaultId,keys)}}normalize(value){return value.metadata===void 0?{secret:value.secret}:{secret:value.secret,metadata:value.metadata}}};function resolveVaultPepper(logger){const fromEnv=(0,import_utils10.getEnv)("VAULT_SECRET")??(0,import_utils10.getEnv)("JWT_SECRET");if(fromEnv&&fromEnv.trim().length>0)return fromEnv;logger.warn("SessionCredentialVault: neither VAULT_SECRET nor JWT_SECRET is set; using a random per-process pepper. Stored credentials will NOT survive a restart and cannot be shared across instances. Set VAULT_SECRET (or JWT_SECRET) for persistent, multi-instance credential storage.");return(0,import_utils10.randomUUID)()+(0,import_utils10.randomUUID)()}function errMsg(err){return err instanceof Error?err.message:String(err)}var import_utils11=require("@frontmcp/utils");function isRedisTokenStorage(config){return typeof config==="object"&&config!==null&&"redis"in config&&!!config.redis}function isSqliteTokenStorage(config){return typeof config==="object"&&config!==null&&"sqlite"in config&&!!config.sqlite}function isPersistentTokenStorage(config){return config!==void 0&&config!=="memory"}async function createTokenStorageAdapter(config){if(config===void 0||config==="memory"){const adapter=new import_utils11.MemoryStorageAdapter;await adapter.connect();return adapter}if(isSqliteTokenStorage(config)){const{SqliteStorageAdapter}=require("@frontmcp/storage-sqlite");const adapter=new SqliteStorageAdapter({path:config.sqlite.path,encryption:config.sqlite.encryption,ttlCleanupIntervalMs:config.sqlite.ttlCleanupIntervalMs??6e4,walMode:config.sqlite.walMode??true,busyTimeoutMs:config.sqlite.busyTimeoutMs});await adapter.connect();return adapter}if(isRedisTokenStorage(config)){const{host,port,password,db,tls,keyPrefix}=config.redis;const adapter=new import_utils11.RedisStorageAdapter({config:{host,port,password,db,tls},keyPrefix:keyPrefix??""});await adapter.connect();return adapter}const fallback=new import_utils11.MemoryStorageAdapter;await fallback.connect();return fallback}async function createSessionCredentialVault(options){const storage=options.storage??await createTokenStorageAdapter(options.tokenStorage);const vault=new SessionCredentialVault({storage,pepper:options.pepper,keyPrefix:options.keyPrefix,ttlMs:options.ttlMs,logger:options.logger});const type=options.tokenStorage===void 0||options.tokenStorage==="memory"?"memory":"sqlite"in options.tokenStorage?"sqlite":"redis";return{vault,type}}var import_utils12=require("@frontmcp/utils");var DEFAULT_RESUME_TTL_MS=6e5;function signCredentialResumeToken(input,secret){const payload={sub:input.sub,key:input.key,...input.context!==void 0?{context:input.context}:{},exp:Date.now()+(input.ttlMs??DEFAULT_RESUME_TTL_MS)};const signedJson=(0,import_utils12.signData)(payload,{secret});return Buffer.from(signedJson,"utf8").toString("base64url")}function verifyCredentialResumeToken(token,secret,now=Date.now()){let signedJson;try{signedJson=Buffer.from(token,"base64url").toString("utf8")}catch{return null}const payload=(0,import_utils12.verifyData)(signedJson,{secret});if(!payload)return null;if(typeof payload.sub!=="string"||typeof payload.key!=="string"||!Number.isFinite(payload.exp)){return null}if(payload.context!==void 0&&typeof payload.context!=="string"){return null}if(now>=payload.exp){return null}return payload}function buildCredentialResumeUrl(basePath,token){const trimmed=basePath.endsWith("/")?basePath.slice(0,-1):basePath;return`${trimmed}/oauth/connect?token=${encodeURIComponent(token)}`}var import_utils13=require("@frontmcp/utils");var DEFAULT_INCREMENTAL_TICKET_TTL_MS=3e5;function signIncrementalAuthTicket(input,secret){const payload={sub:input.sub,appId:input.appId,...input.toolId!==void 0?{toolId:input.toolId}:{},...input.priorAppIds!==void 0?{priorAppIds:input.priorAppIds}:{},jti:(0,import_utils13.randomUUID)(),exp:Date.now()+(input.ttlMs??DEFAULT_INCREMENTAL_TICKET_TTL_MS)};const signedJson=(0,import_utils13.signData)(payload,{secret});return Buffer.from(signedJson,"utf8").toString("base64url")}function verifyIncrementalAuthTicket(token,secret,now=Date.now()){let signedJson;try{signedJson=Buffer.from(token,"base64url").toString("utf8")}catch{return null}const payload=(0,import_utils13.verifyData)(signedJson,{secret});if(!payload)return null;if(typeof payload.sub!=="string"||payload.sub.length===0)return null;if(typeof payload.appId!=="string"||payload.appId.length===0)return null;if(typeof payload.jti!=="string"||payload.jti.length===0)return null;if(!Number.isFinite(payload.exp))return null;if(payload.toolId!==void 0&&typeof payload.toolId!=="string")return null;if(payload.priorAppIds!==void 0&&(!Array.isArray(payload.priorAppIds)||payload.priorAppIds.some(id=>typeof id!=="string"))){return null}if(now>=payload.exp){return null}return payload}var CREDENTIALS_ACCESSOR=Symbol.for("frontmcp:CREDENTIALS_ACCESSOR");var CredentialsAccessorImpl=class{vault;resolveSub;signingSecret;basePath;resumeTtlMs;logger;constructor(deps){this.vault=deps.vault;this.resolveSub=deps.resolveSub;this.signingSecret=deps.signingSecret;this.basePath=deps.basePath;this.resumeTtlMs=deps.resumeTtlMs;this.logger=deps.logger??noopAuthLogger}async get(key){const sub=this.resolveSub();if(!sub)return void 0;return this.vault.get(sub,key)}async list(){const sub=this.resolveSub();if(!sub)return[];return this.vault.list(sub)}async requireConnect(options){const{key,context}=options;const sub=this.resolveSub();if(sub){const existing=await this.vault.get(sub,key);if(existing){return{connected:true,key,credential:existing}}}const token=signCredentialResumeToken({sub:sub??"",key,context,ttlMs:this.resumeTtlMs},this.signingSecret);const resumeUrl=buildCredentialResumeUrl(this.basePath,token);this.logger.debug(`CredentialsAccessor: credential "${key}" not connected; issued resume link`);return{connected:false,key,resumeUrl,message:`Credential "${key}" is not connected. Open the resume URL to connect it.`}}};var DEFAULT_KEY_PREFIX2="mcp:secret:";var EncryptedStorageSecureStoreBackend=class{storage;encryption;keyPrefix;logger;keyCache=new Map;constructor(options){this.storage=options.storage;this.keyPrefix=options.keyPrefix??DEFAULT_KEY_PREFIX2;this.logger=options.logger??noopAuthLogger;this.encryption=new VaultEncryption({pepper:options.pepper,hkdfInfo:"frontmcp-secure-store-v1"})}keysKey(namespace){return`${this.keyPrefix}keys:${namespace}`}dataKey(namespace,key){return`${this.keyPrefix}data:${namespace}:${key}`}deriveKey(namespace){const cached=this.keyCache.get(namespace);if(cached)return cached;const promise=this.encryption.deriveKey({jti:namespace,vaultKey:namespace,sub:namespace,iat:0});this.keyCache.set(namespace,promise);return promise}setOpts(ttlMs){return ttlMs&&ttlMs>0?{ttlSeconds:Math.ceil(ttlMs/1e3)}:void 0}async get(namespace,key){const raw=await this.storage.get(this.dataKey(namespace,key));if(!raw)return null;try{const record=JSON.parse(raw);const aesKey=await this.deriveKey(namespace);return await this.encryption.decrypt(record.enc,aesKey)}catch(err){this.logger.warn(`SecureStore: failed to read secret "${key}": ${errMsg2(err)}`);return null}}async set(namespace,key,value,ttlMs){const aesKey=await this.deriveKey(namespace);const enc=await this.encryption.encrypt(value,aesKey);const record={enc};const opts=this.setOpts(ttlMs);await this.storage.set(this.dataKey(namespace,key),JSON.stringify(record),opts);await this.addKeyToSet(namespace,key,opts)}async delete(namespace,key){const existed=await this.storage.delete(this.dataKey(namespace,key));const keys=await this.readKeySet(namespace);const next=keys.filter(k=>k!==key);if(next.length!==keys.length){await this.writeKeySet(namespace,next)}return existed}async list(namespace){return this.readKeySet(namespace)}async readKeySet(namespace){const raw=await this.storage.get(this.keysKey(namespace));if(!raw)return[];try{const parsed=JSON.parse(raw);return Array.isArray(parsed)?parsed.filter(k=>typeof k==="string"):[]}catch{return[]}}async writeKeySet(namespace,keys,opts){const unique=[...new Set(keys)];await this.storage.set(this.keysKey(namespace),JSON.stringify(unique),opts)}async addKeyToSet(namespace,key,opts){const keys=await this.readKeySet(namespace);if(!keys.includes(key)){keys.push(key);await this.writeKeySet(namespace,keys,opts)}}};function errMsg2(err){return err instanceof Error?err.message:String(err)}var SECURE_STORE_ACCESSOR=Symbol.for("frontmcp:SECURE_STORE_ACCESSOR");var import_utils14=require("@frontmcp/utils");var GLOBAL_NAMESPACE="global";var SecureStoreAccessorImpl=class{backend;scope;resolveSub;resolveSessionId;ttlMs;logger;constructor(deps){this.backend=deps.backend;this.scope=deps.scope??"user";this.resolveSub=deps.resolveSub;this.resolveSessionId=deps.resolveSessionId;this.ttlMs=deps.ttlMs;this.logger=deps.logger??noopAuthLogger}resolveNamespace(){switch(this.scope){case"global":return GLOBAL_NAMESPACE;case"session":{const sid=this.resolveSessionId();return sid?`s:${(0,import_utils14.sha256Hex)(sid).slice(0,32)}`:void 0}case"user":default:{const sub=this.resolveSub();return sub?`u:${(0,import_utils14.sha256Hex)(sub).slice(0,32)}`:void 0}}}async get(key){const namespace=this.resolveNamespace();if(!namespace)return void 0;const raw=await this.backend.get(namespace,key);if(raw===null)return void 0;try{return JSON.parse(raw)}catch(err){this.logger.warn(`SecureStore: failed to parse secret "${key}": ${errMsg3(err)}`);return void 0}}async set(key,value,options){const namespace=this.resolveNamespace();if(!namespace){this.logger.debug(`SecureStore: no ${this.scope} scope for request; skipping set("${key}")`);return}const ttlMs=options?.ttlMs??this.ttlMs;await this.backend.set(namespace,key,JSON.stringify(value),ttlMs)}async delete(key){const namespace=this.resolveNamespace();if(!namespace)return false;return this.backend.delete(namespace,key)}async list(){const namespace=this.resolveNamespace();if(!namespace)return[];return this.backend.list(namespace)}};function errMsg3(err){return err instanceof Error?err.message:String(err)}var import_utils15=require("@frontmcp/utils");function isCustomBackendConfig(config){return typeof config==="object"&&config!==null&&"backend"in config&&!!config.backend}function isSqliteConfig(config){return typeof config==="object"&&config!==null&&"sqlite"in config&&!!config.sqlite}function isRedisConfig(config){return typeof config==="object"&&config!==null&&"redis"in config&&!!config.redis}function readScope(config){if(typeof config==="object"&&config!==null&&"scope"in config&&config.scope){return config.scope}return"user"}function readTtlMs(config){if(typeof config==="object"&&config!==null&&"ttlMs"in config){return config.ttlMs}return void 0}function readPepper(config){if(typeof config==="object"&&config!==null&&"encryption"in config&&config.encryption){return config.encryption.pepper}return void 0}function toTokenStorageConfig(config){if(isSqliteConfig(config)){return{sqlite:config.sqlite}}if(isRedisConfig(config)){return{redis:config.redis}}return"memory"}async function createSecureStore(options){const{config,pepper,storage,logger}=options;const scope=readScope(config);const ttlMs=readTtlMs(config);if(isCustomBackendConfig(config)){return{backend:config.backend,scope,ttlMs,kind:"custom"}}const kind=isSqliteConfig(config)?"sqlite":isRedisConfig(config)?"redis":"memory";let adapter;if(storage){adapter=storage}else if(kind==="memory"){adapter=new import_utils15.MemoryStorageAdapter;await adapter.connect()}else{adapter=await createTokenStorageAdapter(toTokenStorageConfig(config))}const backend=new EncryptedStorageSecureStoreBackend({storage:adapter,pepper:readPepper(config)??pepper,logger});return{backend,scope,ttlMs,kind,...storage?{}:{close:()=>adapter.disconnect()}}}var import_utils16=require("@frontmcp/utils");var TokenVault=class{active;keys=new Map;constructor(keys){if(!Array.isArray(keys)||keys.length===0){throw new Error("TokenVault requires at least one key")}for(const k of keys){if(!(k.key instanceof Uint8Array)||k.key.length!==32){throw new Error(`TokenVault key "${k.kid}" must be a 32-byte Uint8Array for AES-256-GCM`)}if(this.keys.has(k.kid)){throw new Error(`TokenVault duplicate kid: "${k.kid}"`)}this.keys.set(k.kid,k.key)}this.active=keys[0]}rotateTo(k){if(!(k.key instanceof Uint8Array)||k.key.length!==32){throw new Error(`TokenVault key "${k.kid}" must be a 32-byte Uint8Array for AES-256-GCM`)}this.active=k;this.keys.set(k.kid,k.key)}async encrypt(plaintext,opts){const iv=(0,import_utils16.randomBytes)(12);const{ciphertext,tag}=await(0,import_utils16.encryptAesGcm)(this.active.key,new TextEncoder().encode(plaintext),iv);return{alg:"A256GCM",kid:this.active.kid,iv:(0,import_utils16.base64urlEncode)(iv),tag:(0,import_utils16.base64urlEncode)(tag),data:(0,import_utils16.base64urlEncode)(ciphertext),exp:opts?.exp,meta:opts?.meta}}async decrypt(blob){if(blob.exp!==void 0){const nowSeconds=Math.floor(Date.now()/1e3);if(nowSeconds>blob.exp){throw new Error(`vault_expired:${blob.kid}`)}}const key=this.keys.get(blob.kid);if(!key)throw new Error(`vault_unknown_kid:${blob.kid}`);const iv=(0,import_utils16.base64urlDecode)(blob.iv);const tag=(0,import_utils16.base64urlDecode)(blob.tag);const data=(0,import_utils16.base64urlDecode)(blob.data);const plaintext=await(0,import_utils16.decryptAesGcm)(key,data,iv,tag);return new TextDecoder().decode(plaintext)}};var import_utils36=require("@frontmcp/utils");var import_lazy_zod4=require("@frontmcp/lazy-zod");var transportProtocolSchema=import_lazy_zod4.z.enum(["legacy-sse","sse","streamable-http","stateful-http","stateless-http"]);var sseTransportStateSchema=import_lazy_zod4.z.object({type:import_lazy_zod4.z.literal("sse"),lastEventId:import_lazy_zod4.z.string().optional(),lastPing:import_lazy_zod4.z.number().optional(),connectionState:import_lazy_zod4.z.enum(["connecting","open","closed"]).optional()});var streamableHttpTransportStateSchema=import_lazy_zod4.z.object({type:import_lazy_zod4.z.literal("streamable-http"),requestSeq:import_lazy_zod4.z.number(),activeStreamId:import_lazy_zod4.z.string().optional(),pendingRequests:import_lazy_zod4.z.array(import_lazy_zod4.z.string()).optional()});var statefulHttpTransportStateSchema=import_lazy_zod4.z.object({type:import_lazy_zod4.z.literal("stateful-http"),requestSeq:import_lazy_zod4.z.number(),pendingResponses:import_lazy_zod4.z.array(import_lazy_zod4.z.string()).optional(),lastActivity:import_lazy_zod4.z.number().optional()});var statelessHttpTransportStateSchema=import_lazy_zod4.z.object({type:import_lazy_zod4.z.literal("stateless-http"),requestCount:import_lazy_zod4.z.number(),windowStart:import_lazy_zod4.z.number().optional()});var legacySseTransportStateSchema=import_lazy_zod4.z.object({type:import_lazy_zod4.z.literal("legacy-sse"),messagePath:import_lazy_zod4.z.string(),lastEventId:import_lazy_zod4.z.string().optional(),connectionState:import_lazy_zod4.z.enum(["connecting","open","closed"]).optional()});var transportStateSchema=import_lazy_zod4.z.discriminatedUnion("type",[sseTransportStateSchema,streamableHttpTransportStateSchema,statefulHttpTransportStateSchema,statelessHttpTransportStateSchema,legacySseTransportStateSchema]);var transportSessionSchema=import_lazy_zod4.z.object({id:import_lazy_zod4.z.string(),authorizationId:import_lazy_zod4.z.string(),protocol:transportProtocolSchema,createdAt:import_lazy_zod4.z.number(),expiresAt:import_lazy_zod4.z.number().optional(),nodeId:import_lazy_zod4.z.string(),clientFingerprint:import_lazy_zod4.z.string().optional(),transportState:transportStateSchema.optional()});var sessionJwtPayloadSchema=import_lazy_zod4.z.object({sid:import_lazy_zod4.z.string(),aid:import_lazy_zod4.z.string(),proto:transportProtocolSchema,nid:import_lazy_zod4.z.string(),iat:import_lazy_zod4.z.number(),exp:import_lazy_zod4.z.number().optional()});var encryptedBlobSchema=import_lazy_zod4.z.object({alg:import_lazy_zod4.z.literal("A256GCM"),kid:import_lazy_zod4.z.string().optional(),iv:import_lazy_zod4.z.string(),tag:import_lazy_zod4.z.string(),data:import_lazy_zod4.z.string(),exp:import_lazy_zod4.z.number().optional(),meta:import_lazy_zod4.z.record(import_lazy_zod4.z.string(),import_lazy_zod4.z.unknown()).optional()});var storedSessionSchema=import_lazy_zod4.z.object({session:transportSessionSchema,authorizationId:import_lazy_zod4.z.string(),tokens:import_lazy_zod4.z.record(import_lazy_zod4.z.string(),encryptedBlobSchema).optional(),createdAt:import_lazy_zod4.z.number(),lastAccessedAt:import_lazy_zod4.z.number(),initialized:import_lazy_zod4.z.boolean().optional(),maxLifetimeAt:import_lazy_zod4.z.number().optional(),clientCapabilities:import_lazy_zod4.z.record(import_lazy_zod4.z.string(),import_lazy_zod4.z.unknown()).optional(),reassignedAt:import_lazy_zod4.z.number().optional(),reassignedFrom:import_lazy_zod4.z.string().optional()});var redisConfigSchema=import_lazy_zod4.z.object({host:import_lazy_zod4.z.string().min(1),port:import_lazy_zod4.z.number().int().positive().optional().default(6379),password:import_lazy_zod4.z.string().optional(),db:import_lazy_zod4.z.number().int().nonnegative().optional().default(0),tls:import_lazy_zod4.z.boolean().optional().default(false),keyPrefix:import_lazy_zod4.z.string().optional().default("mcp:session:"),defaultTtlMs:import_lazy_zod4.z.number().int().positive().optional().default(36e5)});var import_utils18=require("@frontmcp/utils");var import_utils17=require("@frontmcp/utils");var AuthInternalError=class extends Error{errorId;isPublic=false;statusCode=500;code;constructor(message,code="AUTH_INTERNAL_ERROR"){super(message);this.name=this.constructor.name;this.code=code;this.errorId=`err_${(0,import_utils17.bytesToHex)((0,import_utils17.randomBytes)(8))}`;Error.captureStackTrace(this,this.constructor)}getPublicMessage(){return`Internal auth error. Please contact support with error ID: ${this.errorId}`}getInternalMessage(){return this.message}};var EncryptionContextNotSetError=class extends AuthInternalError{constructor(){super("Encryption context is not set","ENCRYPTION_CONTEXT_NOT_SET")}};var VaultLoadError=class extends AuthInternalError{originalError;constructor(vaultId,originalError){super(`Failed to load vault "${vaultId}"${originalError?`: ${originalError.message}`:""}`,"VAULT_LOAD_ERROR");this.originalError=originalError}};var VaultNotFoundError=class extends AuthInternalError{constructor(entityType,id){super(`${entityType} "${id}" not found in vault`,"VAULT_NOT_FOUND")}};var TokenNotAvailableError=class extends AuthInternalError{constructor(message){super(message,"TOKEN_NOT_AVAILABLE")}};var TokenStoreRequiredError=class extends AuthInternalError{constructor(context){super(`Token store is required for ${context}`,"TOKEN_STORE_REQUIRED")}};var NoProviderIdError=class extends AuthInternalError{constructor(message){super(message,"NO_PROVIDER_ID")}};var TokenLeakDetectedError=class extends AuthInternalError{constructor(detail){super(`Token leak detected: ${detail}`,"TOKEN_LEAK_DETECTED")}};var SessionSecretRequiredError=class extends AuthInternalError{constructor(component){super(`Session secret is required for ${component}`,"SESSION_SECRET_REQUIRED")}};var JwtSecretRequiredError=class extends AuthInternalError{constructor(mode){super(`JWT_SECRET is required in production for auth.mode "${mode}". Without it the server signs tokens with a random per-process secret, so every restart invalidates outstanding tokens and any second instance or isolate rejects tokens the first one minted.`,"JWT_SECRET_REQUIRED")}};var JwtSecretWeakError=class extends AuthInternalError{constructor(byteLength){super(`JWT_SECRET is ${byteLength} bytes; HS256 requires at least 32 (RFC 7518 \xA73.2). A shorter secret is guessable, and whoever guesses it can forge tokens for this server. Generate one with \`openssl rand -hex 32\`.`,"JWT_SECRET_INVALID")}};var CredentialProviderAlreadyRegisteredError=class extends AuthInternalError{constructor(name){super(`Credential provider "${name}" is already registered`,"CREDENTIAL_PROVIDER_ALREADY_REGISTERED")}};var AuthProvidersNotConfiguredError=class extends AuthInternalError{constructor(){super("Auth providers are not configured","AUTH_PROVIDERS_NOT_CONFIGURED")}};var OrchestratedAuthNotAvailableError=class extends AuthInternalError{constructor(){super("Orchestrated auth is not available","ORCHESTRATED_AUTH_NOT_AVAILABLE")}};var EncryptionKeyNotConfiguredError=class extends AuthInternalError{constructor(){super("Encryption key is not configured","ENCRYPTION_KEY_NOT_CONFIGURED")}};var SessionIdEmptyError=class extends AuthInternalError{constructor(storeName){super(`Session ID must not be empty (${storeName})`,"SESSION_ID_EMPTY")}};var ElicitationSecretRequiredError=class extends AuthInternalError{constructor(){super("Elicitation secret is required","ELICITATION_SECRET_REQUIRED")}};var ScopeDeniedError=class extends AuthInternalError{constructor(providerId){super(`Scope access denied for provider "${providerId}"`,"SCOPE_DENIED")}};var InMemoryStoreRequiredError=class extends AuthInternalError{constructor(component){super(`In-memory store is required for ${component}`,"INMEMORY_STORE_REQUIRED")}};var OrchestratorJwksNotAvailableError=class extends AuthInternalError{constructor(){super("Orchestrator JWKS is not available","ORCHESTRATOR_JWKS_NOT_AVAILABLE")}};var AuthInvalidInputError=class extends AuthInternalError{constructor(message){super(message,"AUTH_INVALID_INPUT")}};var CredentialStorageError=class extends AuthInternalError{constructor(message){super(message,"CREDENTIAL_STORAGE_ERROR")}};var AuthFlowError=class extends AuthInternalError{constructor(message,code="AUTH_FLOW_ERROR"){super(message,code)}};function getSigningSecret(config){const secret=config?.secret||(0,import_utils18.getEnv)("MCP_SESSION_SECRET");if(!secret){if((0,import_utils18.isProduction)()){throw new SessionSecretRequiredError("session signing")}console.warn("[SessionCrypto] MCP_SESSION_SECRET not set. Using insecure default for development only.");return"insecure-dev-secret-do-not-use-in-production"}return secret}function resolveConfig(config){return{secret:getSigningSecret(config)}}function signSession(session,config){return(0,import_utils18.signData)(session,resolveConfig(config))}function verifySession(signedData,config){return(0,import_utils18.verifyData)(signedData,resolveConfig(config))}function verifyOrParseSession(data,config){return(0,import_utils18.verifyOrParseData)(data,resolveConfig(config))}var SessionRateLimiter=class{windowMs;maxRequests;requests=new Map;cleanupIntervalMs;cleanupTimer=null;constructor(config={}){this.windowMs=config.windowMs??6e4;this.maxRequests=config.maxRequests??100;this.cleanupIntervalMs=config.cleanupIntervalMs??6e4}ensureCleanupTimer(){if(this.cleanupTimer||this.cleanupIntervalMs<=0)return;this.cleanupTimer=setInterval(()=>this.cleanup(),this.cleanupIntervalMs);if(typeof this.cleanupTimer.unref==="function")this.cleanupTimer.unref()}check(key){this.ensureCleanupTimer();const now=Date.now();const windowStart=now-this.windowMs;let timestamps=this.requests.get(key);if(!timestamps){timestamps=[];this.requests.set(key,timestamps)}const validTimestamps=timestamps.filter(t=>t>windowStart);const oldestInWindow=validTimestamps[0]??now;const resetAt=oldestInWindow+this.windowMs;if(validTimestamps.length>=this.maxRequests){return{allowed:false,remaining:0,resetAt,retryAfterMs:resetAt-now}}validTimestamps.push(now);this.requests.set(key,validTimestamps);return{allowed:true,remaining:this.maxRequests-validTimestamps.length,resetAt}}wouldAllow(key){const now=Date.now();const windowStart=now-this.windowMs;const timestamps=this.requests.get(key);if(!timestamps)return true;const validCount=timestamps.filter(t=>t>windowStart).length;return validCount<this.maxRequests}reset(key){this.requests.delete(key)}cleanup(){const now=Date.now();const windowStart=now-this.windowMs;for(const[key,timestamps]of this.requests.entries()){const valid=timestamps.filter(t=>t>windowStart);if(valid.length===0){this.requests.delete(key)}else if(valid.length<timestamps.length){this.requests.set(key,valid)}}}getStats(){let totalRequests=0;for(const timestamps of this.requests.values()){totalRequests+=timestamps.length}return{totalKeys:this.requests.size,totalRequests}}dispose(){if(this.cleanupTimer){clearInterval(this.cleanupTimer);this.cleanupTimer=null}this.requests.clear()}};var defaultSessionRateLimiter=new SessionRateLimiter;var import_utils19=require("@frontmcp/utils");var TransportIdGenerator=class{static createId(){return(0,import_utils19.randomUUID)().replace(/-/g,"")}};var TinyTtlCache=class{constructor(ttlMs){this.ttlMs=ttlMs}ttlMs;map=new Map;get(k){const hit=this.map.get(k);if(!hit)return void 0;if(hit.exp<Date.now()){this.map.delete(k);return void 0}return hit.v}set(k,v){this.map.set(k,{v,exp:Date.now()+this.ttlMs})}delete(k){return this.map.delete(k)}clear(){this.map.clear()}size(){return this.map.size}cleanup(){const now=Date.now();let removed=0;for(const[k,{exp}]of this.map){if(exp<now){this.map.delete(k);removed++}}return removed}};var import_utils20=require("@frontmcp/utils");function isJwt(token){if(!token)return false;return token.split(".").length===3}function getTokenSignatureFingerprint(token){if(isJwt(token)){const sig=token.split(".")[2];if(sig)return sig}return(0,import_utils20.sha256Base64url)(token)}function extractClaimValue(claims,key,validator){const value=claims[key];return validator(value)?value:void 0}var isString=value=>typeof value==="string";var isNumber=value=>typeof value==="number";var isStringOrStringArray=value=>typeof value==="string"||Array.isArray(value);function deriveTypedUser(claims){return{...claims,iss:extractClaimValue(claims,"iss",isString)??"",sid:extractClaimValue(claims,"sid",isString),sub:extractClaimValue(claims,"sub",isString)??extractClaimValue(claims,"client_id",isString)??extractClaimValue(claims,"azp",isString)??"",exp:extractClaimValue(claims,"exp",isNumber),iat:extractClaimValue(claims,"iat",isNumber),aud:extractClaimValue(claims,"aud",isStringOrStringArray),email:extractClaimValue(claims,"email",isString),preferred_username:extractClaimValue(claims,"preferred_username",isString),username:extractClaimValue(claims,"username",isString),name:extractClaimValue(claims,"name",isString),picture:extractClaimValue(claims,"picture",isString)}}function anonymousCallerClaims(options,anonymousId){const{issuer,scopes=["anonymous"],subject}=options;return{sub:subject??`anon:${anonymousId}`,iss:issuer,name:subject?"Static token":"Anonymous",scope:scopes.join(" ")}}function extractBearerToken(header){if(!header)return void 0;const m=header.match(/^\s*Bearer\s+(\S+)\s*$/i);return m?m[1]:void 0}var import_utils21=require("@frontmcp/utils");var cachedKey=null;function getKey(){if(cachedKey)return cachedKey;const secret=(0,import_utils21.getEnv)("MCP_SESSION_SECRET");if(!secret){if((0,import_utils21.isProduction)()){throw new SessionSecretRequiredError("session ID encryption")}console.warn("[SessionIdUtils] Using machine ID as session encryption secret - NOT SECURE FOR PRODUCTION. Set MCP_SESSION_SECRET environment variable for secure session encryption.")}const base=secret||(0,import_utils21.getMachineId)();cachedKey=(0,import_utils21.sha256)(new TextEncoder().encode(base));return cachedKey}function encryptJson(obj){const key=getKey();const encrypted=(0,import_utils21.encryptValue)(obj,key);return`${encrypted.iv}.${encrypted.tag}.${encrypted.data}`}function decryptSessionJson(sessionId){const parts=sessionId.split(".");if(parts.length!==3)return null;const[ivB64,tagB64,ctB64]=parts;if(!ivB64||!tagB64||!ctB64)return null;const key=getKey();return(0,import_utils21.decryptValue)({alg:"A256GCM",iv:ivB64,tag:tagB64,data:ctB64},key)}function safeDecrypt(sessionId){try{return decryptSessionJson(sessionId)}catch{return null}}function resetCachedKey(){cachedKey=null}var import_utils25=require("@frontmcp/utils");var import_utils26=require("@frontmcp/utils");var import_utils22=require("@frontmcp/utils");var StorageTokenStore=class{storage;namespace;defaultTtlSeconds;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"tok";this.defaultTtlSeconds=options.defaultTtlSeconds;this.storageIsNamespaced="namespace"in storage&&typeof storage.namespace==="function";const namespacedStorage=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.storage=new import_utils22.TypedStorage(namespacedStorage)}allocId(){return(0,import_utils22.randomUUID)()}async put(id,blob){const record={id,blob,updatedAt:Date.now()};const ttlSeconds=this.calculateTtl(blob.exp);await this.storage.set(this.key(id),record,ttlSeconds?{ttlSeconds}:void 0)}async get(id){const record=await this.storage.get(this.key(id));return record??void 0}async del(id){await this.storage.delete(this.key(id))}calculateTtl(exp){if(exp){const nowSeconds=Math.floor(Date.now()/1e3);const ttl=exp-nowSeconds;return ttl>0?ttl:1}return this.defaultTtlSeconds}key(id){return this.storageIsNamespaced?id:`${this.namespace}:${id}`}};var import_utils23=require("@frontmcp/utils");var StorageAuthorizationVault=class{storage;namespace;pendingAuthTtlMs;constructor(storage,options={}){this.namespace=options.namespace??"vault";this.pendingAuthTtlMs=options.pendingAuthTtlMs??10*60*1e3;const namespacedStorage=this.isNamespacedStorage(storage)?storage.namespace(this.namespace):storage;this.storage=new import_utils23.TypedStorage(namespacedStorage,{schema:options.validateOnRead?authorizationVaultEntrySchema:void 0,throwOnInvalid:false})}async create(params){const now=Date.now();const entry={id:(0,import_utils23.randomUUID)(),userSub:params.userSub,userEmail:params.userEmail,userName:params.userName,clientId:params.clientId,createdAt:now,lastAccessAt:now,appCredentials:{},consent:params.consent,federated:params.federated,pendingAuths:[],authorizedAppIds:params.authorizedAppIds??[],skippedAppIds:params.skippedAppIds??[]};await this.storage.set(this.key(entry.id),entry);return entry}async get(id){return this.storage.get(this.key(id))}async update(id,updates){const entry=await this.get(id);if(!entry){console.warn(`[StorageAuthorizationVault] Update failed: vault entry not found for id ${id}`);return}const updated={...entry,...updates,lastAccessAt:Date.now()};await this.storage.set(this.key(id),updated)}async delete(id){await this.storage.delete(this.key(id))}async updateConsent(vaultId,consent){const entry=await this.get(vaultId);if(!entry)return;entry.consent=consent;entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async authorizeApp(vaultId,appId){const entry=await this.get(vaultId);if(!entry)return;entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==appId);if(!entry.authorizedAppIds.includes(appId)){entry.authorizedAppIds.push(appId)}entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async isAppAuthorized(vaultId,appId){const entry=await this.get(vaultId);if(!entry)return false;return entry.authorizedAppIds.includes(appId)}async createPendingAuth(vaultId,params){const entry=await this.get(vaultId);if(!entry){throw new Error(`Vault not found: ${vaultId}`)}const now=Date.now();const pendingAuth={id:(0,import_utils23.randomUUID)(),appId:params.appId,toolId:params.toolId,authUrl:params.authUrl,requiredScopes:params.requiredScopes,elicitId:params.elicitId,createdAt:now,expiresAt:now+(params.ttlMs??this.pendingAuthTtlMs),status:"pending"};entry.pendingAuths.push(pendingAuth);entry.lastAccessAt=now;await this.storage.set(this.key(vaultId),entry);return pendingAuth}async getPendingAuth(vaultId,pendingAuthId){const entry=await this.get(vaultId);if(!entry)return null;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(!pendingAuth)return null;if(Date.now()>pendingAuth.expiresAt&&pendingAuth.status==="pending"){pendingAuth.status="expired";await this.storage.set(this.key(vaultId),entry)}return pendingAuth}async completePendingAuth(vaultId,pendingAuthId){const entry=await this.get(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="completed";entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==pendingAuth.appId);if(!entry.authorizedAppIds.includes(pendingAuth.appId)){entry.authorizedAppIds.push(pendingAuth.appId)}entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}}async cancelPendingAuth(vaultId,pendingAuthId){const entry=await this.get(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="cancelled";await this.storage.set(this.key(vaultId),entry)}}async getPendingAuths(vaultId){const entry=await this.get(vaultId);if(!entry)return[];const now=Date.now();let updated=false;const pending=entry.pendingAuths.filter(p=>{if(now>p.expiresAt&&p.status==="pending"){p.status="expired";updated=true}return p.status==="pending"});if(updated){await this.storage.set(this.key(vaultId),entry)}return pending}credentialKey(appId,providerId){return`${appId}:${providerId}`}async addAppCredential(vaultId,credential){const entry=await this.get(vaultId);if(!entry)return;const shouldStore=await this.shouldStoreCredential(vaultId,credential.appId);if(!shouldStore){return}const key=this.credentialKey(credential.appId,credential.providerId);entry.appCredentials[key]=credential;entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async removeAppCredential(vaultId,appId,providerId){const entry=await this.get(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);delete entry.appCredentials[key];entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async getAppCredentials(vaultId,appId){const entry=await this.get(vaultId);if(!entry)return[];const prefix=`${appId}:`;return Object.entries(entry.appCredentials).filter(([key])=>key.startsWith(prefix)).map(([,cred])=>cred)}async getCredential(vaultId,appId,providerId){const entry=await this.get(vaultId);if(!entry)return null;const key=this.credentialKey(appId,providerId);return entry.appCredentials[key]??null}async getAllCredentials(vaultId,filterByConsent=false){const entry=await this.get(vaultId);if(!entry)return[];const allCredentials=Object.values(entry.appCredentials);if(!filterByConsent||!entry.consent?.enabled){return allCredentials}const consentedToolIds=new Set(entry.consent.selectedToolIds);return allCredentials.filter(cred=>{return Array.from(consentedToolIds).some(toolId=>toolId.startsWith(`${cred.appId}:`))})}async updateCredential(vaultId,appId,providerId,updates){const entry=await this.get(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential)return;Object.assign(credential,updates);entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async shouldStoreCredential(vaultId,appId,toolIds){const entry=await this.get(vaultId);if(!entry)return false;const consent=entry.consent;if(!consent?.enabled){return true}if(toolIds&&toolIds.length>0){return toolIds.some(toolId=>consent.selectedToolIds.includes(toolId))}const consentedToolIds=consent.selectedToolIds;return consentedToolIds.some(toolId=>toolId.startsWith(`${appId}:`))}async invalidateCredential(vaultId,appId,providerId,reason){await this.updateCredential(vaultId,appId,providerId,{isValid:false,invalidReason:reason})}async refreshOAuthCredential(vaultId,appId,providerId,tokens){const entry=await this.get(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential||credential.credential.type!=="oauth"&&credential.credential.type!=="oauth_pkce")return;credential.credential.accessToken=tokens.accessToken;if(tokens.refreshToken!==void 0){credential.credential.refreshToken=tokens.refreshToken}if(tokens.expiresAt!==void 0){credential.credential.expiresAt=tokens.expiresAt;credential.expiresAt=tokens.expiresAt}credential.isValid=true;credential.invalidReason=void 0;entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async cleanup(){const keys=await this.storage.keys("*");const now=Date.now();for(const key of keys){const entry=await this.storage.get(key);if(!entry)continue;const originalLength=entry.pendingAuths.length;entry.pendingAuths=entry.pendingAuths.filter(p=>{if(now>p.expiresAt&&p.status==="pending"){p.status="expired"}return p.status==="pending"});if(entry.pendingAuths.length!==originalLength){await this.storage.set(key,entry)}}}key(id){return this.isNamespacedStorage(this.storage.raw)?id:`${this.namespace}:${id}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_utils24=require("@frontmcp/utils");var InMemoryAuthorizationVault=class extends StorageAuthorizationVault{memoryAdapter;constructor(options={}){const memoryAdapter=new import_utils24.MemoryStorageAdapter;super(memoryAdapter,{namespace:options.namespace??"vault",pendingAuthTtlMs:options.pendingAuthTtlMs});this.memoryAdapter=memoryAdapter;void this.memoryAdapter.connect()}async clear(){const keys=await this.memoryAdapter.keys("*");for(const key of keys){await this.memoryAdapter.delete(key)}}};var import_utils27=require("@frontmcp/utils");var RedisSessionStore=class{storage;keyPrefix;defaultTtlMs;logger;externalInstance=false;security;rateLimiter;constructor(config,logger){this.defaultTtlMs=("defaultTtlMs"in config?config.defaultTtlMs:void 0)??36e5;this.logger=logger;this.keyPrefix=("keyPrefix"in config?config.keyPrefix:void 0)??"mcp:session:";this.security=("security"in config?config.security:void 0)??{};if(this.security.enableRateLimiting){this.rateLimiter=new SessionRateLimiter({windowMs:this.security.rateLimiting?.windowMs,maxRequests:this.security.rateLimiting?.maxRequests})}if("redis"in config&&config.redis){this.storage=new import_utils27.RedisStorageAdapter({client:config.redis,keyPrefix:this.keyPrefix});this.externalInstance=true}else{const redisConfig=config;this.storage=new import_utils27.RedisStorageAdapter({config:{host:redisConfig.host,port:redisConfig.port??6379,password:redisConfig.password,db:redisConfig.db??0,tls:redisConfig.tls},keyPrefix:this.keyPrefix})}}validateSessionId(sessionId){if(!sessionId||sessionId.trim()===""){throw new SessionIdEmptyError("RedisSessionStore")}}async ensureConnected(){await this.storage.connect()}async get(sessionId,options){this.validateSessionId(sessionId);if(this.rateLimiter){const rateLimitKey=options?.clientIdentifier||sessionId;const rateLimitResult=this.rateLimiter.check(rateLimitKey);if(!rateLimitResult.allowed){this.logger?.warn("[RedisSessionStore] Rate limit exceeded for session lookup",{sessionId:sessionId.slice(0,20),clientIdentifier:options?.clientIdentifier?options.clientIdentifier.slice(0,20):void 0,retryAfterMs:rateLimitResult.retryAfterMs});return null}}await this.ensureConnected();let raw;const redis=this.storage.getClient();const ttlSeconds=Math.ceil(this.defaultTtlMs/1e3);if(redis){try{raw=await redis.getex(this.keyPrefix+sessionId,"EX",ttlSeconds)}catch{raw=await this.storage.get(sessionId);if(raw){await this.storage.expire(sessionId,ttlSeconds)}}}else{raw=await this.storage.get(sessionId);if(raw){await this.storage.expire(sessionId,ttlSeconds)}}if(!raw)return null;try{let parsed;if(this.security.enableSigning){parsed=verifyOrParseSession(raw,{secret:this.security.signingSecret});if(!parsed){this.logger?.warn("[RedisSessionStore] Session signature verification failed",{sessionId:sessionId.slice(0,20)});this.delete(sessionId).catch(()=>void 0);return null}}else{parsed=JSON.parse(raw)}const result=storedSessionSchema.safeParse(parsed);if(!result.success){this.logger?.warn("[RedisSessionStore] Invalid session format",{sessionId:sessionId.slice(0,20),errors:result.error.issues.slice(0,3).map(i=>({path:i.path,message:i.message}))});this.delete(sessionId).catch(()=>void 0);return null}const session=result.data;if(session.maxLifetimeAt&&session.maxLifetimeAt<Date.now()){this.logger?.info("[RedisSessionStore] Session exceeded max lifetime",{sessionId:sessionId.slice(0,20),maxLifetimeAt:session.maxLifetimeAt});await this.delete(sessionId);return null}if(session.session.expiresAt&&session.session.expiresAt<Date.now()){await this.delete(sessionId);return null}if(session.session.expiresAt){const ttlMs=Math.min(this.defaultTtlMs,session.session.expiresAt-Date.now());if(ttlMs>0&&ttlMs<this.defaultTtlMs){const boundedTtlSeconds=Math.ceil(ttlMs/1e3);this.storage.expire(sessionId,boundedTtlSeconds).catch(err=>{this.logger?.warn("[RedisSessionStore] TTL extension failed",{sessionId:sessionId.slice(0,20),error:err.message})})}}const updatedSession={...session,lastAccessedAt:Date.now()};return updatedSession}catch(error){this.logger?.warn("[RedisSessionStore] Failed to parse session",{sessionId:sessionId.slice(0,20),error:error.message});this.delete(sessionId).catch(()=>void 0);return null}}async set(sessionId,session,ttlMs){this.validateSessionId(sessionId);await this.ensureConnected();let value;if(this.security.enableSigning){value=signSession(session,{secret:this.security.signingSecret})}else{value=JSON.stringify(session)}if(ttlMs&&ttlMs>0){const ttlSeconds=Math.ceil(ttlMs/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else if(session.session.expiresAt){const ttl=session.session.expiresAt-Date.now();if(ttl>0){const ttlSeconds=Math.ceil(ttl/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else{await this.storage.set(sessionId,value)}}else{await this.storage.set(sessionId,value)}}async delete(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();await this.storage.delete(sessionId)}async exists(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();return this.storage.exists(sessionId)}allocId(){return(0,import_utils27.randomUUID)()}async disconnect(){if(!this.externalInstance){await this.storage.disconnect()}}getRedisClient(){return this.storage.getClient()}async ping(){try{await this.ensureConnected();return this.storage.ping()}catch(error){this.logger?.error("[RedisSessionStore] Connection failed",{error:error.message});return false}}};var import_utils28=require("@frontmcp/utils");var VercelKvSessionStore=class{storage;keyPrefix;defaultTtlMs;logger;security;rateLimiter;constructor(config,logger){this.keyPrefix=config.keyPrefix??"mcp:session:";this.defaultTtlMs=config.defaultTtlMs??36e5;this.logger=logger;this.security=("security"in config?config.security:void 0)??{};if(this.security.enableRateLimiting){this.rateLimiter=new SessionRateLimiter({windowMs:this.security.rateLimiting?.windowMs,maxRequests:this.security.rateLimiting?.maxRequests})}this.storage=new import_utils28.VercelKvStorageAdapter({url:config.url,token:config.token,keyPrefix:this.keyPrefix})}validateSessionId(sessionId){if(!sessionId||sessionId.trim()===""){throw new SessionIdEmptyError("VercelKvSessionStore")}}async connect(){await this.storage.connect()}async ensureConnected(){await this.storage.connect()}async get(sessionId,options){this.validateSessionId(sessionId);if(this.rateLimiter){const rateLimitKey=options?.clientIdentifier||sessionId;const rateLimitResult=this.rateLimiter.check(rateLimitKey);if(!rateLimitResult.allowed){this.logger?.warn("[VercelKvSessionStore] Rate limit exceeded for session lookup",{sessionId:sessionId.slice(0,20),clientIdentifier:options?.clientIdentifier?options.clientIdentifier.slice(0,20):void 0,retryAfterMs:rateLimitResult.retryAfterMs});return null}}await this.ensureConnected();const raw=await this.storage.get(sessionId);if(!raw)return null;const ttlSeconds=Math.ceil(this.defaultTtlMs/1e3);this.storage.expire(sessionId,ttlSeconds).catch(err=>{this.logger?.warn("[VercelKvSessionStore] TTL extension failed",{sessionId:sessionId.slice(0,20),error:err.message})});try{let parsed;if(this.security.enableSigning){parsed=verifyOrParseSession(raw,{secret:this.security.signingSecret});if(!parsed){this.logger?.warn("[VercelKvSessionStore] Session signature verification failed",{sessionId:sessionId.slice(0,20)});this.delete(sessionId).catch(()=>void 0);return null}}else{parsed=JSON.parse(raw)}const result=storedSessionSchema.safeParse(parsed);if(!result.success){this.logger?.warn("[VercelKvSessionStore] Invalid session format",{sessionId:sessionId.slice(0,20),errors:result.error.issues.slice(0,3).map(i=>({path:i.path,message:i.message}))});this.delete(sessionId).catch(()=>void 0);return null}const session=result.data;if(session.maxLifetimeAt&&session.maxLifetimeAt<Date.now()){this.logger?.info("[VercelKvSessionStore] Session exceeded max lifetime",{sessionId:sessionId.slice(0,20),maxLifetimeAt:session.maxLifetimeAt});await this.delete(sessionId);return null}if(session.session.expiresAt&&session.session.expiresAt<Date.now()){await this.delete(sessionId);return null}if(session.session.expiresAt){const ttlMs=Math.min(this.defaultTtlMs,session.session.expiresAt-Date.now());if(ttlMs>0&&ttlMs<this.defaultTtlMs){const boundedTtlSeconds=Math.ceil(ttlMs/1e3);this.storage.expire(sessionId,boundedTtlSeconds).catch(err=>{this.logger?.warn("[VercelKvSessionStore] TTL bound extension failed",{sessionId:sessionId.slice(0,20),error:err.message})})}}const updatedSession={...session,lastAccessedAt:Date.now()};return updatedSession}catch(error){this.logger?.warn("[VercelKvSessionStore] Failed to parse session",{sessionId:sessionId.slice(0,20),error:error.message});this.delete(sessionId).catch(()=>void 0);return null}}async set(sessionId,session,ttlMs){this.validateSessionId(sessionId);await this.ensureConnected();let value;if(this.security.enableSigning){value=signSession(session,{secret:this.security.signingSecret})}else{value=JSON.stringify(session)}if(ttlMs&&ttlMs>0){const ttlSeconds=Math.ceil(ttlMs/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else if(session.session.expiresAt){const ttl=session.session.expiresAt-Date.now();if(ttl>0){const ttlSeconds=Math.ceil(ttl/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else{await this.storage.set(sessionId,value)}}else{await this.storage.set(sessionId,value)}}async delete(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();await this.storage.delete(sessionId)}async exists(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();return this.storage.exists(sessionId)}allocId(){return(0,import_utils28.randomUUID)()}async disconnect(){await this.storage.disconnect()}async ping(){try{await this.ensureConnected();return this.storage.ping()}catch(error){this.logger?.error("[VercelKvSessionStore] Connection failed",{error:error.message});return false}}};var import_utils30=require("@frontmcp/utils");var import_utils29=require("@frontmcp/utils");function recordDropAt(record){if(!record.refreshToken)return record.expiresAt;return Math.max(record.expiresAt??0,record.updatedAt+REFRESH_TOKEN_TTL_MS)}function hasLiveAccessToken(record,refreshSkewMs=0){if(record.expiresAt===void 0)return true;return record.expiresAt-(record.refreshToken?refreshSkewMs:0)>Date.now()}var HKDF_SALT=new TextEncoder().encode("frontmcp-token-store");function deriveKeyForRecord(masterKey,compositeKey,cache){const cached=cache.get(compositeKey);if(cached){return cached}const info=new TextEncoder().encode(`orchestrated-token:${compositeKey}`);const derived=(0,import_utils29.hkdfSha256)(masterKey,HKDF_SALT,info,32);cache.set(compositeKey,derived);return derived}function encryptRecord(key,record){const plaintext=JSON.stringify(record);const iv=(0,import_utils29.randomBytes)(12);const{ciphertext,tag}=(0,import_utils29.encryptAesGcm)(key,new TextEncoder().encode(plaintext),iv);return JSON.stringify({iv:Buffer.from(iv).toString("base64url"),tag:Buffer.from(tag).toString("base64url"),data:Buffer.from(ciphertext).toString("base64url")})}function decryptRecord(key,encrypted){const{iv,tag,data}=JSON.parse(encrypted);const ivBytes=Buffer.from(iv,"base64url");const tagBytes=Buffer.from(tag,"base64url");const ciphertextBytes=Buffer.from(data,"base64url");const plaintext=(0,import_utils29.decryptAesGcm)(key,ciphertextBytes,ivBytes,tagBytes);return JSON.parse(new TextDecoder().decode(plaintext))}var InMemoryOrchestratedTokenStore=class{tokens=new Map;encryptionKey;derivedKeys=new Map;cleanupTimer;defaultTtlMs;refreshSkewMs;constructor(options={}){this.encryptionKey=options.encryptionKey;this.defaultTtlMs=options.defaultTtlMs;this.refreshSkewMs=options.refreshSkewMs??0;const cleanupIntervalMs=options.cleanupIntervalMs??6e4;this.cleanupTimer=setInterval(()=>{void this.cleanup()},cleanupIntervalMs);if(this.cleanupTimer.unref){this.cleanupTimer.unref()}}buildKey(authorizationId,providerId){return`${authorizationId}:${providerId}`}async deriveKeyForRecord(compositeKey){if(!this.encryptionKey){throw new EncryptionKeyNotConfiguredError}const cached=this.derivedKeys.get(compositeKey);if(cached){return cached}const info=new TextEncoder().encode(`orchestrated-token:${compositeKey}`);const salt=new TextEncoder().encode("frontmcp-token-store");const derivedKey=(0,import_utils30.hkdfSha256)(this.encryptionKey,salt,info,32);this.derivedKeys.set(compositeKey,derivedKey);return derivedKey}async encryptRecord(compositeKey,record){const key=await this.deriveKeyForRecord(compositeKey);const plaintext=JSON.stringify(record);const iv=(0,import_utils30.randomBytes)(12);const{ciphertext,tag}=(0,import_utils30.encryptAesGcm)(key,new TextEncoder().encode(plaintext),iv);return JSON.stringify({iv:Buffer.from(iv).toString("base64url"),tag:Buffer.from(tag).toString("base64url"),data:Buffer.from(ciphertext).toString("base64url")})}async decryptRecord(compositeKey,encrypted){const key=await this.deriveKeyForRecord(compositeKey);const{iv,tag,data}=JSON.parse(encrypted);const ivBytes=Buffer.from(iv,"base64url");const tagBytes=Buffer.from(tag,"base64url");const ciphertextBytes=Buffer.from(data,"base64url");const plaintext=(0,import_utils30.decryptAesGcm)(key,ciphertextBytes,ivBytes,tagBytes);return JSON.parse(new TextDecoder().decode(plaintext))}async getRecord(authorizationId,providerId){const key=this.buildKey(authorizationId,providerId);const stored=this.tokens.get(key);if(!stored){return null}let record;if(this.encryptionKey){if(typeof stored!=="string"){return null}try{record=await this.decryptRecord(key,stored)}catch{this.tokens.delete(key);return null}}else{record=stored}const dropAt=recordDropAt(record);if(dropAt&&dropAt<Date.now()){this.tokens.delete(key);return null}return record}async getAccessToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record&&hasLiveAccessToken(record,this.refreshSkewMs)?record.accessToken:null}async getRefreshToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record?.refreshToken??null}async storeTokens(authorizationId,providerId,tokens){const key=this.buildKey(authorizationId,providerId);const now=Date.now();const record={accessToken:tokens.accessToken,refreshToken:tokens.refreshToken,expiresAt:tokens.expiresAt??(this.defaultTtlMs?now+this.defaultTtlMs:void 0),createdAt:now,updatedAt:now};if(this.encryptionKey){const encrypted=await this.encryptRecord(key,record);this.tokens.set(key,encrypted)}else{this.tokens.set(key,record)}}async deleteTokens(authorizationId,providerId){const key=this.buildKey(authorizationId,providerId);this.tokens.delete(key);this.derivedKeys.delete(key)}async hasTokens(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record!==null}async deleteAllForAuthorization(authorizationId){const prefix=`${authorizationId}:`;for(const key of this.tokens.keys()){if(key.startsWith(prefix)){this.tokens.delete(key);this.derivedKeys.delete(key)}}}async getProviderIds(authorizationId){const prefix=`${authorizationId}:`;const providerIds=[];for(const key of this.tokens.keys()){if(key.startsWith(prefix)){const providerId=key.slice(prefix.length);const record=await this.getRecord(authorizationId,providerId);if(record){providerIds.push(providerId)}}}return providerIds}async cleanup(){const now=Date.now();const keysToDelete=[];for(const[key,stored]of this.tokens.entries()){let record=null;if(this.encryptionKey){if(typeof stored==="string"){try{record=await this.decryptRecord(key,stored)}catch{keysToDelete.push(key);continue}}}else{record=stored}const dropAt=record?recordDropAt(record):void 0;if(dropAt&&dropAt<now){keysToDelete.push(key)}}for(const key of keysToDelete){this.tokens.delete(key);this.derivedKeys.delete(key)}}dispose(){if(this.cleanupTimer){clearInterval(this.cleanupTimer);this.cleanupTimer=void 0}}get size(){return this.tokens.size}clear(){this.tokens.clear();this.derivedKeys.clear()}async migrateTokens(fromAuthId,toAuthId){for(const oldKey of await this.copyRecords(fromAuthId,toAuthId)){this.tokens.delete(oldKey);this.derivedKeys.delete(oldKey)}}async copyTokens(fromAuthId,toAuthId){await this.copyRecords(fromAuthId,toAuthId)}async copyRecords(fromAuthId,toAuthId){const prefix=`${fromAuthId}:`;const sourceKeys=[...this.tokens.keys()].filter(key=>key.startsWith(prefix));const copiedKeys=[];for(const oldKey of sourceKeys){const stored=this.tokens.get(oldKey);if(!stored)continue;const newKey=this.buildKey(toAuthId,oldKey.slice(prefix.length));if(this.encryptionKey){try{const record=await this.decryptRecord(oldKey,stored);this.tokens.set(newKey,await this.encryptRecord(newKey,record))}catch{continue}}else{this.tokens.set(newKey,stored)}copiedKeys.push(oldKey)}return copiedKeys}};var StorageOrchestratedTokenStore=class{storage;encryptionKey;defaultTtlMs;refreshSkewMs;namespace;storageIsNamespaced;derivedKeys=new Map;constructor(storage,options={}){this.encryptionKey=options.encryptionKey;this.defaultTtlMs=options.defaultTtlMs;this.refreshSkewMs=options.refreshSkewMs??0;this.namespace=options.namespace??"otok";this.storageIsNamespaced=this.isNamespacedStorage(storage);this.storage=this.storageIsNamespaced?storage.namespace(this.namespace):storage}async getAccessToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record&&hasLiveAccessToken(record,this.refreshSkewMs)?record.accessToken:null}async getRefreshToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record?.refreshToken??null}async storeTokens(authorizationId,providerId,tokens){const compositeKey=this.compositeKey(authorizationId,providerId);const now=Date.now();const record={accessToken:tokens.accessToken,refreshToken:tokens.refreshToken,expiresAt:tokens.expiresAt??(this.defaultTtlMs?now+this.defaultTtlMs:void 0),createdAt:now,updatedAt:now};const value=this.encryptionKey?encryptRecord(this.keyFor(compositeKey),record):JSON.stringify(record);await this.storage.set(this.storageKey(compositeKey),value,this.ttlOptions(recordDropAt(record)))}async deleteTokens(authorizationId,providerId){const compositeKey=this.compositeKey(authorizationId,providerId);await this.storage.delete(this.storageKey(compositeKey));this.derivedKeys.delete(compositeKey)}async hasTokens(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record!==null}async getProviderIds(authorizationId){const prefix=`${authorizationId}:`;const compositeKeys=await this.listCompositeKeys(`${prefix}*`);const providerIds=[];for(const compositeKey of compositeKeys){if(!compositeKey.startsWith(prefix))continue;const providerId=compositeKey.slice(prefix.length);const record=await this.getRecord(authorizationId,providerId);if(record){providerIds.push(providerId)}}return providerIds}async migrateTokens(fromAuthId,toAuthId){for(const oldComposite of await this.copyRecords(fromAuthId,toAuthId)){await this.storage.delete(this.storageKey(oldComposite));this.derivedKeys.delete(oldComposite)}}async copyTokens(fromAuthId,toAuthId){await this.copyRecords(fromAuthId,toAuthId)}async deleteAllForAuthorization(authorizationId){const prefix=`${authorizationId}:`;const compositeKeys=await this.listCompositeKeys(`${prefix}*`);for(const compositeKey of compositeKeys){if(!compositeKey.startsWith(prefix))continue;await this.storage.delete(this.storageKey(compositeKey));this.derivedKeys.delete(compositeKey)}}async copyRecords(fromAuthId,toAuthId){const prefix=`${fromAuthId}:`;const compositeKeys=await this.listCompositeKeys(`${prefix}*`);const copiedKeys=[];for(const oldComposite of compositeKeys){if(!oldComposite.startsWith(prefix))continue;const newComposite=this.compositeKey(toAuthId,oldComposite.slice(prefix.length));const stored=await this.storage.get(this.storageKey(oldComposite));if(stored===null)continue;if(this.encryptionKey){let record;try{record=decryptRecord(this.keyFor(oldComposite),stored)}catch{continue}const value=encryptRecord(this.keyFor(newComposite),record);await this.storage.set(this.storageKey(newComposite),value,this.ttlOptions(recordDropAt(record)))}else{let dropAt;try{dropAt=recordDropAt(JSON.parse(stored))}catch{dropAt=void 0}await this.storage.set(this.storageKey(newComposite),stored,this.ttlOptions(dropAt))}copiedKeys.push(oldComposite)}return copiedKeys}async getRecord(authorizationId,providerId){const compositeKey=this.compositeKey(authorizationId,providerId);const stored=await this.storage.get(this.storageKey(compositeKey));if(stored===null){return null}let record;if(this.encryptionKey){try{record=decryptRecord(this.keyFor(compositeKey),stored)}catch{await this.storage.delete(this.storageKey(compositeKey));return null}}else{try{record=JSON.parse(stored)}catch{await this.storage.delete(this.storageKey(compositeKey));return null}}const dropAt=recordDropAt(record);if(dropAt&&dropAt<Date.now()){await this.storage.delete(this.storageKey(compositeKey));return null}return record}keyFor(compositeKey){if(!this.encryptionKey){throw new EncryptionKeyNotConfiguredError}return deriveKeyForRecord(this.encryptionKey,compositeKey,this.derivedKeys)}compositeKey(authorizationId,providerId){return`${authorizationId}:${providerId}`}storageKey(compositeKey){return this.storageIsNamespaced?compositeKey:`${this.namespace}:${compositeKey}`}async listCompositeKeys(compositeGlob){const pattern=this.storageIsNamespaced?compositeGlob:`${this.namespace}:${compositeGlob}`;const raw=await this.storage.keys(pattern);if(this.storageIsNamespaced){return raw}const stripPrefix=`${this.namespace}:`;return raw.map(k=>k.startsWith(stripPrefix)?k.slice(stripPrefix.length):k)}ttlOptions(expiresAtMs){if(!expiresAtMs){return void 0}const ttl=Math.ceil((expiresAtMs-Date.now())/1e3);return{ttlSeconds:ttl>0?ttl:1}}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_utils31=require("@frontmcp/utils");function toSessionRecord(session){return{...session,completedProviders:Array.from(session.completedProviders.entries())}}function fromSessionRecord(record){return{...record,completedProviders:new Map(record.completedProviders)}}var InMemoryFederatedAuthSessionStore=class{sessions=new Map;sessionTtlMs=15*60*1e3;cleanupTimer;constructor(){this.cleanupTimer=setInterval(()=>{void this.cleanup()},6e4);if(this.cleanupTimer.unref){this.cleanupTimer.unref()}}async store(session){const record=toSessionRecord(session);this.sessions.set(session.id,record)}async get(id){const record=this.sessions.get(id);if(!record){return null}if(Date.now()>record.expiresAt){this.sessions.delete(id);return null}return fromSessionRecord(record)}async delete(id){this.sessions.delete(id)}async update(session){const record=toSessionRecord(session);this.sessions.set(session.id,record)}async cleanup(){const now=Date.now();for(const[id,record]of this.sessions){if(now>record.expiresAt){this.sessions.delete(id)}}}dispose(){if(this.cleanupTimer){clearInterval(this.cleanupTimer);this.cleanupTimer=void 0}}createSession(params){const now=Date.now();return{id:(0,import_utils31.randomUUID)(),pendingAuthId:params.pendingAuthId,clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,state:params.state,resource:params.resource,userInfo:params.userInfo,frontmcpPkce:params.frontmcpPkce,providerQueue:[...params.providerIds],completedProviders:new Map,skippedProviders:[],signinBinding:params.signinBinding,createdAt:now,expiresAt:now+this.sessionTtlMs}}get size(){return this.sessions.size}clear(){this.sessions.clear()}};function createFederatedAuthSession(params,ttlMs=15*60*1e3){const now=Date.now();return{id:(0,import_utils31.randomUUID)(),pendingAuthId:params.pendingAuthId,clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,state:params.state,resource:params.resource,userInfo:params.userInfo,frontmcpPkce:params.frontmcpPkce,providerQueue:[...params.providerIds],completedProviders:new Map,skippedProviders:[],signinBinding:params.signinBinding,createdAt:now,expiresAt:now+ttlMs}}function isSessionComplete(session){return session.providerQueue.length===0&&!session.currentProviderId}function getNextProvider(session){if(session.currentProviderId){return session.currentProviderId}return session.providerQueue[0]}function completeCurrentProvider(session,tokens,userInfo){if(!session.currentProviderId){throw new AuthFlowError("No current provider to complete","AUTH_FLOW_ERROR")}session.completedProviders.set(session.currentProviderId,{providerId:session.currentProviderId,tokens,userInfo,completedAt:Date.now()});session.currentProviderId=void 0;session.currentProviderPkce=void 0;session.currentProviderState=void 0}function startNextProvider(session,pkce,state){if(session.currentProviderId){throw new AuthFlowError("Cannot start next provider while current is in progress","AUTH_FLOW_ERROR")}if(session.providerQueue.length===0){throw new AuthFlowError("No more providers in queue","AUTH_FLOW_ERROR")}const providerId=session.providerQueue.shift();if(!providerId){throw new AuthFlowError("No more providers in queue","AUTH_FLOW_ERROR")}session.currentProviderId=providerId;session.currentProviderPkce=pkce;session.currentProviderState=state;return providerId}var import_utils32=require("@frontmcp/utils");var StorageFederatedAuthSessionStore=class{storage;namespace;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"fed";this.storageIsNamespaced=this.isNamespacedStorage(storage);const namespacedStorage=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.storage=new import_utils32.TypedStorage(namespacedStorage)}async store(session){await this.put(session)}async update(session){await this.put(session)}async get(id){const record=await this.storage.get(this.key(id));if(!record){return null}if(Date.now()>record.expiresAt){await this.storage.delete(this.key(id));return null}return fromSessionRecord(record)}async delete(id){await this.storage.delete(this.key(id))}async put(session){const record=toSessionRecord(session);const ttlSeconds=this.calculateTtl(record.expiresAt);await this.storage.set(this.key(session.id),record,ttlSeconds?{ttlSeconds}:void 0)}calculateTtl(expiresAtMs){const ttl=Math.ceil((expiresAtMs-Date.now())/1e3);return ttl>0?ttl:1}key(id){return this.storageIsNamespaced?id:`${this.namespace}:${id}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};function consentRecordKey(userSub,clientId){return`consent:${userSub}:${clientId}`}var InMemoryConsentStore=class{records=new Map;async get(userSub,clientId){const record=this.records.get(consentRecordKey(userSub,clientId));if(!record)return null;return{...record,selectedToolIds:[...record.selectedToolIds],seenToolIds:[...record.seenToolIds]}}async set(record){this.records.set(consentRecordKey(record.userSub,record.clientId),{...record,selectedToolIds:[...record.selectedToolIds],seenToolIds:[...record.seenToolIds]})}async delete(userSub,clientId){this.records.delete(consentRecordKey(userSub,clientId))}get size(){return this.records.size}clear(){this.records.clear()}};var import_utils33=require("@frontmcp/utils");var StorageConsentStore=class{storage;namespace;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"remembered-consent";this.storageIsNamespaced=this.isNamespacedStorage(storage);const namespacedStorage=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.storage=new import_utils33.TypedStorage(namespacedStorage)}async get(userSub,clientId){return this.storage.get(this.key(userSub,clientId))}async set(record){await this.storage.set(this.key(record.userSub,record.clientId),record)}async delete(userSub,clientId){await this.storage.delete(this.key(userSub,clientId))}key(userSub,clientId){const base=consentRecordKey(userSub,clientId);return this.storageIsNamespaced?base:`${this.namespace}:${base}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_lazy_zod5=require("@frontmcp/lazy-zod");var import_utils34=require("@frontmcp/utils");var redisVaultEntrySchema=import_lazy_zod5.z.object({id:import_lazy_zod5.z.string(),userSub:import_lazy_zod5.z.string(),userEmail:import_lazy_zod5.z.string().optional(),userName:import_lazy_zod5.z.string().optional(),clientId:import_lazy_zod5.z.string(),createdAt:import_lazy_zod5.z.number(),lastAccessAt:import_lazy_zod5.z.number(),authorizedAppIds:import_lazy_zod5.z.array(import_lazy_zod5.z.string()),skippedAppIds:import_lazy_zod5.z.array(import_lazy_zod5.z.string()),pendingAuthIds:import_lazy_zod5.z.array(import_lazy_zod5.z.string()),encrypted:encryptedDataSchema});var encryptionContextStorage=new import_utils34.AsyncLocalStorage;var EncryptedRedisVault=class{constructor(redis,encryption,namespace="vault:"){this.redis=redis;this.encryption=encryption;this.namespace=namespace}redis;encryption;namespace;runWithContext(context,fn){return encryptionContextStorage.run(context,fn)}getKey(){const asyncContext=encryptionContextStorage.getStore();if(asyncContext){return asyncContext.key}throw new EncryptionContextNotSetError}redisKey(id){return`${this.namespace}${id}`}credentialKey(appId,providerId){return`${appId}:${providerId}`}async encryptSensitive(data){return this.encryption.encryptObject(data,this.getKey())}async decryptSensitive(encrypted){return this.encryption.decryptObject(encrypted,this.getKey())}async toVaultEntry(redisEntry){const sensitive=await this.decryptSensitive(redisEntry.encrypted);return{id:redisEntry.id,userSub:redisEntry.userSub,userEmail:redisEntry.userEmail,userName:redisEntry.userName,clientId:redisEntry.clientId,createdAt:redisEntry.createdAt,lastAccessAt:redisEntry.lastAccessAt,appCredentials:sensitive.appCredentials,consent:sensitive.consent,federated:sensitive.federated,pendingAuths:sensitive.pendingAuths,authorizedAppIds:redisEntry.authorizedAppIds,skippedAppIds:redisEntry.skippedAppIds}}async toRedisEntry(entry){const sensitive={appCredentials:entry.appCredentials,consent:entry.consent,federated:entry.federated,pendingAuths:entry.pendingAuths};return{id:entry.id,userSub:entry.userSub,userEmail:entry.userEmail,userName:entry.userName,clientId:entry.clientId,createdAt:entry.createdAt,lastAccessAt:entry.lastAccessAt,authorizedAppIds:entry.authorizedAppIds,skippedAppIds:entry.skippedAppIds,pendingAuthIds:entry.pendingAuths.map(p=>p.id),encrypted:await this.encryptSensitive(sensitive)}}async saveEntry(entry){const redisEntry=await this.toRedisEntry(entry);await this.redis.set(this.redisKey(entry.id),JSON.stringify(redisEntry))}async loadEntry(id){const data=await this.redis.get(this.redisKey(id));if(!data)return null;try{const redisEntry=redisVaultEntrySchema.parse(JSON.parse(data));return await this.toVaultEntry(redisEntry)}catch(error){throw new VaultLoadError(id,error instanceof Error?error:void 0)}}async create(params){const now=Date.now();const entry={id:(0,import_utils34.randomUUID)(),userSub:params.userSub,userEmail:params.userEmail,userName:params.userName,clientId:params.clientId,createdAt:now,lastAccessAt:now,appCredentials:{},consent:params.consent,federated:params.federated,pendingAuths:[],authorizedAppIds:params.authorizedAppIds??[],skippedAppIds:params.skippedAppIds??[]};await this.saveEntry(entry);return entry}async get(id){const entry=await this.loadEntry(id);if(!entry)return null;entry.lastAccessAt=Date.now();await this.saveEntry(entry);return entry}async update(id,updates){const entry=await this.loadEntry(id);if(!entry){throw new VaultNotFoundError("Vault entry",id)}Object.assign(entry,updates,{lastAccessAt:Date.now()});await this.saveEntry(entry)}async delete(id){await this.redis.del(this.redisKey(id))}async updateConsent(vaultId,consent){const entry=await this.loadEntry(vaultId);if(!entry)return;entry.consent=consent;entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async authorizeApp(vaultId,appId){const entry=await this.loadEntry(vaultId);if(!entry)return;entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==appId);if(!entry.authorizedAppIds.includes(appId)){entry.authorizedAppIds.push(appId)}entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async createPendingAuth(vaultId,params){const entry=await this.loadEntry(vaultId);if(!entry){throw new VaultNotFoundError("Vault",vaultId)}const now=Date.now();const pendingAuth={id:(0,import_utils34.randomUUID)(),appId:params.appId,toolId:params.toolId,authUrl:params.authUrl,requiredScopes:params.requiredScopes,elicitId:params.elicitId,createdAt:now,expiresAt:now+(params.ttlMs??10*60*1e3),status:"pending"};entry.pendingAuths.push(pendingAuth);entry.lastAccessAt=now;await this.saveEntry(entry);return pendingAuth}async getPendingAuth(vaultId,pendingAuthId){const entry=await this.loadEntry(vaultId);if(!entry)return null;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(!pendingAuth)return null;if(Date.now()>pendingAuth.expiresAt&&pendingAuth.status==="pending"){pendingAuth.status="expired";await this.saveEntry(entry)}return pendingAuth}async completePendingAuth(vaultId,pendingAuthId){const entry=await this.loadEntry(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="completed";entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==pendingAuth.appId);if(!entry.authorizedAppIds.includes(pendingAuth.appId)){entry.authorizedAppIds.push(pendingAuth.appId)}entry.lastAccessAt=Date.now();await this.saveEntry(entry)}}async cancelPendingAuth(vaultId,pendingAuthId){const entry=await this.loadEntry(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="cancelled";await this.saveEntry(entry)}}async isAppAuthorized(vaultId,appId){const data=await this.redis.get(this.redisKey(vaultId));if(!data)return false;try{const parsed=JSON.parse(data);return Array.isArray(parsed.authorizedAppIds)&&parsed.authorizedAppIds.includes(appId)}catch{return false}}async getPendingAuths(vaultId){const entry=await this.loadEntry(vaultId);if(!entry)return[];const now=Date.now();let updated=false;const pending=entry.pendingAuths.filter(p=>{if(now>p.expiresAt&&p.status==="pending"){p.status="expired";updated=true}return p.status==="pending"});if(updated){await this.saveEntry(entry)}return pending}async addAppCredential(vaultId,credential){const entry=await this.loadEntry(vaultId);if(!entry)return;const shouldStore=await this.shouldStoreCredential(vaultId,credential.appId);if(!shouldStore)return;const key=this.credentialKey(credential.appId,credential.providerId);entry.appCredentials[key]=credential;entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async removeAppCredential(vaultId,appId,providerId){const entry=await this.loadEntry(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);delete entry.appCredentials[key];entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async getAppCredentials(vaultId,appId){const entry=await this.loadEntry(vaultId);if(!entry)return[];const prefix=`${appId}:`;return Object.entries(entry.appCredentials).filter(([key])=>key.startsWith(prefix)).map(([,cred])=>cred)}async getCredential(vaultId,appId,providerId){const entry=await this.loadEntry(vaultId);if(!entry)return null;const key=this.credentialKey(appId,providerId);return entry.appCredentials[key]??null}async getAllCredentials(vaultId,filterByConsent=false){const entry=await this.loadEntry(vaultId);if(!entry)return[];const allCredentials=Object.values(entry.appCredentials);if(!filterByConsent||!entry.consent?.enabled){return allCredentials}const consentedToolIds=new Set(entry.consent.selectedToolIds);return allCredentials.filter(cred=>{return Array.from(consentedToolIds).some(toolId=>toolId.startsWith(`${cred.appId}:`))})}async updateCredential(vaultId,appId,providerId,updates){const entry=await this.loadEntry(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential)return;Object.assign(credential,updates);entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async shouldStoreCredential(vaultId,appId,toolIds){const entry=await this.loadEntry(vaultId);if(!entry)return false;if(!entry.consent?.enabled){return true}if(toolIds&&toolIds.length>0){return toolIds.some(toolId=>entry.consent.selectedToolIds.includes(toolId))}const consentedToolIds=entry.consent.selectedToolIds;return consentedToolIds.some(toolId=>toolId.startsWith(`${appId}:`))}async invalidateCredential(vaultId,appId,providerId,reason){await this.updateCredential(vaultId,appId,providerId,{isValid:false,invalidReason:reason})}async refreshOAuthCredential(vaultId,appId,providerId,tokens){const entry=await this.loadEntry(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential||credential.credential.type!=="oauth")return;credential.credential.accessToken=tokens.accessToken;if(tokens.refreshToken!==void 0){credential.credential.refreshToken=tokens.refreshToken}if(tokens.expiresAt!==void 0){credential.credential.expiresAt=tokens.expiresAt;credential.expiresAt=tokens.expiresAt}credential.isValid=true;credential.invalidReason=void 0;entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async cleanup(){}};function createEncryptedVault(redis,config={}){const encryption=new VaultEncryption({pepper:config.pepper});const vault=new EncryptedRedisVault(redis,encryption,config.namespace);return{vault,encryption}}var import_utils35=require("@frontmcp/utils");function toEpochSeconds(exp){if(exp==null)return void 0;if(exp instanceof Date)return Math.floor(exp.getTime()/1e3);return exp>1e12?Math.floor(exp/1e3):Math.floor(exp)}function isSoonExpiring(exp,skewSec=60){const expSec=toEpochSeconds(exp);if(expSec==null)return false;const now=Math.floor(Date.now()/1e3);return expSec<=now+Math.max(0,skewSec)}function isSoonExpiringProvider(sessionLike,providerId,skewSec=60){const snap=sessionLike.authorizedProviders[providerId];if(!snap)return false;return isSoonExpiring(snap.exp,skewSec)}function tryJwtExp(token){if(!token)return void 0;const parts=token.split(".");if(parts.length<2)return void 0;try{const json=JSON.parse(new TextDecoder().decode((0,import_utils35.base64urlDecode)(parts[1])));const e=json?.exp;return typeof e==="number"?toEpochSeconds(e):void 0}catch{return void 0}}var import_lazy_zod6=require("@frontmcp/lazy-zod");var authModeSchema=import_lazy_zod6.z.enum(["public","transparent","orchestrated"]);var authUserSchema=import_lazy_zod6.z.object({sub:import_lazy_zod6.z.string(),name:import_lazy_zod6.z.string().optional(),email:import_lazy_zod6.z.string().email().optional(),picture:import_lazy_zod6.z.string().url().optional(),anonymous:import_lazy_zod6.z.boolean().optional()});var authorizedToolSchema=import_lazy_zod6.z.object({executionPath:import_lazy_zod6.z.tuple([import_lazy_zod6.z.string(),import_lazy_zod6.z.string()]),scopes:import_lazy_zod6.z.array(import_lazy_zod6.z.string()).optional(),details:import_lazy_zod6.z.record(import_lazy_zod6.z.string(),import_lazy_zod6.z.unknown()).optional()});var authorizedPromptSchema=import_lazy_zod6.z.object({executionPath:import_lazy_zod6.z.tuple([import_lazy_zod6.z.string(),import_lazy_zod6.z.string()]),scopes:import_lazy_zod6.z.array(import_lazy_zod6.z.string()).optional(),details:import_lazy_zod6.z.record(import_lazy_zod6.z.string(),import_lazy_zod6.z.unknown()).optional()});var llmSafeAuthContextSchema=import_lazy_zod6.z.object({authorizationId:import_lazy_zod6.z.string(),sessionId:import_lazy_zod6.z.string(),mode:authModeSchema,isAnonymous:import_lazy_zod6.z.boolean(),user:import_lazy_zod6.z.object({sub:import_lazy_zod6.z.string(),name:import_lazy_zod6.z.string().optional()}),scopes:import_lazy_zod6.z.array(import_lazy_zod6.z.string()),authorizedToolIds:import_lazy_zod6.z.array(import_lazy_zod6.z.string()),authorizedPromptIds:import_lazy_zod6.z.array(import_lazy_zod6.z.string())});var AppAuthState=(AppAuthState2=>{AppAuthState2["AUTHORIZED"]="authorized";AppAuthState2["SKIPPED"]="skipped";AppAuthState2["PENDING"]="pending";return AppAuthState2})(AppAuthState||{});var appAuthStateSchema=import_lazy_zod6.z.nativeEnum(AppAuthState);var appAuthorizationRecordSchema=import_lazy_zod6.z.object({appId:import_lazy_zod6.z.string(),state:appAuthStateSchema,stateChangedAt:import_lazy_zod6.z.number(),grantedScopes:import_lazy_zod6.z.array(import_lazy_zod6.z.string()).optional(),authProviderId:import_lazy_zod6.z.string().optional(),toolIds:import_lazy_zod6.z.array(import_lazy_zod6.z.string())});var progressiveAuthStateSchema=import_lazy_zod6.z.object({apps:import_lazy_zod6.z.record(import_lazy_zod6.z.string(),appAuthorizationRecordSchema),initiallyAuthorized:import_lazy_zod6.z.array(import_lazy_zod6.z.string()),initiallySkipped:import_lazy_zod6.z.array(import_lazy_zod6.z.string())});var import_utils38=require("@frontmcp/utils");var AuthorizationBase=class _AuthorizationBase{id;isAnonymous;user;claims;expiresAt;scopes;authorizedProviders;authorizedProviderIds;authorizedApps;authorizedAppIds;authorizedTools;authorizedToolIds;authorizedPrompts;authorizedPromptIds;authorizedResources;token;#sessions=new Map;createdAt;constructor(ctx){this.id=ctx.id;this.isAnonymous=ctx.isAnonymous;this.user=ctx.user;this.claims=ctx.claims;this.expiresAt=ctx.expiresAt;this.scopes=ctx.scopes??[];this.token=ctx.token;this.createdAt=Date.now();this.authorizedProviders=ctx.authorizedProviders??{};this.authorizedProviderIds=ctx.authorizedProviderIds??Object.keys(this.authorizedProviders);this.authorizedApps=ctx.authorizedApps??{};this.authorizedAppIds=ctx.authorizedAppIds??Object.keys(this.authorizedApps);this.authorizedTools=ctx.authorizedTools??{};this.authorizedToolIds=ctx.authorizedToolIds??Object.keys(this.authorizedTools);this.authorizedPrompts=ctx.authorizedPrompts??{};this.authorizedPromptIds=ctx.authorizedPromptIds??Object.keys(this.authorizedPrompts);this.authorizedResources=ctx.authorizedResources??[]}createTransportSession(protocol,fingerprint){const sessionId=(0,import_utils38.randomUUID)();const session={id:sessionId,authorizationId:this.id,protocol,createdAt:Date.now(),expiresAt:this.expiresAt,nodeId:(0,import_utils38.getMachineId)(),clientFingerprint:fingerprint};this.#sessions.set(session.id,session);return session}getTransportSession(sessionId){return this.#sessions.get(sessionId)}getAllSessions(){return Array.from(this.#sessions.values())}removeTransportSession(sessionId){return this.#sessions.delete(sessionId)}get sessionCount(){return this.#sessions.size}hasScope(scope){return this.scopes.includes(scope)}hasAllScopes(scopes){return scopes.every(s=>this.scopes.includes(s))}hasAnyScope(scopes){return scopes.some(s=>this.scopes.includes(s))}canAccessTool(toolId){return toolId in this.authorizedTools||this.authorizedToolIds.includes(toolId)}canAccessPrompt(promptId){return promptId in this.authorizedPrompts||this.authorizedPromptIds.includes(promptId)}isAppAuthorized(appId){return appId in this.authorizedApps||this.authorizedAppIds.includes(appId)}getProgressiveAuthUrl(appId,baseUrl,ticket){const params=new URLSearchParams({app:appId});if(ticket)params.set("ticket",ticket);return`${baseUrl}/oauth/authorize?${params.toString()}`}isExpired(){if(!this.expiresAt)return false;return Date.now()>this.expiresAt}getTimeToExpiry(){if(!this.expiresAt)return void 0;return this.expiresAt-Date.now()}toSessionJwt(session){const payload={sid:session.id,aid:this.id,proto:session.protocol,nid:session.nodeId,iat:Math.floor(Date.now()/1e3),exp:this.expiresAt?Math.floor(this.expiresAt/1e3):void 0};return encryptJson(payload)}toLLMSafeContext(session){return{authorizationId:this.id,sessionId:session.id,mode:this.mode,isAnonymous:this.isAnonymous,user:{sub:this.user.sub,name:this.user.name},scopes:this.scopes,authorizedToolIds:this.authorizedToolIds,authorizedPromptIds:this.authorizedPromptIds}}static isJwtHeader(segment){try{const bytes=(0,import_utils38.base64urlDecode)(segment);const text=new TextDecoder().decode(bytes);const parsed=JSON.parse(text);return typeof parsed==="object"&&parsed!==null&&typeof parsed.alg==="string"}catch{return false}}static validateNoTokenLeakage(data){const json=JSON.stringify(data);const B64URL=/^[A-Za-z0-9_-]+$/;const MIN_SEG=2;let dotIdx=json.indexOf(".");while(dotIdx!==-1){let seg1Start=dotIdx;while(seg1Start>0&&/[A-Za-z0-9_-]/.test(json[seg1Start-1]))seg1Start--;const seg1Len=dotIdx-seg1Start;if(seg1Len>=MIN_SEG){let seg2End=dotIdx+1;while(seg2End<json.length&&/[A-Za-z0-9_-]/.test(json[seg2End]))seg2End++;const seg2Len=seg2End-(dotIdx+1);if(seg2Len>=MIN_SEG&&seg2End<json.length&&json[seg2End]==="."){const dot2=seg2End;let seg3End=dot2+1;while(seg3End<json.length&&/[A-Za-z0-9_-]/.test(json[seg3End]))seg3End++;const seg3Len=seg3End-(dot2+1);if(seg3Len>=MIN_SEG){const seg1=json.substring(seg1Start,dotIdx);const seg2=json.substring(dotIdx+1,dot2);const seg3=json.substring(dot2+1,seg3End);if(B64URL.test(seg1)&&B64URL.test(seg2)&&B64URL.test(seg3)&&_AuthorizationBase.isJwtHeader(seg1)){throw new TokenLeakDetectedError("JWT pattern detected in LLM context data")}}}}dotIdx=json.indexOf(".",dotIdx+1)}const sensitiveFields=["access_token","refresh_token","id_token","tokenEnc","secretRefId"];for(const field of sensitiveFields){if(json.includes(`"${field}"`)){throw new TokenLeakDetectedError(`Sensitive field "${field}" found in data`)}}}};var import_utils39=require("@frontmcp/utils");var PublicAuthorization=class _PublicAuthorization extends AuthorizationBase{mode="public";issuer;constructor(ctx){super(ctx);this.issuer=ctx.issuer}static create(ctx={}){const{prefix="anon",scopes=["anonymous"],ttlMs=36e5,issuer,allowedTools="all",allowedPrompts="all"}=ctx;const uuid=(0,import_utils39.randomUUID)();const sub=`${prefix}:${uuid}`;const user={sub,name:"Anonymous",anonymous:true};const expiresAt=ttlMs?Date.now()+ttlMs:void 0;const authorizedTools={};const authorizedToolIds=[];if(allowedTools!=="all"&&Array.isArray(allowedTools)){for(const toolId of allowedTools){authorizedTools[toolId]={executionPath:["public",toolId]};authorizedToolIds.push(toolId)}}const authorizedPrompts={};const authorizedPromptIds=[];if(allowedPrompts!=="all"&&Array.isArray(allowedPrompts)){for(const promptId of allowedPrompts){authorizedPrompts[promptId]={executionPath:["public",promptId]};authorizedPromptIds.push(promptId)}}return new _PublicAuthorization({id:sub,isAnonymous:true,user,scopes,expiresAt,issuer,authorizedTools:allowedTools==="all"?void 0:authorizedTools,authorizedToolIds:allowedTools==="all"?void 0:authorizedToolIds,authorizedPrompts:allowedPrompts==="all"?void 0:authorizedPrompts,authorizedPromptIds:allowedPrompts==="all"?void 0:authorizedPromptIds})}async getToken(_providerId){throw new TokenNotAvailableError("PublicAuthorization: Anonymous users cannot access provider tokens. Use transparent or orchestrated mode for token access.")}get allowsAllTools(){return this.authorizedToolIds.length===0&&Object.keys(this.authorizedTools).length===0}get allowsAllPrompts(){return this.authorizedPromptIds.length===0&&Object.keys(this.authorizedPrompts).length===0}canAccessTool(toolId){if(this.allowsAllTools){return true}return super.canAccessTool(toolId)}canAccessPrompt(promptId){if(this.allowsAllPrompts){return true}return super.canAccessPrompt(promptId)}};var import_utils40=require("@frontmcp/utils");var TransparentAuthorization=class _TransparentAuthorization extends AuthorizationBase{mode="transparent";providerId;providerName;constructor(ctx){super(ctx);this.providerId=ctx.providerId;this.providerName=ctx.providerName}static fromVerifiedToken(ctx){const{token,payload,providerId,providerName,...projections}=ctx;const user={sub:payload.sub,name:payload.name,email:payload.email,picture:payload.picture,anonymous:false};const scopes=_TransparentAuthorization.parseScopes(payload.scope);const expiresAt=payload.exp?payload.exp*1e3:void 0;const id=_TransparentAuthorization.generateAuthorizationId(token);const providerSnapshot={id:providerId,exp:expiresAt,payload,embedMode:"plain",token};return new _TransparentAuthorization({id,isAnonymous:false,user,claims:payload,expiresAt,scopes,token,providerId,providerName,authorizedProviders:{[providerId]:providerSnapshot},authorizedProviderIds:[providerId],...projections})}async getToken(_providerId){if(!this.token){throw new TokenNotAvailableError("TransparentAuthorization: Token not available")}return this.token}static parseScopes(scope){if(!scope)return[];if(Array.isArray(scope))return scope;return scope.split(/\s+/).filter(Boolean)}static generateAuthorizationId(token){const parts=token.split(".");const signature=parts[2]||token;return(0,import_utils40.sha256Hex)(signature).substring(0,16)}get issuer(){return this.claims?.["iss"]}get audience(){return this.claims?.["aud"]}hasAudience(aud){const tokenAud=this.audience;if(!tokenAud)return false;if(Array.isArray(tokenAud))return tokenAud.includes(aud);return tokenAud===aud}};var import_utils41=require("@frontmcp/utils");function deriveAuthorizationId(token){const parts=token.split(".");const signature=parts[2]||token;return(0,import_utils41.sha256Hex)(signature).substring(0,16)}var OrchestratedAuthorization=class _OrchestratedAuthorization extends AuthorizationBase{mode="orchestrated";primaryProviderId;#tokenStore;#onTokenRefresh;#providerStates;constructor(ctx){super(ctx);this.primaryProviderId=ctx.primaryProviderId;this.#tokenStore=ctx.tokenStore;this.#onTokenRefresh=ctx.onTokenRefresh;this.#providerStates=ctx.providerStates??new Map}static create(ctx){const{token,user,scopes=[],claims,expiresAt,primaryProviderId,tokenStore,onTokenRefresh,providers={},authorizedProviderIds,...projections}=ctx;const id=deriveAuthorizationId(token);const providerStates=new Map;const authorizedProviders={};const providerIdsFromState=[];for(const[providerId,state]of Object.entries(providers)){providerStates.set(providerId,state);providerIdsFromState.push(providerId);authorizedProviders[providerId]={id:providerId,exp:state.expiresAt,embedMode:state.secretRefId?"ref":"store-only",secretRefId:state.secretRefId,refreshRefId:state.refreshRefId}}const finalAuthorizedProviderIds=authorizedProviderIds??(providerIdsFromState.length>0?providerIdsFromState:void 0);return new _OrchestratedAuthorization({id,isAnonymous:false,user,claims,expiresAt,scopes,token,primaryProviderId,tokenStore,onTokenRefresh,providerStates,authorizedProviders,...projections,authorizedProviderIds:finalAuthorizedProviderIds})}async getToken(providerId){const targetProviderId=providerId??this.primaryProviderId;if(!targetProviderId){throw new NoProviderIdError("OrchestratedAuthorization: No provider ID specified and no primary provider set")}if(!this.#tokenStore){throw new TokenStoreRequiredError("orchestrated token retrieval")}const hasToken=await this.#tokenStore.hasTokens(this.id,targetProviderId);if(!hasToken){throw new TokenNotAvailableError(`OrchestratedAuthorization: No tokens available for provider "${targetProviderId}"`)}const accessToken=await this.#tokenStore.getAccessToken(this.id,targetProviderId);if(accessToken){const providerState=this.#providerStates.get(targetProviderId);if(providerState?.expiresAt&&providerState.expiresAt<Date.now()){return this.refreshAndGetToken(targetProviderId)}return accessToken}return this.refreshAndGetToken(targetProviderId)}async refreshAndGetToken(providerId){if(!this.#tokenStore||!this.#onTokenRefresh){throw new TokenNotAvailableError(`OrchestratedAuthorization: Token expired for provider "${providerId}" and refresh not available`)}const refreshToken=await this.#tokenStore.getRefreshToken(this.id,providerId);if(!refreshToken){throw new TokenNotAvailableError(`OrchestratedAuthorization: No refresh token available for provider "${providerId}"`)}const result=await this.#onTokenRefresh(providerId,refreshToken);await this.#tokenStore.storeTokens(this.id,providerId,{accessToken:result.accessToken,refreshToken:result.refreshToken??refreshToken,expiresAt:result.expiresIn?Date.now()+result.expiresIn*1e3:void 0});const currentState=this.#providerStates.get(providerId);if(currentState){currentState.expiresAt=result.expiresIn?Date.now()+result.expiresIn*1e3:void 0}return result.accessToken}hasProvider(providerId){return this.#providerStates.has(providerId)}getProviderIds(){return Array.from(this.#providerStates.keys())}async addProvider(providerId,tokens){if(!this.#tokenStore){throw new TokenStoreRequiredError("adding providers")}const expiresAt=tokens.expiresIn?Date.now()+tokens.expiresIn*1e3:void 0;await this.#tokenStore.storeTokens(this.id,providerId,{accessToken:tokens.accessToken,refreshToken:tokens.refreshToken,expiresAt});this.#providerStates.set(providerId,{id:providerId,expiresAt,secretRefId:`${this.id}:${providerId}`})}#mutableAuthorizedApps=new Map(Object.entries(this.authorizedApps??{}));async addAppAuthorization(appId,toolIds,tokens){if(!this.#tokenStore){throw new TokenStoreRequiredError("progressive authorization")}const providerId=`app:${appId}`;await this.addProvider(providerId,tokens);this.#mutableAuthorizedApps.set(appId,{id:appId,toolIds})}async getAppToken(appId){if(!this.#mutableAuthorizedApps.has(appId)){return null}const providerId=`app:${appId}`;try{return await this.getToken(providerId)}catch{return null}}isAppAuthorized(appId){return this.#mutableAuthorizedApps.has(appId)||super.isAppAuthorized(appId)}getAllAuthorizedAppIds(){const baseIds=new Set(this.authorizedAppIds??[]);for(const appId of this.#mutableAuthorizedApps.keys()){baseIds.add(appId)}return Array.from(baseIds)}getAppToolIds(appId){return this.#mutableAuthorizedApps.get(appId)?.toolIds??this.authorizedApps?.[appId]?.toolIds}async removeProvider(providerId){if(this.#tokenStore){await this.#tokenStore.deleteTokens(this.id,providerId)}this.#providerStates.delete(providerId)}get issuer(){return this.claims?.["iss"]}};var ORCHESTRATED_AUTH_ACCESSOR=Symbol.for("frontmcp:ORCHESTRATED_AUTH_ACCESSOR");var NullOrchestratedAuthAccessor=class{primaryProviderId=void 0;issuer=void 0;authorizationId="null";isAuthenticated=false;async getToken(providerId){throw new OrchestratedAuthNotAvailableError}async tryGetToken(providerId){return null}async getAppToken(appId){return null}hasProvider(providerId){return false}getProviderIds(){return[]}isAppAuthorized(appId){return false}getAllAuthorizedAppIds(){return[]}getAppToolIds(appId){return void 0}};var OrchestratedAuthAccessorAdapter=class{constructor(authorization){this.authorization=authorization}authorization;get primaryProviderId(){return this.authorization.primaryProviderId}get issuer(){return this.authorization.issuer}get authorizationId(){return this.authorization.id}get isAuthenticated(){return!this.authorization.isAnonymous}async getToken(providerId){return this.authorization.getToken(providerId)}async tryGetToken(providerId){try{return await this.authorization.getToken(providerId)}catch{return null}}async getAppToken(appId){return this.authorization.getAppToken(appId)}hasProvider(providerId){return this.authorization.hasProvider(providerId)}getProviderIds(){return this.authorization.getProviderIds()}isAppAuthorized(appId){return this.authorization.isAppAuthorized(appId)}getAllAuthorizedAppIds(){return this.authorization.getAllAuthorizedAppIds()}getAppToolIds(appId){return this.authorization.getAppToolIds(appId)}};var import_utils42=require("@frontmcp/utils");var DEFAULT_MAX_DYNAMIC_CLIENTS=1e3;function globMatch(pattern,input){let p=0;let i=0;let starIdx=-1;let matchIdx=0;while(i<input.length){if(p<pattern.length&&pattern[p]===input[i]){p++;i++}else if(p<pattern.length&&pattern[p]==="*"){starIdx=p;matchIdx=i;p++}else if(starIdx!==-1){p=starIdx+1;matchIdx++;i=matchIdx}else{return false}}while(p<pattern.length&&pattern[p]==="*")p++;return p===pattern.length}function splitRedirectUri(s){const schemeSep=s.indexOf("://");if(schemeSep===-1)return null;const scheme=s.slice(0,schemeSep);const afterScheme=s.slice(schemeSep+3);let boundary=afterScheme.length;for(let i=0;i<afterScheme.length;i++){const ch=afterScheme[i];if(ch==="/"||ch==="?"||ch==="#"){boundary=i;break}}const authority=afterScheme.slice(0,boundary);const rest=afterScheme.slice(boundary);const at=authority.lastIndexOf("@");const userinfo=at===-1?"":authority.slice(0,at);const hostport=at===-1?authority:authority.slice(at+1);let host=hostport;let port="";if(hostport.startsWith("[")){const close=hostport.indexOf("]");if(close!==-1){host=hostport.slice(0,close+1);if(hostport[close+1]===":")port=hostport.slice(close+2)}}else{const colon=hostport.indexOf(":");if(colon!==-1){host=hostport.slice(0,colon);port=hostport.slice(colon+1)}}return{scheme,userinfo,host,port,rest}}function globMatchRedirectUri(pattern,input){const p=splitRedirectUri(pattern);if(!p)return globMatch(pattern,input);const u=splitRedirectUri(input);if(!u)return false;return globMatch(p.scheme,u.scheme)&&globMatch(p.userinfo,u.userinfo)&&globMatch(p.host,u.host)&&globMatch(p.port,u.port)&&globMatch(p.rest,u.rest)}var DcrClientRegistry=class{constructor(config={}){this.config=config;this.redirectGlobs=config.allowedRedirectUris;this.seedPreRegisteredClients()}config;clients=new Map;redirectGlobs;seedPreRegisteredClients(){const clients=this.config.clients??[];const now=Math.floor(Date.now()/1e3);for(const c of clients){this.clients.set(c.clientId,{client_id:c.clientId,client_secret:c.clientSecret,token_endpoint_auth_method:c.tokenEndpointAuthMethod??"none",grant_types:c.grantTypes??["authorization_code"],response_types:c.responseTypes??["code"],redirect_uris:c.redirectUris,client_name:c.clientName,scope:c.scope,created_at:now,dev:false,preRegistered:true})}}get(clientId){return this.clients.get(clientId)}verifyClientSecret(clientId,presentedSecret){const client=this.clients.get(clientId);if(!client)return"unknown";const method=client.token_endpoint_auth_method;const isConfidential=method==="client_secret_basic"||method==="client_secret_post";if(!isConfidential)return"ok";if(!client.client_secret)return"invalid";if(!presentedSecret)return"invalid";return(0,import_utils42.timingSafeEqual)((0,import_utils42.sha256)(presentedSecret),(0,import_utils42.sha256)(client.client_secret))?"ok":"invalid"}has(clientId){return this.clients.has(clientId)}register(client){const cap=this.dynamicClientCap();const dynamicCount=this.countDynamicClients();const isNew=!this.clients.has(client.client_id);if(isNew&&dynamicCount>=cap){return false}this.clients.set(client.client_id,client);return true}dynamicClientCap(){const configured=this.config.maxDynamicClients;return Number.isSafeInteger(configured)&&configured>=0?configured:DEFAULT_MAX_DYNAMIC_CLIENTS}countDynamicClients(){let n=0;for(const c of this.clients.values())if(c.dev&&!c.preRegistered)n++;return n}hasRedirectAllowlist(){return!!this.redirectGlobs&&this.redirectGlobs.length>0}isRedirectUriAllowed(redirectUri){if(!this.redirectGlobs||this.redirectGlobs.length===0){return true}return this.redirectGlobs.some(glob=>globMatchRedirectUri(glob,redirectUri))}hasClientIdAllowlist(){return!!this.config.allowedClientIds&&this.config.allowedClientIds.length>0}isClientIdAllowed(clientId){const allow=this.config.allowedClientIds;if(!allow||allow.length===0){return true}return allow.includes(clientId)}requiresInitialAccessToken(){return typeof this.config.initialAccessToken==="string"&&this.config.initialAccessToken.length>0}verifyInitialAccessToken(presented){const expected=this.config.initialAccessToken;if(!expected){return false}if(typeof presented!=="string"||presented.length===0){return false}return(0,import_utils42.timingSafeEqual)((0,import_utils42.sha256)(presented),(0,import_utils42.sha256)(expected))}};var import_lazy_zod7=require("@frontmcp/lazy-zod");var jwkParametersSchema=import_lazy_zod7.z.object({kty:import_lazy_zod7.z.string().optional(),alg:import_lazy_zod7.z.string().optional(),key_ops:import_lazy_zod7.z.array(import_lazy_zod7.z.string()).optional(),ext:import_lazy_zod7.z.boolean().optional(),use:import_lazy_zod7.z.string().optional(),x5c:import_lazy_zod7.z.array(import_lazy_zod7.z.string()).optional(),x5t:import_lazy_zod7.z.string().optional(),"x5t#S256":import_lazy_zod7.z.string().optional(),x5u:import_lazy_zod7.z.string().optional(),kid:import_lazy_zod7.z.string().optional()});var jwkSchema=jwkParametersSchema.extend({crv:import_lazy_zod7.z.string().optional(),d:import_lazy_zod7.z.string().optional(),dp:import_lazy_zod7.z.string().optional(),dq:import_lazy_zod7.z.string().optional(),e:import_lazy_zod7.z.string().optional(),k:import_lazy_zod7.z.string().optional(),n:import_lazy_zod7.z.string().optional(),p:import_lazy_zod7.z.string().optional(),q:import_lazy_zod7.z.string().optional(),qi:import_lazy_zod7.z.string().optional(),x:import_lazy_zod7.z.string().optional(),y:import_lazy_zod7.z.string().optional(),pub:import_lazy_zod7.z.string().optional(),priv:import_lazy_zod7.z.string().optional()});var jsonWebKeySetSchema=import_lazy_zod7.z.object({keys:import_lazy_zod7.z.array(jwkSchema)});var import_lazy_zod8=require("@frontmcp/lazy-zod");var aiPlatformTypeSchema=import_lazy_zod8.z.enum(["openai","claude","gemini","cursor","continue","cody","generic-mcp","ext-apps","unknown"]);var userClaimSchema=import_lazy_zod8.z.object({iss:import_lazy_zod8.z.string(),sid:import_lazy_zod8.z.string().optional(),sub:import_lazy_zod8.z.string(),exp:import_lazy_zod8.z.number().optional(),iat:import_lazy_zod8.z.number().optional(),aud:import_lazy_zod8.z.union([import_lazy_zod8.z.string(),import_lazy_zod8.z.array(import_lazy_zod8.z.string())]).optional(),email:import_lazy_zod8.z.string().optional(),username:import_lazy_zod8.z.string().optional(),preferred_username:import_lazy_zod8.z.string().optional(),name:import_lazy_zod8.z.string().optional(),picture:import_lazy_zod8.z.string().optional()}).passthrough();var sessionIdPayloadSchema=import_lazy_zod8.z.object({nodeId:import_lazy_zod8.z.string(),authSig:import_lazy_zod8.z.string(),uuid:import_lazy_zod8.z.string().uuid(),iat:import_lazy_zod8.z.number(),protocol:import_lazy_zod8.z.enum(["legacy-sse","sse","streamable-http","stateful-http","stateless-http"]).optional(),isPublic:import_lazy_zod8.z.boolean().optional(),platformType:aiPlatformTypeSchema.optional(),clientName:import_lazy_zod8.z.string().optional(),clientVersion:import_lazy_zod8.z.string().optional(),supportsElicitation:import_lazy_zod8.z.boolean().optional(),skillsOnlyMode:import_lazy_zod8.z.boolean().optional()});var sessionIdSchema=import_lazy_zod8.z.object({id:import_lazy_zod8.z.string(),payload:sessionIdPayloadSchema.optional()});var authorizationSchema=import_lazy_zod8.z.object({token:import_lazy_zod8.z.string(),session:sessionIdSchema.optional(),user:userClaimSchema});var import_lazy_zod10=require("@frontmcp/lazy-zod");var noopLogger={child:()=>noopLogger,debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}};var import_lazy_zod9=require("@frontmcp/lazy-zod");var clientMetadataDocumentSchema=import_lazy_zod9.z.object({client_id:import_lazy_zod9.z.string().url(),client_name:import_lazy_zod9.z.string().min(1),redirect_uris:import_lazy_zod9.z.array(import_lazy_zod9.z.string().url()).min(1),token_endpoint_auth_method:import_lazy_zod9.z.enum(["none","client_secret_basic","client_secret_post","private_key_jwt"]).default("none"),grant_types:import_lazy_zod9.z.array(import_lazy_zod9.z.string()).default(["authorization_code"]),response_types:import_lazy_zod9.z.array(import_lazy_zod9.z.string()).default(["code"]),client_uri:import_lazy_zod9.z.string().url().optional(),logo_uri:import_lazy_zod9.z.string().url().optional(),jwks_uri:import_lazy_zod9.z.string().url().optional(),jwks:import_lazy_zod9.z.object({keys:import_lazy_zod9.z.array(import_lazy_zod9.z.record(import_lazy_zod9.z.string(),import_lazy_zod9.z.unknown()))}).optional(),tos_uri:import_lazy_zod9.z.string().url().optional(),policy_uri:import_lazy_zod9.z.string().url().optional(),scope:import_lazy_zod9.z.string().optional(),contacts:import_lazy_zod9.z.array(import_lazy_zod9.z.string().email()).optional(),software_statement:import_lazy_zod9.z.string().optional(),software_id:import_lazy_zod9.z.string().optional(),software_version:import_lazy_zod9.z.string().optional()});var cimdRedisCacheConfigSchema=import_lazy_zod9.z.object({url:import_lazy_zod9.z.string().optional(),host:import_lazy_zod9.z.string().optional(),port:import_lazy_zod9.z.number().optional(),password:import_lazy_zod9.z.string().optional(),db:import_lazy_zod9.z.number().optional(),tls:import_lazy_zod9.z.boolean().optional(),keyPrefix:import_lazy_zod9.z.string().default("cimd:")});var cimdCacheConfigSchema=import_lazy_zod9.z.object({type:import_lazy_zod9.z.enum(["memory","redis"]).default("memory"),defaultTtlMs:import_lazy_zod9.z.number().min(0).default(36e5),maxTtlMs:import_lazy_zod9.z.number().min(0).default(864e5),minTtlMs:import_lazy_zod9.z.number().min(0).default(6e4),redis:cimdRedisCacheConfigSchema.optional()});var cimdSecurityConfigSchema=import_lazy_zod9.z.object({blockPrivateIPs:import_lazy_zod9.z.boolean().default(true),allowedDomains:import_lazy_zod9.z.array(import_lazy_zod9.z.string()).optional(),blockedDomains:import_lazy_zod9.z.array(import_lazy_zod9.z.string()).optional(),warnOnLocalhostRedirects:import_lazy_zod9.z.boolean().default(true),allowInsecureForTesting:import_lazy_zod9.z.boolean().default(false)});var cimdNetworkConfigSchema=import_lazy_zod9.z.object({timeoutMs:import_lazy_zod9.z.number().min(100).default(5e3),maxResponseSizeBytes:import_lazy_zod9.z.number().min(1024).default(65536),redirectPolicy:import_lazy_zod9.z.enum(["deny","same-origin","allow"]).default("deny"),maxRedirects:import_lazy_zod9.z.number().int().min(0).default(5)});var cimdConfigSchema=import_lazy_zod9.z.object({enabled:import_lazy_zod9.z.boolean().default(true),cache:cimdCacheConfigSchema.optional(),security:cimdSecurityConfigSchema.optional(),network:cimdNetworkConfigSchema.optional()});init_cimd_cache();var import_utils45=require("@frontmcp/utils");init_cimd_cache();var CimdService=class{config;cacheConfig;securityConfig;networkConfig;cacheBackend;logger;get enabled(){return this.config.enabled}constructor(logger,config){this.logger=(logger??noopLogger).child("CimdService");this.config=cimdConfigSchema.parse(config??{});this.cacheConfig=cimdCacheConfigSchema.parse(this.config.cache??{});this.securityConfig=cimdSecurityConfigSchema.parse(this.config.security??{});this.networkConfig=cimdNetworkConfigSchema.parse(this.config.network??{});this.logger.debug("CimdService initialized",{enabled:this.config.enabled,cacheDefaultTtlMs:this.cacheConfig.defaultTtlMs,networkTimeoutMs:this.networkConfig.timeoutMs});if(this.securityConfig.allowInsecureForTesting){this.logger.warn("CIMD allowInsecureForTesting is enabled. HTTP is allowed for localhost CIMD URLs. This should NEVER be enabled in production!")}}async initialize(){await this.cache()}cache(){if(!this.cacheBackend){this.cacheBackend=createCimdCache(this.cacheConfig).catch(error=>{this.cacheBackend=void 0;throw error})}return this.cacheBackend}async dispose(){const backend=this.cacheBackend;this.cacheBackend=void 0;if(!backend)return;const createdBackend=await backend.catch(()=>void 0);await createdBackend?.close?.()}isCimdClientId(clientId){return isCimdClientId(clientId,this.securityConfig.allowInsecureForTesting)}async resolveClientMetadata(clientId){if(!this.isCimdClientId(clientId)){return{isCimdClient:false,fromCache:false}}validateClientIdUrl(clientId,this.securityConfig);const cache=await this.cache();const cached=await cache.get(clientId);if(cached){this.logger.debug(`Cache hit for CIMD client: ${clientId}`);return{isCimdClient:true,metadata:cached.document,fromCache:true,expiresAt:cached.expiresAt,etag:cached.etag,lastModified:cached.lastModified}}this.logger.info(`Fetching CIMD document: ${clientId}`);const{document,headers}=await this.fetchMetadataDocument(clientId);this.validateDocument(clientId,document);if(this.securityConfig.warnOnLocalhostRedirects&&hasOnlyLocalhostRedirectUris(document.redirect_uris)){this.logger.warn(`CIMD client "${clientId}" has only localhost redirect URIs - this may be a development client`)}await cache.set(clientId,document,headers);const entry=await cache.get(clientId);return{isCimdClient:true,metadata:document,fromCache:false,expiresAt:entry?.expiresAt,etag:entry?.etag,lastModified:entry?.lastModified}}validateRedirectUri(redirectUri,metadata){const normalizedRequestUri=normalizeRedirectUri(redirectUri);const normalizedAllowed=metadata.redirect_uris.map(normalizeRedirectUri);if(!normalizedAllowed.includes(normalizedRequestUri)){throw new RedirectUriMismatchError(metadata.client_id,redirectUri,metadata.redirect_uris)}}async clearCache(clientId){const cache=await this.cache();if(clientId){await cache.delete(clientId);this.logger.debug(`Cache cleared for: ${clientId}`)}else{await cache.clear();this.logger.debug("Cache cleared")}}async getCacheStats(){const cache=await this.cache();return{size:await cache.size()}}async fetchMetadataDocument(clientId){const controller=new AbortController;const timer=setTimeout(()=>controller.abort(),this.networkConfig.timeoutMs);try{const cache=await this.cache();const conditionalHeaders=await cache.getConditionalHeaders(clientId);const originalOrigin=new URL(clientId).origin;const maxRedirects=this.networkConfig.maxRedirects;let currentUrl=clientId;let redirectCount=0;let isFirstRequest=true;while(true){if(this.securityConfig.blockPrivateIPs&&!this.securityConfig.allowInsecureForTesting){await assertHostNotSsrf(new URL(currentUrl).hostname,clientId)}const headers={Accept:"application/json"};if(isFirstRequest&&conditionalHeaders){Object.assign(headers,conditionalHeaders)}const response=await fetch(currentUrl,{method:"GET",headers,signal:controller.signal,redirect:"manual"});if(response.status===304){const staleEntry=await cache.getStale(clientId);if(staleEntry){await cache.revalidate(clientId,response.headers);this.logger.debug(`CIMD document not modified: ${clientId}`);return{document:staleEntry.document,headers:response.headers}}throw new CimdFetchError(clientId,"304 Not Modified but no cached entry",{httpStatus:304})}if((0,import_utils45.isRedirectResponse)(response)){const location=response.headers.get("location");if(!location){throw new CimdFetchError(clientId,"Redirect response missing Location header",{httpStatus:response.status})}const nextUrl=new URL(location,currentUrl).toString();const redirectPolicy=this.networkConfig.redirectPolicy;if(redirectPolicy==="deny"){throw new CimdFetchError(clientId,`CIMD fetch redirected to "${nextUrl}" but redirects are disabled. Host the metadata at the client_id URL or set auth.cimd.network.redirectPolicy to "same-origin" or "allow".`,{httpStatus:response.status})}if(redirectPolicy==="same-origin"){const nextOrigin=new URL(nextUrl).origin;if(nextOrigin!==originalOrigin){throw new CimdFetchError(clientId,`CIMD fetch redirected to "${nextUrl}" which is not the same origin as "${originalOrigin}". Host the metadata at the client_id URL or set auth.cimd.network.redirectPolicy to "allow".`,{httpStatus:response.status})}}validateClientIdUrl(nextUrl,this.securityConfig);redirectCount+=1;if(redirectCount>maxRedirects){throw new CimdFetchError(clientId,`CIMD fetch exceeded max redirects (${maxRedirects}). Host the metadata at the client_id URL or increase auth.cimd.network.maxRedirects.`)}this.logger.warn(`CIMD redirect ${redirectCount}/${maxRedirects}: ${currentUrl} -> ${nextUrl}`);currentUrl=nextUrl;isFirstRequest=false;continue}if(!response.ok){throw new CimdFetchError(clientId,`HTTP ${response.status} ${response.statusText}`,{httpStatus:response.status})}const contentLength=response.headers.get("content-length");if(contentLength){const length=parseInt(contentLength,10);if(!isNaN(length)&&length>this.networkConfig.maxResponseSizeBytes){throw new CimdResponseTooLargeError(clientId,this.networkConfig.maxResponseSizeBytes,length)}}const text=await this.readResponseWithLimit(response,this.networkConfig.maxResponseSizeBytes,clientId);let document;try{document=JSON.parse(text)}catch(e){throw new CimdFetchError(clientId,"Invalid JSON response",{originalError:e instanceof Error?e:new Error(String(e))})}return{document,headers:response.headers}}}catch(error){if(error instanceof CimdFetchError||error instanceof CimdResponseTooLargeError||error instanceof CimdSecurityError){throw error}if(error instanceof Error&&error.name==="AbortError"){throw new CimdFetchError(clientId,"Request timeout",{originalError:error})}throw new CimdFetchError(clientId,error instanceof Error?error.message:"Unknown error",{originalError:error instanceof Error?error:void 0})}finally{clearTimeout(timer)}}async readResponseWithLimit(response,maxBytes,clientId){const reader=response.body?.getReader();if(!reader){const buffer=await response.arrayBuffer();if(buffer.byteLength>maxBytes){throw new CimdResponseTooLargeError(clientId,maxBytes,buffer.byteLength)}return new TextDecoder().decode(buffer)}const chunks=[];let totalBytes=0;try{while(true){const{done,value}=await reader.read();if(done)break;totalBytes+=value.length;if(totalBytes>maxBytes){throw new CimdResponseTooLargeError(clientId,maxBytes,totalBytes)}chunks.push(value)}}finally{reader.releaseLock()}const combined=new Uint8Array(totalBytes);let offset=0;for(const chunk of chunks){combined.set(chunk,offset);offset+=chunk.length}return new TextDecoder().decode(combined)}validateDocument(clientId,document){const result=clientMetadataDocumentSchema.safeParse(document);if(!result.success){const errors=result.error.issues.map(issue=>{const path=issue.path.length>0?`${issue.path.join(".")}: `:"";return`${path}${issue.message}`});throw new CimdValidationError(clientId,errors)}if(result.data.client_id!==clientId){throw new CimdClientIdMismatchError(clientId,result.data.client_id)}}};var LOOPBACK_HOSTNAMES=new Set(["127.0.0.1","::1","[::1]","localhost"]);function isLoopbackHostname(hostname){return LOOPBACK_HOSTNAMES.has(hostname.toLowerCase())}function normalizeRedirectUri(uri){try{const url=new URL(uri);const host=isLoopbackHostname(url.hostname)?url.hostname.toLowerCase():url.host.toLowerCase();let normalized=`${url.protocol.toLowerCase()}//${host}`;normalized+=url.pathname.replace(/\/+$/,"")||"/";if(url.search)normalized+=url.search;return normalized}catch{return uri}}var publicAccessConfigSchema=import_lazy_zod10.z.object({tools:import_lazy_zod10.z.union([import_lazy_zod10.z.literal("all"),import_lazy_zod10.z.array(import_lazy_zod10.z.string())]).default("all"),prompts:import_lazy_zod10.z.union([import_lazy_zod10.z.literal("all"),import_lazy_zod10.z.array(import_lazy_zod10.z.string())]).default("all"),rateLimit:import_lazy_zod10.z.number().default(60)});var localSigningConfigSchema=import_lazy_zod10.z.object({signKey:jwkSchema.or(import_lazy_zod10.z.instanceof(Uint8Array)).optional(),jwks:jsonWebKeySetSchema.optional(),issuer:import_lazy_zod10.z.string().optional()});var providerConfigSchema=import_lazy_zod10.z.object({name:import_lazy_zod10.z.string().optional(),id:import_lazy_zod10.z.string().optional(),jwks:jsonWebKeySetSchema.optional(),jwksUri:import_lazy_zod10.z.string().url().optional(),additionalIssuers:import_lazy_zod10.z.array(import_lazy_zod10.z.string().trim().min(1,"additionalIssuers entries must be non-empty")).optional(),verifyIssuer:import_lazy_zod10.z.boolean().optional(),dcrEnabled:import_lazy_zod10.z.boolean().default(false),authEndpoint:import_lazy_zod10.z.string().url().optional(),tokenEndpoint:import_lazy_zod10.z.string().url().optional(),registrationEndpoint:import_lazy_zod10.z.string().url().optional(),userInfoEndpoint:import_lazy_zod10.z.string().url().optional()});var remoteProviderConfigSchema=import_lazy_zod10.z.object({provider:import_lazy_zod10.z.string().url(),name:import_lazy_zod10.z.string().optional(),id:import_lazy_zod10.z.string().optional(),jwks:jsonWebKeySetSchema.optional(),jwksUri:import_lazy_zod10.z.string().url().optional(),clientId:import_lazy_zod10.z.string().optional(),clientSecret:import_lazy_zod10.z.string().optional(),scopes:import_lazy_zod10.z.array(import_lazy_zod10.z.string()).optional(),dcrEnabled:import_lazy_zod10.z.boolean().default(false),authEndpoint:import_lazy_zod10.z.string().url().optional(),tokenEndpoint:import_lazy_zod10.z.string().url().optional(),registrationEndpoint:import_lazy_zod10.z.string().url().optional(),userInfoEndpoint:import_lazy_zod10.z.string().url().optional()});var upstreamProviderSchema=import_lazy_zod10.z.object({id:import_lazy_zod10.z.string().min(1),name:import_lazy_zod10.z.string().optional(),authorizationEndpoint:import_lazy_zod10.z.string().url().optional(),authorizeUrl:import_lazy_zod10.z.string().url().optional(),tokenEndpoint:import_lazy_zod10.z.string().url().optional(),tokenUrl:import_lazy_zod10.z.string().url().optional(),clientId:import_lazy_zod10.z.string().min(1),clientSecret:import_lazy_zod10.z.string().optional(),scopes:import_lazy_zod10.z.array(import_lazy_zod10.z.string()).optional(),userInfoEndpoint:import_lazy_zod10.z.string().url().optional(),jwksUri:import_lazy_zod10.z.string().url().optional(),issuer:import_lazy_zod10.z.string().url().optional(),additionalIssuers:import_lazy_zod10.z.array(import_lazy_zod10.z.string().trim().min(1,"additionalIssuers entries must be non-empty")).optional()}).refine(p=>!!(p.authorizationEndpoint??p.authorizeUrl),{message:"authorizationEndpoint (or authorizeUrl) is required",path:["authorizationEndpoint"]}).refine(p=>!!(p.tokenEndpoint??p.tokenUrl),{message:"tokenEndpoint (or tokenUrl) is required",path:["tokenEndpoint"]}).refine(p=>!(p.authorizationEndpoint&&p.authorizeUrl),{message:"provide only one of authorizationEndpoint or authorizeUrl",path:["authorizationEndpoint"]}).refine(p=>!(p.tokenEndpoint&&p.tokenUrl),{message:"provide only one of tokenEndpoint or tokenUrl",path:["tokenEndpoint"]});var localDcrClientSchema=import_lazy_zod10.z.object({clientId:import_lazy_zod10.z.string().min(1),clientSecret:import_lazy_zod10.z.string().min(1).optional(),redirectUris:import_lazy_zod10.z.array(import_lazy_zod10.z.string().url()).min(1,"At least one redirect_uri is required"),clientName:import_lazy_zod10.z.string().optional(),tokenEndpointAuthMethod:import_lazy_zod10.z.enum(["none","client_secret_basic","client_secret_post"]).default("none"),grantTypes:import_lazy_zod10.z.array(import_lazy_zod10.z.enum(["authorization_code","refresh_token"])).default(["authorization_code"]),responseTypes:import_lazy_zod10.z.array(import_lazy_zod10.z.enum(["code"])).default(["code"]),scope:import_lazy_zod10.z.string().optional()});var localDcrConfigSchema=import_lazy_zod10.z.object({enabled:import_lazy_zod10.z.boolean().optional(),allowedRedirectUris:import_lazy_zod10.z.array(import_lazy_zod10.z.string().min(1)).optional(),allowedClientIds:import_lazy_zod10.z.array(import_lazy_zod10.z.string().min(1)).optional(),initialAccessToken:import_lazy_zod10.z.string().min(1).optional(),clients:import_lazy_zod10.z.array(localDcrClientSchema).optional(),maxDynamicClients:import_lazy_zod10.z.number().int().min(0).optional()});var flatRemoteProviderFields={provider:import_lazy_zod10.z.string().url(),clientId:import_lazy_zod10.z.string().optional(),clientSecret:import_lazy_zod10.z.string().optional(),scopes:import_lazy_zod10.z.array(import_lazy_zod10.z.string()).optional(),providerConfig:providerConfigSchema.optional()};var tokenStorageSqliteSchema=import_lazy_zod10.z.object({path:import_lazy_zod10.z.string().min(1),encryption:import_lazy_zod10.z.object({secret:import_lazy_zod10.z.string().min(1)}).optional(),ttlCleanupIntervalMs:import_lazy_zod10.z.number().int().nonnegative().optional(),walMode:import_lazy_zod10.z.boolean().optional(),busyTimeoutMs:import_lazy_zod10.z.number().int().nonnegative().optional()});var tokenStorageConfigSchema=import_lazy_zod10.z.union([import_lazy_zod10.z.literal("memory"),import_lazy_zod10.z.object({redis:redisConfigSchema}),import_lazy_zod10.z.object({sqlite:tokenStorageSqliteSchema})]);var secureStoreScopeSchema=import_lazy_zod10.z.enum(["user","session","global"]);var secureStoreEncryptionSchema=import_lazy_zod10.z.object({pepper:import_lazy_zod10.z.string().min(1).optional()});var secureStoreCustomBackendSchema=import_lazy_zod10.z.custom(v=>typeof v==="object"&&v!==null&&typeof v.get==="function"&&typeof v.set==="function"&&typeof v.delete==="function"&&typeof v.list==="function",{message:"secureStore.backend must implement get/set/delete/list (SecureStoreBackend)"});var secureStoreCommonFields={scope:secureStoreScopeSchema.optional(),ttlMs:import_lazy_zod10.z.number().int().positive().optional(),encryption:secureStoreEncryptionSchema.optional()};var secureStoreConfigSchema=import_lazy_zod10.z.union([import_lazy_zod10.z.literal("memory"),import_lazy_zod10.z.object({sqlite:tokenStorageSqliteSchema,...secureStoreCommonFields}),import_lazy_zod10.z.object({redis:redisConfigSchema,...secureStoreCommonFields}),import_lazy_zod10.z.object({backend:secureStoreCustomBackendSchema,...secureStoreCommonFields}),import_lazy_zod10.z.object({...secureStoreCommonFields})]);var tokenRefreshConfigSchema=import_lazy_zod10.z.object({enabled:import_lazy_zod10.z.boolean().default(true),skewSeconds:import_lazy_zod10.z.number().nonnegative().default(60)});var skippedAppBehaviorSchema=import_lazy_zod10.z.enum(["anonymous","require-auth"]);var consentConfigSchema=import_lazy_zod10.z.object({enabled:import_lazy_zod10.z.boolean().default(false),groupByApp:import_lazy_zod10.z.boolean().default(true),showDescriptions:import_lazy_zod10.z.boolean().default(true),allowSelectAll:import_lazy_zod10.z.boolean().default(true),requireSelection:import_lazy_zod10.z.boolean().default(true),customMessage:import_lazy_zod10.z.string().optional(),rememberConsent:import_lazy_zod10.z.boolean().default(true),excludedTools:import_lazy_zod10.z.array(import_lazy_zod10.z.string()).optional(),defaultSelectedTools:import_lazy_zod10.z.array(import_lazy_zod10.z.string()).optional()});var federatedAuthConfigSchema=import_lazy_zod10.z.object({stateValidation:import_lazy_zod10.z.enum(["strict","format"]).default("strict"),minProviders:import_lazy_zod10.z.number().int().positive().optional(),requiredProviders:import_lazy_zod10.z.array(import_lazy_zod10.z.string()).optional()});var incrementalAuthConfigSchema=import_lazy_zod10.z.object({enabled:import_lazy_zod10.z.boolean().default(true),skippedAppBehavior:skippedAppBehaviorSchema.default("anonymous"),allowSkip:import_lazy_zod10.z.boolean().default(true),showAllAppsAtOnce:import_lazy_zod10.z.boolean().default(true)});var import_lazy_zod11=require("@frontmcp/lazy-zod");var publicAuthOptionsSchema=import_lazy_zod11.z.object({mode:import_lazy_zod11.z.literal("public"),issuer:import_lazy_zod11.z.string().optional(),sessionTtl:import_lazy_zod11.z.number().int().positive().default(3600),anonymousScopes:import_lazy_zod11.z.array(import_lazy_zod11.z.string()).default(["anonymous"]),publicAccess:publicAccessConfigSchema.optional(),jwks:jsonWebKeySetSchema.optional(),signKey:jwkSchema.or(import_lazy_zod11.z.instanceof(Uint8Array)).optional()});var import_lazy_zod12=require("@frontmcp/lazy-zod");var staticAuthOptionsSchema=import_lazy_zod12.z.object({mode:import_lazy_zod12.z.literal("static"),tokens:import_lazy_zod12.z.array(import_lazy_zod12.z.string().min(1)).min(1),header:import_lazy_zod12.z.string().min(1).default("authorization"),scheme:import_lazy_zod12.z.string().default("Bearer"),scopes:import_lazy_zod12.z.array(import_lazy_zod12.z.string()).default(["static"]),realm:import_lazy_zod12.z.string().default("mcp"),publicAccess:publicAccessConfigSchema.optional()});var import_lazy_zod13=require("@frontmcp/lazy-zod");var transparentAuthOptionsSchema=import_lazy_zod13.z.object({mode:import_lazy_zod13.z.literal("transparent"),...flatRemoteProviderFields,expectedAudience:import_lazy_zod13.z.union([import_lazy_zod13.z.string(),import_lazy_zod13.z.array(import_lazy_zod13.z.string())]).optional(),requireAudience:import_lazy_zod13.z.boolean().optional(),requiredScopes:import_lazy_zod13.z.array(import_lazy_zod13.z.string()).default([]),allowAnonymous:import_lazy_zod13.z.boolean().default(false),anonymousScopes:import_lazy_zod13.z.array(import_lazy_zod13.z.string()).default(["anonymous"]),publicAccess:publicAccessConfigSchema.optional()});var import_lazy_zod14=require("@frontmcp/lazy-zod");var authSlotSchema=import_lazy_zod14.z.enum(["login","consent","incremental","federated","error"]);var authUiMapSchema=import_lazy_zod14.z.partialRecord(authSlotSchema,import_lazy_zod14.z.string().min(1));var authExtraHandlerSchema=import_lazy_zod14.z.custom(v=>typeof v==="function",{message:"auth.extras entries must be handler functions (input, ctx) => AuthExtraResult."});var authExtrasMapSchema=import_lazy_zod14.z.record(import_lazy_zod14.z.string().min(1),authExtraHandlerSchema);var sharedAuthFields={local:localSigningConfigSchema.optional(),tokenStorage:tokenStorageConfigSchema.default("memory"),secureStore:secureStoreConfigSchema.optional(),allowDefaultPublic:import_lazy_zod14.z.boolean().default(false),anonymousScopes:import_lazy_zod14.z.array(import_lazy_zod14.z.string()).default(["anonymous"]),publicAccess:publicAccessConfigSchema.optional(),consent:consentConfigSchema.optional(),federatedAuth:federatedAuthConfigSchema.optional(),refresh:tokenRefreshConfigSchema.optional(),expectedAudience:import_lazy_zod14.z.union([import_lazy_zod14.z.string(),import_lazy_zod14.z.array(import_lazy_zod14.z.string())]).optional(),incrementalAuth:incrementalAuthConfigSchema.optional(),requireRegisteredClients:import_lazy_zod14.z.boolean().default(true),allowedScopes:import_lazy_zod14.z.array(import_lazy_zod14.z.string().trim().min(1,"allowedScopes entries must be non-empty")).optional(),cimd:cimdConfigSchema.optional(),ui:authUiMapSchema.optional(),extras:authExtrasMapSchema.optional()};var loginFieldSchema=import_lazy_zod14.z.object({type:import_lazy_zod14.z.enum(["text","password","email","select","hidden"]),label:import_lazy_zod14.z.string().optional(),required:import_lazy_zod14.z.boolean().optional(),placeholder:import_lazy_zod14.z.string().optional(),options:import_lazy_zod14.z.array(import_lazy_zod14.z.object({value:import_lazy_zod14.z.string(),label:import_lazy_zod14.z.string()})).optional()});var loginConfigSchema=import_lazy_zod14.z.object({title:import_lazy_zod14.z.string().optional(),subtitle:import_lazy_zod14.z.string().optional(),logoUri:import_lazy_zod14.z.string().optional(),fields:import_lazy_zod14.z.record(import_lazy_zod14.z.string(),loginFieldSchema).optional(),render:import_lazy_zod14.z.custom(v=>typeof v==="function",{message:"login.render must be a function"}).optional(),subject:import_lazy_zod14.z.object({fromField:import_lazy_zod14.z.string().optional(),strategy:import_lazy_zod14.z.enum(["per-session","per-account"]).optional()}).optional()});var authenticateFnSchema=import_lazy_zod14.z.custom(v=>typeof v==="function",{message:"authenticate must be a function"});var localAuthSchema=import_lazy_zod14.z.object({mode:import_lazy_zod14.z.literal("local"),...sharedAuthFields,requireEmail:import_lazy_zod14.z.boolean().default(true),anonymousSubject:import_lazy_zod14.z.string().min(1).default("local-operator"),login:loginConfigSchema.optional(),authenticate:authenticateFnSchema.optional(),providers:import_lazy_zod14.z.array(upstreamProviderSchema).optional(),dcr:localDcrConfigSchema.optional()});var remoteAuthSchema=import_lazy_zod14.z.object({mode:import_lazy_zod14.z.literal("remote"),...flatRemoteProviderFields,...sharedAuthFields});var orchestratedLocalSchema=localAuthSchema;var orchestratedRemoteSchema=remoteAuthSchema;var import_lazy_zod15=require("@frontmcp/lazy-zod");var authOptionsSchema=import_lazy_zod15.z.union([publicAuthOptionsSchema,staticAuthOptionsSchema,transparentAuthOptionsSchema,localAuthSchema,remoteAuthSchema]);var import_lazy_zod16=require("@frontmcp/lazy-zod");var standaloneOptionSchema={standalone:import_lazy_zod16.z.boolean().optional(),excludeFromParent:import_lazy_zod16.z.boolean().optional()};var appAuthOptionsSchema=import_lazy_zod16.z.union([publicAuthOptionsSchema.extend(standaloneOptionSchema),transparentAuthOptionsSchema.extend(standaloneOptionSchema),localAuthSchema.extend(standaloneOptionSchema),remoteAuthSchema.extend(standaloneOptionSchema)]);function parseAuthOptions(input){return authOptionsSchema.parse(input)}function isPublicMode(options){return options.mode==="public"}function isStaticMode(options){return options.mode==="static"}function isTransparentMode(options){return options.mode==="transparent"}function isLocalMode(options){return options.mode==="local"}function isRemoteMode(options){return options.mode==="remote"}function isOrchestratedMode(options){return options.mode==="local"||options.mode==="remote"}function isOrchestratedLocal(options){return options.mode==="local"}function isOrchestratedRemote(options){return options.mode==="remote"}function allowsPublicAccess(options){if(options.mode==="public")return true;if(options.mode==="transparent")return options.allowAnonymous;if(options.mode==="local"||options.mode==="remote")return options.allowDefaultPublic;return false}var import_lazy_zod17=require("@frontmcp/lazy-zod");var consentToolItemSchema=import_lazy_zod17.z.object({id:import_lazy_zod17.z.string().min(1),name:import_lazy_zod17.z.string().min(1),description:import_lazy_zod17.z.string().optional(),appId:import_lazy_zod17.z.string().min(1),appName:import_lazy_zod17.z.string().min(1),defaultSelected:import_lazy_zod17.z.boolean().default(true),requiredScopes:import_lazy_zod17.z.array(import_lazy_zod17.z.string()).optional(),category:import_lazy_zod17.z.string().optional()});var consentSelectionSchema=import_lazy_zod17.z.object({selectedTools:import_lazy_zod17.z.array(import_lazy_zod17.z.string()),allSelected:import_lazy_zod17.z.boolean(),consentedAt:import_lazy_zod17.z.string().datetime(),consentVersion:import_lazy_zod17.z.string().default("1.0")});var consentStateSchema=import_lazy_zod17.z.object({enabled:import_lazy_zod17.z.boolean(),availableTools:import_lazy_zod17.z.array(consentToolItemSchema),preselectedTools:import_lazy_zod17.z.array(import_lazy_zod17.z.string()).optional(),groupByApp:import_lazy_zod17.z.boolean().default(true),customMessage:import_lazy_zod17.z.string().optional()});var federatedProviderItemSchema=import_lazy_zod17.z.object({id:import_lazy_zod17.z.string().min(1),name:import_lazy_zod17.z.string().min(1),description:import_lazy_zod17.z.string().optional(),icon:import_lazy_zod17.z.string().optional(),type:import_lazy_zod17.z.enum(["local","remote","transparent"]),providerUrl:import_lazy_zod17.z.string().url().optional(),appIds:import_lazy_zod17.z.array(import_lazy_zod17.z.string()),appNames:import_lazy_zod17.z.array(import_lazy_zod17.z.string()),scopes:import_lazy_zod17.z.array(import_lazy_zod17.z.string()),isPrimary:import_lazy_zod17.z.boolean(),isOptional:import_lazy_zod17.z.boolean().default(false)});var federatedLoginStateSchema=import_lazy_zod17.z.object({providers:import_lazy_zod17.z.array(federatedProviderItemSchema),primaryProviderId:import_lazy_zod17.z.string().optional(),allowSkip:import_lazy_zod17.z.boolean().default(true),preselectedProviders:import_lazy_zod17.z.array(import_lazy_zod17.z.string()).optional()});var federatedSelectionSchema=import_lazy_zod17.z.object({selectedProviders:import_lazy_zod17.z.array(import_lazy_zod17.z.string()),skippedProviders:import_lazy_zod17.z.array(import_lazy_zod17.z.string()),providerMetadata:import_lazy_zod17.z.record(import_lazy_zod17.z.string(),import_lazy_zod17.z.unknown()).optional()});var import_lazy_zod18=require("@frontmcp/lazy-zod");var detectedAuthProviderSchema=import_lazy_zod18.z.object({id:import_lazy_zod18.z.string(),providerUrl:import_lazy_zod18.z.string().optional(),mode:import_lazy_zod18.z.enum(["public","static","transparent","local","remote"]),appIds:import_lazy_zod18.z.array(import_lazy_zod18.z.string()),scopes:import_lazy_zod18.z.array(import_lazy_zod18.z.string()),isParentProvider:import_lazy_zod18.z.boolean()});var authProviderDetectionResultSchema=import_lazy_zod18.z.object({providers:import_lazy_zod18.z.map(import_lazy_zod18.z.string(),detectedAuthProviderSchema),requiresOrchestration:import_lazy_zod18.z.boolean(),parentProviderId:import_lazy_zod18.z.string().optional(),childProviderIds:import_lazy_zod18.z.array(import_lazy_zod18.z.string()),uniqueProviderCount:import_lazy_zod18.z.number(),validationErrors:import_lazy_zod18.z.array(import_lazy_zod18.z.string()),warnings:import_lazy_zod18.z.array(import_lazy_zod18.z.string())});function deriveProviderId(options){if(isPublicMode(options)){return options.issuer??"public"}if(isTransparentMode(options)){return options.providerConfig?.id??urlToProviderId(options.provider)}if(isOrchestratedMode(options)){if(isOrchestratedRemote(options)){return options.providerConfig?.id??urlToProviderId(options.provider)}return options.local?.issuer??"local"}return"unknown"}function urlToProviderId(url){try{const parsed=new URL(url);return parsed.hostname.replace(/\./g,"_")}catch{return url.replace(/[^a-zA-Z0-9]/g,"_")}}function extractScopes(options){if(isTransparentMode(options)){return options.requiredScopes||[]}if(isOrchestratedMode(options)){if(isOrchestratedRemote(options)){return options.scopes||[]}}return[]}function detectAuthProviders(parentAuth,apps){const providers=new Map;const validationErrors=[];const warnings=[];let parentProviderId;if(parentAuth){parentProviderId=deriveProviderId(parentAuth);providers.set(parentProviderId,{id:parentProviderId,providerUrl:getProviderUrl(parentAuth),mode:parentAuth.mode,appIds:["__parent__"],scopes:extractScopes(parentAuth),isParentProvider:true})}for(const app of apps){if(!app.auth){continue}const providerId=deriveProviderId(app.auth);const existing=providers.get(providerId);if(existing){existing.appIds.push(app.id);const newScopes=extractScopes(app.auth);existing.scopes=[...new Set([...existing.scopes,...newScopes])]}else{providers.set(providerId,{id:providerId,providerUrl:getProviderUrl(app.auth),mode:app.auth.mode,appIds:[app.id],scopes:extractScopes(app.auth),isParentProvider:false})}}const childProviderIds=[...providers.keys()].filter(id=>id!==parentProviderId);const uniqueProviderCount=providers.size;const hasMultipleProviders=uniqueProviderCount>1;const hasChildOnlyProviders=childProviderIds.length>0&&!parentProviderId;const requiresOrchestration=hasMultipleProviders||hasChildOnlyProviders||childProviderIds.length>0&&parentProviderId!==void 0;if(requiresOrchestration&&parentAuth&&isTransparentMode(parentAuth)){validationErrors.push(`Invalid auth configuration: Parent uses transparent mode but apps have their own auth providers. Transparent mode passes tokens through without modification, which is incompatible with multi-provider setups. Change parent auth to local or remote mode to properly manage tokens for each provider. Detected providers: ${[...providers.keys()].join(", ")}`)}const sharedEndpointUnenforced=!parentAuth||isPublicMode(parentAuth)||isStaticMode(parentAuth);const unenforcedAppIds=apps.filter(app=>app.auth&&!isPublicMode(app.auth)&&!staticParentEnforces(parentAuth,app.auth)).map(app=>app.id);if(sharedEndpointUnenforced&&unenforcedAppIds.length>0){validationErrors.push(`App-level auth is not enforced on the shared endpoint of a server in ${parentAuth?.mode??"public"} mode, so the tools of ${unenforcedAppIds.join(", ")} would be served without it. Serve the app on its own endpoint with standalone: true or splitByApp: true, or run the server in local or remote mode with incrementalAuth enabled, which checks each tool call against the apps the caller has authorized (without incrementalAuth, local and remote mode do not check app grants per tool call).`)}const tokenMintingAppIds=apps.filter(app=>app.remoteAuthMode==="forward"&&!(parentAuth&&isTransparentMode(parentAuth))).map(app=>app.id);if(tokenMintingAppIds.length>0){validationErrors.push(`remoteAuth: { mode: 'forward' } on ${tokenMintingAppIds.join(", ")} would send the remote a token this server minted or holds itself: only a server in transparent mode receives its callers' tokens from the identity provider. Use remoteAuth: { mode: 'static', credentials } (or transportOptions.headers) for the remote, or run the server in transparent mode.`)}return{providers,requiresOrchestration,parentProviderId,childProviderIds,uniqueProviderCount,validationErrors,warnings}}function staticParentEnforces(parentAuth,appAuth){if(!parentAuth||!isStaticMode(parentAuth)||!isStaticMode(appAuth))return false;const parent=staticAuthOptionsSchema.safeParse(parentAuth);const app=staticAuthOptionsSchema.safeParse(appAuth);if(!parent.success||!app.success)return false;const sameChallenge=parent.data.header.toLowerCase()===app.data.header.toLowerCase()&&parent.data.scheme===app.data.scheme;return sameChallenge&&parent.data.tokens.every(token=>app.data.tokens.includes(token))}function getProviderUrl(options){if(isTransparentMode(options)){return options.provider}if(isOrchestratedMode(options)&&isOrchestratedRemote(options)){return options.provider}return void 0}function appRequiresOrchestration(appAuth,parentAuth){if(!appAuth){return false}if(!parentAuth){return appAuth.mode!=="public"}const appProviderId=deriveProviderId(appAuth);const parentProviderId=deriveProviderId(parentAuth);return appProviderId!==parentProviderId}function getProviderScopes(detection,providerId){const provider=detection.providers.get(providerId);return provider?.scopes??[]}function getProviderApps(detection,providerId){const provider=detection.providers.get(providerId);return provider?.appIds.filter(id=>id!=="__parent__")??[]}function buildWwwAuthenticate(options={}){const parts=["Bearer"];const params=[];if(options.resourceMetadataUrl){params.push(`resource_metadata="${escapeQuotedString(options.resourceMetadataUrl)}"`)}if(options.realm){params.push(`realm="${escapeQuotedString(options.realm)}"`)}if(options.error){params.push(`error="${options.error}"`)}if(options.errorDescription){params.push(`error_description="${escapeQuotedString(options.errorDescription)}"`)}if(options.errorUri){params.push(`error_uri="${escapeQuotedString(options.errorUri)}"`)}if(options.scope){const scopeValue=Array.isArray(options.scope)?options.scope.join(" "):options.scope;params.push(`scope="${escapeQuotedString(scopeValue)}"`)}if(params.length>0){parts.push(params.join(", "))}return parts.join(" ")}function buildPrmUrl(baseUrl,entryPath,routeBase){const normalizedEntry=normalizePathSegment(entryPath);const normalizedRoute=normalizePathSegment(routeBase);return`${baseUrl}/.well-known/oauth-protected-resource${normalizedEntry}${normalizedRoute}`}function buildUnauthorizedHeader(prmUrl){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl})}function buildInvalidTokenHeader(prmUrl,description){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl,error:"invalid_token",errorDescription:description??"The access token is invalid or expired"})}function buildInsufficientScopeHeader(prmUrl,requiredScopes,description){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl,error:"insufficient_scope",scope:requiredScopes,errorDescription:description??"The request requires higher privileges"})}function buildInvalidRequestHeader(prmUrl,description){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl,error:"invalid_request",errorDescription:description??"The request is missing required parameters"})}function parseWwwAuthenticate(header){const result={};if(!header.toLowerCase().startsWith("bearer")){return result}const paramString=header.substring(6).trim();const params=parseQuotedParams(paramString);for(const[key,value]of params){const unescapedValue=unescapeQuotedString(value);switch(key.toLowerCase()){case"resource_metadata":result.resourceMetadataUrl=unescapedValue;break;case"realm":result.realm=unescapedValue;break;case"error":result.error=unescapedValue;break;case"error_description":result.errorDescription=unescapedValue;break;case"error_uri":result.errorUri=unescapedValue;break;case"scope":result.scope=unescapedValue;break}}return result}function parseQuotedParams(input){const result=[];let i=0;const len=input.length;while(i<len){while(i<len&&(input[i]===" "||input[i]===","||input[i]===" ")){i++}if(i>=len)break;const keyStart=i;while(i<len&&/\w/.test(input[i])){i++}const key=input.slice(keyStart,i);if(!key)break;while(i<len&&(input[i]===" "||input[i]===" ")){i++}if(i>=len||input[i]!=="="){while(i<len&&input[i]!==",")i++;continue}i++;while(i<len&&(input[i]===" "||input[i]===" ")){i++}if(i>=len||input[i]!=='"'){while(i<len&&input[i]!==",")i++;continue}i++;let value="";while(i<len&&input[i]!=='"'){if(input[i]==="\\"&&i+1<len){value+=input[i+1];i+=2}else{value+=input[i];i++}}if(i<len&&input[i]==='"'){i++}result.push([key,value])}return result}function escapeQuotedString(value){return value.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function unescapeQuotedString(value){return value.replace(/\\(.)/g,"$1")}function normalizePathSegment(path){if(!path||path==="/")return"";const normalized=path.startsWith("/")?path:`/${path}`;let end=normalized.length;while(end>0&&normalized[end-1]==="/"){end--}return normalized.slice(0,end)}function validateAudience(tokenAudience,options){const{expectedAudiences,allowNoAudience=false,caseSensitive=true,allowWildcards=false}=options;if(tokenAudience===void 0||tokenAudience===null){if(allowNoAudience){return{valid:true}}return{valid:false,error:"Token is missing audience claim"}}if(expectedAudiences.length===0){return{valid:false,error:"No expected audiences configured - cannot validate token"}}const tokenAuds=Array.isArray(tokenAudience)?tokenAudience:[tokenAudience];for(const tokenAud of tokenAuds){for(const expectedAud of expectedAudiences){if(matchesAudience(tokenAud,expectedAud,caseSensitive,allowWildcards)){return{valid:true,matchedAudience:tokenAud}}}}return{valid:false,error:`Token audience does not match expected audiences. Got: ${tokenAuds.join(", ")}. Expected one of: ${expectedAudiences.join(", ")}`}}function matchesAudience(tokenAud,expectedAud,caseSensitive,allowWildcards){if(caseSensitive){if(tokenAud===expectedAud)return true}else{if(tokenAud.toLowerCase()===expectedAud.toLowerCase())return true}if(allowWildcards&&expectedAud.includes("*")){const wildcardCount=(expectedAud.match(/\*/g)||[]).length;if(wildcardCount>2){return false}const pattern=expectedAud.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^.]*");const regex=new RegExp(`^${pattern}$`,caseSensitive?"":"i");if(regex.test(tokenAud))return true}return false}function createAudienceValidator(options){return audience=>validateAudience(audience,options)}function deriveExpectedAudience(resourceUrl){const audiences=[];try{const url=new URL(resourceUrl);audiences.push(resourceUrl.replace(/\/$/,""));if(url.pathname!=="/"&&url.pathname!==""){audiences.push(url.origin)}}catch{audiences.push(resourceUrl)}return[...new Set(audiences)]}var AudienceValidator=class _AudienceValidator{options;constructor(options={}){this.options={expectedAudiences:[...options.expectedAudiences??[]],allowNoAudience:options.allowNoAudience??false,caseSensitive:options.caseSensitive??true,allowWildcards:options.allowWildcards??false}}validate(audience){return validateAudience(audience,this.options)}addAudiences(...audiences){this.options.expectedAudiences.push(...audiences)}setAudiences(audiences){this.options.expectedAudiences=audiences}static fromResourceUrl(resourceUrl,options={}){return new _AudienceValidator({...options,expectedAudiences:deriveExpectedAudience(resourceUrl)})}};var DEFAULT_ALLOWED_SCOPES=Object.freeze(["openid","profile","email","offline_access"]);function grantScopes(requested,allowed){const patterns=allowed??DEFAULT_ALLOWED_SCOPES;const granted=[];for(const scope of requested){if(!scope||granted.includes(scope))continue;if(patterns.some(pattern=>globMatch(pattern,scope)))granted.push(scope)}return granted}function advertisedScopes(allowed){const scopes=[];for(const scope of allowed??DEFAULT_ALLOWED_SCOPES){if(scope&&!scope.includes("*")&&!scopes.includes(scope))scopes.push(scope)}return scopes}function resourceScopesFor(options){const mode=options?.mode??"public";if(mode==="local"||mode==="remote")return advertisedScopes(options?.allowedScopes);const listed=mode==="public"?options?.anonymousScopes??["anonymous"]:mode==="static"?options?.scopes??["static"]:mode==="transparent"?[...options?.requiredScopes??[],...options?.scopes??[]]:[];return advertisedScopes(listed)}function isLoopbackRedirectUri(uri){let url;try{url=new URL(uri)}catch{return false}if(url.protocol!=="http:"&&url.protocol!=="https:")return false;if(url.username||url.password)return false;const host=url.hostname.replace(/^\[|\]$/g,"").toLowerCase();if(host==="localhost"||host==="::1")return true;const m=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);if(m){const octets=m.slice(1).map(n=>Number(n));return octets.every(o=>o>=0&&o<=255)&&octets[0]===127}return false}function scopesFromClaims(claims){const scopes=[claims?.scope,claims?.scp].flatMap(claim=>{if(typeof claim==="string")return claim.split(/\s+/).filter(Boolean);if(Array.isArray(claim))return claim.filter(scope=>typeof scope==="string");return[]});return[...new Set(scopes)]}var import_lazy_zod19=require("@frontmcp/lazy-zod");var credentialScopeSchema=import_lazy_zod19.z.enum(["global","user","session"]);var loadingStrategySchema=import_lazy_zod19.z.enum(["eager","lazy"]);var getCredentialOptionsSchema=import_lazy_zod19.z.object({forceRefresh:import_lazy_zod19.z.boolean().optional(),scopes:import_lazy_zod19.z.array(import_lazy_zod19.z.string()).optional(),timeout:import_lazy_zod19.z.number().positive().optional()}).strict();var credentialProviderConfigSchema=import_lazy_zod19.z.object({name:import_lazy_zod19.z.string().min(1),description:import_lazy_zod19.z.string().optional(),scope:credentialScopeSchema,loading:loadingStrategySchema,cacheTtl:import_lazy_zod19.z.number().nonnegative().optional(),factory:import_lazy_zod19.z.any(),refresh:import_lazy_zod19.z.any().optional(),toHeaders:import_lazy_zod19.z.any().optional(),metadata:import_lazy_zod19.z.record(import_lazy_zod19.z.string(),import_lazy_zod19.z.unknown()).optional(),required:import_lazy_zod19.z.boolean().optional()}).strict();var authProviderMappingSchema=import_lazy_zod19.z.union([import_lazy_zod19.z.string(),import_lazy_zod19.z.object({name:import_lazy_zod19.z.string().min(1),required:import_lazy_zod19.z.boolean().optional().default(true),scopes:import_lazy_zod19.z.array(import_lazy_zod19.z.string()).optional(),alias:import_lazy_zod19.z.string().optional()}).strict()]);var authProvidersVaultOptionsSchema=import_lazy_zod19.z.object({enabled:import_lazy_zod19.z.boolean().optional(),useSharedStorage:import_lazy_zod19.z.boolean().optional().default(true),namespace:import_lazy_zod19.z.string().optional().default("authproviders:"),defaultCacheTtl:import_lazy_zod19.z.number().nonnegative().optional().default(36e5),maxCredentialsPerSession:import_lazy_zod19.z.number().positive().optional().default(100),providers:import_lazy_zod19.z.array(credentialProviderConfigSchema).optional()}).strict();function extractCredentialExpiry(credential){switch(credential.type){case"oauth":case"oauth_pkce":case"bearer":case"service_account":return credential.expiresAt;default:return void 0}}var CredentialCache=class{cache=new Map;maxSize;stats={hits:0,misses:0,evictions:0,size:0};constructor(maxSize=100){this.maxSize=maxSize}get(providerId){const entry=this.cache.get(providerId);if(!entry){this.stats.misses++;return void 0}if(this.isExpired(entry)){this.cache.delete(providerId);this.stats.size=this.cache.size;this.stats.misses++;this.stats.evictions++;return void 0}if(entry.resolved.expiresAt&&Date.now()>=entry.resolved.expiresAt){this.cache.delete(providerId);this.stats.size=this.cache.size;this.stats.misses++;this.stats.evictions++;return void 0}this.stats.hits++;return entry.resolved}set(providerId,resolved,ttl=0){if(this.cache.size>=this.maxSize&&!this.cache.has(providerId)){this.evictOldest()}const entry={resolved,cachedAt:Date.now(),ttl};this.cache.set(providerId,entry);this.stats.size=this.cache.size}has(providerId){const entry=this.cache.get(providerId);if(!entry)return false;if(this.isExpired(entry)){this.cache.delete(providerId);this.stats.size=this.cache.size;this.stats.evictions++;return false}return true}invalidate(providerId){const deleted=this.cache.delete(providerId);if(deleted){this.stats.size=this.cache.size}return deleted}invalidateAll(){this.cache.clear();this.stats.size=0}invalidateByScope(scope){for(const[key,entry]of this.cache){if(entry.resolved.scope===scope){this.cache.delete(key)}}this.stats.size=this.cache.size}keys(){this.cleanup();return[...this.cache.keys()]}get size(){return this.cache.size}getStats(){return{...this.stats}}resetStats(){this.stats={hits:0,misses:0,evictions:0,size:this.cache.size}}cleanup(){const now=Date.now();for(const[key,entry]of this.cache){if(this.isExpiredAt(entry,now)){this.cache.delete(key);this.stats.evictions++}}this.stats.size=this.cache.size}isExpired(entry){return this.isExpiredAt(entry,Date.now())}isExpiredAt(entry,now){if(entry.ttl>0&&now-entry.cachedAt>=entry.ttl){return true}if(entry.resolved.expiresAt&&now>=entry.resolved.expiresAt){return true}if(!entry.resolved.isValid){return true}return false}evictOldest(){let oldestKey;let oldestTime=Infinity;for(const[key,entry]of this.cache){if(entry.cachedAt<oldestTime){oldestTime=entry.cachedAt;oldestKey=key}}if(oldestKey){this.cache.delete(oldestKey);this.stats.evictions++;this.stats.size=this.cache.size}}};var AUTH_PROVIDERS_ACCESSOR=Symbol.for("frontmcp:AUTH_PROVIDERS_ACCESSOR");var import_utils48=require("@frontmcp/utils");var AuthProvidersAccessorImpl=class{constructor(registry,vault,cache,loader,context,logger){this.registry=registry;this.vault=vault;this.cache=cache;this.loader=loader;this.context=context;this.logger=logger}registry;vault;cache;loader;context;logger;async get(providerName,options){const config=this.registry.get(providerName);if(!config){this.logger?.debug(`Provider "${providerName}" is not registered`);return null}if(!options?.forceRefresh){const cached=this.cache.get(providerName);if(cached&&this.isValid(cached)){this.logger?.debug(`Cache hit for "${providerName}"`);return cached}}if(!options?.forceRefresh){const fromVault=await this.loadFromVault(providerName,config);if(fromVault&&this.isValid(fromVault)){this.cache.set(providerName,fromVault,config.cacheTtl);this.logger?.debug(`Vault hit for "${providerName}"`);return fromVault}}const loaded=await this.loader.load(config,this.context);if(!loaded){return null}await this.storeInVault(providerName,loaded,config);this.cache.set(providerName,loaded,config.cacheTtl);return loaded}async getMany(providerNames,options){const results=new Map;const promises=providerNames.map(async name=>{const result=await this.get(name,options);return{name,result}});const settled=await Promise.allSettled(promises);for(const outcome of settled){if(outcome.status==="fulfilled"){results.set(outcome.value.name,outcome.value.result)}else{this.logger?.warn("Failed to load credential:",outcome.reason)}}return results}async headers(providerName){const resolved=await this.get(providerName);if(!resolved){return{}}const config=this.registry.get(providerName);if(config?.toHeaders){return config.toHeaders(resolved.credential)}return this.defaultHeaders(resolved.credential)}async headersMany(providerNames){const allHeaders={};for(const name of providerNames){const headers=await this.headers(name);Object.assign(allHeaders,headers)}return allHeaders}async refresh(providerName){const config=this.registry.get(providerName);if(!config){this.logger?.debug(`Cannot refresh: provider "${providerName}" not registered`);return null}const existing=this.cache.get(providerName);const existingCredential=existing?.credential;try{const refreshed=await this.loader.refresh(config,{...this.context,existingCredential});if(!refreshed){return null}await this.storeInVault(providerName,refreshed,config);this.cache.set(providerName,refreshed,config.cacheTtl);return refreshed}catch(error){this.logger?.warn(`Failed to refresh credential "${providerName}":`,error);return null}}async has(providerName){const cached=this.cache.get(providerName);if(cached){if(this.isValid(cached)){return true}this.cache.invalidate(providerName)}const config=this.registry.get(providerName);if(!config){return false}const fromVault=await this.loadFromVault(providerName,config);return fromVault!==null&&this.isValid(fromVault)}isRegistered(providerName){return this.registry.has(providerName)}invalidate(providerName){this.cache.invalidate(providerName);this.logger?.debug(`Invalidated cache for "${providerName}"`)}invalidateAll(){this.cache.invalidateAll();this.logger?.debug("Invalidated all cached credentials")}listProviders(){return this.registry.getNames()}async listAvailable(){const available=[];for(const name of this.registry.getNames()){if(await this.has(name)){available.push(name)}}return available}async loadFromVault(providerName,config){try{const credential=await this.vault.getCredential(this.context.sessionId,providerName,config.scope,this.context.userSub);if(!credential){return null}return{credential,providerId:providerName,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope}}catch(error){this.logger?.warn(`Failed to load from vault "${providerName}":`,error);return null}}async storeInVault(providerName,resolved,config){try{await this.vault.storeCredential(this.context.sessionId,providerName,resolved.credential,config.scope,this.context.userSub)}catch(error){this.logger?.warn(`Failed to store in vault "${providerName}":`,error)}}isValid(resolved){if(!resolved.isValid){return false}if(resolved.expiresAt&&Date.now()>=resolved.expiresAt){return false}return true}defaultHeaders(credential){switch(credential.type){case"oauth":case"oauth_pkce":return{Authorization:`${credential.tokenType} ${credential.accessToken}`};case"bearer":return{Authorization:`Bearer ${credential.token}`};case"api_key":if(credential.headerPrefix){return{[credential.headerName]:`${credential.headerPrefix}${credential.key}`}}return{[credential.headerName]:credential.key};case"basic":{const value=`${credential.username}:${credential.password}`;const encoded=credential.encodedValue??(0,import_utils48.base64Encode)(new TextEncoder().encode(value));return{Authorization:`Basic ${encoded}`}}case"custom":return credential.headers??{};case"ssh_key":case"mtls":case"private_key":case"service_account":return{};default:return{}}}};var AuthProvidersRegistry=class{providers=new Map;defaultCacheTtl;constructor(options){this.defaultCacheTtl=options?.defaultCacheTtl??36e5;if(options?.providers){for(const provider of options.providers){this.register(provider)}}}register(config){if(this.providers.has(config.name)){throw new CredentialProviderAlreadyRegisteredError(config.name)}const normalized=this.normalize(config);this.providers.set(config.name,normalized)}unregister(name){return this.providers.delete(name)}get(name){return this.providers.get(name)}has(name){return this.providers.has(name)}getNames(){return[...this.providers.keys()]}getAll(){return[...this.providers.values()]}getByScope(scope){return this.getAll().filter(p=>p.scope===scope)}getByLoading(loading){return this.getAll().filter(p=>p.loading===loading)}getRequired(){return this.getAll().filter(p=>p.required)}getEager(){return this.getByLoading("eager")}getLazy(){return this.getByLoading("lazy")}get size(){return this.providers.size}isEmpty(){return this.providers.size===0}clear(){this.providers.clear()}normalize(config){return{name:config.name,description:config.description,scope:config.scope,loading:config.loading,cacheTtl:config.cacheTtl??this.defaultCacheTtl,factory:config.factory,refresh:config.refresh,toHeaders:config.toHeaders,metadata:config.metadata,required:config.required??false}}};var AUTH_PROVIDERS_REGISTRY=Symbol.for("frontmcp:AUTH_PROVIDERS_REGISTRY");var AuthProvidersVault=class{constructor(baseVault,namespace="authproviders:",logger){this.baseVault=baseVault;this.namespace=namespace;this.logger=logger}baseVault;namespace;logger;async storeCredential(sessionId,providerId,credential,scope,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);const appCredential={appId:this.namespace,providerId,credential,acquiredAt:Date.now(),isValid:true,expiresAt:extractCredentialExpiry(credential)};try{await this.baseVault.addAppCredential(vaultKey,appCredential);this.logger?.debug(`Stored credential "${providerId}" with scope "${scope}"`)}catch(error){this.logger?.warn(`Failed to store credential "${providerId}":`,error);throw error}}async getCredential(sessionId,providerId,scope,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{const appCredential=await this.baseVault.getCredential(vaultKey,this.namespace,providerId);if(!appCredential){return null}if(!appCredential.isValid){this.logger?.debug(`Credential "${providerId}" is marked as invalid`);return null}if(appCredential.expiresAt&&Date.now()>=appCredential.expiresAt){this.logger?.debug(`Credential "${providerId}" has expired`);return null}return appCredential.credential}catch(error){this.logger?.warn(`Failed to get credential "${providerId}":`,error);if(error instanceof CredentialStorageError){throw error}throw new CredentialStorageError(`Storage error while retrieving credential "${providerId}": ${error instanceof Error?error.message:String(error)}`)}}async removeCredential(sessionId,providerId,scope,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{await this.baseVault.removeAppCredential(vaultKey,this.namespace,providerId);this.logger?.debug(`Removed credential "${providerId}"`)}catch(error){this.logger?.warn(`Failed to remove credential "${providerId}":`,error)}}async invalidateCredential(sessionId,providerId,scope,reason,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{await this.baseVault.invalidateCredential(vaultKey,this.namespace,providerId,reason);this.logger?.debug(`Invalidated credential "${providerId}": ${reason}`)}catch(error){this.logger?.warn(`Failed to invalidate credential "${providerId}":`,error)}}async refreshOAuthCredential(sessionId,providerId,scope,tokens,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{await this.baseVault.refreshOAuthCredential(vaultKey,this.namespace,providerId,tokens);this.logger?.debug(`Refreshed OAuth credential "${providerId}"`)}catch(error){this.logger?.warn(`Failed to refresh OAuth credential "${providerId}":`,error);throw error}}async getAllCredentials(sessionId,scope,userId){if(scope){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{return await this.baseVault.getAppCredentials(vaultKey,this.namespace)}catch{return[]}}const credentials=[];try{const sessionCreds=await this.baseVault.getAppCredentials(this.buildVaultKey(sessionId,"session"),this.namespace);credentials.push(...sessionCreds)}catch{}if(userId){try{const userCreds=await this.baseVault.getAppCredentials(this.buildVaultKey(sessionId,"user",userId),this.namespace);credentials.push(...userCreds)}catch{}}try{const globalCreds=await this.baseVault.getAppCredentials(this.buildVaultKey(sessionId,"global"),this.namespace);credentials.push(...globalCreds)}catch{}return credentials}buildVaultKey(sessionId,scope,userId){switch(scope){case"global":return`${this.namespace}global`;case"user":if(!userId){throw new AuthInvalidInputError(`userId is required for user-scoped credentials (namespace: ${this.namespace})`)}return`${this.namespace}user:${userId}`;case"session":return`${this.namespace}session:${sessionId}`;default:{const _exhaustive=scope;throw new AuthInvalidInputError(`Unknown credential scope: ${_exhaustive}`)}}}};var AUTH_PROVIDERS_VAULT=Symbol.for("frontmcp:AUTH_PROVIDERS_VAULT");var EagerCredentialLoader=class{constructor(registry,cache,logger){this.registry=registry;this.cache=cache;this.logger=logger}registry;cache;logger;async loadForSession(context){const startTime=Date.now();const eagerProviders=this.registry.getEager();if(eagerProviders.length===0){return{loaded:new Map,failed:new Map,duration:Date.now()-startTime}}this.logger?.debug(`Loading ${eagerProviders.length} eager credential providers`);const loaded=new Map;const failed=new Map;const results=await Promise.allSettled(eagerProviders.map(async config=>{const credential=await this.loadOne(config,context);return{name:config.name,credential,config}}));for(const result of results){if(result.status==="fulfilled"){const{name,credential,config}=result.value;if(credential){const resolved=this.wrapCredential(name,credential,config);loaded.set(name,resolved);this.cache.set(name,resolved,config.cacheTtl);this.logger?.debug(`Loaded eager credential: ${name}`)}else if(config.required){failed.set(name,new Error(`Required credential "${name}" returned null`));this.logger?.warn(`Required eager credential "${name}" returned null`)}}else{const providerName=result.reason?.providerName||"unknown";const error=result.reason instanceof Error?result.reason:new Error(String(result.reason));failed.set(providerName,error);this.logger?.warn(`Failed to load eager credential "${providerName}":`,error.message)}}const duration=Date.now()-startTime;this.logger?.debug(`Eager loading complete: ${loaded.size} loaded, ${failed.size} failed, ${duration}ms`);return{loaded,failed,duration}}async loadOne(config,context){try{return await config.factory({...context,metadata:config.metadata})}catch(error){error.providerName=config.name;throw error}}wrapCredential(providerId,credential,config){return{credential,providerId,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope}}};var LazyCredentialLoader=class{constructor(logger){this.logger=logger}logger;loading=new Map;async load(config,context){const existing=this.loading.get(config.name);if(existing){this.logger?.debug(`Waiting for in-flight load: ${config.name}`);return existing}const promise=this.doLoad(config,context);this.loading.set(config.name,promise);try{return await promise}finally{this.loading.delete(config.name)}}async doLoad(config,context){const startTime=Date.now();this.logger?.debug(`Loading lazy credential: ${config.name}`);try{const credential=await config.factory({...context,metadata:config.metadata});if(!credential){this.logger?.debug(`Lazy credential "${config.name}" returned null`);return null}const resolved={credential,providerId:config.name,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope};const duration=Date.now()-startTime;this.logger?.debug(`Loaded lazy credential "${config.name}" in ${duration}ms`);return resolved}catch(error){const duration=Date.now()-startTime;this.logger?.warn(`Failed to load lazy credential "${config.name}" after ${duration}ms:`,error);throw error}}async refresh(config,context){const startTime=Date.now();this.logger?.debug(`Refreshing credential: ${config.name}`);try{let credential;if(config.refresh){credential=await config.refresh(context)}else{credential=await config.factory(context)}if(!credential){this.logger?.debug(`Credential refresh "${config.name}" returned null`);return null}const resolved={credential,providerId:config.name,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope};const duration=Date.now()-startTime;this.logger?.debug(`Refreshed credential "${config.name}" in ${duration}ms`);return resolved}catch(error){const duration=Date.now()-startTime;this.logger?.warn(`Failed to refresh credential "${config.name}" after ${duration}ms:`,error);throw error}}isLoading(name){return this.loading.has(name)}cancelAll(){this.loading.clear()}};var import_utils49=require("@frontmcp/utils");function resolveDotPath(obj,path){if(path in obj){return obj[path]}const segments=path.split(".");let current=obj;for(const segment of segments){if(current===null||current===void 0||typeof current!=="object"){return void 0}current=current[segment]}return current}function toStringArray(value){if(Array.isArray(value)){return value.filter(v=>typeof v==="string")}if(typeof value==="string"){return value.split(/\s+/).filter(Boolean)}return[]}var noopRelationshipResolver={async check(){return false}};function resolveAuthUser(authInfo){const extraUser=authInfo?.extra?.["user"];if(authInfo?.user)return authInfo.user;return typeof extraUser==="object"&&extraUser!==null?extraUser:{}}function isAnonymousSubject(sub){return typeof sub!=="string"||sub===""||sub.startsWith("anon:")}function signedInSubject(rawSub,mappedSub){if(rawSub!==void 0&&isAnonymousSubject(rawSub))return void 0;return[mappedSub,rawSub].find(candidate=>!isAnonymousSubject(candidate))}var runtimeEnv=new Proxy({},{get:(_target,name)=>typeof name==="string"?(0,import_utils49.getEnv)(name):void 0});var AuthoritiesContextBuilder=class{claimsMapping;claimsResolver;relationshipResolver;constructor(options={}){this.claimsMapping=options.claimsMapping;this.claimsResolver=options.claimsResolver;this.relationshipResolver=options.relationshipResolver??noopRelationshipResolver}build(authInfo,input={},env=runtimeEnv){if(this.claimsResolver){const resolved=this.claimsResolver(authInfo);return{user:{sub:signedInSubject(resolveAuthUser(authInfo).sub),roles:resolved.roles,permissions:resolved.permissions,claims:resolved.claims},input,env,relationships:this.relationshipResolver}}const user=resolveAuthUser(authInfo);const authorization=authInfo?.extra?.["authorization"];const authorizationClaims=authorization?.["claims"]??{};const rawClaims={...authorizationClaims,...user};let roles;if(this.claimsMapping?.roles){roles=toStringArray(resolveDotPath(rawClaims,this.claimsMapping.roles))}else{roles=toStringArray(user["roles"]??authorization?.["scopes"]??[])}let permissions;if(this.claimsMapping?.permissions){permissions=toStringArray(resolveDotPath(rawClaims,this.claimsMapping.permissions))}else{permissions=toStringArray(user["permissions"]??[])}const mappedSub=this.claimsMapping?.userId?resolveDotPath(rawClaims,this.claimsMapping.userId):void 0;return{user:{sub:signedInSubject(user.sub,mappedSub),roles,permissions,claims:rawClaims},input,env,relationships:this.relationshipResolver}}};function toStringArray2(value){if(Array.isArray(value)){return value.filter(v=>typeof v==="string")}if(typeof value==="string"){return value.split(/\s+/).filter(Boolean)}return[]}var FrontMcpAuthContextImpl=class{user;isAnonymous;mode;sessionId;scopes;claims;roles;permissions;constructor(source,claimsMapping,claimsResolver){const rawUser=resolveAuthUser(source);const mappedSub=!claimsResolver&&claimsMapping?.userId?resolveDotPath(this.buildRawClaims(source),claimsMapping.userId):void 0;const signedInSub=signedInSubject(rawUser.sub,mappedSub);const sub=signedInSub??(typeof rawUser.sub==="string"?rawUser.sub:"");this.user=Object.freeze({sub,name:rawUser.name,email:rawUser.email,picture:rawUser.picture});this.isAnonymous=signedInSub===void 0;const extraAuth=source.extra?.["authorization"];this.mode=String(source.extra?.["authMode"]??extraAuth?.["mode"]??(source.extra?.["isPublic"]===true||rawUser["anonymous"]===true?"public":"authenticated"));this.sessionId=typeof source.sessionId==="string"?source.sessionId:"";this.scopes=Object.freeze(Array.isArray(source.scopes)?source.scopes.filter(s=>typeof s==="string"):[]);if(claimsResolver){const resolved=claimsResolver(source);this.claims=Object.freeze({...resolved.claims});this.roles=Object.freeze([...toStringArray2(resolved.roles)]);this.permissions=Object.freeze([...toStringArray2(resolved.permissions)]);return}const rawClaims=this.buildRawClaims(source);this.claims=Object.freeze({...rawClaims});if(claimsMapping?.roles){this.roles=Object.freeze([...toStringArray2(resolveDotPath(rawClaims,claimsMapping.roles))])}else{this.roles=Object.freeze([...toStringArray2(rawUser["roles"]??extraAuth?.["scopes"]??[])])}if(claimsMapping?.permissions){this.permissions=Object.freeze([...toStringArray2(resolveDotPath(rawClaims,claimsMapping.permissions))])}else{this.permissions=Object.freeze([...toStringArray2(rawUser["permissions"]??[])])}}hasRole(role){return this.roles.includes(role)}hasAllRoles(roles){return roles.every(r=>this.roles.includes(r))}hasAnyRole(roles){return roles.some(r=>this.roles.includes(r))}hasPermission(permission){return this.permissions.includes(permission)}hasAllPermissions(permissions){return permissions.every(p=>this.permissions.includes(p))}hasAnyPermission(permissions){return permissions.some(p=>this.permissions.includes(p))}hasScope(scope){return this.scopes.includes(scope)}hasAllScopes(scopes){return scopes.every(s=>this.scopes.includes(s))}hasAnyScope(scopes){return scopes.some(s=>this.scopes.includes(s))}buildRawClaims(source){const rawUser=resolveAuthUser(source);const extraAuth=source.extra?.["authorization"];const authorizationClaims=extraAuth?.["claims"]??{};return{...authorizationClaims,...rawUser}}};function buildAuthContext(authInfo,claimsMapping,pipes,claimsResolver){const base=new FrontMcpAuthContextImpl(authInfo,claimsMapping,claimsResolver);if(!pipes||pipes.length===0){return base}return runPipes(base,pipes)}async function runPipes(base,pipes){const extensions={};for(const pipe of pipes){try{const result=await pipe(base.claims);if(result&&typeof result==="object"){Object.assign(extensions,result)}}catch(error){const message=error instanceof Error?error.message:String(error);console.warn(`[FrontMcpAuth] pipe failed: ${message}`)}}const merged=Object.create(Object.getPrototypeOf(base));Object.assign(merged,base,extensions);return Object.freeze(merged)}function resolveRequiredScopes(denial,mapping,authorities){const scopes=new Set;if(typeof authorities==="string"&&mapping.profiles?.[authorities]){mapping.profiles[authorities].forEach(s=>scopes.add(s))}if(Array.isArray(authorities)){for(const profileName of authorities){if(typeof profileName==="string"&&mapping.profiles?.[profileName]){mapping.profiles[profileName].forEach(s=>scopes.add(s))}}}if(denial.kind==="roles"&&denial.missing&&mapping.roles){for(const role of denial.missing){const mapped=mapping.roles[role];if(mapped)mapped.forEach(s=>scopes.add(s))}}if(denial.kind==="permissions"&&denial.missing&&mapping.permissions){for(const perm of denial.missing){const mapped=mapping.permissions[perm];if(mapped)mapped.forEach(s=>scopes.add(s))}}return scopes.size>0?[...scopes].sort():void 0}var import_lazy_zod20=require("@frontmcp/lazy-zod");var rbacRolesPolicySchema=import_lazy_zod20.z.object({all:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional(),any:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional()}).refine(data=>data.all!==void 0||data.any!==void 0,{message:'Roles policy must have at least "all" or "any"'});var rbacPermissionsPolicySchema=import_lazy_zod20.z.object({all:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional(),any:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional()}).refine(data=>data.all!==void 0||data.any!==void 0,{message:'Permissions policy must have at least "all" or "any"'});var abacOperatorSchema=import_lazy_zod20.z.enum(["eq","neq","in","notIn","gt","gte","lt","lte","contains","startsWith","endsWith","exists","matches"]);var abacConditionSchema=import_lazy_zod20.z.object({path:import_lazy_zod20.z.string().min(1),op:abacOperatorSchema,value:import_lazy_zod20.z.unknown()});var abacPolicySchema=import_lazy_zod20.z.object({match:import_lazy_zod20.z.record(import_lazy_zod20.z.string(),import_lazy_zod20.z.unknown()).optional(),conditions:import_lazy_zod20.z.array(abacConditionSchema).optional()}).refine(data=>data.match!==void 0||data.conditions!==void 0,{message:'Attributes policy must have at least "match" or "conditions"'});var resourceIdRefSchema=import_lazy_zod20.z.union([import_lazy_zod20.z.string().min(1),import_lazy_zod20.z.object({fromInput:import_lazy_zod20.z.string().min(1)}).strict(),import_lazy_zod20.z.object({fromClaims:import_lazy_zod20.z.string().min(1)}).strict()]);var rebacPolicySchema=import_lazy_zod20.z.object({type:import_lazy_zod20.z.string().min(1),resource:import_lazy_zod20.z.string().min(1),resourceId:resourceIdRefSchema});var basePolicyShape={roles:rbacRolesPolicySchema.optional(),permissions:rbacPermissionsPolicySchema.optional(),attributes:abacPolicySchema.optional(),relationships:import_lazy_zod20.z.union([rebacPolicySchema,import_lazy_zod20.z.array(rebacPolicySchema)]).optional(),custom:import_lazy_zod20.z.record(import_lazy_zod20.z.string(),import_lazy_zod20.z.unknown()).optional(),guards:import_lazy_zod20.z.array(import_lazy_zod20.z.instanceof(Function)).optional(),operator:import_lazy_zod20.z.enum(["AND","OR"]).optional()};var authoritiesPolicySchema=import_lazy_zod20.z.lazy(()=>import_lazy_zod20.z.object({...basePolicyShape,not:authoritiesPolicySchema.optional(),anyOf:import_lazy_zod20.z.array(authoritiesPolicySchema).optional(),allOf:import_lazy_zod20.z.array(authoritiesPolicySchema).optional()}));var authoritiesMetadataSchema=import_lazy_zod20.z.union([import_lazy_zod20.z.string().min(1),import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).min(1),authoritiesPolicySchema]);var authoritiesClaimsMappingSchema=import_lazy_zod20.z.record(import_lazy_zod20.z.string(),import_lazy_zod20.z.string().optional()).refine(data=>Object.values(data).some(v=>v!==void 0),{message:"Claims mapping must have at least one mapping"});var authoritiesConfigSchema=import_lazy_zod20.z.object({claimsMapping:authoritiesClaimsMappingSchema.optional(),profiles:import_lazy_zod20.z.record(import_lazy_zod20.z.string().min(1),authoritiesPolicySchema).optional()});function evaluateRbacRoles(policy,ctx){const userRoles=ctx.user.roles;if(policy.all){const missing=policy.all.filter(r=>!userRoles.includes(r));if(missing.length>0){return{granted:false,deniedBy:`roles.all: missing ${missing.map(r=>`'${r}'`).join(", ")}`,denial:{kind:"roles",path:"roles.all",missing},evaluatedPolicies:["roles.all"]}}}if(policy.any){const hasAny=policy.any.some(r=>userRoles.includes(r));if(!hasAny){return{granted:false,deniedBy:`roles.any: user has none of ${policy.any.map(r=>`'${r}'`).join(", ")}`,denial:{kind:"roles",path:"roles.any",missing:policy.any},evaluatedPolicies:["roles.any"]}}}return{granted:true,evaluatedPolicies:["roles"]}}function evaluateRbacPermissions(policy,ctx){const userPerms=ctx.user.permissions;if(policy.all){const missing=policy.all.filter(p=>!userPerms.includes(p));if(missing.length>0){return{granted:false,deniedBy:`permissions.all: missing ${missing.map(p=>`'${p}'`).join(", ")}`,denial:{kind:"permissions",path:"permissions.all",missing},evaluatedPolicies:["permissions.all"]}}}if(policy.any){const hasAny=policy.any.some(p=>userPerms.includes(p));if(!hasAny){return{granted:false,deniedBy:`permissions.any: user has none of ${policy.any.map(p=>`'${p}'`).join(", ")}`,denial:{kind:"permissions",path:"permissions.any",missing:policy.any},evaluatedPolicies:["permissions.any"]}}}return{granted:true,evaluatedPolicies:["permissions"]}}function buildContextEnvelope(ctx){return{user:ctx.user,claims:ctx.user.claims,input:ctx.input,env:ctx.env}}function resolveValue(value,ctx){if(value!==null&&typeof value==="object"&&!Array.isArray(value)){const obj=value;if("fromInput"in obj&&typeof obj["fromInput"]==="string"){return ctx.input[obj["fromInput"]]}if("fromClaims"in obj&&typeof obj["fromClaims"]==="string"){return resolveDotPath(ctx.user.claims,obj["fromClaims"])}}return value}function applyOperator(actual,op,expected){switch(op){case"eq":return expected!==void 0&&actual===expected;case"neq":return actual!==expected;case"in":return Array.isArray(expected)&&expected.includes(actual);case"notIn":return Array.isArray(expected)&&!expected.includes(actual);case"gt":return typeof actual==="number"&&typeof expected==="number"&&actual>expected;case"gte":return typeof actual==="number"&&typeof expected==="number"&&actual>=expected;case"lt":return typeof actual==="number"&&typeof expected==="number"&&actual<expected;case"lte":return typeof actual==="number"&&typeof expected==="number"&&actual<=expected;case"contains":if(typeof actual==="string"&&typeof expected==="string")return actual.includes(expected);if(Array.isArray(actual))return actual.includes(expected);return false;case"startsWith":return typeof actual==="string"&&typeof expected==="string"&&actual.startsWith(expected);case"endsWith":return typeof actual==="string"&&typeof expected==="string"&&actual.endsWith(expected);case"exists":return expected?actual!==void 0&&actual!==null:actual===void 0||actual===null;case"matches":if(typeof actual!=="string"||typeof expected!=="string")return false;if(expected.length>256)return false;if(/(\+\+|\*\*|\{\d+,\d*\}\{)/.test(expected))return false;try{return new RegExp(expected).test(actual)}catch{return false}default:return false}}function evaluateCondition(condition,envelope,ctx){const actual=resolveDotPath(envelope,condition.path);const expected=resolveValue(condition.value,ctx);return applyOperator(actual,condition.op,expected)}var REDACTED_ENV_VALUE="[redacted]";function reportableActual(path,actual){return path==="env"||path.startsWith("env.")?REDACTED_ENV_VALUE:actual}function evaluateAbac(policy,ctx){const envelope=buildContextEnvelope(ctx);if(policy.match){for(const[path,expectedRaw]of Object.entries(policy.match)){const actual=resolveDotPath(envelope,path);const expected=resolveValue(expectedRaw,ctx);if(expected===void 0||actual!==expected){const reported=reportableActual(path,actual);return{granted:false,deniedBy:`attributes.match: '${path}' expected '${String(expected)}' but got '${String(reported)}'`,denial:{kind:"attributes",path:"attributes.match",expected,actual:reported},evaluatedPolicies:["attributes.match"]}}}}if(policy.conditions){for(let i=0;i<policy.conditions.length;i++){const condition=policy.conditions[i];if(!evaluateCondition(condition,envelope,ctx)){const expected=resolveValue(condition.value,ctx);const actual=reportableActual(condition.path,resolveDotPath(envelope,condition.path));return{granted:false,deniedBy:`attributes.conditions: '${condition.path}' failed '${condition.op}' check against '${String(expected)}'`,denial:{kind:"attributes",path:`attributes.conditions[${i}]`,expected,actual},evaluatedPolicies:["attributes.conditions"]}}}}return{granted:true,evaluatedPolicies:["attributes"]}}function resolveResourceId(ref,ctx){if(typeof ref==="string")return ref;if("fromInput"in ref){const val=ctx.input[ref.fromInput];return typeof val==="string"?val:void 0}if("fromClaims"in ref){const val=resolveDotPath(ctx.user.claims,ref.fromClaims);return typeof val==="string"?val:void 0}return void 0}async function evaluateSingleRebac(policy,ctx){const userSub=ctx.user.sub;if(userSub===void 0||isAnonymousSubject(userSub)){return{granted:false,deniedBy:`relationships: an anonymous caller cannot be '${policy.type}' of ${policy.resource}`,denial:{kind:"relationships",path:"user.sub",expected:"a signed-in caller",actual:void 0},evaluatedPolicies:["relationships"]}}const resourceId=resolveResourceId(policy.resourceId,ctx);if(resourceId===void 0){return{granted:false,deniedBy:`relationships: could not resolve resourceId for ${policy.resource}`,denial:{kind:"relationships",path:"relationships",expected:`${policy.resource}:resourceId`,actual:void 0},evaluatedPolicies:["relationships"]}}const hasRelationship=await ctx.relationships.check(policy.type,policy.resource,resourceId,userSub,ctx);if(!hasRelationship){return{granted:false,deniedBy:`relationships: user '${userSub}' is not '${policy.type}' of ${policy.resource}:${resourceId}`,denial:{kind:"relationships",path:"relationships",expected:`${policy.type}:${policy.resource}:${resourceId}`},evaluatedPolicies:["relationships"]}}return{granted:true,evaluatedPolicies:["relationships"]}}async function evaluateRebac(policy,ctx){const policies=Array.isArray(policy)?policy:[policy];for(const p of policies){const result=await evaluateSingleRebac(p,ctx);if(!result.granted)return result}return{granted:true,evaluatedPolicies:["relationships"]}}var ABAC_OPERATORS=new Set(["eq","neq","in","notIn","gt","gte","lt","lte","contains","startsWith","endsWith","exists","matches"]);var CHECK_FIELDS=["roles","permissions","attributes","relationships","custom","guards","allOf","anyOf","not"];var RULE_FIELDS=new Set([...CHECK_FIELDS,"operator"]);function isPlainObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function isNonEmptyString(value){return typeof value==="string"&&value.length>0}function unknownFields(value,known,path){const prefix=path?`${path} has`:"has";return Object.keys(value).filter(key=>!known.has(key)).map(key=>`${prefix} an unknown field "${key}"`)}function checkStringList(value,path){if(!Array.isArray(value))return[`${path} must be a list of names`];if(value.length===0)return[`${path} is empty`];return value.every(isNonEmptyString)?[]:[`${path} must contain only non-empty names`]}var ALL_OR_ANY=new Set(["all","any"]);function checkAllOrAny(value,path){if(!isPlainObject(value))return[`${path} must be an object with "all" or "any"`];const problems=unknownFields(value,ALL_OR_ANY,path);if(value["all"]===void 0&&value["any"]===void 0){problems.push(`${path} needs "all" or "any"`)}if(value["all"]!==void 0)problems.push(...checkStringList(value["all"],`${path}.all`));if(value["any"]!==void 0)problems.push(...checkStringList(value["any"],`${path}.any`));return problems}var ATTRIBUTE_FIELDS=new Set(["match","conditions"]);var CONDITION_FIELDS=new Set(["path","op","value"]);function isValueReference(value){return isPlainObject(value)&&("fromInput"in value||"fromClaims"in value)}function checkValueReference(value,path){const ref=value["fromInput"]??value["fromClaims"];return Object.keys(value).length===1&&isNonEmptyString(ref)?[]:[`${path} must be { fromInput: "<name>" } or { fromClaims: "<path>" }`]}var OPERATOR_VALUES={in:{accepts:Array.isArray,needs:"a list"},notIn:{accepts:Array.isArray,needs:"a list"},gt:{accepts:value=>typeof value==="number",needs:"a number"},gte:{accepts:value=>typeof value==="number",needs:"a number"},lt:{accepts:value=>typeof value==="number",needs:"a number"},lte:{accepts:value=>typeof value==="number",needs:"a number"},startsWith:{accepts:value=>typeof value==="string",needs:"a string"},endsWith:{accepts:value=>typeof value==="string",needs:"a string"},matches:{accepts:value=>typeof value==="string",needs:"a string"}};function checkConditionValue(op,condition,path){const value=condition["value"];if(value===void 0)return[`${path} is missing`];if(op==="exists"){return typeof value==="boolean"?[]:[`${path} must be true or false for "exists"`]}if(isValueReference(value))return checkValueReference(value,path);const expected=OPERATOR_VALUES[op];if(expected&&!expected.accepts(value))return[`${path} must be ${expected.needs} for "${op}"`];if(Array.isArray(value)&&value.length===0&&(op==="in"||op==="notIn"))return[`${path} is empty`];return[]}function checkAttributes(value,path){if(!isPlainObject(value))return[`${path} must be an object with "match" or "conditions"`];const problems=unknownFields(value,ATTRIBUTE_FIELDS,path);const{match,conditions}=value;if(match===void 0&&conditions===void 0){problems.push(`${path} needs "match" or "conditions"`)}if(match!==void 0){if(!isPlainObject(match))problems.push(`${path}.match must be an object`);else if(Object.keys(match).length===0)problems.push(`${path}.match is empty`);else{for(const[attribute,expected]of Object.entries(match)){const at=`${path}.match[${JSON.stringify(attribute)}]`;if(expected===void 0)problems.push(`${at} has no value`);else if(isValueReference(expected))problems.push(...checkValueReference(expected,at))}}}if(conditions!==void 0){if(!Array.isArray(conditions))problems.push(`${path}.conditions must be a list`);else if(conditions.length===0)problems.push(`${path}.conditions is empty`);else{conditions.forEach((condition,index)=>{const at=`${path}.conditions[${index}]`;if(!isPlainObject(condition)){problems.push(`${at} must be an object with "path" and "op"`);return}problems.push(...unknownFields(condition,CONDITION_FIELDS,at));if(!isNonEmptyString(condition["path"]))problems.push(`${at}.path must be a non-empty string`);const op=condition["op"];if(!ABAC_OPERATORS.has(op)){problems.push(`${at}.op "${String(condition["op"])}" is not an operator`)}else{problems.push(...checkConditionValue(op,condition,`${at}.value`))}})}}return problems}var RELATIONSHIP_FIELDS=new Set(["type","resource","resourceId"]);function checkResourceId(value,path){if(isNonEmptyString(value))return[];if(isPlainObject(value)&&Object.keys(value).length===1){const ref=value["fromInput"]??value["fromClaims"];if(isNonEmptyString(ref))return[]}return[`${path} must be a string, { fromInput } or { fromClaims }`]}function checkRelationship(value,path){if(!isPlainObject(value))return[`${path} must be an object with "type", "resource" and "resourceId"`];const problems=unknownFields(value,RELATIONSHIP_FIELDS,path);if(!isNonEmptyString(value["type"]))problems.push(`${path}.type must be a non-empty string`);if(!isNonEmptyString(value["resource"]))problems.push(`${path}.resource must be a non-empty string`);problems.push(...checkResourceId(value["resourceId"],`${path}.resourceId`));return problems}function checkRelationships(value,path){if(!Array.isArray(value))return checkRelationship(value,path);if(value.length===0)return[`${path} is empty`];return value.flatMap((relationship,index)=>checkRelationship(relationship,`${path}[${index}]`))}function checkRuleList(value,path){if(!Array.isArray(value))return[`${path} must be a list of rules`];if(value.length===0)return[`${path} is empty`];return value.flatMap((rule,index)=>checkRule(rule,`${path}[${index}]`))}function checkRule(rule,path){if(!isPlainObject(rule)){return[`${path||"the rule"} must be a rule object${typeof rule==="string"?", not a profile name":""}`]}const problems=unknownFields(rule,RULE_FIELDS,path);if(!CHECK_FIELDS.some(field=>rule[field]!==void 0)){problems.push(`${path?`${path} `:""}checks nothing`)}if(rule["operator"]!==void 0&&rule["operator"]!=="AND"&&rule["operator"]!=="OR"){problems.push(`${path}.operator must be "AND" or "OR"`)}if(rule["roles"]!==void 0)problems.push(...checkAllOrAny(rule["roles"],`${path}.roles`));if(rule["permissions"]!==void 0)problems.push(...checkAllOrAny(rule["permissions"],`${path}.permissions`));if(rule["attributes"]!==void 0)problems.push(...checkAttributes(rule["attributes"],`${path}.attributes`));if(rule["relationships"]!==void 0){problems.push(...checkRelationships(rule["relationships"],`${path}.relationships`))}if(rule["custom"]!==void 0){if(!isPlainObject(rule["custom"]))problems.push(`${path}.custom must be an object`);else if(Object.keys(rule["custom"]).length===0)problems.push(`${path}.custom is empty`)}if(rule["guards"]!==void 0){const guards=rule["guards"];if(!Array.isArray(guards))problems.push(`${path}.guards must be a list of functions`);else if(guards.length===0)problems.push(`${path}.guards is empty`);else if(!guards.every(guard=>typeof guard==="function")){problems.push(`${path}.guards must contain only functions`)}}if(rule["allOf"]!==void 0)problems.push(...checkRuleList(rule["allOf"],`${path}.allOf`));if(rule["anyOf"]!==void 0)problems.push(...checkRuleList(rule["anyOf"],`${path}.anyOf`));if(rule["not"]!==void 0)problems.push(...checkRule(rule["not"],`${path}.not`));return problems}function findAuthoritiesRuleProblems(authorities){if(typeof authorities==="string"){return authorities.length>0?[]:["the profile name is empty"]}if(Array.isArray(authorities)){if(authorities.length===0)return["the list of profiles is empty"];return authorities.every(isNonEmptyString)?[]:["a list of profiles must contain only non-empty profile names"]}if(!isPlainObject(authorities)){return["must be a profile name, a list of profile names, or a rule object"]}return checkRule(authorities,"")}function findAuthoritiesProfileProblems(name,policy){return checkRule(policy,"").map(problem=>`profile "${name}": ${problem.replace(/^\./,"")}`)}function mergeResult(base,...others){const evaluatedPolicies=[...base.evaluatedPolicies];for(const other of others){evaluatedPolicies.push(...other.evaluatedPolicies)}return{...base,evaluatedPolicies}}function invalidRule(problems,policies=[]){return{granted:false,deniedBy:`invalid authorities rule: ${problems.join("; ")}`,evaluatedPolicies:policies}}var AuthoritiesEngine=class{constructor(profiles,evaluators){this.profiles=profiles;this.evaluators=evaluators}profiles;evaluators;ruleProblems=new WeakMap;findRuleProblems(authorities){const problems=findAuthoritiesRuleProblems(authorities);if(problems.length>0)return problems;const names=typeof authorities==="string"?[authorities]:Array.isArray(authorities)?authorities:[];return names.filter(name=>typeof name==="string"&&!this.profiles.has(name)).map(name=>`names an unknown profile "${name}"`)}findProfileProblems(){return Object.entries(this.profiles.getAll()).flatMap(([name,policy])=>findAuthoritiesProfileProblems(name,policy))}async evaluate(authorities,ctx){const problems=this.problemsOf(authorities,findAuthoritiesRuleProblems);if(problems.length>0)return invalidRule(problems);if(typeof authorities==="string"){return this.evaluateProfile(authorities,ctx)}if(Array.isArray(authorities)){return this.evaluateProfileArray(authorities,ctx)}return this.evaluatePolicy(authorities,ctx)}async evaluateProfile(name,ctx){const policy=this.profiles.resolve(name);if(!policy){return{granted:false,deniedBy:`profile '${name}' is not registered`,evaluatedPolicies:[`profile:${name}`]}}const problems=this.problemsOf(policy,rule=>findAuthoritiesProfileProblems(name,rule));if(problems.length>0)return invalidRule(problems,[`profile:${name}`]);const result=await this.evaluatePolicy(policy,ctx);if(!result.granted){return{...result,deniedBy:`profile:${name}: ${result.deniedBy}`,evaluatedPolicies:[`profile:${name}`,...result.evaluatedPolicies]}}return mergeResult(result,{granted:true,evaluatedPolicies:[`profile:${name}`]})}problemsOf(rule,find){if(typeof rule!=="object"||rule===null)return find(rule);let problems=this.ruleProblems.get(rule);if(!problems){problems=find(rule);this.ruleProblems.set(rule,problems)}return problems}async evaluateProfileArray(names,ctx){const allPolicies=[];for(const name of names){const result=await this.evaluateProfile(name,ctx);allPolicies.push(...result.evaluatedPolicies);if(!result.granted){return{...result,evaluatedPolicies:allPolicies}}}return{granted:true,evaluatedPolicies:allPolicies}}async evaluatePolicy(policy,ctx){const operator=policy.operator??"AND";const results=[];if(policy.roles){results.push(evaluateRbacRoles(policy.roles,ctx))}if(policy.permissions){results.push(evaluateRbacPermissions(policy.permissions,ctx))}if(policy.attributes){results.push(evaluateAbac(policy.attributes,ctx))}if(policy.relationships){results.push(await evaluateRebac(policy.relationships,ctx))}if(policy.custom){results.push(await this.evaluateCustom(policy.custom,ctx))}if(policy.guards&&policy.guards.length>0){results.push(await this.evaluateGuards(policy.guards,ctx))}if(policy.allOf){results.push(await this.evaluateAllOf(policy.allOf,ctx))}if(policy.anyOf){results.push(await this.evaluateAnyOf(policy.anyOf,ctx))}if(policy.not){results.push(await this.evaluateNot(policy.not,ctx))}if(results.length===0){return invalidRule(["checks nothing"])}return this.combineResults(results,operator)}combineResults(results,operator){const allPolicies=results.flatMap(r=>r.evaluatedPolicies);if(operator==="AND"){const denied=results.find(r=>!r.granted);if(denied){return{...denied,evaluatedPolicies:allPolicies}}return{granted:true,evaluatedPolicies:allPolicies}}const anyGranted=results.some(r=>r.granted);if(anyGranted){return{granted:true,evaluatedPolicies:allPolicies}}const firstDenied=results.find(r=>!r.granted);return{granted:false,deniedBy:firstDenied?.deniedBy??"all policies denied (OR)",evaluatedPolicies:allPolicies}}async evaluateCustom(custom,ctx){const allPolicies=[];for(const[name,config]of Object.entries(custom)){const evaluator=this.evaluators.get(name);if(!evaluator){return{granted:false,deniedBy:`custom evaluator '${name}' is not registered`,evaluatedPolicies:[...allPolicies,`custom.${name}`]}}const result=await evaluator.evaluate(config,ctx);allPolicies.push(`custom.${name}`,...result.evaluatedPolicies);if(!result.granted){return{...result,evaluatedPolicies:allPolicies}}}return{granted:true,evaluatedPolicies:allPolicies}}async evaluateGuards(guards,ctx){for(let i=0;i<guards.length;i++){const guard=guards[i];const result=await guard(ctx);if(result!==true){const denialMessage=typeof result==="string"?result:result===false?`guard[${i}] denied`:`guard[${i}] did not return true (returned ${result===null?"null":typeof result})`;return{granted:false,deniedBy:`guards[${i}]: ${denialMessage}`,denial:{kind:"custom",path:`guards[${i}]`},evaluatedPolicies:["guards"]}}}return{granted:true,evaluatedPolicies:["guards"]}}async evaluateAllOf(policies,ctx){const allPolicies=["allOf"];for(const policy of policies){const result=await this.evaluatePolicy(policy,ctx);allPolicies.push(...result.evaluatedPolicies);if(!result.granted){return{...result,evaluatedPolicies:allPolicies}}}return{granted:true,evaluatedPolicies:allPolicies}}async evaluateAnyOf(policies,ctx){const allPolicies=["anyOf"];let lastDenied;for(const policy of policies){const result=await this.evaluatePolicy(policy,ctx);allPolicies.push(...result.evaluatedPolicies);if(result.granted){return{granted:true,evaluatedPolicies:allPolicies}}lastDenied=result}return{granted:false,deniedBy:lastDenied?.deniedBy??"no policies in anyOf",denial:lastDenied?.denial??{kind:"anyOf",path:"anyOf"},evaluatedPolicies:allPolicies}}async evaluateNot(policy,ctx){const result=await this.evaluatePolicy(policy,ctx);return{granted:!result.granted,deniedBy:result.granted?"not: inner policy was granted (negated to denied)":void 0,denial:result.granted?{kind:"not",path:"not"}:void 0,evaluatedPolicies:["not",...result.evaluatedPolicies]}}resolveProfile(name){return this.profiles.resolve(name)}};var AuthoritiesProfileRegistry=class{profiles=new Map;register(name,policy){this.profiles.set(name,policy)}registerAll(profiles){for(const[name,policy]of Object.entries(profiles)){this.profiles.set(name,policy)}}resolve(name){return this.profiles.get(name)}has(name){return this.profiles.has(name)}getAll(){const result={};for(const[name,policy]of this.profiles){result[name]=policy}return result}get size(){return this.profiles.size}remove(name){return this.profiles.delete(name)}clear(){this.profiles.clear()}};var AuthoritiesEvaluatorRegistry=class{evaluators=new Map;register(name,evaluator){this.evaluators.set(name,evaluator)}registerAll(evaluators){for(const[name,evaluator]of Object.entries(evaluators)){this.evaluators.set(name,evaluator)}}get(name){return this.evaluators.get(name)}has(name){return this.evaluators.has(name)}get size(){return this.evaluators.size}remove(name){return this.evaluators.delete(name)}clear(){this.evaluators.clear()}};var import_utils50=require("@frontmcp/utils");var FORBIDDEN_CODE=-32003;var AuthorityDeniedError=class extends Error{static[Symbol.hasInstance](value){return(0,import_utils50.isBrandedInstance)(this,value)}mcpErrorCode=FORBIDDEN_CODE;statusCode=403;code="AUTHORITY_DENIED";entryType;entryName;deniedBy;denial;requiredScopes;constructor(params){const msg=params.message??`Access denied to ${params.entryType} "${params.entryName}": ${params.deniedBy}`;super(msg);this.name="AuthorityDeniedError";this.entryType=params.entryType;this.entryName=params.entryName;this.deniedBy=params.deniedBy;this.denial=params.denial;this.requiredScopes=params.requiredScopes}toJsonRpcError(){const data={entryType:this.entryType,entryName:this.entryName,deniedBy:this.deniedBy};if(this.denial!==void 0)data["denial"]=this.denial;if(this.requiredScopes!==void 0)data["requiredScopes"]=this.requiredScopes;return{code:this.mcpErrorCode,message:this.message,data}}};(0,import_utils50.brandClass)(AuthorityDeniedError,"@frontmcp/auth:AuthorityDeniedError");var bearerApplier={apply(token,_url,init){const headers=new Headers(init.headers);headers.set("Authorization",`Bearer ${token}`);return{init:{...init,headers}}}};function headerApplier(headerName,prefix){return{apply(token,_url,init){const headers=new Headers(init.headers);headers.set(headerName,prefix?`${prefix} ${token}`:token);return{init:{...init,headers}}}}}function queryApplier(paramName){return{apply(token,url,init){const urlObj=new URL(url);urlObj.searchParams.set(paramName,token);return{init,url:urlObj.toString()}}}}var basicApplier={apply(token,_url,init){const headers=new Headers(init.headers);const encoded=typeof btoa==="function"?btoa(token):Buffer.from(token).toString("base64");headers.set("Authorization",`Basic ${encoded}`);return{init:{...init,headers}}}};function isFrontMcpCredentials(creds){return typeof creds==="object"&&creds!==null&&"provider"in creds&&typeof creds.provider==="string"&&creds.provider.length>0}function providerHeadersCredentials(resolveHeaders){return{async applyCredentials(_url,init){const{credentials,...cleanInit}=init;if(!isFrontMcpCredentials(credentials)){return{init:typeof credentials==="string"?init:cleanInit}}const headers=new Headers(cleanInit.headers);for(const[name,value]of Object.entries(await resolveHeaders(credentials.provider))){headers.set(name,value)}return{init:{...cleanInit,headers}}}}}var FetchCredentialMiddleware=class{constructor(tokenAccessor,appliers){this.tokenAccessor=tokenAccessor;this.appliers=new Map(Object.entries(appliers??{}))}tokenAccessor;appliers;async applyCredentials(url,init){const creds=init.credentials;if(!creds||typeof creds==="string"){return{init}}if(!isFrontMcpCredentials(creds)){const{credentials:_removed2,...rest}=init;return{init:rest}}const token=await this.tokenAccessor.getToken(creds.provider);if(!token){const{credentials:_removed2,...rest}=init;return{init:rest}}const applier=this.appliers.get(creds.provider)??bearerApplier;const{credentials:_removed,...cleanInit}=init;return applier.apply(token,url,cleanInit)}};0&&(module.exports={AUTH_PROVIDERS_ACCESSOR,AUTH_PROVIDERS_REGISTRY,AUTH_PROVIDERS_VAULT,AppAuthState,AudienceValidator,AuthInternalError,AuthInvalidInputError,AuthProvidersAccessorImpl,AuthProvidersNotConfiguredError,AuthProvidersRegistry,AuthProvidersVault,AuthoritiesContextBuilder,AuthoritiesEngine,AuthoritiesEvaluatorRegistry,AuthoritiesProfileRegistry,AuthorityDeniedError,AuthorizationBase,BUILT_IN_AUTH_PAGE_CSP,CDN,CREDENTIALS_ACCESSOR,CimdClientIdMismatchError,CimdDisabledError,CimdError,CimdFetchError,CimdResponseTooLargeError,CimdSecurityError,CimdService,CimdValidationError,CredentialCache,CredentialProviderAlreadyRegisteredError,CredentialStorageError,CredentialsAccessorImpl,DEFAULT_ALLOWED_SCOPES,DEFAULT_INCREMENTAL_TICKET_TTL_MS,DEFAULT_RESUME_TTL_MS,DEFAULT_THEME,DcrClientRegistry,EagerCredentialLoader,ElicitationSecretRequiredError,EncryptedRedisVault,EncryptedStorageError,EncryptedStorageSecureStoreBackend,EncryptedTypedStorage,EncryptionContextNotSetError,EncryptionKeyNotConfiguredError,FetchCredentialMiddleware,FrontMcpAuthContextImpl,InMemoryAuthorizationStore,InMemoryAuthorizationVault,InMemoryCimdCache,InMemoryConsentStore,InMemoryFederatedAuthSessionStore,InMemoryOrchestratedTokenStore,InMemoryStoreRequiredError,InvalidClientIdUrlError,JwksService,JwtSecretRequiredError,JwtSecretWeakError,LazyCredentialLoader,NoProviderIdError,NullOrchestratedAuthAccessor,ORCHESTRATED_AUTH_ACCESSOR,OrchestratedAuthAccessorAdapter,OrchestratedAuthNotAvailableError,OrchestratedAuthorization,OrchestratorJwksNotAvailableError,PublicAuthorization,RedirectUriMismatchError,RedisAuthorizationStore,RedisSessionStore,SECURE_STORE_ACCESSOR,SIGNIN_BINDING_COOKIE_PREFIX,SIGNIN_BINDING_MAX_AGE_SECONDS,SIGNIN_BINDING_SECURE_COOKIE_PREFIX,ScopeDeniedError,SecureStoreAccessorImpl,SessionCredentialVault,SessionIdEmptyError,SessionRateLimiter,SessionSecretRequiredError,StorageAuthorizationStore,StorageAuthorizationVault,StorageConsentStore,StorageFederatedAuthSessionStore,StorageOrchestratedTokenStore,StorageTokenStore,TinyTtlCache,TokenLeakDetectedError,TokenNotAvailableError,TokenStoreRequiredError,TokenVault,TransparentAuthorization,TransportIdGenerator,TypedStorage,VaultEncryption,VaultLoadError,VaultNotFoundError,VercelKvSessionStore,abacConditionSchema,abacOperatorSchema,abacPolicySchema,advertisedScopes,aiPlatformTypeSchema,allowsPublicAccess,anonymousCallerClaims,apiKeyCredentialSchema,appAuthOptionsSchema,appAuthStateSchema,appAuthorizationRecordSchema,appCredentialSchema,appRequiresOrchestration,authLayout,authModeSchema,authOptionsSchema,authProviderDetectionResultSchema,authProviderMappingSchema,authProvidersVaultOptionsSchema,authUserSchema,authenticateFnSchema,authoritiesClaimsMappingSchema,authoritiesConfigSchema,authoritiesMetadataSchema,authoritiesPolicySchema,authorizationCodeRecordSchema,authorizationVaultEntrySchema,authorizedPromptSchema,authorizedToolSchema,baseLayout,basicApplier,basicAuthCredentialSchema,bearerApplier,bearerCredentialSchema,buildAuthContext,buildCodeRecord,buildConnectPage,buildConnectSuccessPage,buildConsentPage,buildCredentialResumeUrl,buildErrorPage,buildFederatedLoginPage,buildIncrementalAuthPage,buildInsufficientScopeHeader,buildInvalidRequestHeader,buildInvalidTokenHeader,buildLoginPage,buildPendingRecord,buildPrmUrl,buildRefreshTokenRecord,buildToolConsentPage,buildUnauthorizedHeader,buildWwwAuthenticate,builtInAuthPageHeaders,centeredCardLayout,checkSsrfProtection,cimdCacheConfigSchema,cimdConfigSchema,cimdNetworkConfigSchema,cimdSecurityConfigSchema,clientMetadataDocumentSchema,completeCurrentProvider,consentConfigSchema,consentRecordKey,consentSelectionSchema,consentStateSchema,consentToolItemSchema,createAudienceValidator,createEncryptedVault,createFederatedAuthSession,createLayout,createSecureStore,createSessionCredentialVault,createSigninBinding,createTokenStorageAdapter,credentialProviderConfigSchema,credentialSchema,credentialScopeSchema,credentialTypeSchema,customCredentialSchema,decodeJwtPayloadSafe,decryptAesGcm,decryptSessionJson,decryptValue,defaultSessionRateLimiter,deriveAuthorizationId,deriveExpectedAudience,deriveProviderId,deriveTypedUser,detectAuthProviders,detectedAuthProviderSchema,encryptAesGcm,encryptJson,encryptValue,encryptedBlobSchema,encryptedDataSchema,encryptedVaultEntrySchema,escapeHtml,extraWideLayout,extractBearerToken,extractCacheHeaders,extractCredentialExpiry,federatedAuthConfigSchema,federatedLoginStateSchema,federatedProviderItemSchema,federatedSelectionSchema,findAuthoritiesProfileProblems,findAuthoritiesRuleProblems,flatRemoteProviderFields,fromSessionRecord,generateAuthorizationCode,generatePkceChallenge,generateRefreshTokenValue,getCredentialOptionsSchema,getKey,getNextProvider,getProviderApps,getProviderScopes,getTokenSignatureFingerprint,grantScopes,hasOnlyLocalhostRedirectUris,headerApplier,hkdfSha256,incrementalAuthConfigSchema,isAnonymousSubject,isCimdClientId,isFrontMcpCredentials,isJwt,isLocalMode,isLoopbackRedirectUri,isOrchestratedLocal,isOrchestratedMode,isOrchestratedRemote,isPersistentTokenStorage,isPublicMode,isRedisTokenStorage,isRemoteMode,isSessionComplete,isSignedSession,isSoonExpiring,isSoonExpiringProvider,isSqliteTokenStorage,isStaticMode,isTransparentMode,jsonWebKeySetSchema,jwkParametersSchema,jwkSchema,legacySseTransportStateSchema,llmSafeAuthContextSchema,loadingStrategySchema,localAuthSchema,localDcrClientSchema,localDcrConfigSchema,localSigningConfigSchema,loginConfigSchema,mtlsCredentialSchema,noopLogger,normalizeIssuer,oauthCredentialSchema,openPendingLogin,orchestratedLocalSchema,orchestratedRemoteSchema,parseAuthOptions,parseCacheHeaders,parseWwwAuthenticate,pendingIncrementalAuthSchema,pkceChallengeSchema,pkceOAuthCredentialSchema,privateKeyCredentialSchema,progressiveAuthStateSchema,providerConfigSchema,providerHeadersCredentials,publicAccessConfigSchema,publicAuthOptionsSchema,queryApplier,rbacPermissionsPolicySchema,rbacRolesPolicySchema,rebacPolicySchema,redisConfigSchema,redisVaultEntrySchema,remoteAuthSchema,remoteProviderConfigSchema,renderLocalLoginPage,renderToHtml,resetCachedKey,resolveRequiredScopes,resourceIdRefSchema,resourceScopesFor,safeDecrypt,scopesFromClaims,sealPendingLogin,secureStoreConfigSchema,secureStoreCustomBackendSchema,secureStoreEncryptionSchema,secureStoreScopeSchema,serviceAccountCredentialSchema,sessionIdPayloadSchema,sessionJwtPayloadSchema,signCredentialResumeToken,signIncrementalAuthTicket,signSession,signinBindingCookieName,signinBindingMatches,skippedAppBehaviorSchema,sseTransportStateSchema,sshKeyCredentialSchema,startNextProvider,statefulHttpTransportStateSchema,statelessHttpTransportStateSchema,staticAuthOptionsSchema,storedSessionSchema,streamableHttpTransportStateSchema,toEpochSeconds,toLoginExtraFields,toSessionRecord,tokenRefreshConfigSchema,tokenStorageConfigSchema,tokenStorageSqliteSchema,transparentAuthOptionsSchema,transportProtocolSchema,transportSessionSchema,transportStateSchema,trimSlash,tryJwtExp,upstreamProviderSchema,userClaimSchema,validateAudience,validateClientIdUrl,vaultConsentRecordSchema,vaultFederatedRecordSchema,verifyCredentialResumeToken,verifyIncrementalAuthTicket,verifyOrParseSession,verifyPkce,verifySession,wideLayout,withoutSecretFieldValues});
354
+ </div>`;return centeredCardLayout(content,{title:"Error"})}function renderToHtml(html,_options){return html}function toLoginExtraFields(fields,values){if(!fields)return[];return Object.entries(fields).map(([name,def])=>({name,type:def.type,label:def.label,required:def.required,placeholder:def.placeholder,options:def.options,value:values?.[name]}))}function withoutSecretFieldValues(values,fields){if(!values)return void 0;const kept={};for(const[name,value]of Object.entries(values)){if(fields?.[name]?.type==="password")continue;kept[name]=value}return kept}function renderLocalLoginPage(login,ctx,submitted){const values=withoutSecretFieldValues(submitted,login?.fields);if(login?.render){return login.render({...ctx,values})}const extraFields=login?.fields?toLoginExtraFields(login.fields,values):void 0;return buildLoginPage({clientName:ctx.clientName,scope:ctx.scopes.join(" "),pendingAuthId:ctx.pendingAuthId,callbackPath:ctx.callbackPath,title:login?.title,subtitle:login?.subtitle,logoUri:login?.logoUri??ctx.logoUri,error:ctx.error,extraFields})}var import_lazy_zod=require("@frontmcp/lazy-zod");var import_utils5=require("@frontmcp/utils");var pkceChallengeSchema=import_lazy_zod.internalZ.object({challenge:import_lazy_zod.internalZ.string().min(43).max(128),method:import_lazy_zod.internalZ.literal("S256")});var authorizationCodeRecordSchema=import_lazy_zod.internalZ.object({code:import_lazy_zod.internalZ.string().min(1),clientId:import_lazy_zod.internalZ.string().min(1),redirectUri:import_lazy_zod.internalZ.string().url(),scopes:import_lazy_zod.internalZ.array(import_lazy_zod.internalZ.string()),pkce:pkceChallengeSchema,userSub:import_lazy_zod.internalZ.string().min(1),userEmail:import_lazy_zod.internalZ.string().email().optional(),userName:import_lazy_zod.internalZ.string().optional(),state:import_lazy_zod.internalZ.string().optional(),createdAt:import_lazy_zod.internalZ.number(),expiresAt:import_lazy_zod.internalZ.number(),used:import_lazy_zod.internalZ.boolean(),resource:import_lazy_zod.internalZ.string().url().optional(),selectedToolIds:import_lazy_zod.internalZ.array(import_lazy_zod.internalZ.string()).optional(),selectedProviderIds:import_lazy_zod.internalZ.array(import_lazy_zod.internalZ.string()).optional(),skippedProviderIds:import_lazy_zod.internalZ.array(import_lazy_zod.internalZ.string()).optional(),consentEnabled:import_lazy_zod.internalZ.boolean().optional(),federatedLoginUsed:import_lazy_zod.internalZ.boolean().optional(),pendingAuthId:import_lazy_zod.internalZ.string().optional(),authorizedAppIds:import_lazy_zod.internalZ.array(import_lazy_zod.internalZ.string()).optional(),customClaims:import_lazy_zod.internalZ.record(import_lazy_zod.internalZ.string(),import_lazy_zod.internalZ.unknown()).optional()});var AUTH_CODE_TTL_MS=60*1e3;var PENDING_AUTH_TTL_MS=10*60*1e3;var REFRESH_TOKEN_TTL_MS=30*24*60*60*1e3;function generateAuthorizationCode(){return(0,import_utils5.randomUUID)().replace(/-/g,"")+(0,import_utils5.randomUUID)().replace(/-/g,"")}function generateRefreshTokenValue(){return(0,import_utils5.randomUUID)()+"-"+(0,import_utils5.randomUUID)()}function buildCodeRecord(params){const now=Date.now();return{code:generateAuthorizationCode(),clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,pkce:params.pkce,userSub:params.userSub,userEmail:params.userEmail,userName:params.userName,state:params.state,resource:params.resource,createdAt:now,expiresAt:now+AUTH_CODE_TTL_MS,used:false,selectedToolIds:params.selectedToolIds,selectedProviderIds:params.selectedProviderIds,skippedProviderIds:params.skippedProviderIds,consentEnabled:params.consentEnabled,federatedLoginUsed:params.federatedLoginUsed,pendingAuthId:params.pendingAuthId,authorizedAppIds:params.authorizedAppIds,customClaims:params.customClaims}}function buildPendingRecord(params){const now=Date.now();return{id:(0,import_utils5.randomUUID)(),clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,pkce:params.pkce,state:params.state,resource:params.resource,createdAt:now,expiresAt:now+PENDING_AUTH_TTL_MS,isIncremental:params.isIncremental,incrementalSub:params.incrementalSub,targetAppId:params.targetAppId,targetToolId:params.targetToolId,existingSessionId:params.existingSessionId,existingAuthorizationId:params.existingAuthorizationId,priorAuthorizedAppIds:params.priorAuthorizedAppIds,federatedLogin:params.federatedLogin,consent:params.consent,authUiCsrf:params.authUiCsrf,signinBinding:params.signinBinding}}function buildRefreshTokenRecord(params){const now=Date.now();return{token:generateRefreshTokenValue(),clientId:params.clientId,userSub:params.userSub,scopes:params.scopes,resource:params.resource,createdAt:now,expiresAt:now+REFRESH_TOKEN_TTL_MS,revoked:false,userEmail:params.userEmail,userName:params.userName,consentEnabled:params.consentEnabled,selectedToolIds:params.selectedToolIds,authorizedAppIds:params.authorizedAppIds,customClaims:params.customClaims,federatedLoginUsed:params.federatedLoginUsed,selectedProviderIds:params.selectedProviderIds,skippedProviderIds:params.skippedProviderIds,providerTokensId:params.providerTokensId}}function verifyPkce(codeVerifier,challenge){if(challenge.method!=="S256"){return false}const hash=(0,import_utils5.sha256Base64url)(codeVerifier);return hash===challenge.challenge}function generatePkceChallenge(codeVerifier){const challenge=(0,import_utils5.sha256Base64url)(codeVerifier);return{challenge,method:"S256"}}var InMemoryAuthorizationStore=class{codes=new Map;pending=new Map;refreshTokens=new Map;generateCode(){return generateAuthorizationCode()}generateRefreshToken(){return generateRefreshTokenValue()}async storeAuthorizationCode(record){this.codes.set(record.code,record)}async getAuthorizationCode(code){const record=this.codes.get(code);if(!record)return null;if(Date.now()>record.expiresAt){this.codes.delete(code);return null}return record}async markCodeUsed(code,issuedRefreshToken){const record=this.codes.get(code);if(record){record.used=true;if(issuedRefreshToken)record.issuedRefreshToken=issuedRefreshToken}}async deleteAuthorizationCode(code){this.codes.delete(code)}async storePendingAuthorization(record){this.pending.set(record.id,record)}async getPendingAuthorization(id){const record=this.pending.get(id);if(!record)return null;if(Date.now()>record.expiresAt){this.pending.delete(id);return null}return record}async deletePendingAuthorization(id){this.pending.delete(id)}async storeRefreshToken(record){this.refreshTokens.set(record.token,record)}async getRefreshToken(token){const record=this.refreshTokens.get(token);if(!record)return null;if(Date.now()>record.expiresAt||record.revoked){return null}return record}async revokeRefreshToken(token){const record=this.refreshTokens.get(token);if(record){record.revoked=true}}async rotateRefreshToken(oldToken,newRecord){await this.revokeRefreshToken(oldToken);newRecord.previousToken=oldToken;await this.storeRefreshToken(newRecord)}async cleanup(){const now=Date.now();for(const[code,record]of this.codes){if(now>record.expiresAt){this.codes.delete(code)}}for(const[id,record]of this.pending){if(now>record.expiresAt){this.pending.delete(id)}}for(const[token,record]of this.refreshTokens){if(now>record.expiresAt||record.revoked){this.refreshTokens.delete(token)}}}createCodeRecord(params){return buildCodeRecord(params)}createPendingRecord(params){return buildPendingRecord(params)}createRefreshTokenRecord(params){return buildRefreshTokenRecord(params)}};var RedisAuthorizationStore=class{constructor(redis,namespace="oauth:"){this.redis=redis;this.namespace=namespace}redis;namespace;key(type,id){return`${this.namespace}${type}:${id}`}generateCode(){return generateAuthorizationCode()}generateRefreshToken(){return generateRefreshTokenValue()}createCodeRecord(params){return buildCodeRecord(params)}createPendingRecord(params){return buildPendingRecord(params)}createRefreshTokenRecord(params){return buildRefreshTokenRecord(params)}async storeAuthorizationCode(record){const ttl=Math.max(Math.ceil((record.expiresAt-Date.now())/1e3),1);await this.redis.set(this.key("code",record.code),JSON.stringify(record),"EX",Math.max(ttl,1))}async getAuthorizationCode(code){const data=await this.redis.get(this.key("code",code));if(!data)return null;return JSON.parse(data)}async markCodeUsed(code,issuedRefreshToken){const record=await this.getAuthorizationCode(code);if(record){record.used=true;if(issuedRefreshToken)record.issuedRefreshToken=issuedRefreshToken;const ttl=Math.ceil((record.expiresAt-Date.now())/1e3);await this.redis.set(this.key("code",code),JSON.stringify(record),"EX",Math.max(ttl,1))}}async deleteAuthorizationCode(code){await this.redis.del(this.key("code",code))}async storePendingAuthorization(record){const ttl=Math.max(Math.ceil((record.expiresAt-Date.now())/1e3),1);await this.redis.set(this.key("pending",record.id),JSON.stringify(record),"EX",ttl)}async getPendingAuthorization(id){const data=await this.redis.get(this.key("pending",id));if(!data)return null;return JSON.parse(data)}async deletePendingAuthorization(id){await this.redis.del(this.key("pending",id))}async storeRefreshToken(record){const ttl=Math.ceil((record.expiresAt-Date.now())/1e3);await this.redis.set(this.key("refresh",record.token),JSON.stringify(record),"EX",ttl)}async getRefreshToken(token){const data=await this.redis.get(this.key("refresh",token));if(!data)return null;const record=JSON.parse(data);if(record.revoked)return null;return record}async revokeRefreshToken(token){const record=await this.getRefreshToken(token);if(record){record.revoked=true;const ttl=Math.ceil((record.expiresAt-Date.now())/1e3);await this.redis.set(this.key("refresh",token),JSON.stringify(record),"EX",Math.max(ttl,1))}}async rotateRefreshToken(oldToken,newRecord){await this.revokeRefreshToken(oldToken);newRecord.previousToken=oldToken;await this.storeRefreshToken(newRecord)}async cleanup(){}};var import_utils6=require("@frontmcp/utils");var SALT=new TextEncoder().encode("frontmcp-pending-login");function keyFor(secret,pendingAuthId){return(0,import_utils6.hkdfSha256)(secret,SALT,new TextEncoder().encode(`pending-login:${pendingAuthId}`),32)}function sealPendingLogin(secret,pendingAuthId,state){const iv=(0,import_utils6.randomBytes)(12);const{ciphertext,tag}=(0,import_utils6.encryptAesGcm)(keyFor(secret,pendingAuthId),new TextEncoder().encode(JSON.stringify(state)),iv);return[iv,tag,ciphertext].map(part=>(0,import_utils6.base64urlEncode)(part)).join(".")}function openPendingLogin(secret,pendingAuthId,sealed){try{const[iv,tag,ciphertext]=sealed.split(".").map(part=>(0,import_utils6.base64urlDecode)(part));if(!iv||!tag||!ciphertext)return void 0;const plaintext=(0,import_utils6.decryptAesGcm)(keyFor(secret,pendingAuthId),ciphertext,iv,tag);const state=JSON.parse(new TextDecoder().decode(plaintext));return typeof state?.sub==="string"&&state.sub.length>0?state:void 0}catch{return void 0}}var import_utils7=require("@frontmcp/utils");var SIGNIN_BINDING_COOKIE_PREFIX="frontmcp_signin_";var SIGNIN_BINDING_SECURE_COOKIE_PREFIX=`__Host-${SIGNIN_BINDING_COOKIE_PREFIX}`;var SIGNIN_BINDING_MAX_AGE_SECONDS=30*60;function signinBindingCookieName(pendingAuthId,options={}){const prefix=options.secure?SIGNIN_BINDING_SECURE_COOKIE_PREFIX:SIGNIN_BINDING_COOKIE_PREFIX;return`${prefix}${(0,import_utils7.sha256Hex)(`signin:${pendingAuthId}`).slice(0,16)}`}function createSigninBinding(pendingAuthId,options={}){const value=(0,import_utils7.base64urlEncode)((0,import_utils7.randomBytes)(32));return{cookieName:signinBindingCookieName(pendingAuthId,options),value,hash:(0,import_utils7.sha256Hex)(value)}}function signinBindingMatches(cookieHeader,pendingAuthId,expectedHash,options={}){if(!expectedHash)return false;const value=(0,import_utils7.getCookie)(cookieHeader,signinBindingCookieName(pendingAuthId,options));if(!value)return false;const encoder2=new TextEncoder;const actual=encoder2.encode((0,import_utils7.sha256Hex)(value));const expected=encoder2.encode(expectedHash);return actual.length===expected.length&&(0,import_utils7.timingSafeEqual)(actual,expected)}var import_utils8=require("@frontmcp/utils");var StorageAuthorizationStore=class{codeStore;pendingStore;refreshStore;namespace;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"oauth";this.storageIsNamespaced=this.isNamespacedStorage(storage);const base=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.codeStore=new import_utils8.TypedStorage(base);this.pendingStore=new import_utils8.TypedStorage(base);this.refreshStore=new import_utils8.TypedStorage(base)}generateCode(){return generateAuthorizationCode()}generateRefreshToken(){return generateRefreshTokenValue()}createCodeRecord(params){return buildCodeRecord(params)}createPendingRecord(params){return buildPendingRecord(params)}createRefreshTokenRecord(params){return buildRefreshTokenRecord(params)}async storeAuthorizationCode(record){await this.codeStore.set(this.key("code",record.code),record,this.ttl(record.expiresAt))}async getAuthorizationCode(code){const record=await this.codeStore.get(this.key("code",code));if(!record)return null;if(Date.now()>record.expiresAt){await this.codeStore.delete(this.key("code",code));return null}return record}async markCodeUsed(code,issuedRefreshToken){const record=await this.getAuthorizationCode(code);if(record){record.used=true;if(issuedRefreshToken)record.issuedRefreshToken=issuedRefreshToken;await this.codeStore.set(this.key("code",code),record,this.ttl(record.expiresAt))}}async deleteAuthorizationCode(code){await this.codeStore.delete(this.key("code",code))}async storePendingAuthorization(record){await this.pendingStore.set(this.key("pending",record.id),record,this.ttl(record.expiresAt))}async getPendingAuthorization(id){const record=await this.pendingStore.get(this.key("pending",id));if(!record)return null;if(Date.now()>record.expiresAt){await this.pendingStore.delete(this.key("pending",id));return null}return record}async deletePendingAuthorization(id){await this.pendingStore.delete(this.key("pending",id))}async storeRefreshToken(record){await this.refreshStore.set(this.key("refresh",record.token),record,this.ttl(record.expiresAt))}async getRefreshToken(token){const record=await this.refreshStore.get(this.key("refresh",token));if(!record)return null;if(Date.now()>record.expiresAt||record.revoked){return null}return record}async revokeRefreshToken(token){const record=await this.refreshStore.get(this.key("refresh",token));if(record){record.revoked=true;await this.refreshStore.set(this.key("refresh",token),record,this.ttl(record.expiresAt))}}async rotateRefreshToken(oldToken,newRecord){await this.revokeRefreshToken(oldToken);newRecord.previousToken=oldToken;await this.storeRefreshToken(newRecord)}async cleanup(){}ttl(expiresAtMs){const ttl=Math.ceil((expiresAtMs-Date.now())/1e3);return{ttlSeconds:ttl>0?ttl:1}}key(type,id){const composite=`${type}:${id}`;return this.storageIsNamespaced?composite:`${this.namespace}:${composite}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_lazy_zod2=require("@frontmcp/lazy-zod");var credentialTypeSchema=import_lazy_zod2.internalZ.enum(["oauth","api_key","basic","bearer","private_key","mtls","custom","ssh_key","service_account","oauth_pkce"]);var oauthCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("oauth"),accessToken:import_lazy_zod2.internalZ.string(),refreshToken:import_lazy_zod2.internalZ.string().optional(),tokenType:import_lazy_zod2.internalZ.string().default("Bearer"),expiresAt:import_lazy_zod2.internalZ.number().optional(),scopes:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()).default([]),idToken:import_lazy_zod2.internalZ.string().optional()});var apiKeyCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("api_key"),key:import_lazy_zod2.internalZ.string().min(1),headerName:import_lazy_zod2.internalZ.string().default("X-API-Key"),headerPrefix:import_lazy_zod2.internalZ.string().optional(),queryParam:import_lazy_zod2.internalZ.string().optional()});var basicAuthCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("basic"),username:import_lazy_zod2.internalZ.string().min(1),password:import_lazy_zod2.internalZ.string(),encodedValue:import_lazy_zod2.internalZ.string().optional()});var bearerCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("bearer"),token:import_lazy_zod2.internalZ.string().min(1),expiresAt:import_lazy_zod2.internalZ.number().optional()});var privateKeyCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("private_key"),format:import_lazy_zod2.internalZ.enum(["pem","jwk","pkcs8","pkcs12"]),keyData:import_lazy_zod2.internalZ.string(),keyId:import_lazy_zod2.internalZ.string().optional(),algorithm:import_lazy_zod2.internalZ.string().optional(),passphrase:import_lazy_zod2.internalZ.string().optional(),certificate:import_lazy_zod2.internalZ.string().optional()});var mtlsCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("mtls"),certificate:import_lazy_zod2.internalZ.string(),privateKey:import_lazy_zod2.internalZ.string(),passphrase:import_lazy_zod2.internalZ.string().optional(),caCertificate:import_lazy_zod2.internalZ.string().optional()});var customCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("custom"),customType:import_lazy_zod2.internalZ.string().min(1),data:import_lazy_zod2.internalZ.record(import_lazy_zod2.internalZ.string(),import_lazy_zod2.internalZ.unknown()),headers:import_lazy_zod2.internalZ.record(import_lazy_zod2.internalZ.string(),import_lazy_zod2.internalZ.string()).optional()});var sshKeyCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("ssh_key"),privateKey:import_lazy_zod2.internalZ.string().min(1),publicKey:import_lazy_zod2.internalZ.string().optional(),passphrase:import_lazy_zod2.internalZ.string().optional(),keyType:import_lazy_zod2.internalZ.enum(["rsa","ed25519","ecdsa","dsa"]).default("ed25519"),fingerprint:import_lazy_zod2.internalZ.string().optional(),username:import_lazy_zod2.internalZ.string().optional()});var serviceAccountCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("service_account"),provider:import_lazy_zod2.internalZ.enum(["gcp","aws","azure","custom"]),credentials:import_lazy_zod2.internalZ.record(import_lazy_zod2.internalZ.string(),import_lazy_zod2.internalZ.unknown()),projectId:import_lazy_zod2.internalZ.string().optional(),region:import_lazy_zod2.internalZ.string().optional(),assumeRoleArn:import_lazy_zod2.internalZ.string().optional(),externalId:import_lazy_zod2.internalZ.string().optional(),serviceAccountId:import_lazy_zod2.internalZ.string().optional(),expiresAt:import_lazy_zod2.internalZ.number().optional()});var pkceOAuthCredentialSchema=import_lazy_zod2.internalZ.object({type:import_lazy_zod2.internalZ.literal("oauth_pkce"),accessToken:import_lazy_zod2.internalZ.string(),refreshToken:import_lazy_zod2.internalZ.string().optional(),tokenType:import_lazy_zod2.internalZ.string().default("Bearer"),expiresAt:import_lazy_zod2.internalZ.number().optional(),scopes:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()).default([]),idToken:import_lazy_zod2.internalZ.string().optional(),issuer:import_lazy_zod2.internalZ.string().optional()});var credentialSchema=import_lazy_zod2.internalZ.discriminatedUnion("type",[oauthCredentialSchema,apiKeyCredentialSchema,basicAuthCredentialSchema,bearerCredentialSchema,privateKeyCredentialSchema,mtlsCredentialSchema,customCredentialSchema,sshKeyCredentialSchema,serviceAccountCredentialSchema,pkceOAuthCredentialSchema]);var appCredentialSchema=import_lazy_zod2.internalZ.object({appId:import_lazy_zod2.internalZ.string().min(1),providerId:import_lazy_zod2.internalZ.string().min(1),credential:credentialSchema,acquiredAt:import_lazy_zod2.internalZ.number(),lastUsedAt:import_lazy_zod2.internalZ.number().optional(),expiresAt:import_lazy_zod2.internalZ.number().optional(),isValid:import_lazy_zod2.internalZ.boolean().default(true),invalidReason:import_lazy_zod2.internalZ.string().optional(),userInfo:import_lazy_zod2.internalZ.object({sub:import_lazy_zod2.internalZ.string().optional(),email:import_lazy_zod2.internalZ.string().optional(),name:import_lazy_zod2.internalZ.string().optional()}).optional(),metadata:import_lazy_zod2.internalZ.record(import_lazy_zod2.internalZ.string(),import_lazy_zod2.internalZ.unknown()).optional()});var vaultConsentRecordSchema=import_lazy_zod2.internalZ.object({enabled:import_lazy_zod2.internalZ.boolean(),selectedToolIds:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()),availableToolIds:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()),consentedAt:import_lazy_zod2.internalZ.number(),version:import_lazy_zod2.internalZ.string().default("1.0")});var vaultFederatedRecordSchema=import_lazy_zod2.internalZ.object({selectedProviderIds:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()),skippedProviderIds:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()),primaryProviderId:import_lazy_zod2.internalZ.string().optional(),completedAt:import_lazy_zod2.internalZ.number()});var pendingIncrementalAuthSchema=import_lazy_zod2.internalZ.object({id:import_lazy_zod2.internalZ.string(),appId:import_lazy_zod2.internalZ.string(),toolId:import_lazy_zod2.internalZ.string().optional(),authUrl:import_lazy_zod2.internalZ.string(),requiredScopes:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()).optional(),elicitId:import_lazy_zod2.internalZ.string().optional(),createdAt:import_lazy_zod2.internalZ.number(),expiresAt:import_lazy_zod2.internalZ.number(),status:import_lazy_zod2.internalZ.enum(["pending","completed","cancelled","expired"])});var authorizationVaultEntrySchema=import_lazy_zod2.internalZ.object({id:import_lazy_zod2.internalZ.string(),userSub:import_lazy_zod2.internalZ.string(),userEmail:import_lazy_zod2.internalZ.string().optional(),userName:import_lazy_zod2.internalZ.string().optional(),clientId:import_lazy_zod2.internalZ.string(),createdAt:import_lazy_zod2.internalZ.number(),lastAccessAt:import_lazy_zod2.internalZ.number(),appCredentials:import_lazy_zod2.internalZ.record(import_lazy_zod2.internalZ.string(),appCredentialSchema).default({}),consent:vaultConsentRecordSchema.optional(),federated:vaultFederatedRecordSchema.optional(),pendingAuths:import_lazy_zod2.internalZ.array(pendingIncrementalAuthSchema),authorizedAppIds:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string()),skippedAppIds:import_lazy_zod2.internalZ.array(import_lazy_zod2.internalZ.string())});var import_utils10=require("@frontmcp/utils");var import_lazy_zod3=require("@frontmcp/lazy-zod");var import_utils9=require("@frontmcp/utils");var encryptedDataSchema=import_lazy_zod3.z.object({v:import_lazy_zod3.z.literal(1),alg:import_lazy_zod3.z.literal("aes-256-gcm"),iv:import_lazy_zod3.z.string(),ct:import_lazy_zod3.z.string(),tag:import_lazy_zod3.z.string()});var VaultEncryption=class{pepper;hkdfInfo;constructor(config={}){this.pepper=new TextEncoder().encode(config.pepper??"");this.hkdfInfo=config.hkdfInfo??"frontmcp-vault-v1"}async deriveKey(claims){const ikmParts=[claims.jti,claims.vaultKey??"",claims.sub,claims.iat.toString(),new TextDecoder().decode(this.pepper)];const ikm=new TextEncoder().encode(ikmParts.join(""));const infoBytes=new TextEncoder().encode(this.hkdfInfo);const key=await(0,import_utils9.hkdfSha256)(ikm,new Uint8Array(0),infoBytes,32);return key}async deriveKeyFromToken(token,claims){const parts=token.split(".");const signature=parts[2]??"";const ikmParts=[claims.jti,claims.vaultKey??"",claims.sub,claims.iat.toString(),signature,new TextDecoder().decode(this.pepper)];const ikm=new TextEncoder().encode(ikmParts.join(""));const infoBytes=new TextEncoder().encode(this.hkdfInfo);const key=await(0,import_utils9.hkdfSha256)(ikm,new Uint8Array(0),infoBytes,32);return key}async encrypt(plaintext,key){if(key.length!==32){throw new Error("Encryption key must be 32 bytes")}const iv=(0,import_utils9.randomBytes)(12);const{ciphertext,tag}=await(0,import_utils9.encryptAesGcm)(key,new TextEncoder().encode(plaintext),iv);return{v:1,alg:"aes-256-gcm",iv:(0,import_utils9.base64urlEncode)(iv),ct:(0,import_utils9.base64urlEncode)(ciphertext),tag:(0,import_utils9.base64urlEncode)(tag)}}async decrypt(encrypted,key){if(key.length!==32){throw new Error("Encryption key must be 32 bytes")}const parsed=encryptedDataSchema.safeParse(encrypted);if(!parsed.success){throw new Error("Invalid encrypted data format")}const{iv,ct,tag}=parsed.data;const ivBuffer=(0,import_utils9.base64urlDecode)(iv);const ciphertext=(0,import_utils9.base64urlDecode)(ct);const tagBuffer=(0,import_utils9.base64urlDecode)(tag);try{const plaintext=await(0,import_utils9.decryptAesGcm)(key,ciphertext,ivBuffer,tagBuffer);return new TextDecoder().decode(plaintext)}catch(_error){throw new Error("Decryption failed: invalid key or corrupted data")}}async encryptObject(data,key){return this.encrypt(JSON.stringify(data),key)}async decryptObject(encrypted,key){const plaintext=await this.decrypt(encrypted,key);return JSON.parse(plaintext)}isEncrypted(data){return encryptedDataSchema.safeParse(data).success}};var encryptedVaultEntrySchema=import_lazy_zod3.z.object({id:import_lazy_zod3.z.string(),userSub:import_lazy_zod3.z.string(),userEmail:import_lazy_zod3.z.string().optional(),userName:import_lazy_zod3.z.string().optional(),clientId:import_lazy_zod3.z.string(),createdAt:import_lazy_zod3.z.number(),lastAccessAt:import_lazy_zod3.z.number(),encryptedData:encryptedDataSchema,authorizedAppIds:import_lazy_zod3.z.array(import_lazy_zod3.z.string()),skippedAppIds:import_lazy_zod3.z.array(import_lazy_zod3.z.string()),pendingAuthIds:import_lazy_zod3.z.array(import_lazy_zod3.z.string()).default([])});var DEFAULT_KEY_PREFIX="mcp:cred:";var DEFAULT_PENDING_TTL_MS=6e5;var SessionCredentialVault=class{storage;encryption;keyPrefix;ttlMs;pendingTtlMs;logger;keyCache=new Map;constructor(options){this.storage=options.storage;this.keyPrefix=options.keyPrefix??DEFAULT_KEY_PREFIX;this.ttlMs=options.ttlMs;this.pendingTtlMs=options.pendingTtlMs??DEFAULT_PENDING_TTL_MS;this.logger=options.logger??noopAuthLogger;const pepper=options.pepper??resolveVaultPepper(this.logger);this.encryption=new VaultEncryption({pepper,hkdfInfo:"frontmcp-session-credential-vault-v1"})}indexKey(sub){return`${this.keyPrefix}idx:${sub}`}keysKey(sub,vaultId){return`${this.keyPrefix}keys:${sub}:${vaultId}`}dataKey(sub,vaultId,key){return`${this.keyPrefix}data:${sub}:${vaultId}:${key}`}pendingKey(pendingId){return`${this.keyPrefix}pending:${pendingId}`}get credentialSetOpts(){return this.ttlMs?{ttlSeconds:Math.ceil(this.ttlMs/1e3)}:void 0}deriveKey(sub,vaultId){const cacheKey=`${sub}:${vaultId}`;const cached=this.keyCache.get(cacheKey);if(cached)return cached;const promise=this.encryption.deriveKey({jti:vaultId,vaultKey:vaultId,sub,iat:0});this.keyCache.set(cacheKey,promise);return promise}async getVaultId(sub){const raw=await this.storage.get(this.indexKey(sub));return raw??void 0}async rotateVault(sub){const vaultId=(0,import_utils10.randomUUID)();await this.storage.set(this.indexKey(sub),vaultId,this.credentialSetOpts);return vaultId}async store(sub,vaultId,key,value){const aesKey=await this.deriveKey(sub,vaultId);const enc=await this.encryption.encryptObject(this.normalize(value),aesKey);const record={enc};await this.storage.set(this.dataKey(sub,vaultId,key),JSON.stringify(record),this.credentialSetOpts);await this.addKeyToSet(sub,vaultId,key)}async get(sub,key){const vaultId=await this.getVaultId(sub);if(!vaultId)return void 0;const raw=await this.storage.get(this.dataKey(sub,vaultId,key));if(!raw)return void 0;try{const record=JSON.parse(raw);const aesKey=await this.deriveKey(sub,vaultId);return await this.encryption.decryptObject(record.enc,aesKey)}catch(err){this.logger.warn(`SessionCredentialVault: failed to read credential "${key}": ${errMsg(err)}`);return void 0}}async list(sub){const vaultId=await this.getVaultId(sub);if(!vaultId)return[];return this.readKeySet(sub,vaultId)}async remove(sub,key){const vaultId=await this.getVaultId(sub);if(!vaultId)return;await this.storage.delete(this.dataKey(sub,vaultId,key));const keys=await this.readKeySet(sub,vaultId);const next=keys.filter(k=>k!==key);if(next.length!==keys.length){await this.writeKeySet(sub,vaultId,next)}}async stage(pendingId,sub,credentials){const vaultId=await this.rotateVault(sub);const creds={};for(const cred of credentials){const aesKey=await this.deriveKey(sub,vaultId);const{key,...value}=cred;creds[key]={enc:await this.encryption.encryptObject(this.normalize(value),aesKey)}}const batch={sub,vaultId,creds};await this.storage.set(this.pendingKey(pendingId),JSON.stringify(batch),{ttlSeconds:Math.ceil(this.pendingTtlMs/1e3)});return vaultId}async commit(pendingId,sub){const raw=await this.storage.get(this.pendingKey(pendingId));if(!raw)return false;let batch;try{batch=JSON.parse(raw)}catch{await this.storage.delete(this.pendingKey(pendingId));return false}if(batch.sub!==sub){this.logger.warn("SessionCredentialVault: pending batch subject mismatch on commit; discarding");await this.storage.delete(this.pendingKey(pendingId));return false}await this.storage.set(this.indexKey(sub),batch.vaultId,this.credentialSetOpts);const keys=[];for(const[key,record]of Object.entries(batch.creds)){await this.storage.set(this.dataKey(sub,batch.vaultId,key),JSON.stringify(record),this.credentialSetOpts);keys.push(key)}await this.writeKeySet(sub,batch.vaultId,keys);await this.storage.delete(this.pendingKey(pendingId));return true}async readKeySet(sub,vaultId){const raw=await this.storage.get(this.keysKey(sub,vaultId));if(!raw)return[];try{const parsed=JSON.parse(raw);return Array.isArray(parsed)?parsed.filter(k=>typeof k==="string"):[]}catch{return[]}}async writeKeySet(sub,vaultId,keys){const unique=[...new Set(keys)];await this.storage.set(this.keysKey(sub,vaultId),JSON.stringify(unique),this.credentialSetOpts)}async addKeyToSet(sub,vaultId,key){const keys=await this.readKeySet(sub,vaultId);if(!keys.includes(key)){keys.push(key);await this.writeKeySet(sub,vaultId,keys)}}normalize(value){return value.metadata===void 0?{secret:value.secret}:{secret:value.secret,metadata:value.metadata}}};function resolveVaultPepper(logger){const fromEnv=(0,import_utils10.getEnv)("VAULT_SECRET")??(0,import_utils10.getEnv)("JWT_SECRET");if(fromEnv&&fromEnv.trim().length>0)return fromEnv;logger.warn("SessionCredentialVault: neither VAULT_SECRET nor JWT_SECRET is set; using a random per-process pepper. Stored credentials will NOT survive a restart and cannot be shared across instances. Set VAULT_SECRET (or JWT_SECRET) for persistent, multi-instance credential storage.");return(0,import_utils10.randomUUID)()+(0,import_utils10.randomUUID)()}function errMsg(err){return err instanceof Error?err.message:String(err)}var import_utils11=require("@frontmcp/utils");function isRedisTokenStorage(config){return typeof config==="object"&&config!==null&&"redis"in config&&!!config.redis}function isSqliteTokenStorage(config){return typeof config==="object"&&config!==null&&"sqlite"in config&&!!config.sqlite}function isPersistentTokenStorage(config){return config!==void 0&&config!=="memory"}async function createTokenStorageAdapter(config){if(config===void 0||config==="memory"){const adapter=new import_utils11.MemoryStorageAdapter;await adapter.connect();return adapter}if(isSqliteTokenStorage(config)){const{SqliteStorageAdapter}=require("@frontmcp/storage-sqlite");const adapter=new SqliteStorageAdapter({path:config.sqlite.path,encryption:config.sqlite.encryption,ttlCleanupIntervalMs:config.sqlite.ttlCleanupIntervalMs??6e4,walMode:config.sqlite.walMode??true,busyTimeoutMs:config.sqlite.busyTimeoutMs});await adapter.connect();return adapter}if(isRedisTokenStorage(config)){const{host,port,password,db,tls,keyPrefix}=config.redis;const adapter=new import_utils11.RedisStorageAdapter({config:{host,port,password,db,tls},keyPrefix:keyPrefix??""});await adapter.connect();return adapter}const fallback=new import_utils11.MemoryStorageAdapter;await fallback.connect();return fallback}async function createSessionCredentialVault(options){const storage=options.storage??await createTokenStorageAdapter(options.tokenStorage);const vault=new SessionCredentialVault({storage,pepper:options.pepper,keyPrefix:options.keyPrefix,ttlMs:options.ttlMs,logger:options.logger});const type=options.tokenStorage===void 0||options.tokenStorage==="memory"?"memory":"sqlite"in options.tokenStorage?"sqlite":"redis";return{vault,type}}var import_utils12=require("@frontmcp/utils");var DEFAULT_RESUME_TTL_MS=6e5;function signCredentialResumeToken(input,secret){const payload={sub:input.sub,key:input.key,...input.context!==void 0?{context:input.context}:{},exp:Date.now()+(input.ttlMs??DEFAULT_RESUME_TTL_MS)};const signedJson=(0,import_utils12.signData)(payload,{secret});return Buffer.from(signedJson,"utf8").toString("base64url")}function verifyCredentialResumeToken(token,secret,now=Date.now()){let signedJson;try{signedJson=Buffer.from(token,"base64url").toString("utf8")}catch{return null}const payload=(0,import_utils12.verifyData)(signedJson,{secret});if(!payload)return null;if(typeof payload.sub!=="string"||typeof payload.key!=="string"||!Number.isFinite(payload.exp)){return null}if(payload.context!==void 0&&typeof payload.context!=="string"){return null}if(now>=payload.exp){return null}return payload}function buildCredentialResumeUrl(basePath,token){const trimmed=basePath.endsWith("/")?basePath.slice(0,-1):basePath;return`${trimmed}/oauth/connect?token=${encodeURIComponent(token)}`}var import_utils13=require("@frontmcp/utils");var DEFAULT_INCREMENTAL_TICKET_TTL_MS=3e5;function signIncrementalAuthTicket(input,secret){const payload={sub:input.sub,appId:input.appId,...input.toolId!==void 0?{toolId:input.toolId}:{},...input.priorAppIds!==void 0?{priorAppIds:input.priorAppIds}:{},jti:(0,import_utils13.randomUUID)(),exp:Date.now()+(input.ttlMs??DEFAULT_INCREMENTAL_TICKET_TTL_MS)};const signedJson=(0,import_utils13.signData)(payload,{secret});return Buffer.from(signedJson,"utf8").toString("base64url")}function verifyIncrementalAuthTicket(token,secret,now=Date.now()){let signedJson;try{signedJson=Buffer.from(token,"base64url").toString("utf8")}catch{return null}const payload=(0,import_utils13.verifyData)(signedJson,{secret});if(!payload)return null;if(typeof payload.sub!=="string"||payload.sub.length===0)return null;if(typeof payload.appId!=="string"||payload.appId.length===0)return null;if(typeof payload.jti!=="string"||payload.jti.length===0)return null;if(!Number.isFinite(payload.exp))return null;if(payload.toolId!==void 0&&typeof payload.toolId!=="string")return null;if(payload.priorAppIds!==void 0&&(!Array.isArray(payload.priorAppIds)||payload.priorAppIds.some(id=>typeof id!=="string"))){return null}if(now>=payload.exp){return null}return payload}var CREDENTIALS_ACCESSOR=Symbol.for("frontmcp:CREDENTIALS_ACCESSOR");var CredentialsAccessorImpl=class{vault;resolveSub;signingSecret;basePath;resumeTtlMs;logger;constructor(deps){this.vault=deps.vault;this.resolveSub=deps.resolveSub;this.signingSecret=deps.signingSecret;this.basePath=deps.basePath;this.resumeTtlMs=deps.resumeTtlMs;this.logger=deps.logger??noopAuthLogger}async get(key){const sub=this.resolveSub();if(!sub)return void 0;return this.vault.get(sub,key)}async list(){const sub=this.resolveSub();if(!sub)return[];return this.vault.list(sub)}async requireConnect(options){const{key,context}=options;const sub=this.resolveSub();if(sub){const existing=await this.vault.get(sub,key);if(existing){return{connected:true,key,credential:existing}}}const token=signCredentialResumeToken({sub:sub??"",key,context,ttlMs:this.resumeTtlMs},this.signingSecret);const resumeUrl=buildCredentialResumeUrl(this.basePath,token);this.logger.debug(`CredentialsAccessor: credential "${key}" not connected; issued resume link`);return{connected:false,key,resumeUrl,message:`Credential "${key}" is not connected. Open the resume URL to connect it.`}}};var DEFAULT_KEY_PREFIX2="mcp:secret:";var EncryptedStorageSecureStoreBackend=class{storage;encryption;keyPrefix;logger;keyCache=new Map;constructor(options){this.storage=options.storage;this.keyPrefix=options.keyPrefix??DEFAULT_KEY_PREFIX2;this.logger=options.logger??noopAuthLogger;this.encryption=new VaultEncryption({pepper:options.pepper,hkdfInfo:"frontmcp-secure-store-v1"})}keysKey(namespace){return`${this.keyPrefix}keys:${namespace}`}dataKey(namespace,key){return`${this.keyPrefix}data:${namespace}:${key}`}deriveKey(namespace){const cached=this.keyCache.get(namespace);if(cached)return cached;const promise=this.encryption.deriveKey({jti:namespace,vaultKey:namespace,sub:namespace,iat:0});this.keyCache.set(namespace,promise);return promise}setOpts(ttlMs){return ttlMs&&ttlMs>0?{ttlSeconds:Math.ceil(ttlMs/1e3)}:void 0}async get(namespace,key){const raw=await this.storage.get(this.dataKey(namespace,key));if(!raw)return null;try{const record=JSON.parse(raw);const aesKey=await this.deriveKey(namespace);return await this.encryption.decrypt(record.enc,aesKey)}catch(err){this.logger.warn(`SecureStore: failed to read secret "${key}": ${errMsg2(err)}`);return null}}async set(namespace,key,value,ttlMs){const aesKey=await this.deriveKey(namespace);const enc=await this.encryption.encrypt(value,aesKey);const record={enc};const opts=this.setOpts(ttlMs);await this.storage.set(this.dataKey(namespace,key),JSON.stringify(record),opts);await this.addKeyToSet(namespace,key,opts)}async delete(namespace,key){const existed=await this.storage.delete(this.dataKey(namespace,key));const keys=await this.readKeySet(namespace);const next=keys.filter(k=>k!==key);if(next.length!==keys.length){await this.writeKeySet(namespace,next)}return existed}async list(namespace){return this.readKeySet(namespace)}async readKeySet(namespace){const raw=await this.storage.get(this.keysKey(namespace));if(!raw)return[];try{const parsed=JSON.parse(raw);return Array.isArray(parsed)?parsed.filter(k=>typeof k==="string"):[]}catch{return[]}}async writeKeySet(namespace,keys,opts){const unique=[...new Set(keys)];await this.storage.set(this.keysKey(namespace),JSON.stringify(unique),opts)}async addKeyToSet(namespace,key,opts){const keys=await this.readKeySet(namespace);if(!keys.includes(key)){keys.push(key);await this.writeKeySet(namespace,keys,opts)}}};function errMsg2(err){return err instanceof Error?err.message:String(err)}var SECURE_STORE_ACCESSOR=Symbol.for("frontmcp:SECURE_STORE_ACCESSOR");var import_utils14=require("@frontmcp/utils");var GLOBAL_NAMESPACE="global";var SecureStoreAccessorImpl=class{backend;scope;resolveSub;resolveSessionId;ttlMs;logger;constructor(deps){this.backend=deps.backend;this.scope=deps.scope??"user";this.resolveSub=deps.resolveSub;this.resolveSessionId=deps.resolveSessionId;this.ttlMs=deps.ttlMs;this.logger=deps.logger??noopAuthLogger}resolveNamespace(){switch(this.scope){case"global":return GLOBAL_NAMESPACE;case"session":{const sid=this.resolveSessionId();return sid?`s:${(0,import_utils14.sha256Hex)(sid).slice(0,32)}`:void 0}case"user":default:{const sub=this.resolveSub();return sub?`u:${(0,import_utils14.sha256Hex)(sub).slice(0,32)}`:void 0}}}async get(key){const namespace=this.resolveNamespace();if(!namespace)return void 0;const raw=await this.backend.get(namespace,key);if(raw===null)return void 0;try{return JSON.parse(raw)}catch(err){this.logger.warn(`SecureStore: failed to parse secret "${key}": ${errMsg3(err)}`);return void 0}}async set(key,value,options){const namespace=this.resolveNamespace();if(!namespace){this.logger.debug(`SecureStore: no ${this.scope} scope for request; skipping set("${key}")`);return}const ttlMs=options?.ttlMs??this.ttlMs;await this.backend.set(namespace,key,JSON.stringify(value),ttlMs)}async delete(key){const namespace=this.resolveNamespace();if(!namespace)return false;return this.backend.delete(namespace,key)}async list(){const namespace=this.resolveNamespace();if(!namespace)return[];return this.backend.list(namespace)}};function errMsg3(err){return err instanceof Error?err.message:String(err)}var import_utils19=require("@frontmcp/utils");var import_utils15=require("@frontmcp/utils");var AuthInternalError=class extends Error{errorId;isPublic=false;statusCode=500;code;constructor(message,code="AUTH_INTERNAL_ERROR"){super(message);this.name=this.constructor.name;this.code=code;this.errorId=`err_${(0,import_utils15.bytesToHex)((0,import_utils15.randomBytes)(8))}`;Error.captureStackTrace(this,this.constructor)}getPublicMessage(){return`Internal auth error. Please contact support with error ID: ${this.errorId}`}getInternalMessage(){return this.message}};var EncryptionContextNotSetError=class extends AuthInternalError{constructor(){super("Encryption context is not set","ENCRYPTION_CONTEXT_NOT_SET")}};var VaultLoadError=class extends AuthInternalError{originalError;constructor(vaultId,originalError){super(`Failed to load vault "${vaultId}"${originalError?`: ${originalError.message}`:""}`,"VAULT_LOAD_ERROR");this.originalError=originalError}};var VaultNotFoundError=class extends AuthInternalError{constructor(entityType,id){super(`${entityType} "${id}" not found in vault`,"VAULT_NOT_FOUND")}};var TokenNotAvailableError=class extends AuthInternalError{constructor(message){super(message,"TOKEN_NOT_AVAILABLE")}};var TokenStoreRequiredError=class extends AuthInternalError{constructor(context){super(`Token store is required for ${context}`,"TOKEN_STORE_REQUIRED")}};var NoProviderIdError=class extends AuthInternalError{constructor(message){super(message,"NO_PROVIDER_ID")}};var TokenLeakDetectedError=class extends AuthInternalError{constructor(detail){super(`Token leak detected: ${detail}`,"TOKEN_LEAK_DETECTED")}};var SessionSecretRequiredError=class extends AuthInternalError{constructor(component){super(`Session secret is required for ${component}`,"SESSION_SECRET_REQUIRED")}};var JwtSecretRequiredError=class extends AuthInternalError{constructor(mode){super(`JWT_SECRET is required in production for auth.mode "${mode}". Without it the server signs tokens with a random per-process secret, so every restart invalidates outstanding tokens and any second instance or isolate rejects tokens the first one minted.`,"JWT_SECRET_REQUIRED")}};var JwtSecretWeakError=class extends AuthInternalError{constructor(byteLength){super(`JWT_SECRET is ${byteLength} bytes; HS256 requires at least 32 (RFC 7518 \xA73.2). A shorter secret is guessable, and whoever guesses it can forge tokens for this server. Generate one with \`openssl rand -hex 32\`.`,"JWT_SECRET_INVALID")}};var CredentialProviderAlreadyRegisteredError=class extends AuthInternalError{constructor(name){super(`Credential provider "${name}" is already registered`,"CREDENTIAL_PROVIDER_ALREADY_REGISTERED")}};var AuthProvidersNotConfiguredError=class extends AuthInternalError{constructor(){super("Auth providers are not configured","AUTH_PROVIDERS_NOT_CONFIGURED")}};var OrchestratedAuthNotAvailableError=class extends AuthInternalError{constructor(){super("Orchestrated auth is not available","ORCHESTRATED_AUTH_NOT_AVAILABLE")}};var EncryptionKeyNotConfiguredError=class extends AuthInternalError{constructor(){super("Encryption key is not configured","ENCRYPTION_KEY_NOT_CONFIGURED")}};var SessionIdEmptyError=class extends AuthInternalError{constructor(storeName){super(`Session ID must not be empty (${storeName})`,"SESSION_ID_EMPTY")}};var ElicitationSecretRequiredError=class extends AuthInternalError{constructor(){super("Elicitation secret is required","ELICITATION_SECRET_REQUIRED")}};var ScopeDeniedError=class extends AuthInternalError{constructor(providerId){super(`Scope access denied for provider "${providerId}"`,"SCOPE_DENIED")}};var InMemoryStoreRequiredError=class extends AuthInternalError{constructor(component){super(`In-memory store is required for ${component}`,"INMEMORY_STORE_REQUIRED")}};var OrchestratorJwksNotAvailableError=class extends AuthInternalError{constructor(){super("Orchestrator JWKS is not available","ORCHESTRATOR_JWKS_NOT_AVAILABLE")}};var SecureStoreConfigError=class extends AuthInternalError{constructor(message){super(`Invalid auth.secureStore: ${message}`,"SECURE_STORE_CONFIG_INVALID")}};var AuthInvalidInputError=class extends AuthInternalError{constructor(message){super(message,"AUTH_INVALID_INPUT")}};var CredentialStorageError=class extends AuthInternalError{constructor(message){super(message,"CREDENTIAL_STORAGE_ERROR")}};var AuthFlowError=class extends AuthInternalError{constructor(message,code="AUTH_FLOW_ERROR"){super(message,code)}};var import_lazy_zod7=require("@frontmcp/lazy-zod");var import_lazy_zod4=require("@frontmcp/lazy-zod");var jwkParametersSchema=import_lazy_zod4.internalZ.object({kty:import_lazy_zod4.internalZ.string().optional(),alg:import_lazy_zod4.internalZ.string().optional(),key_ops:import_lazy_zod4.internalZ.array(import_lazy_zod4.internalZ.string()).optional(),ext:import_lazy_zod4.internalZ.boolean().optional(),use:import_lazy_zod4.internalZ.string().optional(),x5c:import_lazy_zod4.internalZ.array(import_lazy_zod4.internalZ.string()).optional(),x5t:import_lazy_zod4.internalZ.string().optional(),"x5t#S256":import_lazy_zod4.internalZ.string().optional(),x5u:import_lazy_zod4.internalZ.string().optional(),kid:import_lazy_zod4.internalZ.string().optional()});var jwkSchema=jwkParametersSchema.extend({crv:import_lazy_zod4.internalZ.string().optional(),d:import_lazy_zod4.internalZ.string().optional(),dp:import_lazy_zod4.internalZ.string().optional(),dq:import_lazy_zod4.internalZ.string().optional(),e:import_lazy_zod4.internalZ.string().optional(),k:import_lazy_zod4.internalZ.string().optional(),n:import_lazy_zod4.internalZ.string().optional(),p:import_lazy_zod4.internalZ.string().optional(),q:import_lazy_zod4.internalZ.string().optional(),qi:import_lazy_zod4.internalZ.string().optional(),x:import_lazy_zod4.internalZ.string().optional(),y:import_lazy_zod4.internalZ.string().optional(),pub:import_lazy_zod4.internalZ.string().optional(),priv:import_lazy_zod4.internalZ.string().optional()});var jsonWebKeySetSchema=import_lazy_zod4.internalZ.object({keys:import_lazy_zod4.internalZ.array(jwkSchema)});var import_lazy_zod5=require("@frontmcp/lazy-zod");var transportProtocolSchema=import_lazy_zod5.internalZ.enum(["legacy-sse","sse","streamable-http","stateful-http","stateless-http"]);var sseTransportStateSchema=import_lazy_zod5.internalZ.object({type:import_lazy_zod5.internalZ.literal("sse"),lastEventId:import_lazy_zod5.internalZ.string().optional(),lastPing:import_lazy_zod5.internalZ.number().optional(),connectionState:import_lazy_zod5.internalZ.enum(["connecting","open","closed"]).optional()});var streamableHttpTransportStateSchema=import_lazy_zod5.internalZ.object({type:import_lazy_zod5.internalZ.literal("streamable-http"),requestSeq:import_lazy_zod5.internalZ.number(),activeStreamId:import_lazy_zod5.internalZ.string().optional(),pendingRequests:import_lazy_zod5.internalZ.array(import_lazy_zod5.internalZ.string()).optional()});var statefulHttpTransportStateSchema=import_lazy_zod5.internalZ.object({type:import_lazy_zod5.internalZ.literal("stateful-http"),requestSeq:import_lazy_zod5.internalZ.number(),pendingResponses:import_lazy_zod5.internalZ.array(import_lazy_zod5.internalZ.string()).optional(),lastActivity:import_lazy_zod5.internalZ.number().optional()});var statelessHttpTransportStateSchema=import_lazy_zod5.internalZ.object({type:import_lazy_zod5.internalZ.literal("stateless-http"),requestCount:import_lazy_zod5.internalZ.number(),windowStart:import_lazy_zod5.internalZ.number().optional()});var legacySseTransportStateSchema=import_lazy_zod5.internalZ.object({type:import_lazy_zod5.internalZ.literal("legacy-sse"),messagePath:import_lazy_zod5.internalZ.string(),lastEventId:import_lazy_zod5.internalZ.string().optional(),connectionState:import_lazy_zod5.internalZ.enum(["connecting","open","closed"]).optional()});var transportStateSchema=import_lazy_zod5.internalZ.discriminatedUnion("type",[sseTransportStateSchema,streamableHttpTransportStateSchema,statefulHttpTransportStateSchema,statelessHttpTransportStateSchema,legacySseTransportStateSchema]);var transportSessionSchema=import_lazy_zod5.internalZ.object({id:import_lazy_zod5.internalZ.string(),authorizationId:import_lazy_zod5.internalZ.string(),protocol:transportProtocolSchema,createdAt:import_lazy_zod5.internalZ.number(),expiresAt:import_lazy_zod5.internalZ.number().optional(),nodeId:import_lazy_zod5.internalZ.string(),clientFingerprint:import_lazy_zod5.internalZ.string().optional(),transportState:transportStateSchema.optional()});var sessionJwtPayloadSchema=import_lazy_zod5.internalZ.object({sid:import_lazy_zod5.internalZ.string(),aid:import_lazy_zod5.internalZ.string(),proto:transportProtocolSchema,nid:import_lazy_zod5.internalZ.string(),iat:import_lazy_zod5.internalZ.number(),exp:import_lazy_zod5.internalZ.number().optional()});var encryptedBlobSchema=import_lazy_zod5.internalZ.object({alg:import_lazy_zod5.internalZ.literal("A256GCM"),kid:import_lazy_zod5.internalZ.string().optional(),iv:import_lazy_zod5.internalZ.string(),tag:import_lazy_zod5.internalZ.string(),data:import_lazy_zod5.internalZ.string(),exp:import_lazy_zod5.internalZ.number().optional(),meta:import_lazy_zod5.internalZ.record(import_lazy_zod5.internalZ.string(),import_lazy_zod5.internalZ.unknown()).optional()});var storedSessionSchema=import_lazy_zod5.internalZ.object({session:transportSessionSchema,authorizationId:import_lazy_zod5.internalZ.string(),tokens:import_lazy_zod5.internalZ.record(import_lazy_zod5.internalZ.string(),encryptedBlobSchema).optional(),createdAt:import_lazy_zod5.internalZ.number(),lastAccessedAt:import_lazy_zod5.internalZ.number(),initialized:import_lazy_zod5.internalZ.boolean().optional(),maxLifetimeAt:import_lazy_zod5.internalZ.number().optional(),clientCapabilities:import_lazy_zod5.internalZ.record(import_lazy_zod5.internalZ.string(),import_lazy_zod5.internalZ.unknown()).optional(),reassignedAt:import_lazy_zod5.internalZ.number().optional(),reassignedFrom:import_lazy_zod5.internalZ.string().optional()});var redisConfigSchema=import_lazy_zod5.internalZ.object({host:import_lazy_zod5.internalZ.string().min(1),port:import_lazy_zod5.internalZ.number().int().positive().optional().default(6379),password:import_lazy_zod5.internalZ.string().optional(),db:import_lazy_zod5.internalZ.number().int().nonnegative().optional().default(0),tls:import_lazy_zod5.internalZ.boolean().optional().default(false),keyPrefix:import_lazy_zod5.internalZ.string().optional().default("mcp:session:"),defaultTtlMs:import_lazy_zod5.internalZ.number().int().positive().optional().default(36e5)});var noopLogger={child:()=>noopLogger,debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}};var import_lazy_zod6=require("@frontmcp/lazy-zod");var clientMetadataDocumentSchema=import_lazy_zod6.internalZ.object({client_id:import_lazy_zod6.internalZ.string().url(),client_name:import_lazy_zod6.internalZ.string().min(1),redirect_uris:import_lazy_zod6.internalZ.array(import_lazy_zod6.internalZ.string().url()).min(1),token_endpoint_auth_method:import_lazy_zod6.internalZ.enum(["none","client_secret_basic","client_secret_post","private_key_jwt"]).default("none"),grant_types:import_lazy_zod6.internalZ.array(import_lazy_zod6.internalZ.string()).default(["authorization_code"]),response_types:import_lazy_zod6.internalZ.array(import_lazy_zod6.internalZ.string()).default(["code"]),client_uri:import_lazy_zod6.internalZ.string().url().optional(),logo_uri:import_lazy_zod6.internalZ.string().url().optional(),jwks_uri:import_lazy_zod6.internalZ.string().url().optional(),jwks:import_lazy_zod6.internalZ.object({keys:import_lazy_zod6.internalZ.array(import_lazy_zod6.internalZ.record(import_lazy_zod6.internalZ.string(),import_lazy_zod6.internalZ.unknown()))}).optional(),tos_uri:import_lazy_zod6.internalZ.string().url().optional(),policy_uri:import_lazy_zod6.internalZ.string().url().optional(),scope:import_lazy_zod6.internalZ.string().optional(),contacts:import_lazy_zod6.internalZ.array(import_lazy_zod6.internalZ.string().email()).optional(),software_statement:import_lazy_zod6.internalZ.string().optional(),software_id:import_lazy_zod6.internalZ.string().optional(),software_version:import_lazy_zod6.internalZ.string().optional()});var cimdRedisCacheConfigSchema=import_lazy_zod6.internalZ.object({url:import_lazy_zod6.internalZ.string().optional(),host:import_lazy_zod6.internalZ.string().optional(),port:import_lazy_zod6.internalZ.number().optional(),password:import_lazy_zod6.internalZ.string().optional(),db:import_lazy_zod6.internalZ.number().optional(),tls:import_lazy_zod6.internalZ.boolean().optional(),keyPrefix:import_lazy_zod6.internalZ.string().default("cimd:")});var cimdCacheConfigSchema=import_lazy_zod6.internalZ.object({type:import_lazy_zod6.internalZ.enum(["memory","redis"]).default("memory"),defaultTtlMs:import_lazy_zod6.internalZ.number().min(0).default(36e5),maxTtlMs:import_lazy_zod6.internalZ.number().min(0).default(864e5),minTtlMs:import_lazy_zod6.internalZ.number().min(0).default(6e4),redis:cimdRedisCacheConfigSchema.optional()});var cimdSecurityConfigSchema=import_lazy_zod6.internalZ.object({blockPrivateIPs:import_lazy_zod6.internalZ.boolean().default(true),allowedDomains:import_lazy_zod6.internalZ.array(import_lazy_zod6.internalZ.string()).optional(),blockedDomains:import_lazy_zod6.internalZ.array(import_lazy_zod6.internalZ.string()).optional(),warnOnLocalhostRedirects:import_lazy_zod6.internalZ.boolean().default(true),allowInsecureForTesting:import_lazy_zod6.internalZ.boolean().default(false)});var cimdNetworkConfigSchema=import_lazy_zod6.internalZ.object({timeoutMs:import_lazy_zod6.internalZ.number().min(100).default(5e3),maxResponseSizeBytes:import_lazy_zod6.internalZ.number().min(1024).default(65536),redirectPolicy:import_lazy_zod6.internalZ.enum(["deny","same-origin","allow"]).default("deny"),maxRedirects:import_lazy_zod6.internalZ.number().int().min(0).default(5)});var cimdConfigSchema=import_lazy_zod6.internalZ.object({enabled:import_lazy_zod6.internalZ.boolean().default(true),cache:cimdCacheConfigSchema.optional(),security:cimdSecurityConfigSchema.optional(),network:cimdNetworkConfigSchema.optional()});init_cimd_cache();var import_utils18=require("@frontmcp/utils");init_cimd_cache();var CimdService=class{config;cacheConfig;securityConfig;networkConfig;cacheBackend;logger;get enabled(){return this.config.enabled}constructor(logger,config){this.logger=(logger??noopLogger).child("CimdService");this.config=cimdConfigSchema.parse(config??{});this.cacheConfig=cimdCacheConfigSchema.parse(this.config.cache??{});this.securityConfig=cimdSecurityConfigSchema.parse(this.config.security??{});this.networkConfig=cimdNetworkConfigSchema.parse(this.config.network??{});this.logger.debug("CimdService initialized",{enabled:this.config.enabled,cacheDefaultTtlMs:this.cacheConfig.defaultTtlMs,networkTimeoutMs:this.networkConfig.timeoutMs});if(this.securityConfig.allowInsecureForTesting){this.logger.warn("CIMD allowInsecureForTesting is enabled. HTTP is allowed for localhost CIMD URLs. This should NEVER be enabled in production!")}}async initialize(){await this.cache()}cache(){if(!this.cacheBackend){this.cacheBackend=createCimdCache(this.cacheConfig).catch(error=>{this.cacheBackend=void 0;throw error})}return this.cacheBackend}async dispose(){const backend=this.cacheBackend;this.cacheBackend=void 0;if(!backend)return;const createdBackend=await backend.catch(()=>void 0);await createdBackend?.close?.()}isCimdClientId(clientId){return isCimdClientId(clientId,this.securityConfig.allowInsecureForTesting)}async resolveClientMetadata(clientId){if(!this.isCimdClientId(clientId)){return{isCimdClient:false,fromCache:false}}validateClientIdUrl(clientId,this.securityConfig);const cache=await this.cache();const cached=await cache.get(clientId);if(cached){this.logger.debug(`Cache hit for CIMD client: ${clientId}`);return{isCimdClient:true,metadata:cached.document,fromCache:true,expiresAt:cached.expiresAt,etag:cached.etag,lastModified:cached.lastModified}}this.logger.info(`Fetching CIMD document: ${clientId}`);const{document,headers}=await this.fetchMetadataDocument(clientId);this.validateDocument(clientId,document);if(this.securityConfig.warnOnLocalhostRedirects&&hasOnlyLocalhostRedirectUris(document.redirect_uris)){this.logger.warn(`CIMD client "${clientId}" has only localhost redirect URIs - this may be a development client`)}await cache.set(clientId,document,headers);const entry=await cache.get(clientId);return{isCimdClient:true,metadata:document,fromCache:false,expiresAt:entry?.expiresAt,etag:entry?.etag,lastModified:entry?.lastModified}}validateRedirectUri(redirectUri,metadata){const normalizedRequestUri=normalizeRedirectUri(redirectUri);const normalizedAllowed=metadata.redirect_uris.map(normalizeRedirectUri);if(!normalizedAllowed.includes(normalizedRequestUri)){throw new RedirectUriMismatchError(metadata.client_id,redirectUri,metadata.redirect_uris)}}async clearCache(clientId){const cache=await this.cache();if(clientId){await cache.delete(clientId);this.logger.debug(`Cache cleared for: ${clientId}`)}else{await cache.clear();this.logger.debug("Cache cleared")}}async getCacheStats(){const cache=await this.cache();return{size:await cache.size()}}async fetchMetadataDocument(clientId){const controller=new AbortController;const timer=setTimeout(()=>controller.abort(),this.networkConfig.timeoutMs);try{const cache=await this.cache();const conditionalHeaders=await cache.getConditionalHeaders(clientId);const originalOrigin=new URL(clientId).origin;const maxRedirects=this.networkConfig.maxRedirects;let currentUrl=clientId;let redirectCount=0;let isFirstRequest=true;while(true){if(this.securityConfig.blockPrivateIPs&&!this.securityConfig.allowInsecureForTesting){await assertHostNotSsrf(new URL(currentUrl).hostname,clientId)}const headers={Accept:"application/json"};if(isFirstRequest&&conditionalHeaders){Object.assign(headers,conditionalHeaders)}const response=await fetch(currentUrl,{method:"GET",headers,signal:controller.signal,redirect:"manual"});if(response.status===304){const staleEntry=await cache.getStale(clientId);if(staleEntry){await cache.revalidate(clientId,response.headers);this.logger.debug(`CIMD document not modified: ${clientId}`);return{document:staleEntry.document,headers:response.headers}}throw new CimdFetchError(clientId,"304 Not Modified but no cached entry",{httpStatus:304})}if((0,import_utils18.isRedirectResponse)(response)){const location=response.headers.get("location");if(!location){throw new CimdFetchError(clientId,"Redirect response missing Location header",{httpStatus:response.status})}const nextUrl=new URL(location,currentUrl).toString();const redirectPolicy=this.networkConfig.redirectPolicy;if(redirectPolicy==="deny"){throw new CimdFetchError(clientId,`CIMD fetch redirected to "${nextUrl}" but redirects are disabled. Host the metadata at the client_id URL or set auth.cimd.network.redirectPolicy to "same-origin" or "allow".`,{httpStatus:response.status})}if(redirectPolicy==="same-origin"){const nextOrigin=new URL(nextUrl).origin;if(nextOrigin!==originalOrigin){throw new CimdFetchError(clientId,`CIMD fetch redirected to "${nextUrl}" which is not the same origin as "${originalOrigin}". Host the metadata at the client_id URL or set auth.cimd.network.redirectPolicy to "allow".`,{httpStatus:response.status})}}validateClientIdUrl(nextUrl,this.securityConfig);redirectCount+=1;if(redirectCount>maxRedirects){throw new CimdFetchError(clientId,`CIMD fetch exceeded max redirects (${maxRedirects}). Host the metadata at the client_id URL or increase auth.cimd.network.maxRedirects.`)}this.logger.warn(`CIMD redirect ${redirectCount}/${maxRedirects}: ${currentUrl} -> ${nextUrl}`);currentUrl=nextUrl;isFirstRequest=false;continue}if(!response.ok){throw new CimdFetchError(clientId,`HTTP ${response.status} ${response.statusText}`,{httpStatus:response.status})}const contentLength=response.headers.get("content-length");if(contentLength){const length=parseInt(contentLength,10);if(!isNaN(length)&&length>this.networkConfig.maxResponseSizeBytes){throw new CimdResponseTooLargeError(clientId,this.networkConfig.maxResponseSizeBytes,length)}}const text=await this.readResponseWithLimit(response,this.networkConfig.maxResponseSizeBytes,clientId);let document;try{document=JSON.parse(text)}catch(e){throw new CimdFetchError(clientId,"Invalid JSON response",{originalError:e instanceof Error?e:new Error(String(e))})}return{document,headers:response.headers}}}catch(error){if(error instanceof CimdFetchError||error instanceof CimdResponseTooLargeError||error instanceof CimdSecurityError){throw error}if(error instanceof Error&&error.name==="AbortError"){throw new CimdFetchError(clientId,"Request timeout",{originalError:error})}throw new CimdFetchError(clientId,error instanceof Error?error.message:"Unknown error",{originalError:error instanceof Error?error:void 0})}finally{clearTimeout(timer)}}async readResponseWithLimit(response,maxBytes,clientId){const reader=response.body?.getReader();if(!reader){const buffer=await response.arrayBuffer();if(buffer.byteLength>maxBytes){throw new CimdResponseTooLargeError(clientId,maxBytes,buffer.byteLength)}return new TextDecoder().decode(buffer)}const chunks=[];let totalBytes=0;try{while(true){const{done,value}=await reader.read();if(done)break;totalBytes+=value.length;if(totalBytes>maxBytes){throw new CimdResponseTooLargeError(clientId,maxBytes,totalBytes)}chunks.push(value)}}finally{reader.releaseLock()}const combined=new Uint8Array(totalBytes);let offset=0;for(const chunk of chunks){combined.set(chunk,offset);offset+=chunk.length}return new TextDecoder().decode(combined)}validateDocument(clientId,document){const result=clientMetadataDocumentSchema.safeParse(document);if(!result.success){const errors=result.error.issues.map(issue=>{const path=issue.path.length>0?`${issue.path.join(".")}: `:"";return`${path}${issue.message}`});throw new CimdValidationError(clientId,errors)}if(result.data.client_id!==clientId){throw new CimdClientIdMismatchError(clientId,result.data.client_id)}}};var LOOPBACK_HOSTNAMES=new Set(["127.0.0.1","::1","[::1]","localhost"]);function isLoopbackHostname(hostname){return LOOPBACK_HOSTNAMES.has(hostname.toLowerCase())}function normalizeRedirectUri(uri){try{const url=new URL(uri);const host=isLoopbackHostname(url.hostname)?url.hostname.toLowerCase():url.host.toLowerCase();let normalized=`${url.protocol.toLowerCase()}//${host}`;normalized+=url.pathname.replace(/\/+$/,"")||"/";if(url.search)normalized+=url.search;return normalized}catch{return uri}}var publicAccessConfigSchema=import_lazy_zod7.internalZ.object({tools:import_lazy_zod7.internalZ.union([import_lazy_zod7.internalZ.literal("all"),import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string())]).default("all"),prompts:import_lazy_zod7.internalZ.union([import_lazy_zod7.internalZ.literal("all"),import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string())]).default("all"),rateLimit:import_lazy_zod7.internalZ.number().default(60)});var localSigningConfigSchema=import_lazy_zod7.internalZ.object({signKey:jwkSchema.or(import_lazy_zod7.internalZ.instanceof(Uint8Array)).optional(),jwks:jsonWebKeySetSchema.optional(),issuer:import_lazy_zod7.internalZ.string().optional()});var providerConfigSchema=import_lazy_zod7.internalZ.object({name:import_lazy_zod7.internalZ.string().optional(),id:import_lazy_zod7.internalZ.string().optional(),jwks:jsonWebKeySetSchema.optional(),jwksUri:import_lazy_zod7.internalZ.string().url().optional(),additionalIssuers:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string().trim().min(1,"additionalIssuers entries must be non-empty")).optional(),verifyIssuer:import_lazy_zod7.internalZ.boolean().optional(),dcrEnabled:import_lazy_zod7.internalZ.boolean().default(false),authEndpoint:import_lazy_zod7.internalZ.string().url().optional(),tokenEndpoint:import_lazy_zod7.internalZ.string().url().optional(),registrationEndpoint:import_lazy_zod7.internalZ.string().url().optional(),userInfoEndpoint:import_lazy_zod7.internalZ.string().url().optional()});var remoteProviderConfigSchema=import_lazy_zod7.internalZ.object({provider:import_lazy_zod7.internalZ.string().url(),name:import_lazy_zod7.internalZ.string().optional(),id:import_lazy_zod7.internalZ.string().optional(),jwks:jsonWebKeySetSchema.optional(),jwksUri:import_lazy_zod7.internalZ.string().url().optional(),clientId:import_lazy_zod7.internalZ.string().optional(),clientSecret:import_lazy_zod7.internalZ.string().optional(),scopes:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string()).optional(),dcrEnabled:import_lazy_zod7.internalZ.boolean().default(false),authEndpoint:import_lazy_zod7.internalZ.string().url().optional(),tokenEndpoint:import_lazy_zod7.internalZ.string().url().optional(),registrationEndpoint:import_lazy_zod7.internalZ.string().url().optional(),userInfoEndpoint:import_lazy_zod7.internalZ.string().url().optional()});var upstreamProviderSchema=import_lazy_zod7.internalZ.object({id:import_lazy_zod7.internalZ.string().min(1),name:import_lazy_zod7.internalZ.string().optional(),authorizationEndpoint:import_lazy_zod7.internalZ.string().url().optional(),authorizeUrl:import_lazy_zod7.internalZ.string().url().optional(),tokenEndpoint:import_lazy_zod7.internalZ.string().url().optional(),tokenUrl:import_lazy_zod7.internalZ.string().url().optional(),clientId:import_lazy_zod7.internalZ.string().min(1),clientSecret:import_lazy_zod7.internalZ.string().optional(),scopes:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string()).optional(),userInfoEndpoint:import_lazy_zod7.internalZ.string().url().optional(),jwksUri:import_lazy_zod7.internalZ.string().url().optional(),issuer:import_lazy_zod7.internalZ.string().url().optional(),additionalIssuers:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string().trim().min(1,"additionalIssuers entries must be non-empty")).optional()}).refine(p=>!!(p.authorizationEndpoint??p.authorizeUrl),{message:"authorizationEndpoint (or authorizeUrl) is required",path:["authorizationEndpoint"]}).refine(p=>!!(p.tokenEndpoint??p.tokenUrl),{message:"tokenEndpoint (or tokenUrl) is required",path:["tokenEndpoint"]}).refine(p=>!(p.authorizationEndpoint&&p.authorizeUrl),{message:"provide only one of authorizationEndpoint or authorizeUrl",path:["authorizationEndpoint"]}).refine(p=>!(p.tokenEndpoint&&p.tokenUrl),{message:"provide only one of tokenEndpoint or tokenUrl",path:["tokenEndpoint"]});var localDcrClientSchema=import_lazy_zod7.internalZ.object({clientId:import_lazy_zod7.internalZ.string().min(1),clientSecret:import_lazy_zod7.internalZ.string().min(1).optional(),redirectUris:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string().url()).min(1,"At least one redirect_uri is required"),clientName:import_lazy_zod7.internalZ.string().optional(),tokenEndpointAuthMethod:import_lazy_zod7.internalZ.enum(["none","client_secret_basic","client_secret_post"]).default("none"),grantTypes:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.enum(["authorization_code","refresh_token"])).default(["authorization_code"]),responseTypes:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.enum(["code"])).default(["code"]),scope:import_lazy_zod7.internalZ.string().optional()});var localDcrConfigSchema=import_lazy_zod7.internalZ.object({enabled:import_lazy_zod7.internalZ.boolean().optional(),allowedRedirectUris:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string().min(1)).optional(),allowedClientIds:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string().min(1)).optional(),initialAccessToken:import_lazy_zod7.internalZ.string().min(1).optional(),clients:import_lazy_zod7.internalZ.array(localDcrClientSchema).optional(),maxDynamicClients:import_lazy_zod7.internalZ.number().int().min(0).optional()});var flatRemoteProviderFields={provider:import_lazy_zod7.internalZ.string().url(),clientId:import_lazy_zod7.internalZ.string().optional(),clientSecret:import_lazy_zod7.internalZ.string().optional(),scopes:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string()).optional(),providerConfig:providerConfigSchema.optional()};var tokenStorageSqliteSchema=import_lazy_zod7.internalZ.object({path:import_lazy_zod7.internalZ.string().min(1),encryption:import_lazy_zod7.internalZ.object({secret:import_lazy_zod7.internalZ.string().min(1)}).optional(),ttlCleanupIntervalMs:import_lazy_zod7.internalZ.number().int().nonnegative().optional(),walMode:import_lazy_zod7.internalZ.boolean().optional(),busyTimeoutMs:import_lazy_zod7.internalZ.number().int().nonnegative().optional()});var tokenStorageConfigSchema=import_lazy_zod7.internalZ.union([import_lazy_zod7.internalZ.literal("memory"),import_lazy_zod7.internalZ.object({redis:redisConfigSchema}),import_lazy_zod7.internalZ.object({sqlite:tokenStorageSqliteSchema})]);var secureStoreScopeSchema=import_lazy_zod7.internalZ.enum(["user","session","global"]);var secureStoreEncryptionSchema=import_lazy_zod7.internalZ.object({pepper:import_lazy_zod7.internalZ.string().min(1).optional()});var secureStoreCustomBackendSchema=import_lazy_zod7.internalZ.custom(v=>typeof v==="object"&&v!==null&&typeof v.get==="function"&&typeof v.set==="function"&&typeof v.delete==="function"&&typeof v.list==="function",{message:"secureStore.backend must implement get/set/delete/list (SecureStoreBackend)"});var secureStoreCommonFields={scope:secureStoreScopeSchema.optional(),ttlMs:import_lazy_zod7.internalZ.number().int().positive().optional(),encryption:secureStoreEncryptionSchema.optional()};var secureStoreBackingSchemas={sqlite:tokenStorageSqliteSchema,redis:redisConfigSchema,backend:secureStoreCustomBackendSchema};function secureStoreBackingError(issue){if(typeof issue.input!=="object"||issue.input===null)return void 0;const config=issue.input;const named=Object.keys(secureStoreBackingSchemas).filter(backing=>config[backing]!==void 0);if(named.length>1)return`secureStore takes one backing, not ${named.join(" and ")}`;for(const[backing,schema2]of Object.entries(secureStoreBackingSchemas)){if(config[backing]===void 0)continue;const nested=schema2.safeParse(config[backing]).error?.issues[0];if(!nested)continue;const where=["secureStore",backing,...nested.path.map(String)].join(".");return nested.message.startsWith(where)?nested.message:`${where}: ${nested.message}`}return void 0}var noBacking={sqlite:import_lazy_zod7.internalZ.undefined().optional(),redis:import_lazy_zod7.internalZ.undefined().optional(),backend:import_lazy_zod7.internalZ.undefined().optional()};var secureStoreConfigSchema=import_lazy_zod7.internalZ.union([import_lazy_zod7.internalZ.literal("memory"),import_lazy_zod7.internalZ.object({...noBacking,sqlite:secureStoreBackingSchemas.sqlite,...secureStoreCommonFields}),import_lazy_zod7.internalZ.object({...noBacking,redis:secureStoreBackingSchemas.redis,...secureStoreCommonFields}),import_lazy_zod7.internalZ.object({...noBacking,backend:secureStoreBackingSchemas.backend,...secureStoreCommonFields}),import_lazy_zod7.internalZ.object({...noBacking,...secureStoreCommonFields})],{error:secureStoreBackingError});var tokenRefreshConfigSchema=import_lazy_zod7.internalZ.object({enabled:import_lazy_zod7.internalZ.boolean().default(true),skewSeconds:import_lazy_zod7.internalZ.number().nonnegative().default(60)});var skippedAppBehaviorSchema=import_lazy_zod7.internalZ.enum(["anonymous","require-auth"]);var consentConfigSchema=import_lazy_zod7.internalZ.object({enabled:import_lazy_zod7.internalZ.boolean().default(false),groupByApp:import_lazy_zod7.internalZ.boolean().default(true),showDescriptions:import_lazy_zod7.internalZ.boolean().default(true),allowSelectAll:import_lazy_zod7.internalZ.boolean().default(true),requireSelection:import_lazy_zod7.internalZ.boolean().default(true),customMessage:import_lazy_zod7.internalZ.string().optional(),rememberConsent:import_lazy_zod7.internalZ.boolean().default(true),excludedTools:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string()).optional(),defaultSelectedTools:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string()).optional()});var federatedAuthConfigSchema=import_lazy_zod7.internalZ.object({stateValidation:import_lazy_zod7.internalZ.enum(["strict","format"]).default("strict"),minProviders:import_lazy_zod7.internalZ.number().int().positive().optional(),requiredProviders:import_lazy_zod7.internalZ.array(import_lazy_zod7.internalZ.string()).optional()});var incrementalAuthConfigSchema=import_lazy_zod7.internalZ.object({enabled:import_lazy_zod7.internalZ.boolean().default(true),skippedAppBehavior:skippedAppBehaviorSchema.default("anonymous"),allowSkip:import_lazy_zod7.internalZ.boolean().default(true),showAllAppsAtOnce:import_lazy_zod7.internalZ.boolean().default(true)});function isCustomBackendConfig(config){return typeof config==="object"&&config!==null&&"backend"in config&&!!config.backend}function isSqliteConfig(config){return typeof config==="object"&&config!==null&&"sqlite"in config&&!!config.sqlite}function isRedisConfig(config){return typeof config==="object"&&config!==null&&"redis"in config&&!!config.redis}function readScope(config){if(typeof config==="object"&&config!==null&&"scope"in config&&config.scope){return config.scope}return"user"}function readTtlMs(config){if(typeof config==="object"&&config!==null&&"ttlMs"in config){return config.ttlMs}return void 0}function readPepper(config){if(typeof config==="object"&&config!==null&&"encryption"in config&&config.encryption){return config.encryption.pepper}return void 0}function toTokenStorageConfig(config){if(isSqliteConfig(config)){return{sqlite:config.sqlite}}if(isRedisConfig(config)){return{redis:config.redis}}return"memory"}function refuseUnusableConfig(config){if(config===void 0)return;const issue=secureStoreConfigSchema.safeParse(config).error?.issues[0];if(!issue)return;const where=issue.path.length>0?`secureStore.${issue.path.map(String).join(".")}: `:"";throw new SecureStoreConfigError(`${where}${issue.message}`)}async function createSecureStore(options){const{config,pepper,storage,logger}=options;refuseUnusableConfig(config);const scope=readScope(config);const ttlMs=readTtlMs(config);if(isCustomBackendConfig(config)){return{backend:config.backend,scope,ttlMs,kind:"custom"}}const kind=isSqliteConfig(config)?"sqlite":isRedisConfig(config)?"redis":"memory";let adapter;if(storage){adapter=storage}else if(kind==="memory"){adapter=new import_utils19.MemoryStorageAdapter;await adapter.connect()}else{adapter=await createTokenStorageAdapter(toTokenStorageConfig(config))}const backend=new EncryptedStorageSecureStoreBackend({storage:adapter,pepper:readPepper(config)??pepper,logger});return{backend,scope,ttlMs,kind,...storage?{}:{close:()=>adapter.disconnect()}}}var import_utils20=require("@frontmcp/utils");var TokenVault=class{active;keys=new Map;constructor(keys){if(!Array.isArray(keys)||keys.length===0){throw new Error("TokenVault requires at least one key")}for(const k of keys){if(!(k.key instanceof Uint8Array)||k.key.length!==32){throw new Error(`TokenVault key "${k.kid}" must be a 32-byte Uint8Array for AES-256-GCM`)}if(this.keys.has(k.kid)){throw new Error(`TokenVault duplicate kid: "${k.kid}"`)}this.keys.set(k.kid,k.key)}this.active=keys[0]}rotateTo(k){if(!(k.key instanceof Uint8Array)||k.key.length!==32){throw new Error(`TokenVault key "${k.kid}" must be a 32-byte Uint8Array for AES-256-GCM`)}this.active=k;this.keys.set(k.kid,k.key)}async encrypt(plaintext,opts){const iv=(0,import_utils20.randomBytes)(12);const{ciphertext,tag}=await(0,import_utils20.encryptAesGcm)(this.active.key,new TextEncoder().encode(plaintext),iv);return{alg:"A256GCM",kid:this.active.kid,iv:(0,import_utils20.base64urlEncode)(iv),tag:(0,import_utils20.base64urlEncode)(tag),data:(0,import_utils20.base64urlEncode)(ciphertext),exp:opts?.exp,meta:opts?.meta}}async decrypt(blob){if(blob.exp!==void 0){const nowSeconds=Math.floor(Date.now()/1e3);if(nowSeconds>blob.exp){throw new Error(`vault_expired:${blob.kid}`)}}const key=this.keys.get(blob.kid);if(!key)throw new Error(`vault_unknown_kid:${blob.kid}`);const iv=(0,import_utils20.base64urlDecode)(blob.iv);const tag=(0,import_utils20.base64urlDecode)(blob.tag);const data=(0,import_utils20.base64urlDecode)(blob.data);const plaintext=await(0,import_utils20.decryptAesGcm)(key,data,iv,tag);return new TextDecoder().decode(plaintext)}};var import_utils39=require("@frontmcp/utils");var import_utils21=require("@frontmcp/utils");function getSigningSecret(config){const secret=config?.secret||(0,import_utils21.getEnv)("MCP_SESSION_SECRET");if(!secret){if((0,import_utils21.isProduction)()){throw new SessionSecretRequiredError("session signing")}console.warn("[SessionCrypto] MCP_SESSION_SECRET not set. Using insecure default for development only.");return"insecure-dev-secret-do-not-use-in-production"}return secret}function resolveConfig(config){return{secret:getSigningSecret(config)}}function signSession(session,config){return(0,import_utils21.signData)(session,resolveConfig(config))}function verifySession(signedData,config){return(0,import_utils21.verifyData)(signedData,resolveConfig(config))}function verifyOrParseSession(data,config){return(0,import_utils21.verifyOrParseData)(data,resolveConfig(config))}var SessionRateLimiter=class{windowMs;maxRequests;requests=new Map;cleanupIntervalMs;cleanupTimer=null;constructor(config={}){this.windowMs=config.windowMs??6e4;this.maxRequests=config.maxRequests??100;this.cleanupIntervalMs=config.cleanupIntervalMs??6e4}ensureCleanupTimer(){if(this.cleanupTimer||this.cleanupIntervalMs<=0)return;this.cleanupTimer=setInterval(()=>this.cleanup(),this.cleanupIntervalMs);if(typeof this.cleanupTimer.unref==="function")this.cleanupTimer.unref()}check(key){this.ensureCleanupTimer();const now=Date.now();const windowStart=now-this.windowMs;let timestamps=this.requests.get(key);if(!timestamps){timestamps=[];this.requests.set(key,timestamps)}const validTimestamps=timestamps.filter(t=>t>windowStart);const oldestInWindow=validTimestamps[0]??now;const resetAt=oldestInWindow+this.windowMs;if(validTimestamps.length>=this.maxRequests){return{allowed:false,remaining:0,resetAt,retryAfterMs:resetAt-now}}validTimestamps.push(now);this.requests.set(key,validTimestamps);return{allowed:true,remaining:this.maxRequests-validTimestamps.length,resetAt}}wouldAllow(key){const now=Date.now();const windowStart=now-this.windowMs;const timestamps=this.requests.get(key);if(!timestamps)return true;const validCount=timestamps.filter(t=>t>windowStart).length;return validCount<this.maxRequests}reset(key){this.requests.delete(key)}cleanup(){const now=Date.now();const windowStart=now-this.windowMs;for(const[key,timestamps]of this.requests.entries()){const valid=timestamps.filter(t=>t>windowStart);if(valid.length===0){this.requests.delete(key)}else if(valid.length<timestamps.length){this.requests.set(key,valid)}}}getStats(){let totalRequests=0;for(const timestamps of this.requests.values()){totalRequests+=timestamps.length}return{totalKeys:this.requests.size,totalRequests}}dispose(){if(this.cleanupTimer){clearInterval(this.cleanupTimer);this.cleanupTimer=null}this.requests.clear()}};var defaultSessionRateLimiter=new SessionRateLimiter;var import_utils22=require("@frontmcp/utils");var TransportIdGenerator=class{static createId(){return(0,import_utils22.randomUUID)().replace(/-/g,"")}};var TinyTtlCache=class{constructor(ttlMs){this.ttlMs=ttlMs}ttlMs;map=new Map;get(k){const hit=this.map.get(k);if(!hit)return void 0;if(hit.exp<Date.now()){this.map.delete(k);return void 0}return hit.v}set(k,v){this.map.set(k,{v,exp:Date.now()+this.ttlMs})}delete(k){return this.map.delete(k)}clear(){this.map.clear()}size(){return this.map.size}cleanup(){const now=Date.now();let removed=0;for(const[k,{exp}]of this.map){if(exp<now){this.map.delete(k);removed++}}return removed}};var import_utils23=require("@frontmcp/utils");function isJwt(token){if(!token)return false;return token.split(".").length===3}function getTokenSignatureFingerprint(token){if(isJwt(token)){const sig=token.split(".")[2];if(sig)return sig}return(0,import_utils23.sha256Base64url)(token)}function extractClaimValue(claims,key,validator){const value=claims[key];return validator(value)?value:void 0}var isString=value=>typeof value==="string";var isNumber=value=>typeof value==="number";var isStringOrStringArray=value=>typeof value==="string"||Array.isArray(value);function deriveTypedUser(claims){return{...claims,iss:extractClaimValue(claims,"iss",isString)??"",sid:extractClaimValue(claims,"sid",isString),sub:extractClaimValue(claims,"sub",isString)??extractClaimValue(claims,"client_id",isString)??extractClaimValue(claims,"azp",isString)??"",exp:extractClaimValue(claims,"exp",isNumber),iat:extractClaimValue(claims,"iat",isNumber),aud:extractClaimValue(claims,"aud",isStringOrStringArray),email:extractClaimValue(claims,"email",isString),preferred_username:extractClaimValue(claims,"preferred_username",isString),username:extractClaimValue(claims,"username",isString),name:extractClaimValue(claims,"name",isString),picture:extractClaimValue(claims,"picture",isString)}}function anonymousCallerClaims(options,anonymousId){const{issuer,scopes=["anonymous"],subject}=options;return{sub:subject??`anon:${anonymousId}`,iss:issuer,name:subject?"Static token":"Anonymous",scope:scopes.join(" ")}}function extractBearerToken(header){if(!header)return void 0;const m=header.match(/^\s*Bearer\s+(\S+)\s*$/i);return m?m[1]:void 0}var import_utils24=require("@frontmcp/utils");var cachedKey=null;function getKey(){if(cachedKey)return cachedKey;const secret=(0,import_utils24.getEnv)("MCP_SESSION_SECRET");if(!secret){if((0,import_utils24.isProduction)()){throw new SessionSecretRequiredError("session ID encryption")}console.warn("[SessionIdUtils] Using machine ID as session encryption secret - NOT SECURE FOR PRODUCTION. Set MCP_SESSION_SECRET environment variable for secure session encryption.")}const base=secret||(0,import_utils24.getMachineId)();cachedKey=(0,import_utils24.sha256)(new TextEncoder().encode(base));return cachedKey}function encryptJson(obj){const key=getKey();const encrypted=(0,import_utils24.encryptValue)(obj,key);return`${encrypted.iv}.${encrypted.tag}.${encrypted.data}`}function decryptSessionJson(sessionId){const parts=sessionId.split(".");if(parts.length!==3)return null;const[ivB64,tagB64,ctB64]=parts;if(!ivB64||!tagB64||!ctB64)return null;const key=getKey();return(0,import_utils24.decryptValue)({alg:"A256GCM",iv:ivB64,tag:tagB64,data:ctB64},key)}function safeDecrypt(sessionId){try{return decryptSessionJson(sessionId)}catch{return null}}function resetCachedKey(){cachedKey=null}var import_utils28=require("@frontmcp/utils");var import_utils29=require("@frontmcp/utils");var import_utils25=require("@frontmcp/utils");var StorageTokenStore=class{storage;namespace;defaultTtlSeconds;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"tok";this.defaultTtlSeconds=options.defaultTtlSeconds;this.storageIsNamespaced="namespace"in storage&&typeof storage.namespace==="function";const namespacedStorage=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.storage=new import_utils25.TypedStorage(namespacedStorage)}allocId(){return(0,import_utils25.randomUUID)()}async put(id,blob){const record={id,blob,updatedAt:Date.now()};const ttlSeconds=this.calculateTtl(blob.exp);await this.storage.set(this.key(id),record,ttlSeconds?{ttlSeconds}:void 0)}async get(id){const record=await this.storage.get(this.key(id));return record??void 0}async del(id){await this.storage.delete(this.key(id))}calculateTtl(exp){if(exp){const nowSeconds=Math.floor(Date.now()/1e3);const ttl=exp-nowSeconds;return ttl>0?ttl:1}return this.defaultTtlSeconds}key(id){return this.storageIsNamespaced?id:`${this.namespace}:${id}`}};var import_utils26=require("@frontmcp/utils");var StorageAuthorizationVault=class{storage;namespace;pendingAuthTtlMs;constructor(storage,options={}){this.namespace=options.namespace??"vault";this.pendingAuthTtlMs=options.pendingAuthTtlMs??10*60*1e3;const namespacedStorage=this.isNamespacedStorage(storage)?storage.namespace(this.namespace):storage;this.storage=new import_utils26.TypedStorage(namespacedStorage,{schema:options.validateOnRead?authorizationVaultEntrySchema:void 0,throwOnInvalid:false})}async create(params){const now=Date.now();const entry={id:(0,import_utils26.randomUUID)(),userSub:params.userSub,userEmail:params.userEmail,userName:params.userName,clientId:params.clientId,createdAt:now,lastAccessAt:now,appCredentials:{},consent:params.consent,federated:params.federated,pendingAuths:[],authorizedAppIds:params.authorizedAppIds??[],skippedAppIds:params.skippedAppIds??[]};await this.storage.set(this.key(entry.id),entry);return entry}async get(id){return this.storage.get(this.key(id))}async update(id,updates){const entry=await this.get(id);if(!entry){console.warn(`[StorageAuthorizationVault] Update failed: vault entry not found for id ${id}`);return}const updated={...entry,...updates,lastAccessAt:Date.now()};await this.storage.set(this.key(id),updated)}async delete(id){await this.storage.delete(this.key(id))}async updateConsent(vaultId,consent){const entry=await this.get(vaultId);if(!entry)return;entry.consent=consent;entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async authorizeApp(vaultId,appId){const entry=await this.get(vaultId);if(!entry)return;entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==appId);if(!entry.authorizedAppIds.includes(appId)){entry.authorizedAppIds.push(appId)}entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async isAppAuthorized(vaultId,appId){const entry=await this.get(vaultId);if(!entry)return false;return entry.authorizedAppIds.includes(appId)}async createPendingAuth(vaultId,params){const entry=await this.get(vaultId);if(!entry){throw new Error(`Vault not found: ${vaultId}`)}const now=Date.now();const pendingAuth={id:(0,import_utils26.randomUUID)(),appId:params.appId,toolId:params.toolId,authUrl:params.authUrl,requiredScopes:params.requiredScopes,elicitId:params.elicitId,createdAt:now,expiresAt:now+(params.ttlMs??this.pendingAuthTtlMs),status:"pending"};entry.pendingAuths.push(pendingAuth);entry.lastAccessAt=now;await this.storage.set(this.key(vaultId),entry);return pendingAuth}async getPendingAuth(vaultId,pendingAuthId){const entry=await this.get(vaultId);if(!entry)return null;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(!pendingAuth)return null;if(Date.now()>pendingAuth.expiresAt&&pendingAuth.status==="pending"){pendingAuth.status="expired";await this.storage.set(this.key(vaultId),entry)}return pendingAuth}async completePendingAuth(vaultId,pendingAuthId){const entry=await this.get(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="completed";entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==pendingAuth.appId);if(!entry.authorizedAppIds.includes(pendingAuth.appId)){entry.authorizedAppIds.push(pendingAuth.appId)}entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}}async cancelPendingAuth(vaultId,pendingAuthId){const entry=await this.get(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="cancelled";await this.storage.set(this.key(vaultId),entry)}}async getPendingAuths(vaultId){const entry=await this.get(vaultId);if(!entry)return[];const now=Date.now();let updated=false;const pending=entry.pendingAuths.filter(p=>{if(now>p.expiresAt&&p.status==="pending"){p.status="expired";updated=true}return p.status==="pending"});if(updated){await this.storage.set(this.key(vaultId),entry)}return pending}credentialKey(appId,providerId){return`${appId}:${providerId}`}async addAppCredential(vaultId,credential){const entry=await this.get(vaultId);if(!entry)return;const shouldStore=await this.shouldStoreCredential(vaultId,credential.appId);if(!shouldStore){return}const key=this.credentialKey(credential.appId,credential.providerId);entry.appCredentials[key]=credential;entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async removeAppCredential(vaultId,appId,providerId){const entry=await this.get(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);delete entry.appCredentials[key];entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async getAppCredentials(vaultId,appId){const entry=await this.get(vaultId);if(!entry)return[];const prefix=`${appId}:`;return Object.entries(entry.appCredentials).filter(([key])=>key.startsWith(prefix)).map(([,cred])=>cred)}async getCredential(vaultId,appId,providerId){const entry=await this.get(vaultId);if(!entry)return null;const key=this.credentialKey(appId,providerId);return entry.appCredentials[key]??null}async getAllCredentials(vaultId,filterByConsent=false){const entry=await this.get(vaultId);if(!entry)return[];const allCredentials=Object.values(entry.appCredentials);if(!filterByConsent||!entry.consent?.enabled){return allCredentials}const consentedToolIds=new Set(entry.consent.selectedToolIds);return allCredentials.filter(cred=>{return Array.from(consentedToolIds).some(toolId=>toolId.startsWith(`${cred.appId}:`))})}async updateCredential(vaultId,appId,providerId,updates){const entry=await this.get(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential)return;Object.assign(credential,updates);entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async shouldStoreCredential(vaultId,appId,toolIds){const entry=await this.get(vaultId);if(!entry)return false;const consent=entry.consent;if(!consent?.enabled){return true}if(toolIds&&toolIds.length>0){return toolIds.some(toolId=>consent.selectedToolIds.includes(toolId))}const consentedToolIds=consent.selectedToolIds;return consentedToolIds.some(toolId=>toolId.startsWith(`${appId}:`))}async invalidateCredential(vaultId,appId,providerId,reason){await this.updateCredential(vaultId,appId,providerId,{isValid:false,invalidReason:reason})}async refreshOAuthCredential(vaultId,appId,providerId,tokens){const entry=await this.get(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential||credential.credential.type!=="oauth"&&credential.credential.type!=="oauth_pkce")return;credential.credential.accessToken=tokens.accessToken;if(tokens.refreshToken!==void 0){credential.credential.refreshToken=tokens.refreshToken}if(tokens.expiresAt!==void 0){credential.credential.expiresAt=tokens.expiresAt;credential.expiresAt=tokens.expiresAt}credential.isValid=true;credential.invalidReason=void 0;entry.lastAccessAt=Date.now();await this.storage.set(this.key(vaultId),entry)}async cleanup(){const keys=await this.storage.keys("*");const now=Date.now();for(const key of keys){const entry=await this.storage.get(key);if(!entry)continue;const originalLength=entry.pendingAuths.length;entry.pendingAuths=entry.pendingAuths.filter(p=>{if(now>p.expiresAt&&p.status==="pending"){p.status="expired"}return p.status==="pending"});if(entry.pendingAuths.length!==originalLength){await this.storage.set(key,entry)}}}key(id){return this.isNamespacedStorage(this.storage.raw)?id:`${this.namespace}:${id}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_utils27=require("@frontmcp/utils");var InMemoryAuthorizationVault=class extends StorageAuthorizationVault{memoryAdapter;constructor(options={}){const memoryAdapter=new import_utils27.MemoryStorageAdapter;super(memoryAdapter,{namespace:options.namespace??"vault",pendingAuthTtlMs:options.pendingAuthTtlMs});this.memoryAdapter=memoryAdapter;void this.memoryAdapter.connect()}async clear(){const keys=await this.memoryAdapter.keys("*");for(const key of keys){await this.memoryAdapter.delete(key)}}};var import_utils30=require("@frontmcp/utils");var RedisSessionStore=class{storage;keyPrefix;defaultTtlMs;logger;externalInstance=false;security;rateLimiter;constructor(config,logger){this.defaultTtlMs=("defaultTtlMs"in config?config.defaultTtlMs:void 0)??36e5;this.logger=logger;this.keyPrefix=("keyPrefix"in config?config.keyPrefix:void 0)??"mcp:session:";this.security=("security"in config?config.security:void 0)??{};if(this.security.enableRateLimiting){this.rateLimiter=new SessionRateLimiter({windowMs:this.security.rateLimiting?.windowMs,maxRequests:this.security.rateLimiting?.maxRequests})}if("redis"in config&&config.redis){this.storage=new import_utils30.RedisStorageAdapter({client:config.redis,keyPrefix:this.keyPrefix});this.externalInstance=true}else{const redisConfig=config;this.storage=new import_utils30.RedisStorageAdapter({config:{host:redisConfig.host,port:redisConfig.port??6379,password:redisConfig.password,db:redisConfig.db??0,tls:redisConfig.tls},keyPrefix:this.keyPrefix})}}validateSessionId(sessionId){if(!sessionId||sessionId.trim()===""){throw new SessionIdEmptyError("RedisSessionStore")}}async ensureConnected(){await this.storage.connect()}async get(sessionId,options){this.validateSessionId(sessionId);if(this.rateLimiter){const rateLimitKey=options?.clientIdentifier||sessionId;const rateLimitResult=this.rateLimiter.check(rateLimitKey);if(!rateLimitResult.allowed){this.logger?.warn("[RedisSessionStore] Rate limit exceeded for session lookup",{sessionId:sessionId.slice(0,20),clientIdentifier:options?.clientIdentifier?options.clientIdentifier.slice(0,20):void 0,retryAfterMs:rateLimitResult.retryAfterMs});return null}}await this.ensureConnected();let raw;const redis=this.storage.getClient();const ttlSeconds=Math.ceil(this.defaultTtlMs/1e3);if(redis){try{raw=await redis.getex(this.keyPrefix+sessionId,"EX",ttlSeconds)}catch{raw=await this.storage.get(sessionId);if(raw){await this.storage.expire(sessionId,ttlSeconds)}}}else{raw=await this.storage.get(sessionId);if(raw){await this.storage.expire(sessionId,ttlSeconds)}}if(!raw)return null;try{let parsed;if(this.security.enableSigning){parsed=verifyOrParseSession(raw,{secret:this.security.signingSecret});if(!parsed){this.logger?.warn("[RedisSessionStore] Session signature verification failed",{sessionId:sessionId.slice(0,20)});this.delete(sessionId).catch(()=>void 0);return null}}else{parsed=JSON.parse(raw)}const result=storedSessionSchema.safeParse(parsed);if(!result.success){this.logger?.warn("[RedisSessionStore] Invalid session format",{sessionId:sessionId.slice(0,20),errors:result.error.issues.slice(0,3).map(i=>({path:i.path,message:i.message}))});this.delete(sessionId).catch(()=>void 0);return null}const session=result.data;if(session.maxLifetimeAt&&session.maxLifetimeAt<Date.now()){this.logger?.info("[RedisSessionStore] Session exceeded max lifetime",{sessionId:sessionId.slice(0,20),maxLifetimeAt:session.maxLifetimeAt});await this.delete(sessionId);return null}if(session.session.expiresAt&&session.session.expiresAt<Date.now()){await this.delete(sessionId);return null}if(session.session.expiresAt){const ttlMs=Math.min(this.defaultTtlMs,session.session.expiresAt-Date.now());if(ttlMs>0&&ttlMs<this.defaultTtlMs){const boundedTtlSeconds=Math.ceil(ttlMs/1e3);this.storage.expire(sessionId,boundedTtlSeconds).catch(err=>{this.logger?.warn("[RedisSessionStore] TTL extension failed",{sessionId:sessionId.slice(0,20),error:err.message})})}}const updatedSession={...session,lastAccessedAt:Date.now()};return updatedSession}catch(error){this.logger?.warn("[RedisSessionStore] Failed to parse session",{sessionId:sessionId.slice(0,20),error:error.message});this.delete(sessionId).catch(()=>void 0);return null}}async set(sessionId,session,ttlMs){this.validateSessionId(sessionId);await this.ensureConnected();let value;if(this.security.enableSigning){value=signSession(session,{secret:this.security.signingSecret})}else{value=JSON.stringify(session)}if(ttlMs&&ttlMs>0){const ttlSeconds=Math.ceil(ttlMs/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else if(session.session.expiresAt){const ttl=session.session.expiresAt-Date.now();if(ttl>0){const ttlSeconds=Math.ceil(ttl/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else{await this.storage.set(sessionId,value)}}else{await this.storage.set(sessionId,value)}}async delete(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();await this.storage.delete(sessionId)}async exists(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();return this.storage.exists(sessionId)}allocId(){return(0,import_utils30.randomUUID)()}async disconnect(){if(!this.externalInstance){await this.storage.disconnect()}}getRedisClient(){return this.storage.getClient()}async ping(){try{await this.ensureConnected();return this.storage.ping()}catch(error){this.logger?.error("[RedisSessionStore] Connection failed",{error:error.message});return false}}};var import_utils31=require("@frontmcp/utils");var VercelKvSessionStore=class{storage;keyPrefix;defaultTtlMs;logger;security;rateLimiter;constructor(config,logger){this.keyPrefix=config.keyPrefix??"mcp:session:";this.defaultTtlMs=config.defaultTtlMs??36e5;this.logger=logger;this.security=("security"in config?config.security:void 0)??{};if(this.security.enableRateLimiting){this.rateLimiter=new SessionRateLimiter({windowMs:this.security.rateLimiting?.windowMs,maxRequests:this.security.rateLimiting?.maxRequests})}this.storage=new import_utils31.VercelKvStorageAdapter({url:config.url,token:config.token,keyPrefix:this.keyPrefix})}validateSessionId(sessionId){if(!sessionId||sessionId.trim()===""){throw new SessionIdEmptyError("VercelKvSessionStore")}}async connect(){await this.storage.connect()}async ensureConnected(){await this.storage.connect()}async get(sessionId,options){this.validateSessionId(sessionId);if(this.rateLimiter){const rateLimitKey=options?.clientIdentifier||sessionId;const rateLimitResult=this.rateLimiter.check(rateLimitKey);if(!rateLimitResult.allowed){this.logger?.warn("[VercelKvSessionStore] Rate limit exceeded for session lookup",{sessionId:sessionId.slice(0,20),clientIdentifier:options?.clientIdentifier?options.clientIdentifier.slice(0,20):void 0,retryAfterMs:rateLimitResult.retryAfterMs});return null}}await this.ensureConnected();const raw=await this.storage.get(sessionId);if(!raw)return null;const ttlSeconds=Math.ceil(this.defaultTtlMs/1e3);this.storage.expire(sessionId,ttlSeconds).catch(err=>{this.logger?.warn("[VercelKvSessionStore] TTL extension failed",{sessionId:sessionId.slice(0,20),error:err.message})});try{let parsed;if(this.security.enableSigning){parsed=verifyOrParseSession(raw,{secret:this.security.signingSecret});if(!parsed){this.logger?.warn("[VercelKvSessionStore] Session signature verification failed",{sessionId:sessionId.slice(0,20)});this.delete(sessionId).catch(()=>void 0);return null}}else{parsed=JSON.parse(raw)}const result=storedSessionSchema.safeParse(parsed);if(!result.success){this.logger?.warn("[VercelKvSessionStore] Invalid session format",{sessionId:sessionId.slice(0,20),errors:result.error.issues.slice(0,3).map(i=>({path:i.path,message:i.message}))});this.delete(sessionId).catch(()=>void 0);return null}const session=result.data;if(session.maxLifetimeAt&&session.maxLifetimeAt<Date.now()){this.logger?.info("[VercelKvSessionStore] Session exceeded max lifetime",{sessionId:sessionId.slice(0,20),maxLifetimeAt:session.maxLifetimeAt});await this.delete(sessionId);return null}if(session.session.expiresAt&&session.session.expiresAt<Date.now()){await this.delete(sessionId);return null}if(session.session.expiresAt){const ttlMs=Math.min(this.defaultTtlMs,session.session.expiresAt-Date.now());if(ttlMs>0&&ttlMs<this.defaultTtlMs){const boundedTtlSeconds=Math.ceil(ttlMs/1e3);this.storage.expire(sessionId,boundedTtlSeconds).catch(err=>{this.logger?.warn("[VercelKvSessionStore] TTL bound extension failed",{sessionId:sessionId.slice(0,20),error:err.message})})}}const updatedSession={...session,lastAccessedAt:Date.now()};return updatedSession}catch(error){this.logger?.warn("[VercelKvSessionStore] Failed to parse session",{sessionId:sessionId.slice(0,20),error:error.message});this.delete(sessionId).catch(()=>void 0);return null}}async set(sessionId,session,ttlMs){this.validateSessionId(sessionId);await this.ensureConnected();let value;if(this.security.enableSigning){value=signSession(session,{secret:this.security.signingSecret})}else{value=JSON.stringify(session)}if(ttlMs&&ttlMs>0){const ttlSeconds=Math.ceil(ttlMs/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else if(session.session.expiresAt){const ttl=session.session.expiresAt-Date.now();if(ttl>0){const ttlSeconds=Math.ceil(ttl/1e3);await this.storage.set(sessionId,value,{ttlSeconds})}else{await this.storage.set(sessionId,value)}}else{await this.storage.set(sessionId,value)}}async delete(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();await this.storage.delete(sessionId)}async exists(sessionId){this.validateSessionId(sessionId);await this.ensureConnected();return this.storage.exists(sessionId)}allocId(){return(0,import_utils31.randomUUID)()}async disconnect(){await this.storage.disconnect()}async ping(){try{await this.ensureConnected();return this.storage.ping()}catch(error){this.logger?.error("[VercelKvSessionStore] Connection failed",{error:error.message});return false}}};var import_utils33=require("@frontmcp/utils");var import_utils32=require("@frontmcp/utils");function recordDropAt(record){if(!record.refreshToken)return record.expiresAt;return Math.max(record.expiresAt??0,record.updatedAt+REFRESH_TOKEN_TTL_MS)}function hasLiveAccessToken(record,refreshSkewMs=0){if(record.expiresAt===void 0)return true;return record.expiresAt-(record.refreshToken?refreshSkewMs:0)>Date.now()}var HKDF_SALT=new TextEncoder().encode("frontmcp-token-store");function deriveKeyForRecord(masterKey,compositeKey,cache){const cached=cache.get(compositeKey);if(cached){return cached}const info=new TextEncoder().encode(`orchestrated-token:${compositeKey}`);const derived=(0,import_utils32.hkdfSha256)(masterKey,HKDF_SALT,info,32);cache.set(compositeKey,derived);return derived}function encryptRecord(key,record){const plaintext=JSON.stringify(record);const iv=(0,import_utils32.randomBytes)(12);const{ciphertext,tag}=(0,import_utils32.encryptAesGcm)(key,new TextEncoder().encode(plaintext),iv);return JSON.stringify({iv:Buffer.from(iv).toString("base64url"),tag:Buffer.from(tag).toString("base64url"),data:Buffer.from(ciphertext).toString("base64url")})}function decryptRecord(key,encrypted){const{iv,tag,data}=JSON.parse(encrypted);const ivBytes=Buffer.from(iv,"base64url");const tagBytes=Buffer.from(tag,"base64url");const ciphertextBytes=Buffer.from(data,"base64url");const plaintext=(0,import_utils32.decryptAesGcm)(key,ciphertextBytes,ivBytes,tagBytes);return JSON.parse(new TextDecoder().decode(plaintext))}var InMemoryOrchestratedTokenStore=class{tokens=new Map;encryptionKey;derivedKeys=new Map;cleanupTimer;defaultTtlMs;refreshSkewMs;constructor(options={}){this.encryptionKey=options.encryptionKey;this.defaultTtlMs=options.defaultTtlMs;this.refreshSkewMs=options.refreshSkewMs??0;const cleanupIntervalMs=options.cleanupIntervalMs??6e4;this.cleanupTimer=setInterval(()=>{void this.cleanup()},cleanupIntervalMs);if(this.cleanupTimer.unref){this.cleanupTimer.unref()}}buildKey(authorizationId,providerId){return`${authorizationId}:${providerId}`}async deriveKeyForRecord(compositeKey){if(!this.encryptionKey){throw new EncryptionKeyNotConfiguredError}const cached=this.derivedKeys.get(compositeKey);if(cached){return cached}const info=new TextEncoder().encode(`orchestrated-token:${compositeKey}`);const salt=new TextEncoder().encode("frontmcp-token-store");const derivedKey=(0,import_utils33.hkdfSha256)(this.encryptionKey,salt,info,32);this.derivedKeys.set(compositeKey,derivedKey);return derivedKey}async encryptRecord(compositeKey,record){const key=await this.deriveKeyForRecord(compositeKey);const plaintext=JSON.stringify(record);const iv=(0,import_utils33.randomBytes)(12);const{ciphertext,tag}=(0,import_utils33.encryptAesGcm)(key,new TextEncoder().encode(plaintext),iv);return JSON.stringify({iv:Buffer.from(iv).toString("base64url"),tag:Buffer.from(tag).toString("base64url"),data:Buffer.from(ciphertext).toString("base64url")})}async decryptRecord(compositeKey,encrypted){const key=await this.deriveKeyForRecord(compositeKey);const{iv,tag,data}=JSON.parse(encrypted);const ivBytes=Buffer.from(iv,"base64url");const tagBytes=Buffer.from(tag,"base64url");const ciphertextBytes=Buffer.from(data,"base64url");const plaintext=(0,import_utils33.decryptAesGcm)(key,ciphertextBytes,ivBytes,tagBytes);return JSON.parse(new TextDecoder().decode(plaintext))}async getRecord(authorizationId,providerId){const key=this.buildKey(authorizationId,providerId);const stored=this.tokens.get(key);if(!stored){return null}let record;if(this.encryptionKey){if(typeof stored!=="string"){return null}try{record=await this.decryptRecord(key,stored)}catch{this.tokens.delete(key);return null}}else{record=stored}const dropAt=recordDropAt(record);if(dropAt&&dropAt<Date.now()){this.tokens.delete(key);return null}return record}async getAccessToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record&&hasLiveAccessToken(record,this.refreshSkewMs)?record.accessToken:null}async getRefreshToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record?.refreshToken??null}async storeTokens(authorizationId,providerId,tokens){const key=this.buildKey(authorizationId,providerId);const now=Date.now();const record={accessToken:tokens.accessToken,refreshToken:tokens.refreshToken,expiresAt:tokens.expiresAt??(this.defaultTtlMs?now+this.defaultTtlMs:void 0),createdAt:now,updatedAt:now};if(this.encryptionKey){const encrypted=await this.encryptRecord(key,record);this.tokens.set(key,encrypted)}else{this.tokens.set(key,record)}}async deleteTokens(authorizationId,providerId){const key=this.buildKey(authorizationId,providerId);this.tokens.delete(key);this.derivedKeys.delete(key)}async hasTokens(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record!==null}async deleteAllForAuthorization(authorizationId){const prefix=`${authorizationId}:`;for(const key of this.tokens.keys()){if(key.startsWith(prefix)){this.tokens.delete(key);this.derivedKeys.delete(key)}}}async getProviderIds(authorizationId){const prefix=`${authorizationId}:`;const providerIds=[];for(const key of this.tokens.keys()){if(key.startsWith(prefix)){const providerId=key.slice(prefix.length);const record=await this.getRecord(authorizationId,providerId);if(record){providerIds.push(providerId)}}}return providerIds}async cleanup(){const now=Date.now();const keysToDelete=[];for(const[key,stored]of this.tokens.entries()){let record=null;if(this.encryptionKey){if(typeof stored==="string"){try{record=await this.decryptRecord(key,stored)}catch{keysToDelete.push(key);continue}}}else{record=stored}const dropAt=record?recordDropAt(record):void 0;if(dropAt&&dropAt<now){keysToDelete.push(key)}}for(const key of keysToDelete){this.tokens.delete(key);this.derivedKeys.delete(key)}}dispose(){if(this.cleanupTimer){clearInterval(this.cleanupTimer);this.cleanupTimer=void 0}}get size(){return this.tokens.size}clear(){this.tokens.clear();this.derivedKeys.clear()}async migrateTokens(fromAuthId,toAuthId){for(const oldKey of await this.copyRecords(fromAuthId,toAuthId)){this.tokens.delete(oldKey);this.derivedKeys.delete(oldKey)}}async copyTokens(fromAuthId,toAuthId){await this.copyRecords(fromAuthId,toAuthId)}async copyRecords(fromAuthId,toAuthId){const prefix=`${fromAuthId}:`;const sourceKeys=[...this.tokens.keys()].filter(key=>key.startsWith(prefix));const copiedKeys=[];for(const oldKey of sourceKeys){const stored=this.tokens.get(oldKey);if(!stored)continue;const newKey=this.buildKey(toAuthId,oldKey.slice(prefix.length));if(this.encryptionKey){try{const record=await this.decryptRecord(oldKey,stored);this.tokens.set(newKey,await this.encryptRecord(newKey,record))}catch{continue}}else{this.tokens.set(newKey,stored)}copiedKeys.push(oldKey)}return copiedKeys}};var StorageOrchestratedTokenStore=class{storage;encryptionKey;defaultTtlMs;refreshSkewMs;namespace;storageIsNamespaced;derivedKeys=new Map;constructor(storage,options={}){this.encryptionKey=options.encryptionKey;this.defaultTtlMs=options.defaultTtlMs;this.refreshSkewMs=options.refreshSkewMs??0;this.namespace=options.namespace??"otok";this.storageIsNamespaced=this.isNamespacedStorage(storage);this.storage=this.storageIsNamespaced?storage.namespace(this.namespace):storage}async getAccessToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record&&hasLiveAccessToken(record,this.refreshSkewMs)?record.accessToken:null}async getRefreshToken(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record?.refreshToken??null}async storeTokens(authorizationId,providerId,tokens){const compositeKey=this.compositeKey(authorizationId,providerId);const now=Date.now();const record={accessToken:tokens.accessToken,refreshToken:tokens.refreshToken,expiresAt:tokens.expiresAt??(this.defaultTtlMs?now+this.defaultTtlMs:void 0),createdAt:now,updatedAt:now};const value=this.encryptionKey?encryptRecord(this.keyFor(compositeKey),record):JSON.stringify(record);await this.storage.set(this.storageKey(compositeKey),value,this.ttlOptions(recordDropAt(record)))}async deleteTokens(authorizationId,providerId){const compositeKey=this.compositeKey(authorizationId,providerId);await this.storage.delete(this.storageKey(compositeKey));this.derivedKeys.delete(compositeKey)}async hasTokens(authorizationId,providerId){const record=await this.getRecord(authorizationId,providerId);return record!==null}async getProviderIds(authorizationId){const prefix=`${authorizationId}:`;const compositeKeys=await this.listCompositeKeys(`${prefix}*`);const providerIds=[];for(const compositeKey of compositeKeys){if(!compositeKey.startsWith(prefix))continue;const providerId=compositeKey.slice(prefix.length);const record=await this.getRecord(authorizationId,providerId);if(record){providerIds.push(providerId)}}return providerIds}async migrateTokens(fromAuthId,toAuthId){for(const oldComposite of await this.copyRecords(fromAuthId,toAuthId)){await this.storage.delete(this.storageKey(oldComposite));this.derivedKeys.delete(oldComposite)}}async copyTokens(fromAuthId,toAuthId){await this.copyRecords(fromAuthId,toAuthId)}async deleteAllForAuthorization(authorizationId){const prefix=`${authorizationId}:`;const compositeKeys=await this.listCompositeKeys(`${prefix}*`);for(const compositeKey of compositeKeys){if(!compositeKey.startsWith(prefix))continue;await this.storage.delete(this.storageKey(compositeKey));this.derivedKeys.delete(compositeKey)}}async copyRecords(fromAuthId,toAuthId){const prefix=`${fromAuthId}:`;const compositeKeys=await this.listCompositeKeys(`${prefix}*`);const copiedKeys=[];for(const oldComposite of compositeKeys){if(!oldComposite.startsWith(prefix))continue;const newComposite=this.compositeKey(toAuthId,oldComposite.slice(prefix.length));const stored=await this.storage.get(this.storageKey(oldComposite));if(stored===null)continue;if(this.encryptionKey){let record;try{record=decryptRecord(this.keyFor(oldComposite),stored)}catch{continue}const value=encryptRecord(this.keyFor(newComposite),record);await this.storage.set(this.storageKey(newComposite),value,this.ttlOptions(recordDropAt(record)))}else{let dropAt;try{dropAt=recordDropAt(JSON.parse(stored))}catch{dropAt=void 0}await this.storage.set(this.storageKey(newComposite),stored,this.ttlOptions(dropAt))}copiedKeys.push(oldComposite)}return copiedKeys}async getRecord(authorizationId,providerId){const compositeKey=this.compositeKey(authorizationId,providerId);const stored=await this.storage.get(this.storageKey(compositeKey));if(stored===null){return null}let record;if(this.encryptionKey){try{record=decryptRecord(this.keyFor(compositeKey),stored)}catch{await this.storage.delete(this.storageKey(compositeKey));return null}}else{try{record=JSON.parse(stored)}catch{await this.storage.delete(this.storageKey(compositeKey));return null}}const dropAt=recordDropAt(record);if(dropAt&&dropAt<Date.now()){await this.storage.delete(this.storageKey(compositeKey));return null}return record}keyFor(compositeKey){if(!this.encryptionKey){throw new EncryptionKeyNotConfiguredError}return deriveKeyForRecord(this.encryptionKey,compositeKey,this.derivedKeys)}compositeKey(authorizationId,providerId){return`${authorizationId}:${providerId}`}storageKey(compositeKey){return this.storageIsNamespaced?compositeKey:`${this.namespace}:${compositeKey}`}async listCompositeKeys(compositeGlob){const pattern=this.storageIsNamespaced?compositeGlob:`${this.namespace}:${compositeGlob}`;const raw=await this.storage.keys(pattern);if(this.storageIsNamespaced){return raw}const stripPrefix=`${this.namespace}:`;return raw.map(k=>k.startsWith(stripPrefix)?k.slice(stripPrefix.length):k)}ttlOptions(expiresAtMs){if(!expiresAtMs){return void 0}const ttl=Math.ceil((expiresAtMs-Date.now())/1e3);return{ttlSeconds:ttl>0?ttl:1}}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_utils34=require("@frontmcp/utils");function toSessionRecord(session){return{...session,completedProviders:Array.from(session.completedProviders.entries())}}function fromSessionRecord(record){return{...record,completedProviders:new Map(record.completedProviders)}}var InMemoryFederatedAuthSessionStore=class{sessions=new Map;sessionTtlMs=15*60*1e3;cleanupTimer;constructor(){this.cleanupTimer=setInterval(()=>{void this.cleanup()},6e4);if(this.cleanupTimer.unref){this.cleanupTimer.unref()}}async store(session){const record=toSessionRecord(session);this.sessions.set(session.id,record)}async get(id){const record=this.sessions.get(id);if(!record){return null}if(Date.now()>record.expiresAt){this.sessions.delete(id);return null}return fromSessionRecord(record)}async delete(id){this.sessions.delete(id)}async update(session){const record=toSessionRecord(session);this.sessions.set(session.id,record)}async cleanup(){const now=Date.now();for(const[id,record]of this.sessions){if(now>record.expiresAt){this.sessions.delete(id)}}}dispose(){if(this.cleanupTimer){clearInterval(this.cleanupTimer);this.cleanupTimer=void 0}}createSession(params){const now=Date.now();return{id:(0,import_utils34.randomUUID)(),pendingAuthId:params.pendingAuthId,clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,state:params.state,resource:params.resource,userInfo:params.userInfo,frontmcpPkce:params.frontmcpPkce,providerQueue:[...params.providerIds],completedProviders:new Map,skippedProviders:[],signinBinding:params.signinBinding,createdAt:now,expiresAt:now+this.sessionTtlMs}}get size(){return this.sessions.size}clear(){this.sessions.clear()}};function createFederatedAuthSession(params,ttlMs=15*60*1e3){const now=Date.now();return{id:(0,import_utils34.randomUUID)(),pendingAuthId:params.pendingAuthId,clientId:params.clientId,redirectUri:params.redirectUri,scopes:params.scopes,state:params.state,resource:params.resource,userInfo:params.userInfo,frontmcpPkce:params.frontmcpPkce,providerQueue:[...params.providerIds],completedProviders:new Map,skippedProviders:[],signinBinding:params.signinBinding,createdAt:now,expiresAt:now+ttlMs}}function isSessionComplete(session){return session.providerQueue.length===0&&!session.currentProviderId}function getNextProvider(session){if(session.currentProviderId){return session.currentProviderId}return session.providerQueue[0]}function completeCurrentProvider(session,tokens,userInfo){if(!session.currentProviderId){throw new AuthFlowError("No current provider to complete","AUTH_FLOW_ERROR")}session.completedProviders.set(session.currentProviderId,{providerId:session.currentProviderId,tokens,userInfo,completedAt:Date.now()});session.currentProviderId=void 0;session.currentProviderPkce=void 0;session.currentProviderState=void 0}function startNextProvider(session,pkce,state){if(session.currentProviderId){throw new AuthFlowError("Cannot start next provider while current is in progress","AUTH_FLOW_ERROR")}if(session.providerQueue.length===0){throw new AuthFlowError("No more providers in queue","AUTH_FLOW_ERROR")}const providerId=session.providerQueue.shift();if(!providerId){throw new AuthFlowError("No more providers in queue","AUTH_FLOW_ERROR")}session.currentProviderId=providerId;session.currentProviderPkce=pkce;session.currentProviderState=state;return providerId}var import_utils35=require("@frontmcp/utils");var StorageFederatedAuthSessionStore=class{storage;namespace;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"fed";this.storageIsNamespaced=this.isNamespacedStorage(storage);const namespacedStorage=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.storage=new import_utils35.TypedStorage(namespacedStorage)}async store(session){await this.put(session)}async update(session){await this.put(session)}async get(id){const record=await this.storage.get(this.key(id));if(!record){return null}if(Date.now()>record.expiresAt){await this.storage.delete(this.key(id));return null}return fromSessionRecord(record)}async delete(id){await this.storage.delete(this.key(id))}async put(session){const record=toSessionRecord(session);const ttlSeconds=this.calculateTtl(record.expiresAt);await this.storage.set(this.key(session.id),record,ttlSeconds?{ttlSeconds}:void 0)}calculateTtl(expiresAtMs){const ttl=Math.ceil((expiresAtMs-Date.now())/1e3);return ttl>0?ttl:1}key(id){return this.storageIsNamespaced?id:`${this.namespace}:${id}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};function consentRecordKey(userSub,clientId){return`consent:${userSub}:${clientId}`}var InMemoryConsentStore=class{records=new Map;async get(userSub,clientId){const record=this.records.get(consentRecordKey(userSub,clientId));if(!record)return null;return{...record,selectedToolIds:[...record.selectedToolIds],seenToolIds:[...record.seenToolIds]}}async set(record){this.records.set(consentRecordKey(record.userSub,record.clientId),{...record,selectedToolIds:[...record.selectedToolIds],seenToolIds:[...record.seenToolIds]})}async delete(userSub,clientId){this.records.delete(consentRecordKey(userSub,clientId))}get size(){return this.records.size}clear(){this.records.clear()}};var import_utils36=require("@frontmcp/utils");var StorageConsentStore=class{storage;namespace;storageIsNamespaced;constructor(storage,options={}){this.namespace=options.namespace??"remembered-consent";this.storageIsNamespaced=this.isNamespacedStorage(storage);const namespacedStorage=this.storageIsNamespaced?storage.namespace(this.namespace):storage;this.storage=new import_utils36.TypedStorage(namespacedStorage)}async get(userSub,clientId){return this.storage.get(this.key(userSub,clientId))}async set(record){await this.storage.set(this.key(record.userSub,record.clientId),record)}async delete(userSub,clientId){await this.storage.delete(this.key(userSub,clientId))}key(userSub,clientId){const base=consentRecordKey(userSub,clientId);return this.storageIsNamespaced?base:`${this.namespace}:${base}`}isNamespacedStorage(storage){return"namespace"in storage&&typeof storage.namespace==="function"}};var import_lazy_zod8=require("@frontmcp/lazy-zod");var import_utils37=require("@frontmcp/utils");var redisVaultEntrySchema=import_lazy_zod8.internalZ.object({id:import_lazy_zod8.internalZ.string(),userSub:import_lazy_zod8.internalZ.string(),userEmail:import_lazy_zod8.internalZ.string().optional(),userName:import_lazy_zod8.internalZ.string().optional(),clientId:import_lazy_zod8.internalZ.string(),createdAt:import_lazy_zod8.internalZ.number(),lastAccessAt:import_lazy_zod8.internalZ.number(),authorizedAppIds:import_lazy_zod8.internalZ.array(import_lazy_zod8.internalZ.string()),skippedAppIds:import_lazy_zod8.internalZ.array(import_lazy_zod8.internalZ.string()),pendingAuthIds:import_lazy_zod8.internalZ.array(import_lazy_zod8.internalZ.string()),encrypted:encryptedDataSchema});var encryptionContextStorage=new import_utils37.AsyncLocalStorage;var EncryptedRedisVault=class{constructor(redis,encryption,namespace="vault:"){this.redis=redis;this.encryption=encryption;this.namespace=namespace}redis;encryption;namespace;runWithContext(context,fn){return encryptionContextStorage.run(context,fn)}getKey(){const asyncContext=encryptionContextStorage.getStore();if(asyncContext){return asyncContext.key}throw new EncryptionContextNotSetError}redisKey(id){return`${this.namespace}${id}`}credentialKey(appId,providerId){return`${appId}:${providerId}`}async encryptSensitive(data){return this.encryption.encryptObject(data,this.getKey())}async decryptSensitive(encrypted){return this.encryption.decryptObject(encrypted,this.getKey())}async toVaultEntry(redisEntry){const sensitive=await this.decryptSensitive(redisEntry.encrypted);return{id:redisEntry.id,userSub:redisEntry.userSub,userEmail:redisEntry.userEmail,userName:redisEntry.userName,clientId:redisEntry.clientId,createdAt:redisEntry.createdAt,lastAccessAt:redisEntry.lastAccessAt,appCredentials:sensitive.appCredentials,consent:sensitive.consent,federated:sensitive.federated,pendingAuths:sensitive.pendingAuths,authorizedAppIds:redisEntry.authorizedAppIds,skippedAppIds:redisEntry.skippedAppIds}}async toRedisEntry(entry){const sensitive={appCredentials:entry.appCredentials,consent:entry.consent,federated:entry.federated,pendingAuths:entry.pendingAuths};return{id:entry.id,userSub:entry.userSub,userEmail:entry.userEmail,userName:entry.userName,clientId:entry.clientId,createdAt:entry.createdAt,lastAccessAt:entry.lastAccessAt,authorizedAppIds:entry.authorizedAppIds,skippedAppIds:entry.skippedAppIds,pendingAuthIds:entry.pendingAuths.map(p=>p.id),encrypted:await this.encryptSensitive(sensitive)}}async saveEntry(entry){const redisEntry=await this.toRedisEntry(entry);await this.redis.set(this.redisKey(entry.id),JSON.stringify(redisEntry))}async loadEntry(id){const data=await this.redis.get(this.redisKey(id));if(!data)return null;try{const redisEntry=redisVaultEntrySchema.parse(JSON.parse(data));return await this.toVaultEntry(redisEntry)}catch(error){throw new VaultLoadError(id,error instanceof Error?error:void 0)}}async create(params){const now=Date.now();const entry={id:(0,import_utils37.randomUUID)(),userSub:params.userSub,userEmail:params.userEmail,userName:params.userName,clientId:params.clientId,createdAt:now,lastAccessAt:now,appCredentials:{},consent:params.consent,federated:params.federated,pendingAuths:[],authorizedAppIds:params.authorizedAppIds??[],skippedAppIds:params.skippedAppIds??[]};await this.saveEntry(entry);return entry}async get(id){const entry=await this.loadEntry(id);if(!entry)return null;entry.lastAccessAt=Date.now();await this.saveEntry(entry);return entry}async update(id,updates){const entry=await this.loadEntry(id);if(!entry){throw new VaultNotFoundError("Vault entry",id)}Object.assign(entry,updates,{lastAccessAt:Date.now()});await this.saveEntry(entry)}async delete(id){await this.redis.del(this.redisKey(id))}async updateConsent(vaultId,consent){const entry=await this.loadEntry(vaultId);if(!entry)return;entry.consent=consent;entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async authorizeApp(vaultId,appId){const entry=await this.loadEntry(vaultId);if(!entry)return;entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==appId);if(!entry.authorizedAppIds.includes(appId)){entry.authorizedAppIds.push(appId)}entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async createPendingAuth(vaultId,params){const entry=await this.loadEntry(vaultId);if(!entry){throw new VaultNotFoundError("Vault",vaultId)}const now=Date.now();const pendingAuth={id:(0,import_utils37.randomUUID)(),appId:params.appId,toolId:params.toolId,authUrl:params.authUrl,requiredScopes:params.requiredScopes,elicitId:params.elicitId,createdAt:now,expiresAt:now+(params.ttlMs??10*60*1e3),status:"pending"};entry.pendingAuths.push(pendingAuth);entry.lastAccessAt=now;await this.saveEntry(entry);return pendingAuth}async getPendingAuth(vaultId,pendingAuthId){const entry=await this.loadEntry(vaultId);if(!entry)return null;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(!pendingAuth)return null;if(Date.now()>pendingAuth.expiresAt&&pendingAuth.status==="pending"){pendingAuth.status="expired";await this.saveEntry(entry)}return pendingAuth}async completePendingAuth(vaultId,pendingAuthId){const entry=await this.loadEntry(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="completed";entry.skippedAppIds=entry.skippedAppIds.filter(id=>id!==pendingAuth.appId);if(!entry.authorizedAppIds.includes(pendingAuth.appId)){entry.authorizedAppIds.push(pendingAuth.appId)}entry.lastAccessAt=Date.now();await this.saveEntry(entry)}}async cancelPendingAuth(vaultId,pendingAuthId){const entry=await this.loadEntry(vaultId);if(!entry)return;const pendingAuth=entry.pendingAuths.find(p=>p.id===pendingAuthId);if(pendingAuth){pendingAuth.status="cancelled";await this.saveEntry(entry)}}async isAppAuthorized(vaultId,appId){const data=await this.redis.get(this.redisKey(vaultId));if(!data)return false;try{const parsed=JSON.parse(data);return Array.isArray(parsed.authorizedAppIds)&&parsed.authorizedAppIds.includes(appId)}catch{return false}}async getPendingAuths(vaultId){const entry=await this.loadEntry(vaultId);if(!entry)return[];const now=Date.now();let updated=false;const pending=entry.pendingAuths.filter(p=>{if(now>p.expiresAt&&p.status==="pending"){p.status="expired";updated=true}return p.status==="pending"});if(updated){await this.saveEntry(entry)}return pending}async addAppCredential(vaultId,credential){const entry=await this.loadEntry(vaultId);if(!entry)return;const shouldStore=await this.shouldStoreCredential(vaultId,credential.appId);if(!shouldStore)return;const key=this.credentialKey(credential.appId,credential.providerId);entry.appCredentials[key]=credential;entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async removeAppCredential(vaultId,appId,providerId){const entry=await this.loadEntry(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);delete entry.appCredentials[key];entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async getAppCredentials(vaultId,appId){const entry=await this.loadEntry(vaultId);if(!entry)return[];const prefix=`${appId}:`;return Object.entries(entry.appCredentials).filter(([key])=>key.startsWith(prefix)).map(([,cred])=>cred)}async getCredential(vaultId,appId,providerId){const entry=await this.loadEntry(vaultId);if(!entry)return null;const key=this.credentialKey(appId,providerId);return entry.appCredentials[key]??null}async getAllCredentials(vaultId,filterByConsent=false){const entry=await this.loadEntry(vaultId);if(!entry)return[];const allCredentials=Object.values(entry.appCredentials);if(!filterByConsent||!entry.consent?.enabled){return allCredentials}const consentedToolIds=new Set(entry.consent.selectedToolIds);return allCredentials.filter(cred=>{return Array.from(consentedToolIds).some(toolId=>toolId.startsWith(`${cred.appId}:`))})}async updateCredential(vaultId,appId,providerId,updates){const entry=await this.loadEntry(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential)return;Object.assign(credential,updates);entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async shouldStoreCredential(vaultId,appId,toolIds){const entry=await this.loadEntry(vaultId);if(!entry)return false;if(!entry.consent?.enabled){return true}if(toolIds&&toolIds.length>0){return toolIds.some(toolId=>entry.consent.selectedToolIds.includes(toolId))}const consentedToolIds=entry.consent.selectedToolIds;return consentedToolIds.some(toolId=>toolId.startsWith(`${appId}:`))}async invalidateCredential(vaultId,appId,providerId,reason){await this.updateCredential(vaultId,appId,providerId,{isValid:false,invalidReason:reason})}async refreshOAuthCredential(vaultId,appId,providerId,tokens){const entry=await this.loadEntry(vaultId);if(!entry)return;const key=this.credentialKey(appId,providerId);const credential=entry.appCredentials[key];if(!credential||credential.credential.type!=="oauth")return;credential.credential.accessToken=tokens.accessToken;if(tokens.refreshToken!==void 0){credential.credential.refreshToken=tokens.refreshToken}if(tokens.expiresAt!==void 0){credential.credential.expiresAt=tokens.expiresAt;credential.expiresAt=tokens.expiresAt}credential.isValid=true;credential.invalidReason=void 0;entry.lastAccessAt=Date.now();await this.saveEntry(entry)}async cleanup(){}};function createEncryptedVault(redis,config={}){const encryption=new VaultEncryption({pepper:config.pepper});const vault=new EncryptedRedisVault(redis,encryption,config.namespace);return{vault,encryption}}var import_utils38=require("@frontmcp/utils");function toEpochSeconds(exp){if(exp==null)return void 0;if(exp instanceof Date)return Math.floor(exp.getTime()/1e3);return exp>1e12?Math.floor(exp/1e3):Math.floor(exp)}function isSoonExpiring(exp,skewSec=60){const expSec=toEpochSeconds(exp);if(expSec==null)return false;const now=Math.floor(Date.now()/1e3);return expSec<=now+Math.max(0,skewSec)}function isSoonExpiringProvider(sessionLike,providerId,skewSec=60){const snap=sessionLike.authorizedProviders[providerId];if(!snap)return false;return isSoonExpiring(snap.exp,skewSec)}function tryJwtExp(token){if(!token)return void 0;const parts=token.split(".");if(parts.length<2)return void 0;try{const json=JSON.parse(new TextDecoder().decode((0,import_utils38.base64urlDecode)(parts[1])));const e=json?.exp;return typeof e==="number"?toEpochSeconds(e):void 0}catch{return void 0}}var import_lazy_zod9=require("@frontmcp/lazy-zod");var authModeSchema=import_lazy_zod9.internalZ.enum(["public","transparent","orchestrated"]);var authUserSchema=import_lazy_zod9.internalZ.object({sub:import_lazy_zod9.internalZ.string(),name:import_lazy_zod9.internalZ.string().optional(),email:import_lazy_zod9.internalZ.string().email().optional(),picture:import_lazy_zod9.internalZ.string().url().optional(),anonymous:import_lazy_zod9.internalZ.boolean().optional()});var authorizedToolSchema=import_lazy_zod9.internalZ.object({executionPath:import_lazy_zod9.internalZ.tuple([import_lazy_zod9.internalZ.string(),import_lazy_zod9.internalZ.string()]),scopes:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string()).optional(),details:import_lazy_zod9.internalZ.record(import_lazy_zod9.internalZ.string(),import_lazy_zod9.internalZ.unknown()).optional()});var authorizedPromptSchema=import_lazy_zod9.internalZ.object({executionPath:import_lazy_zod9.internalZ.tuple([import_lazy_zod9.internalZ.string(),import_lazy_zod9.internalZ.string()]),scopes:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string()).optional(),details:import_lazy_zod9.internalZ.record(import_lazy_zod9.internalZ.string(),import_lazy_zod9.internalZ.unknown()).optional()});var llmSafeAuthContextSchema=import_lazy_zod9.internalZ.object({authorizationId:import_lazy_zod9.internalZ.string(),sessionId:import_lazy_zod9.internalZ.string(),mode:authModeSchema,isAnonymous:import_lazy_zod9.internalZ.boolean(),user:import_lazy_zod9.internalZ.object({sub:import_lazy_zod9.internalZ.string(),name:import_lazy_zod9.internalZ.string().optional()}),scopes:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string()),authorizedToolIds:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string()),authorizedPromptIds:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string())});var AppAuthState=(AppAuthState2=>{AppAuthState2["AUTHORIZED"]="authorized";AppAuthState2["SKIPPED"]="skipped";AppAuthState2["PENDING"]="pending";return AppAuthState2})(AppAuthState||{});var appAuthStateSchema=import_lazy_zod9.internalZ.nativeEnum(AppAuthState);var appAuthorizationRecordSchema=import_lazy_zod9.internalZ.object({appId:import_lazy_zod9.internalZ.string(),state:appAuthStateSchema,stateChangedAt:import_lazy_zod9.internalZ.number(),grantedScopes:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string()).optional(),authProviderId:import_lazy_zod9.internalZ.string().optional(),toolIds:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string())});var progressiveAuthStateSchema=import_lazy_zod9.internalZ.object({apps:import_lazy_zod9.internalZ.record(import_lazy_zod9.internalZ.string(),appAuthorizationRecordSchema),initiallyAuthorized:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string()),initiallySkipped:import_lazy_zod9.internalZ.array(import_lazy_zod9.internalZ.string())});var import_utils41=require("@frontmcp/utils");var AuthorizationBase=class _AuthorizationBase{id;isAnonymous;user;claims;expiresAt;scopes;authorizedProviders;authorizedProviderIds;authorizedApps;authorizedAppIds;authorizedTools;authorizedToolIds;authorizedPrompts;authorizedPromptIds;authorizedResources;token;#sessions=new Map;createdAt;constructor(ctx){this.id=ctx.id;this.isAnonymous=ctx.isAnonymous;this.user=ctx.user;this.claims=ctx.claims;this.expiresAt=ctx.expiresAt;this.scopes=ctx.scopes??[];this.token=ctx.token;this.createdAt=Date.now();this.authorizedProviders=ctx.authorizedProviders??{};this.authorizedProviderIds=ctx.authorizedProviderIds??Object.keys(this.authorizedProviders);this.authorizedApps=ctx.authorizedApps??{};this.authorizedAppIds=ctx.authorizedAppIds??Object.keys(this.authorizedApps);this.authorizedTools=ctx.authorizedTools??{};this.authorizedToolIds=ctx.authorizedToolIds??Object.keys(this.authorizedTools);this.authorizedPrompts=ctx.authorizedPrompts??{};this.authorizedPromptIds=ctx.authorizedPromptIds??Object.keys(this.authorizedPrompts);this.authorizedResources=ctx.authorizedResources??[]}createTransportSession(protocol,fingerprint){const sessionId=(0,import_utils41.randomUUID)();const session={id:sessionId,authorizationId:this.id,protocol,createdAt:Date.now(),expiresAt:this.expiresAt,nodeId:(0,import_utils41.getMachineId)(),clientFingerprint:fingerprint};this.#sessions.set(session.id,session);return session}getTransportSession(sessionId){return this.#sessions.get(sessionId)}getAllSessions(){return Array.from(this.#sessions.values())}removeTransportSession(sessionId){return this.#sessions.delete(sessionId)}get sessionCount(){return this.#sessions.size}hasScope(scope){return this.scopes.includes(scope)}hasAllScopes(scopes){return scopes.every(s=>this.scopes.includes(s))}hasAnyScope(scopes){return scopes.some(s=>this.scopes.includes(s))}canAccessTool(toolId){return toolId in this.authorizedTools||this.authorizedToolIds.includes(toolId)}canAccessPrompt(promptId){return promptId in this.authorizedPrompts||this.authorizedPromptIds.includes(promptId)}isAppAuthorized(appId){return appId in this.authorizedApps||this.authorizedAppIds.includes(appId)}getProgressiveAuthUrl(appId,baseUrl,ticket){const params=new URLSearchParams({app:appId});if(ticket)params.set("ticket",ticket);return`${baseUrl}/oauth/authorize?${params.toString()}`}isExpired(){if(!this.expiresAt)return false;return Date.now()>this.expiresAt}getTimeToExpiry(){if(!this.expiresAt)return void 0;return this.expiresAt-Date.now()}toSessionJwt(session){const payload={sid:session.id,aid:this.id,proto:session.protocol,nid:session.nodeId,iat:Math.floor(Date.now()/1e3),exp:this.expiresAt?Math.floor(this.expiresAt/1e3):void 0};return encryptJson(payload)}toLLMSafeContext(session){return{authorizationId:this.id,sessionId:session.id,mode:this.mode,isAnonymous:this.isAnonymous,user:{sub:this.user.sub,name:this.user.name},scopes:this.scopes,authorizedToolIds:this.authorizedToolIds,authorizedPromptIds:this.authorizedPromptIds}}static isJwtHeader(segment){try{const bytes=(0,import_utils41.base64urlDecode)(segment);const text=new TextDecoder().decode(bytes);const parsed=JSON.parse(text);return typeof parsed==="object"&&parsed!==null&&typeof parsed.alg==="string"}catch{return false}}static validateNoTokenLeakage(data){const json=JSON.stringify(data);const B64URL=/^[A-Za-z0-9_-]+$/;const MIN_SEG=2;let dotIdx=json.indexOf(".");while(dotIdx!==-1){let seg1Start=dotIdx;while(seg1Start>0&&/[A-Za-z0-9_-]/.test(json[seg1Start-1]))seg1Start--;const seg1Len=dotIdx-seg1Start;if(seg1Len>=MIN_SEG){let seg2End=dotIdx+1;while(seg2End<json.length&&/[A-Za-z0-9_-]/.test(json[seg2End]))seg2End++;const seg2Len=seg2End-(dotIdx+1);if(seg2Len>=MIN_SEG&&seg2End<json.length&&json[seg2End]==="."){const dot2=seg2End;let seg3End=dot2+1;while(seg3End<json.length&&/[A-Za-z0-9_-]/.test(json[seg3End]))seg3End++;const seg3Len=seg3End-(dot2+1);if(seg3Len>=MIN_SEG){const seg1=json.substring(seg1Start,dotIdx);const seg2=json.substring(dotIdx+1,dot2);const seg3=json.substring(dot2+1,seg3End);if(B64URL.test(seg1)&&B64URL.test(seg2)&&B64URL.test(seg3)&&_AuthorizationBase.isJwtHeader(seg1)){throw new TokenLeakDetectedError("JWT pattern detected in LLM context data")}}}}dotIdx=json.indexOf(".",dotIdx+1)}const sensitiveFields=["access_token","refresh_token","id_token","tokenEnc","secretRefId"];for(const field of sensitiveFields){if(json.includes(`"${field}"`)){throw new TokenLeakDetectedError(`Sensitive field "${field}" found in data`)}}}};var import_utils42=require("@frontmcp/utils");var PublicAuthorization=class _PublicAuthorization extends AuthorizationBase{mode="public";issuer;constructor(ctx){super(ctx);this.issuer=ctx.issuer}static create(ctx={}){const{prefix="anon",scopes=["anonymous"],ttlMs=36e5,issuer,allowedTools="all",allowedPrompts="all"}=ctx;const uuid=(0,import_utils42.randomUUID)();const sub=`${prefix}:${uuid}`;const user={sub,name:"Anonymous",anonymous:true};const expiresAt=ttlMs?Date.now()+ttlMs:void 0;const authorizedTools={};const authorizedToolIds=[];if(allowedTools!=="all"&&Array.isArray(allowedTools)){for(const toolId of allowedTools){authorizedTools[toolId]={executionPath:["public",toolId]};authorizedToolIds.push(toolId)}}const authorizedPrompts={};const authorizedPromptIds=[];if(allowedPrompts!=="all"&&Array.isArray(allowedPrompts)){for(const promptId of allowedPrompts){authorizedPrompts[promptId]={executionPath:["public",promptId]};authorizedPromptIds.push(promptId)}}return new _PublicAuthorization({id:sub,isAnonymous:true,user,scopes,expiresAt,issuer,authorizedTools:allowedTools==="all"?void 0:authorizedTools,authorizedToolIds:allowedTools==="all"?void 0:authorizedToolIds,authorizedPrompts:allowedPrompts==="all"?void 0:authorizedPrompts,authorizedPromptIds:allowedPrompts==="all"?void 0:authorizedPromptIds})}async getToken(_providerId){throw new TokenNotAvailableError("PublicAuthorization: Anonymous users cannot access provider tokens. Use transparent or orchestrated mode for token access.")}get allowsAllTools(){return this.authorizedToolIds.length===0&&Object.keys(this.authorizedTools).length===0}get allowsAllPrompts(){return this.authorizedPromptIds.length===0&&Object.keys(this.authorizedPrompts).length===0}canAccessTool(toolId){if(this.allowsAllTools){return true}return super.canAccessTool(toolId)}canAccessPrompt(promptId){if(this.allowsAllPrompts){return true}return super.canAccessPrompt(promptId)}};var import_utils43=require("@frontmcp/utils");var TransparentAuthorization=class _TransparentAuthorization extends AuthorizationBase{mode="transparent";providerId;providerName;constructor(ctx){super(ctx);this.providerId=ctx.providerId;this.providerName=ctx.providerName}static fromVerifiedToken(ctx){const{token,payload,providerId,providerName,...projections}=ctx;const user={sub:payload.sub,name:payload.name,email:payload.email,picture:payload.picture,anonymous:false};const scopes=_TransparentAuthorization.parseScopes(payload.scope);const expiresAt=payload.exp?payload.exp*1e3:void 0;const id=_TransparentAuthorization.generateAuthorizationId(token);const providerSnapshot={id:providerId,exp:expiresAt,payload,embedMode:"plain",token};return new _TransparentAuthorization({id,isAnonymous:false,user,claims:payload,expiresAt,scopes,token,providerId,providerName,authorizedProviders:{[providerId]:providerSnapshot},authorizedProviderIds:[providerId],...projections})}async getToken(_providerId){if(!this.token){throw new TokenNotAvailableError("TransparentAuthorization: Token not available")}return this.token}static parseScopes(scope){if(!scope)return[];if(Array.isArray(scope))return scope;return scope.split(/\s+/).filter(Boolean)}static generateAuthorizationId(token){const parts=token.split(".");const signature=parts[2]||token;return(0,import_utils43.sha256Hex)(signature).substring(0,16)}get issuer(){return this.claims?.["iss"]}get audience(){return this.claims?.["aud"]}hasAudience(aud){const tokenAud=this.audience;if(!tokenAud)return false;if(Array.isArray(tokenAud))return tokenAud.includes(aud);return tokenAud===aud}};var import_utils44=require("@frontmcp/utils");function deriveAuthorizationId(token){const parts=token.split(".");const signature=parts[2]||token;return(0,import_utils44.sha256Hex)(signature).substring(0,16)}var OrchestratedAuthorization=class _OrchestratedAuthorization extends AuthorizationBase{mode="orchestrated";primaryProviderId;#tokenStore;#onTokenRefresh;#providerStates;constructor(ctx){super(ctx);this.primaryProviderId=ctx.primaryProviderId;this.#tokenStore=ctx.tokenStore;this.#onTokenRefresh=ctx.onTokenRefresh;this.#providerStates=ctx.providerStates??new Map}static create(ctx){const{token,user,scopes=[],claims,expiresAt,primaryProviderId,tokenStore,onTokenRefresh,providers={},authorizedProviderIds,...projections}=ctx;const id=deriveAuthorizationId(token);const providerStates=new Map;const authorizedProviders={};const providerIdsFromState=[];for(const[providerId,state]of Object.entries(providers)){providerStates.set(providerId,state);providerIdsFromState.push(providerId);authorizedProviders[providerId]={id:providerId,exp:state.expiresAt,embedMode:state.secretRefId?"ref":"store-only",secretRefId:state.secretRefId,refreshRefId:state.refreshRefId}}const finalAuthorizedProviderIds=authorizedProviderIds??(providerIdsFromState.length>0?providerIdsFromState:void 0);return new _OrchestratedAuthorization({id,isAnonymous:false,user,claims,expiresAt,scopes,token,primaryProviderId,tokenStore,onTokenRefresh,providerStates,authorizedProviders,...projections,authorizedProviderIds:finalAuthorizedProviderIds})}async getToken(providerId){const targetProviderId=providerId??this.primaryProviderId;if(!targetProviderId){throw new NoProviderIdError("OrchestratedAuthorization: No provider ID specified and no primary provider set")}if(!this.#tokenStore){throw new TokenStoreRequiredError("orchestrated token retrieval")}const hasToken=await this.#tokenStore.hasTokens(this.id,targetProviderId);if(!hasToken){throw new TokenNotAvailableError(`OrchestratedAuthorization: No tokens available for provider "${targetProviderId}"`)}const accessToken=await this.#tokenStore.getAccessToken(this.id,targetProviderId);if(accessToken){const providerState=this.#providerStates.get(targetProviderId);if(providerState?.expiresAt&&providerState.expiresAt<Date.now()){return this.refreshAndGetToken(targetProviderId)}return accessToken}return this.refreshAndGetToken(targetProviderId)}async refreshAndGetToken(providerId){if(!this.#tokenStore||!this.#onTokenRefresh){throw new TokenNotAvailableError(`OrchestratedAuthorization: Token expired for provider "${providerId}" and refresh not available`)}const refreshToken=await this.#tokenStore.getRefreshToken(this.id,providerId);if(!refreshToken){throw new TokenNotAvailableError(`OrchestratedAuthorization: No refresh token available for provider "${providerId}"`)}const result=await this.#onTokenRefresh(providerId,refreshToken);await this.#tokenStore.storeTokens(this.id,providerId,{accessToken:result.accessToken,refreshToken:result.refreshToken??refreshToken,expiresAt:result.expiresIn?Date.now()+result.expiresIn*1e3:void 0});const currentState=this.#providerStates.get(providerId);if(currentState){currentState.expiresAt=result.expiresIn?Date.now()+result.expiresIn*1e3:void 0}return result.accessToken}hasProvider(providerId){return this.#providerStates.has(providerId)}getProviderIds(){return Array.from(this.#providerStates.keys())}async addProvider(providerId,tokens){if(!this.#tokenStore){throw new TokenStoreRequiredError("adding providers")}const expiresAt=tokens.expiresIn?Date.now()+tokens.expiresIn*1e3:void 0;await this.#tokenStore.storeTokens(this.id,providerId,{accessToken:tokens.accessToken,refreshToken:tokens.refreshToken,expiresAt});this.#providerStates.set(providerId,{id:providerId,expiresAt,secretRefId:`${this.id}:${providerId}`})}#mutableAuthorizedApps=new Map(Object.entries(this.authorizedApps??{}));async addAppAuthorization(appId,toolIds,tokens){if(!this.#tokenStore){throw new TokenStoreRequiredError("progressive authorization")}const providerId=`app:${appId}`;await this.addProvider(providerId,tokens);this.#mutableAuthorizedApps.set(appId,{id:appId,toolIds})}async getAppToken(appId){if(!this.#mutableAuthorizedApps.has(appId)){return null}const providerId=`app:${appId}`;try{return await this.getToken(providerId)}catch{return null}}isAppAuthorized(appId){return this.#mutableAuthorizedApps.has(appId)||super.isAppAuthorized(appId)}getAllAuthorizedAppIds(){const baseIds=new Set(this.authorizedAppIds??[]);for(const appId of this.#mutableAuthorizedApps.keys()){baseIds.add(appId)}return Array.from(baseIds)}getAppToolIds(appId){return this.#mutableAuthorizedApps.get(appId)?.toolIds??this.authorizedApps?.[appId]?.toolIds}async removeProvider(providerId){if(this.#tokenStore){await this.#tokenStore.deleteTokens(this.id,providerId)}this.#providerStates.delete(providerId)}get issuer(){return this.claims?.["iss"]}};var ORCHESTRATED_AUTH_ACCESSOR=Symbol.for("frontmcp:ORCHESTRATED_AUTH_ACCESSOR");var NullOrchestratedAuthAccessor=class{primaryProviderId=void 0;issuer=void 0;authorizationId="null";isAuthenticated=false;async getToken(providerId){throw new OrchestratedAuthNotAvailableError}async tryGetToken(providerId){return null}async getAppToken(appId){return null}hasProvider(providerId){return false}getProviderIds(){return[]}isAppAuthorized(appId){return false}getAllAuthorizedAppIds(){return[]}getAppToolIds(appId){return void 0}};var OrchestratedAuthAccessorAdapter=class{constructor(authorization){this.authorization=authorization}authorization;get primaryProviderId(){return this.authorization.primaryProviderId}get issuer(){return this.authorization.issuer}get authorizationId(){return this.authorization.id}get isAuthenticated(){return!this.authorization.isAnonymous}async getToken(providerId){return this.authorization.getToken(providerId)}async tryGetToken(providerId){try{return await this.authorization.getToken(providerId)}catch{return null}}async getAppToken(appId){return this.authorization.getAppToken(appId)}hasProvider(providerId){return this.authorization.hasProvider(providerId)}getProviderIds(){return this.authorization.getProviderIds()}isAppAuthorized(appId){return this.authorization.isAppAuthorized(appId)}getAllAuthorizedAppIds(){return this.authorization.getAllAuthorizedAppIds()}getAppToolIds(appId){return this.authorization.getAppToolIds(appId)}};var import_utils45=require("@frontmcp/utils");var DEFAULT_MAX_DYNAMIC_CLIENTS=1e3;function globMatch(pattern,input){let p=0;let i=0;let starIdx=-1;let matchIdx=0;while(i<input.length){if(p<pattern.length&&pattern[p]===input[i]){p++;i++}else if(p<pattern.length&&pattern[p]==="*"){starIdx=p;matchIdx=i;p++}else if(starIdx!==-1){p=starIdx+1;matchIdx++;i=matchIdx}else{return false}}while(p<pattern.length&&pattern[p]==="*")p++;return p===pattern.length}function splitRedirectUri(s){const schemeSep=s.indexOf("://");if(schemeSep===-1)return null;const scheme=s.slice(0,schemeSep);const afterScheme=s.slice(schemeSep+3);let boundary=afterScheme.length;for(let i=0;i<afterScheme.length;i++){const ch=afterScheme[i];if(ch==="/"||ch==="?"||ch==="#"){boundary=i;break}}const authority=afterScheme.slice(0,boundary);const rest=afterScheme.slice(boundary);const at=authority.lastIndexOf("@");const userinfo=at===-1?"":authority.slice(0,at);const hostport=at===-1?authority:authority.slice(at+1);let host=hostport;let port="";if(hostport.startsWith("[")){const close=hostport.indexOf("]");if(close!==-1){host=hostport.slice(0,close+1);if(hostport[close+1]===":")port=hostport.slice(close+2)}}else{const colon=hostport.indexOf(":");if(colon!==-1){host=hostport.slice(0,colon);port=hostport.slice(colon+1)}}return{scheme,userinfo,host,port,rest}}function globMatchRedirectUri(pattern,input){const p=splitRedirectUri(pattern);if(!p)return globMatch(pattern,input);const u=splitRedirectUri(input);if(!u)return false;return globMatch(p.scheme,u.scheme)&&globMatch(p.userinfo,u.userinfo)&&globMatch(p.host,u.host)&&globMatch(p.port,u.port)&&globMatch(p.rest,u.rest)}var DcrClientRegistry=class{constructor(config={}){this.config=config;this.redirectGlobs=config.allowedRedirectUris;this.seedPreRegisteredClients()}config;clients=new Map;redirectGlobs;seedPreRegisteredClients(){const clients=this.config.clients??[];const now=Math.floor(Date.now()/1e3);for(const c of clients){this.clients.set(c.clientId,{client_id:c.clientId,client_secret:c.clientSecret,token_endpoint_auth_method:c.tokenEndpointAuthMethod??"none",grant_types:c.grantTypes??["authorization_code"],response_types:c.responseTypes??["code"],redirect_uris:c.redirectUris,client_name:c.clientName,scope:c.scope,created_at:now,dev:false,preRegistered:true})}}get(clientId){return this.clients.get(clientId)}verifyClientSecret(clientId,presentedSecret){const client=this.clients.get(clientId);if(!client)return"unknown";const method=client.token_endpoint_auth_method;const isConfidential=method==="client_secret_basic"||method==="client_secret_post";if(!isConfidential)return"ok";if(!client.client_secret)return"invalid";if(!presentedSecret)return"invalid";return(0,import_utils45.timingSafeEqual)((0,import_utils45.sha256)(presentedSecret),(0,import_utils45.sha256)(client.client_secret))?"ok":"invalid"}has(clientId){return this.clients.has(clientId)}register(client){const cap=this.dynamicClientCap();const dynamicCount=this.countDynamicClients();const isNew=!this.clients.has(client.client_id);if(isNew&&dynamicCount>=cap){return false}this.clients.set(client.client_id,client);return true}dynamicClientCap(){const configured=this.config.maxDynamicClients;return Number.isSafeInteger(configured)&&configured>=0?configured:DEFAULT_MAX_DYNAMIC_CLIENTS}countDynamicClients(){let n=0;for(const c of this.clients.values())if(c.dev&&!c.preRegistered)n++;return n}hasRedirectAllowlist(){return!!this.redirectGlobs&&this.redirectGlobs.length>0}isRedirectUriAllowed(redirectUri){if(!this.redirectGlobs||this.redirectGlobs.length===0){return true}return this.redirectGlobs.some(glob=>globMatchRedirectUri(glob,redirectUri))}hasClientIdAllowlist(){return!!this.config.allowedClientIds&&this.config.allowedClientIds.length>0}isClientIdAllowed(clientId){const allow=this.config.allowedClientIds;if(!allow||allow.length===0){return true}return allow.includes(clientId)}requiresInitialAccessToken(){return typeof this.config.initialAccessToken==="string"&&this.config.initialAccessToken.length>0}verifyInitialAccessToken(presented){const expected=this.config.initialAccessToken;if(!expected){return false}if(typeof presented!=="string"||presented.length===0){return false}return(0,import_utils45.timingSafeEqual)((0,import_utils45.sha256)(presented),(0,import_utils45.sha256)(expected))}};var import_lazy_zod10=require("@frontmcp/lazy-zod");var aiPlatformTypeSchema=import_lazy_zod10.internalZ.enum(["openai","claude","claude-code","codex","gemini","cursor","continue","cody","generic-mcp","ext-apps","unknown"]);var userClaimSchema=import_lazy_zod10.internalZ.object({iss:import_lazy_zod10.internalZ.string(),sid:import_lazy_zod10.internalZ.string().optional(),sub:import_lazy_zod10.internalZ.string(),exp:import_lazy_zod10.internalZ.number().optional(),iat:import_lazy_zod10.internalZ.number().optional(),aud:import_lazy_zod10.internalZ.union([import_lazy_zod10.internalZ.string(),import_lazy_zod10.internalZ.array(import_lazy_zod10.internalZ.string())]).optional(),email:import_lazy_zod10.internalZ.string().optional(),username:import_lazy_zod10.internalZ.string().optional(),preferred_username:import_lazy_zod10.internalZ.string().optional(),name:import_lazy_zod10.internalZ.string().optional(),picture:import_lazy_zod10.internalZ.string().optional()}).passthrough();var sessionIdPayloadSchema=import_lazy_zod10.internalZ.object({nodeId:import_lazy_zod10.internalZ.string(),authSig:import_lazy_zod10.internalZ.string(),uuid:import_lazy_zod10.internalZ.string().uuid(),iat:import_lazy_zod10.internalZ.number(),protocol:import_lazy_zod10.internalZ.enum(["legacy-sse","sse","streamable-http","stateful-http","stateless-http"]).optional(),isPublic:import_lazy_zod10.internalZ.boolean().optional(),platformType:aiPlatformTypeSchema.optional(),clientName:import_lazy_zod10.internalZ.string().optional(),clientVersion:import_lazy_zod10.internalZ.string().optional(),supportsElicitation:import_lazy_zod10.internalZ.boolean().optional(),skillsOnlyMode:import_lazy_zod10.internalZ.boolean().optional()});var sessionIdSchema=import_lazy_zod10.internalZ.object({id:import_lazy_zod10.internalZ.string(),payload:sessionIdPayloadSchema.optional()});var authorizationSchema=import_lazy_zod10.internalZ.object({token:import_lazy_zod10.internalZ.string(),session:sessionIdSchema.optional(),user:userClaimSchema});var import_lazy_zod11=require("@frontmcp/lazy-zod");var publicAuthOptionsSchema=import_lazy_zod11.internalZ.object({mode:import_lazy_zod11.internalZ.literal("public"),issuer:import_lazy_zod11.internalZ.string().optional(),sessionTtl:import_lazy_zod11.internalZ.number().int().positive().default(3600),anonymousScopes:import_lazy_zod11.internalZ.array(import_lazy_zod11.internalZ.string()).default(["anonymous"]),publicAccess:publicAccessConfigSchema.optional(),jwks:jsonWebKeySetSchema.optional(),signKey:jwkSchema.or(import_lazy_zod11.internalZ.instanceof(Uint8Array)).optional()});var import_lazy_zod12=require("@frontmcp/lazy-zod");var staticAuthOptionsSchema=import_lazy_zod12.internalZ.object({mode:import_lazy_zod12.internalZ.literal("static"),tokens:import_lazy_zod12.internalZ.array(import_lazy_zod12.internalZ.string().min(1)).min(1),header:import_lazy_zod12.internalZ.string().min(1).default("authorization"),scheme:import_lazy_zod12.internalZ.string().default("Bearer"),scopes:import_lazy_zod12.internalZ.array(import_lazy_zod12.internalZ.string()).default(["static"]),realm:import_lazy_zod12.internalZ.string().default("mcp"),publicAccess:publicAccessConfigSchema.optional()});var import_lazy_zod13=require("@frontmcp/lazy-zod");var transparentAuthOptionsSchema=import_lazy_zod13.internalZ.object({mode:import_lazy_zod13.internalZ.literal("transparent"),...flatRemoteProviderFields,expectedAudience:import_lazy_zod13.internalZ.union([import_lazy_zod13.internalZ.string(),import_lazy_zod13.internalZ.array(import_lazy_zod13.internalZ.string())]).optional(),requireAudience:import_lazy_zod13.internalZ.boolean().optional(),requiredScopes:import_lazy_zod13.internalZ.array(import_lazy_zod13.internalZ.string()).default([]),allowAnonymous:import_lazy_zod13.internalZ.boolean().default(false),anonymousScopes:import_lazy_zod13.internalZ.array(import_lazy_zod13.internalZ.string()).default(["anonymous"]),publicAccess:publicAccessConfigSchema.optional()});var import_lazy_zod14=require("@frontmcp/lazy-zod");var authSlotSchema=import_lazy_zod14.internalZ.enum(["login","consent","incremental","federated","error"]);var authUiMapSchema=import_lazy_zod14.internalZ.partialRecord(authSlotSchema,import_lazy_zod14.internalZ.string().min(1));var authExtraHandlerSchema=import_lazy_zod14.internalZ.custom(v=>typeof v==="function",{message:"auth.extras entries must be handler functions (input, ctx) => AuthExtraResult."});var authExtrasMapSchema=import_lazy_zod14.internalZ.record(import_lazy_zod14.internalZ.string().min(1),authExtraHandlerSchema);var sharedAuthFields={local:localSigningConfigSchema.optional(),tokenStorage:tokenStorageConfigSchema.default("memory"),secureStore:secureStoreConfigSchema.optional(),allowDefaultPublic:import_lazy_zod14.internalZ.boolean().default(false),anonymousScopes:import_lazy_zod14.internalZ.array(import_lazy_zod14.internalZ.string()).default(["anonymous"]),publicAccess:publicAccessConfigSchema.optional(),consent:consentConfigSchema.optional(),federatedAuth:federatedAuthConfigSchema.optional(),refresh:tokenRefreshConfigSchema.optional(),expectedAudience:import_lazy_zod14.internalZ.union([import_lazy_zod14.internalZ.string(),import_lazy_zod14.internalZ.array(import_lazy_zod14.internalZ.string())]).optional(),incrementalAuth:incrementalAuthConfigSchema.optional(),requireRegisteredClients:import_lazy_zod14.internalZ.boolean().default(true),allowedScopes:import_lazy_zod14.internalZ.array(import_lazy_zod14.internalZ.string().trim().min(1,"allowedScopes entries must be non-empty")).optional(),cimd:cimdConfigSchema.optional(),ui:authUiMapSchema.optional(),extras:authExtrasMapSchema.optional()};var loginFieldSchema=import_lazy_zod14.internalZ.object({type:import_lazy_zod14.internalZ.enum(["text","password","email","select","hidden"]),label:import_lazy_zod14.internalZ.string().optional(),required:import_lazy_zod14.internalZ.boolean().optional(),placeholder:import_lazy_zod14.internalZ.string().optional(),options:import_lazy_zod14.internalZ.array(import_lazy_zod14.internalZ.object({value:import_lazy_zod14.internalZ.string(),label:import_lazy_zod14.internalZ.string()})).optional()});var loginConfigSchema=import_lazy_zod14.internalZ.object({title:import_lazy_zod14.internalZ.string().optional(),subtitle:import_lazy_zod14.internalZ.string().optional(),logoUri:import_lazy_zod14.internalZ.string().optional(),fields:import_lazy_zod14.internalZ.record(import_lazy_zod14.internalZ.string(),loginFieldSchema).optional(),render:import_lazy_zod14.internalZ.custom(v=>typeof v==="function",{message:"login.render must be a function"}).optional(),subject:import_lazy_zod14.internalZ.object({fromField:import_lazy_zod14.internalZ.string().optional(),strategy:import_lazy_zod14.internalZ.enum(["per-session","per-account"]).optional()}).optional()});var authenticateFnSchema=import_lazy_zod14.internalZ.custom(v=>typeof v==="function",{message:"authenticate must be a function"});var localAuthSchema=import_lazy_zod14.internalZ.object({mode:import_lazy_zod14.internalZ.literal("local"),...sharedAuthFields,requireEmail:import_lazy_zod14.internalZ.boolean().default(true),anonymousSubject:import_lazy_zod14.internalZ.string().min(1).default("local-operator"),login:loginConfigSchema.optional(),authenticate:authenticateFnSchema.optional(),providers:import_lazy_zod14.internalZ.array(upstreamProviderSchema).optional(),dcr:localDcrConfigSchema.optional()});var remoteAuthSchema=import_lazy_zod14.internalZ.object({mode:import_lazy_zod14.internalZ.literal("remote"),...flatRemoteProviderFields,...sharedAuthFields});var orchestratedLocalSchema=localAuthSchema;var orchestratedRemoteSchema=remoteAuthSchema;var import_lazy_zod15=require("@frontmcp/lazy-zod");var authOptionsSchema=import_lazy_zod15.internalZ.union([publicAuthOptionsSchema,staticAuthOptionsSchema,transparentAuthOptionsSchema,localAuthSchema,remoteAuthSchema]);var import_lazy_zod16=require("@frontmcp/lazy-zod");var standaloneOptionSchema={standalone:import_lazy_zod16.internalZ.boolean().optional(),excludeFromParent:import_lazy_zod16.internalZ.boolean().optional()};var appAuthOptionsSchema=import_lazy_zod16.internalZ.union([publicAuthOptionsSchema.extend(standaloneOptionSchema),transparentAuthOptionsSchema.extend(standaloneOptionSchema),localAuthSchema.extend(standaloneOptionSchema),remoteAuthSchema.extend(standaloneOptionSchema)]);function parseAuthOptions(input){return authOptionsSchema.parse(input)}function isPublicMode(options){return options.mode==="public"}function isStaticMode(options){return options.mode==="static"}function isTransparentMode(options){return options.mode==="transparent"}function isLocalMode(options){return options.mode==="local"}function isRemoteMode(options){return options.mode==="remote"}function isOrchestratedMode(options){return options.mode==="local"||options.mode==="remote"}function isOrchestratedLocal(options){return options.mode==="local"}function isOrchestratedRemote(options){return options.mode==="remote"}function allowsPublicAccess(options){if(options.mode==="public")return true;if(options.mode==="transparent")return options.allowAnonymous;if(options.mode==="local"||options.mode==="remote")return options.allowDefaultPublic;return false}var import_lazy_zod17=require("@frontmcp/lazy-zod");var consentToolItemSchema=import_lazy_zod17.internalZ.object({id:import_lazy_zod17.internalZ.string().min(1),name:import_lazy_zod17.internalZ.string().min(1),description:import_lazy_zod17.internalZ.string().optional(),appId:import_lazy_zod17.internalZ.string().min(1),appName:import_lazy_zod17.internalZ.string().min(1),defaultSelected:import_lazy_zod17.internalZ.boolean().default(true),requiredScopes:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()).optional(),category:import_lazy_zod17.internalZ.string().optional()});var consentSelectionSchema=import_lazy_zod17.internalZ.object({selectedTools:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()),allSelected:import_lazy_zod17.internalZ.boolean(),consentedAt:import_lazy_zod17.internalZ.string().datetime(),consentVersion:import_lazy_zod17.internalZ.string().default("1.0")});var consentStateSchema=import_lazy_zod17.internalZ.object({enabled:import_lazy_zod17.internalZ.boolean(),availableTools:import_lazy_zod17.internalZ.array(consentToolItemSchema),preselectedTools:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()).optional(),groupByApp:import_lazy_zod17.internalZ.boolean().default(true),customMessage:import_lazy_zod17.internalZ.string().optional()});var federatedProviderItemSchema=import_lazy_zod17.internalZ.object({id:import_lazy_zod17.internalZ.string().min(1),name:import_lazy_zod17.internalZ.string().min(1),description:import_lazy_zod17.internalZ.string().optional(),icon:import_lazy_zod17.internalZ.string().optional(),type:import_lazy_zod17.internalZ.enum(["local","remote","transparent"]),providerUrl:import_lazy_zod17.internalZ.string().url().optional(),appIds:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()),appNames:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()),scopes:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()),isPrimary:import_lazy_zod17.internalZ.boolean(),isOptional:import_lazy_zod17.internalZ.boolean().default(false)});var federatedLoginStateSchema=import_lazy_zod17.internalZ.object({providers:import_lazy_zod17.internalZ.array(federatedProviderItemSchema),primaryProviderId:import_lazy_zod17.internalZ.string().optional(),allowSkip:import_lazy_zod17.internalZ.boolean().default(true),preselectedProviders:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()).optional()});var federatedSelectionSchema=import_lazy_zod17.internalZ.object({selectedProviders:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()),skippedProviders:import_lazy_zod17.internalZ.array(import_lazy_zod17.internalZ.string()),providerMetadata:import_lazy_zod17.internalZ.record(import_lazy_zod17.internalZ.string(),import_lazy_zod17.internalZ.unknown()).optional()});var import_lazy_zod18=require("@frontmcp/lazy-zod");var detectedAuthProviderSchema=import_lazy_zod18.internalZ.object({id:import_lazy_zod18.internalZ.string(),providerUrl:import_lazy_zod18.internalZ.string().optional(),mode:import_lazy_zod18.internalZ.enum(["public","static","transparent","local","remote"]),appIds:import_lazy_zod18.internalZ.array(import_lazy_zod18.internalZ.string()),scopes:import_lazy_zod18.internalZ.array(import_lazy_zod18.internalZ.string()),isParentProvider:import_lazy_zod18.internalZ.boolean()});var authProviderDetectionResultSchema=import_lazy_zod18.internalZ.object({providers:import_lazy_zod18.internalZ.map(import_lazy_zod18.internalZ.string(),detectedAuthProviderSchema),requiresOrchestration:import_lazy_zod18.internalZ.boolean(),parentProviderId:import_lazy_zod18.internalZ.string().optional(),childProviderIds:import_lazy_zod18.internalZ.array(import_lazy_zod18.internalZ.string()),uniqueProviderCount:import_lazy_zod18.internalZ.number(),validationErrors:import_lazy_zod18.internalZ.array(import_lazy_zod18.internalZ.string()),warnings:import_lazy_zod18.internalZ.array(import_lazy_zod18.internalZ.string())});function deriveProviderId(options){if(isPublicMode(options)){return options.issuer??"public"}if(isTransparentMode(options)){return options.providerConfig?.id??urlToProviderId(options.provider)}if(isOrchestratedMode(options)){if(isOrchestratedRemote(options)){return options.providerConfig?.id??urlToProviderId(options.provider)}return options.local?.issuer??"local"}return"unknown"}function urlToProviderId(url){try{const parsed=new URL(url);return parsed.hostname.replace(/\./g,"_")}catch{return url.replace(/[^a-zA-Z0-9]/g,"_")}}function extractScopes(options){if(isTransparentMode(options)){return options.requiredScopes||[]}if(isOrchestratedMode(options)){if(isOrchestratedRemote(options)){return options.scopes||[]}}return[]}function detectAuthProviders(parentAuth,apps){const providers=new Map;const validationErrors=[];const warnings=[];let parentProviderId;if(parentAuth){parentProviderId=deriveProviderId(parentAuth);providers.set(parentProviderId,{id:parentProviderId,providerUrl:getProviderUrl(parentAuth),mode:parentAuth.mode,appIds:["__parent__"],scopes:extractScopes(parentAuth),isParentProvider:true})}for(const app of apps){if(!app.auth){continue}const providerId=deriveProviderId(app.auth);const existing=providers.get(providerId);if(existing){existing.appIds.push(app.id);const newScopes=extractScopes(app.auth);existing.scopes=[...new Set([...existing.scopes,...newScopes])]}else{providers.set(providerId,{id:providerId,providerUrl:getProviderUrl(app.auth),mode:app.auth.mode,appIds:[app.id],scopes:extractScopes(app.auth),isParentProvider:false})}}const childProviderIds=[...providers.keys()].filter(id=>id!==parentProviderId);const uniqueProviderCount=providers.size;const hasMultipleProviders=uniqueProviderCount>1;const hasChildOnlyProviders=childProviderIds.length>0&&!parentProviderId;const requiresOrchestration=hasMultipleProviders||hasChildOnlyProviders||childProviderIds.length>0&&parentProviderId!==void 0;if(requiresOrchestration&&parentAuth&&isTransparentMode(parentAuth)){validationErrors.push(`Invalid auth configuration: Parent uses transparent mode but apps have their own auth providers. Transparent mode passes tokens through without modification, which is incompatible with multi-provider setups. Change parent auth to local or remote mode to properly manage tokens for each provider. Detected providers: ${[...providers.keys()].join(", ")}`)}const sharedEndpointUnenforced=!parentAuth||isPublicMode(parentAuth)||isStaticMode(parentAuth);const unenforcedAppIds=apps.filter(app=>app.auth&&!isPublicMode(app.auth)&&!staticParentEnforces(parentAuth,app.auth)).map(app=>app.id);if(sharedEndpointUnenforced&&unenforcedAppIds.length>0){validationErrors.push(`App-level auth is not enforced on the shared endpoint of a server in ${parentAuth?.mode??"public"} mode, so the tools of ${unenforcedAppIds.join(", ")} would be served without it. Serve the app on its own endpoint with standalone: true or splitByApp: true, or run the server in local or remote mode with incrementalAuth enabled, which checks each tool call against the apps the caller has authorized (without incrementalAuth, local and remote mode do not check app grants per tool call).`)}const tokenMintingAppIds=apps.filter(app=>app.remoteAuthMode==="forward"&&!(parentAuth&&isTransparentMode(parentAuth))).map(app=>app.id);if(tokenMintingAppIds.length>0){validationErrors.push(`remoteAuth: { mode: 'forward' } on ${tokenMintingAppIds.join(", ")} would send the remote a token this server minted or holds itself: only a server in transparent mode receives its callers' tokens from the identity provider. Use remoteAuth: { mode: 'static', credentials } (or transportOptions.headers) for the remote, or run the server in transparent mode.`)}return{providers,requiresOrchestration,parentProviderId,childProviderIds,uniqueProviderCount,validationErrors,warnings}}function staticParentEnforces(parentAuth,appAuth){if(!parentAuth||!isStaticMode(parentAuth)||!isStaticMode(appAuth))return false;const parent=staticAuthOptionsSchema.safeParse(parentAuth);const app=staticAuthOptionsSchema.safeParse(appAuth);if(!parent.success||!app.success)return false;const sameChallenge=parent.data.header.toLowerCase()===app.data.header.toLowerCase()&&parent.data.scheme===app.data.scheme;return sameChallenge&&parent.data.tokens.every(token=>app.data.tokens.includes(token))}function getProviderUrl(options){if(isTransparentMode(options)){return options.provider}if(isOrchestratedMode(options)&&isOrchestratedRemote(options)){return options.provider}return void 0}function appRequiresOrchestration(appAuth,parentAuth){if(!appAuth){return false}if(!parentAuth){return appAuth.mode!=="public"}const appProviderId=deriveProviderId(appAuth);const parentProviderId=deriveProviderId(parentAuth);return appProviderId!==parentProviderId}function getProviderScopes(detection,providerId){const provider=detection.providers.get(providerId);return provider?.scopes??[]}function getProviderApps(detection,providerId){const provider=detection.providers.get(providerId);return provider?.appIds.filter(id=>id!=="__parent__")??[]}function buildWwwAuthenticate(options={}){const parts=["Bearer"];const params=[];if(options.resourceMetadataUrl){params.push(`resource_metadata="${escapeQuotedString(options.resourceMetadataUrl)}"`)}if(options.realm){params.push(`realm="${escapeQuotedString(options.realm)}"`)}if(options.error){params.push(`error="${options.error}"`)}if(options.errorDescription){params.push(`error_description="${escapeQuotedString(options.errorDescription)}"`)}if(options.errorUri){params.push(`error_uri="${escapeQuotedString(options.errorUri)}"`)}if(options.scope){const scopeValue=Array.isArray(options.scope)?options.scope.join(" "):options.scope;params.push(`scope="${escapeQuotedString(scopeValue)}"`)}if(params.length>0){parts.push(params.join(", "))}return parts.join(" ")}function buildPrmUrl(baseUrl,entryPath,routeBase){const normalizedEntry=normalizePathSegment(entryPath);const normalizedRoute=normalizePathSegment(routeBase);return`${baseUrl}/.well-known/oauth-protected-resource${normalizedEntry}${normalizedRoute}`}function buildUnauthorizedHeader(prmUrl){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl})}function buildInvalidTokenHeader(prmUrl,description){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl,error:"invalid_token",errorDescription:description??"The access token is invalid or expired"})}function buildInsufficientScopeHeader(prmUrl,requiredScopes,description){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl,error:"insufficient_scope",scope:requiredScopes,errorDescription:description??"The request requires higher privileges"})}function buildInvalidRequestHeader(prmUrl,description){return buildWwwAuthenticate({resourceMetadataUrl:prmUrl,error:"invalid_request",errorDescription:description??"The request is missing required parameters"})}function parseWwwAuthenticate(header){const result={};if(!header.toLowerCase().startsWith("bearer")){return result}const paramString=header.substring(6).trim();const params=parseQuotedParams(paramString);for(const[key,value]of params){const unescapedValue=unescapeQuotedString(value);switch(key.toLowerCase()){case"resource_metadata":result.resourceMetadataUrl=unescapedValue;break;case"realm":result.realm=unescapedValue;break;case"error":result.error=unescapedValue;break;case"error_description":result.errorDescription=unescapedValue;break;case"error_uri":result.errorUri=unescapedValue;break;case"scope":result.scope=unescapedValue;break}}return result}function parseQuotedParams(input){const result=[];let i=0;const len=input.length;while(i<len){while(i<len&&(input[i]===" "||input[i]===","||input[i]===" ")){i++}if(i>=len)break;const keyStart=i;while(i<len&&/\w/.test(input[i])){i++}const key=input.slice(keyStart,i);if(!key)break;while(i<len&&(input[i]===" "||input[i]===" ")){i++}if(i>=len||input[i]!=="="){while(i<len&&input[i]!==",")i++;continue}i++;while(i<len&&(input[i]===" "||input[i]===" ")){i++}if(i>=len||input[i]!=='"'){while(i<len&&input[i]!==",")i++;continue}i++;let value="";while(i<len&&input[i]!=='"'){if(input[i]==="\\"&&i+1<len){value+=input[i+1];i+=2}else{value+=input[i];i++}}if(i<len&&input[i]==='"'){i++}result.push([key,value])}return result}function escapeQuotedString(value){return value.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function unescapeQuotedString(value){return value.replace(/\\(.)/g,"$1")}function normalizePathSegment(path){if(!path||path==="/")return"";const normalized=path.startsWith("/")?path:`/${path}`;let end=normalized.length;while(end>0&&normalized[end-1]==="/"){end--}return normalized.slice(0,end)}function validateAudience(tokenAudience,options){const{expectedAudiences,allowNoAudience=false,caseSensitive=true,allowWildcards=false}=options;if(tokenAudience===void 0||tokenAudience===null){if(allowNoAudience){return{valid:true}}return{valid:false,error:"Token is missing audience claim"}}if(expectedAudiences.length===0){return{valid:false,error:"No expected audiences configured - cannot validate token"}}const tokenAuds=Array.isArray(tokenAudience)?tokenAudience:[tokenAudience];for(const tokenAud of tokenAuds){for(const expectedAud of expectedAudiences){if(matchesAudience(tokenAud,expectedAud,caseSensitive,allowWildcards)){return{valid:true,matchedAudience:tokenAud}}}}return{valid:false,error:`Token audience does not match expected audiences. Got: ${tokenAuds.join(", ")}. Expected one of: ${expectedAudiences.join(", ")}`}}function matchesAudience(tokenAud,expectedAud,caseSensitive,allowWildcards){if(caseSensitive){if(tokenAud===expectedAud)return true}else{if(tokenAud.toLowerCase()===expectedAud.toLowerCase())return true}if(allowWildcards&&expectedAud.includes("*")){const wildcardCount=(expectedAud.match(/\*/g)||[]).length;if(wildcardCount>2){return false}const pattern=expectedAud.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^.]*");const regex=new RegExp(`^${pattern}$`,caseSensitive?"":"i");if(regex.test(tokenAud))return true}return false}function createAudienceValidator(options){return audience=>validateAudience(audience,options)}function deriveExpectedAudience(resourceUrl){const audiences=[];try{const url=new URL(resourceUrl);audiences.push(resourceUrl.replace(/\/$/,""));if(url.pathname!=="/"&&url.pathname!==""){audiences.push(url.origin)}}catch{audiences.push(resourceUrl)}return[...new Set(audiences)]}var AudienceValidator=class _AudienceValidator{options;constructor(options={}){this.options={expectedAudiences:[...options.expectedAudiences??[]],allowNoAudience:options.allowNoAudience??false,caseSensitive:options.caseSensitive??true,allowWildcards:options.allowWildcards??false}}validate(audience){return validateAudience(audience,this.options)}addAudiences(...audiences){this.options.expectedAudiences.push(...audiences)}setAudiences(audiences){this.options.expectedAudiences=audiences}static fromResourceUrl(resourceUrl,options={}){return new _AudienceValidator({...options,expectedAudiences:deriveExpectedAudience(resourceUrl)})}};var DEFAULT_ALLOWED_SCOPES=Object.freeze(["openid","profile","email","offline_access"]);function grantScopes(requested,allowed){const patterns=allowed??DEFAULT_ALLOWED_SCOPES;const granted=[];for(const scope of requested){if(!scope||granted.includes(scope))continue;if(patterns.some(pattern=>globMatch(pattern,scope)))granted.push(scope)}return granted}function advertisedScopes(allowed){const scopes=[];for(const scope of allowed??DEFAULT_ALLOWED_SCOPES){if(scope&&!scope.includes("*")&&!scopes.includes(scope))scopes.push(scope)}return scopes}function resourceScopesFor(options){const mode=options?.mode??"public";if(mode==="local"||mode==="remote")return advertisedScopes(options?.allowedScopes);const listed=mode==="public"?options?.anonymousScopes??["anonymous"]:mode==="static"?options?.scopes??["static"]:mode==="transparent"?[...options?.requiredScopes??[],...options?.scopes??[]]:[];return advertisedScopes(listed)}function isLoopbackRedirectUri(uri){let url;try{url=new URL(uri)}catch{return false}if(url.protocol!=="http:"&&url.protocol!=="https:")return false;if(url.username||url.password)return false;const host=url.hostname.replace(/^\[|\]$/g,"").toLowerCase();if(host==="localhost"||host==="::1")return true;const m=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);if(m){const octets=m.slice(1).map(n=>Number(n));return octets.every(o=>o>=0&&o<=255)&&octets[0]===127}return false}function scopesFromClaims(claims){const scopes=[claims?.scope,claims?.scp].flatMap(claim=>{if(typeof claim==="string")return claim.split(/\s+/).filter(Boolean);if(Array.isArray(claim))return claim.filter(scope=>typeof scope==="string");return[]});return[...new Set(scopes)]}var import_lazy_zod19=require("@frontmcp/lazy-zod");var credentialScopeSchema=import_lazy_zod19.internalZ.enum(["global","user","session"]);var loadingStrategySchema=import_lazy_zod19.internalZ.enum(["eager","lazy"]);var getCredentialOptionsSchema=import_lazy_zod19.internalZ.object({forceRefresh:import_lazy_zod19.internalZ.boolean().optional(),scopes:import_lazy_zod19.internalZ.array(import_lazy_zod19.internalZ.string()).optional(),timeout:import_lazy_zod19.internalZ.number().positive().optional()}).strict();var credentialProviderConfigSchema=import_lazy_zod19.internalZ.object({name:import_lazy_zod19.internalZ.string().min(1),description:import_lazy_zod19.internalZ.string().optional(),scope:credentialScopeSchema,loading:loadingStrategySchema,cacheTtl:import_lazy_zod19.internalZ.number().nonnegative().optional(),factory:import_lazy_zod19.internalZ.any(),refresh:import_lazy_zod19.internalZ.any().optional(),toHeaders:import_lazy_zod19.internalZ.any().optional(),metadata:import_lazy_zod19.internalZ.record(import_lazy_zod19.internalZ.string(),import_lazy_zod19.internalZ.unknown()).optional(),required:import_lazy_zod19.internalZ.boolean().optional()}).strict();var authProviderMappingSchema=import_lazy_zod19.internalZ.union([import_lazy_zod19.internalZ.string(),import_lazy_zod19.internalZ.object({name:import_lazy_zod19.internalZ.string().min(1),required:import_lazy_zod19.internalZ.boolean().optional().default(true),scopes:import_lazy_zod19.internalZ.array(import_lazy_zod19.internalZ.string()).optional(),alias:import_lazy_zod19.internalZ.string().optional()}).strict()]);var authProvidersVaultOptionsSchema=import_lazy_zod19.internalZ.object({enabled:import_lazy_zod19.internalZ.boolean().optional(),useSharedStorage:import_lazy_zod19.internalZ.boolean().optional().default(true),namespace:import_lazy_zod19.internalZ.string().optional().default("authproviders:"),defaultCacheTtl:import_lazy_zod19.internalZ.number().nonnegative().optional().default(36e5),maxCredentialsPerSession:import_lazy_zod19.internalZ.number().positive().optional().default(100),providers:import_lazy_zod19.internalZ.array(credentialProviderConfigSchema).optional()}).strict();function extractCredentialExpiry(credential){switch(credential.type){case"oauth":case"oauth_pkce":case"bearer":case"service_account":return credential.expiresAt;default:return void 0}}var CredentialCache=class{cache=new Map;maxSize;stats={hits:0,misses:0,evictions:0,size:0};constructor(maxSize=100){this.maxSize=maxSize}get(providerId){const entry=this.cache.get(providerId);if(!entry){this.stats.misses++;return void 0}if(this.isExpired(entry)){this.cache.delete(providerId);this.stats.size=this.cache.size;this.stats.misses++;this.stats.evictions++;return void 0}if(entry.resolved.expiresAt&&Date.now()>=entry.resolved.expiresAt){this.cache.delete(providerId);this.stats.size=this.cache.size;this.stats.misses++;this.stats.evictions++;return void 0}this.stats.hits++;return entry.resolved}set(providerId,resolved,ttl=0){if(this.cache.size>=this.maxSize&&!this.cache.has(providerId)){this.evictOldest()}const entry={resolved,cachedAt:Date.now(),ttl};this.cache.set(providerId,entry);this.stats.size=this.cache.size}has(providerId){const entry=this.cache.get(providerId);if(!entry)return false;if(this.isExpired(entry)){this.cache.delete(providerId);this.stats.size=this.cache.size;this.stats.evictions++;return false}return true}invalidate(providerId){const deleted=this.cache.delete(providerId);if(deleted){this.stats.size=this.cache.size}return deleted}invalidateAll(){this.cache.clear();this.stats.size=0}invalidateByScope(scope){for(const[key,entry]of this.cache){if(entry.resolved.scope===scope){this.cache.delete(key)}}this.stats.size=this.cache.size}keys(){this.cleanup();return[...this.cache.keys()]}get size(){return this.cache.size}getStats(){return{...this.stats}}resetStats(){this.stats={hits:0,misses:0,evictions:0,size:this.cache.size}}cleanup(){const now=Date.now();for(const[key,entry]of this.cache){if(this.isExpiredAt(entry,now)){this.cache.delete(key);this.stats.evictions++}}this.stats.size=this.cache.size}isExpired(entry){return this.isExpiredAt(entry,Date.now())}isExpiredAt(entry,now){if(entry.ttl>0&&now-entry.cachedAt>=entry.ttl){return true}if(entry.resolved.expiresAt&&now>=entry.resolved.expiresAt){return true}if(!entry.resolved.isValid){return true}return false}evictOldest(){let oldestKey;let oldestTime=Infinity;for(const[key,entry]of this.cache){if(entry.cachedAt<oldestTime){oldestTime=entry.cachedAt;oldestKey=key}}if(oldestKey){this.cache.delete(oldestKey);this.stats.evictions++;this.stats.size=this.cache.size}}};var AUTH_PROVIDERS_ACCESSOR=Symbol.for("frontmcp:AUTH_PROVIDERS_ACCESSOR");var import_utils48=require("@frontmcp/utils");var AuthProvidersAccessorImpl=class{constructor(registry,vault,cache,loader,context,logger){this.registry=registry;this.vault=vault;this.cache=cache;this.loader=loader;this.context=context;this.logger=logger}registry;vault;cache;loader;context;logger;async get(providerName,options){const config=this.registry.get(providerName);if(!config){this.logger?.debug(`Provider "${providerName}" is not registered`);return null}if(!options?.forceRefresh){const cached=this.cache.get(providerName);if(cached&&this.isValid(cached)){this.logger?.debug(`Cache hit for "${providerName}"`);return cached}}if(!options?.forceRefresh){const fromVault=await this.loadFromVault(providerName,config);if(fromVault&&this.isValid(fromVault)){this.cache.set(providerName,fromVault,config.cacheTtl);this.logger?.debug(`Vault hit for "${providerName}"`);return fromVault}}const loaded=await this.loader.load(config,this.context);if(!loaded){return null}await this.storeInVault(providerName,loaded,config);this.cache.set(providerName,loaded,config.cacheTtl);return loaded}async getMany(providerNames,options){const results=new Map;const promises=providerNames.map(async name=>{const result=await this.get(name,options);return{name,result}});const settled=await Promise.allSettled(promises);for(const outcome of settled){if(outcome.status==="fulfilled"){results.set(outcome.value.name,outcome.value.result)}else{this.logger?.warn("Failed to load credential:",outcome.reason)}}return results}async headers(providerName){const resolved=await this.get(providerName);if(!resolved){return{}}const config=this.registry.get(providerName);if(config?.toHeaders){return config.toHeaders(resolved.credential)}return this.defaultHeaders(resolved.credential)}async headersMany(providerNames){const allHeaders={};for(const name of providerNames){const headers=await this.headers(name);Object.assign(allHeaders,headers)}return allHeaders}async refresh(providerName){const config=this.registry.get(providerName);if(!config){this.logger?.debug(`Cannot refresh: provider "${providerName}" not registered`);return null}const existing=this.cache.get(providerName);const existingCredential=existing?.credential;try{const refreshed=await this.loader.refresh(config,{...this.context,existingCredential});if(!refreshed){return null}await this.storeInVault(providerName,refreshed,config);this.cache.set(providerName,refreshed,config.cacheTtl);return refreshed}catch(error){this.logger?.warn(`Failed to refresh credential "${providerName}":`,error);return null}}async has(providerName){const cached=this.cache.get(providerName);if(cached){if(this.isValid(cached)){return true}this.cache.invalidate(providerName)}const config=this.registry.get(providerName);if(!config){return false}const fromVault=await this.loadFromVault(providerName,config);return fromVault!==null&&this.isValid(fromVault)}isRegistered(providerName){return this.registry.has(providerName)}invalidate(providerName){this.cache.invalidate(providerName);this.logger?.debug(`Invalidated cache for "${providerName}"`)}invalidateAll(){this.cache.invalidateAll();this.logger?.debug("Invalidated all cached credentials")}listProviders(){return this.registry.getNames()}async listAvailable(){const available=[];for(const name of this.registry.getNames()){if(await this.has(name)){available.push(name)}}return available}async loadFromVault(providerName,config){try{const credential=await this.vault.getCredential(this.context.sessionId,providerName,config.scope,this.context.userSub);if(!credential){return null}return{credential,providerId:providerName,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope}}catch(error){this.logger?.warn(`Failed to load from vault "${providerName}":`,error);return null}}async storeInVault(providerName,resolved,config){try{await this.vault.storeCredential(this.context.sessionId,providerName,resolved.credential,config.scope,this.context.userSub)}catch(error){this.logger?.warn(`Failed to store in vault "${providerName}":`,error)}}isValid(resolved){if(!resolved.isValid){return false}if(resolved.expiresAt&&Date.now()>=resolved.expiresAt){return false}return true}defaultHeaders(credential){switch(credential.type){case"oauth":case"oauth_pkce":return{Authorization:`${credential.tokenType} ${credential.accessToken}`};case"bearer":return{Authorization:`Bearer ${credential.token}`};case"api_key":if(credential.headerPrefix){return{[credential.headerName]:`${credential.headerPrefix}${credential.key}`}}return{[credential.headerName]:credential.key};case"basic":{const value=`${credential.username}:${credential.password}`;const encoded=credential.encodedValue??(0,import_utils48.base64Encode)(new TextEncoder().encode(value));return{Authorization:`Basic ${encoded}`}}case"custom":return credential.headers??{};case"ssh_key":case"mtls":case"private_key":case"service_account":return{};default:return{}}}};var AuthProvidersRegistry=class{providers=new Map;defaultCacheTtl;constructor(options){this.defaultCacheTtl=options?.defaultCacheTtl??36e5;if(options?.providers){for(const provider of options.providers){this.register(provider)}}}register(config){if(this.providers.has(config.name)){throw new CredentialProviderAlreadyRegisteredError(config.name)}const normalized=this.normalize(config);this.providers.set(config.name,normalized)}unregister(name){return this.providers.delete(name)}get(name){return this.providers.get(name)}has(name){return this.providers.has(name)}getNames(){return[...this.providers.keys()]}getAll(){return[...this.providers.values()]}getByScope(scope){return this.getAll().filter(p=>p.scope===scope)}getByLoading(loading){return this.getAll().filter(p=>p.loading===loading)}getRequired(){return this.getAll().filter(p=>p.required)}getEager(){return this.getByLoading("eager")}getLazy(){return this.getByLoading("lazy")}get size(){return this.providers.size}isEmpty(){return this.providers.size===0}clear(){this.providers.clear()}normalize(config){return{name:config.name,description:config.description,scope:config.scope,loading:config.loading,cacheTtl:config.cacheTtl??this.defaultCacheTtl,factory:config.factory,refresh:config.refresh,toHeaders:config.toHeaders,metadata:config.metadata,required:config.required??false}}};var AUTH_PROVIDERS_REGISTRY=Symbol.for("frontmcp:AUTH_PROVIDERS_REGISTRY");var AuthProvidersVault=class{constructor(baseVault,namespace="authproviders:",logger){this.baseVault=baseVault;this.namespace=namespace;this.logger=logger}baseVault;namespace;logger;async storeCredential(sessionId,providerId,credential,scope,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);const appCredential={appId:this.namespace,providerId,credential,acquiredAt:Date.now(),isValid:true,expiresAt:extractCredentialExpiry(credential)};try{await this.baseVault.addAppCredential(vaultKey,appCredential);this.logger?.debug(`Stored credential "${providerId}" with scope "${scope}"`)}catch(error){this.logger?.warn(`Failed to store credential "${providerId}":`,error);throw error}}async getCredential(sessionId,providerId,scope,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{const appCredential=await this.baseVault.getCredential(vaultKey,this.namespace,providerId);if(!appCredential){return null}if(!appCredential.isValid){this.logger?.debug(`Credential "${providerId}" is marked as invalid`);return null}if(appCredential.expiresAt&&Date.now()>=appCredential.expiresAt){this.logger?.debug(`Credential "${providerId}" has expired`);return null}return appCredential.credential}catch(error){this.logger?.warn(`Failed to get credential "${providerId}":`,error);if(error instanceof CredentialStorageError){throw error}throw new CredentialStorageError(`Storage error while retrieving credential "${providerId}": ${error instanceof Error?error.message:String(error)}`)}}async removeCredential(sessionId,providerId,scope,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{await this.baseVault.removeAppCredential(vaultKey,this.namespace,providerId);this.logger?.debug(`Removed credential "${providerId}"`)}catch(error){this.logger?.warn(`Failed to remove credential "${providerId}":`,error)}}async invalidateCredential(sessionId,providerId,scope,reason,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{await this.baseVault.invalidateCredential(vaultKey,this.namespace,providerId,reason);this.logger?.debug(`Invalidated credential "${providerId}": ${reason}`)}catch(error){this.logger?.warn(`Failed to invalidate credential "${providerId}":`,error)}}async refreshOAuthCredential(sessionId,providerId,scope,tokens,userId){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{await this.baseVault.refreshOAuthCredential(vaultKey,this.namespace,providerId,tokens);this.logger?.debug(`Refreshed OAuth credential "${providerId}"`)}catch(error){this.logger?.warn(`Failed to refresh OAuth credential "${providerId}":`,error);throw error}}async getAllCredentials(sessionId,scope,userId){if(scope){const vaultKey=this.buildVaultKey(sessionId,scope,userId);try{return await this.baseVault.getAppCredentials(vaultKey,this.namespace)}catch{return[]}}const credentials=[];try{const sessionCreds=await this.baseVault.getAppCredentials(this.buildVaultKey(sessionId,"session"),this.namespace);credentials.push(...sessionCreds)}catch{}if(userId){try{const userCreds=await this.baseVault.getAppCredentials(this.buildVaultKey(sessionId,"user",userId),this.namespace);credentials.push(...userCreds)}catch{}}try{const globalCreds=await this.baseVault.getAppCredentials(this.buildVaultKey(sessionId,"global"),this.namespace);credentials.push(...globalCreds)}catch{}return credentials}buildVaultKey(sessionId,scope,userId){switch(scope){case"global":return`${this.namespace}global`;case"user":if(!userId){throw new AuthInvalidInputError(`userId is required for user-scoped credentials (namespace: ${this.namespace})`)}return`${this.namespace}user:${userId}`;case"session":return`${this.namespace}session:${sessionId}`;default:{const _exhaustive=scope;throw new AuthInvalidInputError(`Unknown credential scope: ${_exhaustive}`)}}}};var AUTH_PROVIDERS_VAULT=Symbol.for("frontmcp:AUTH_PROVIDERS_VAULT");var EagerCredentialLoader=class{constructor(registry,cache,logger){this.registry=registry;this.cache=cache;this.logger=logger}registry;cache;logger;async loadForSession(context){const startTime=Date.now();const eagerProviders=this.registry.getEager();if(eagerProviders.length===0){return{loaded:new Map,failed:new Map,duration:Date.now()-startTime}}this.logger?.debug(`Loading ${eagerProviders.length} eager credential providers`);const loaded=new Map;const failed=new Map;const results=await Promise.allSettled(eagerProviders.map(async config=>{const credential=await this.loadOne(config,context);return{name:config.name,credential,config}}));for(const result of results){if(result.status==="fulfilled"){const{name,credential,config}=result.value;if(credential){const resolved=this.wrapCredential(name,credential,config);loaded.set(name,resolved);this.cache.set(name,resolved,config.cacheTtl);this.logger?.debug(`Loaded eager credential: ${name}`)}else if(config.required){failed.set(name,new Error(`Required credential "${name}" returned null`));this.logger?.warn(`Required eager credential "${name}" returned null`)}}else{const providerName=result.reason?.providerName||"unknown";const error=result.reason instanceof Error?result.reason:new Error(String(result.reason));failed.set(providerName,error);this.logger?.warn(`Failed to load eager credential "${providerName}":`,error.message)}}const duration=Date.now()-startTime;this.logger?.debug(`Eager loading complete: ${loaded.size} loaded, ${failed.size} failed, ${duration}ms`);return{loaded,failed,duration}}async loadOne(config,context){try{return await config.factory({...context,metadata:config.metadata})}catch(error){error.providerName=config.name;throw error}}wrapCredential(providerId,credential,config){return{credential,providerId,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope}}};var LazyCredentialLoader=class{constructor(logger){this.logger=logger}logger;loading=new Map;async load(config,context){const existing=this.loading.get(config.name);if(existing){this.logger?.debug(`Waiting for in-flight load: ${config.name}`);return existing}const promise=this.doLoad(config,context);this.loading.set(config.name,promise);try{return await promise}finally{this.loading.delete(config.name)}}async doLoad(config,context){const startTime=Date.now();this.logger?.debug(`Loading lazy credential: ${config.name}`);try{const credential=await config.factory({...context,metadata:config.metadata});if(!credential){this.logger?.debug(`Lazy credential "${config.name}" returned null`);return null}const resolved={credential,providerId:config.name,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope};const duration=Date.now()-startTime;this.logger?.debug(`Loaded lazy credential "${config.name}" in ${duration}ms`);return resolved}catch(error){const duration=Date.now()-startTime;this.logger?.warn(`Failed to load lazy credential "${config.name}" after ${duration}ms:`,error);throw error}}async refresh(config,context){const startTime=Date.now();this.logger?.debug(`Refreshing credential: ${config.name}`);try{let credential;if(config.refresh){credential=await config.refresh(context)}else{credential=await config.factory(context)}if(!credential){this.logger?.debug(`Credential refresh "${config.name}" returned null`);return null}const resolved={credential,providerId:config.name,acquiredAt:Date.now(),expiresAt:extractCredentialExpiry(credential),isValid:true,scope:config.scope};const duration=Date.now()-startTime;this.logger?.debug(`Refreshed credential "${config.name}" in ${duration}ms`);return resolved}catch(error){const duration=Date.now()-startTime;this.logger?.warn(`Failed to refresh credential "${config.name}" after ${duration}ms:`,error);throw error}}isLoading(name){return this.loading.has(name)}cancelAll(){this.loading.clear()}};var import_utils49=require("@frontmcp/utils");function resolveDotPath(obj,path){if(path in obj){return obj[path]}const segments=path.split(".");let current=obj;for(const segment of segments){if(current===null||current===void 0||typeof current!=="object"){return void 0}current=current[segment]}return current}function toStringArray(value){if(Array.isArray(value)){return value.filter(v=>typeof v==="string")}if(typeof value==="string"){return value.split(/\s+/).filter(Boolean)}return[]}var noopRelationshipResolver={async check(){return false}};function resolveAuthUser(authInfo){const extraUser=authInfo?.extra?.["user"];if(authInfo?.user)return authInfo.user;return typeof extraUser==="object"&&extraUser!==null?extraUser:{}}function isAnonymousSubject(sub){return typeof sub!=="string"||sub===""||sub.startsWith("anon:")}function signedInSubject(rawSub,mappedSub){if(rawSub!==void 0&&isAnonymousSubject(rawSub))return void 0;return[mappedSub,rawSub].find(candidate=>!isAnonymousSubject(candidate))}var runtimeEnv=new Proxy({},{get:(_target,name)=>typeof name==="string"?(0,import_utils49.getEnv)(name):void 0});var AuthoritiesContextBuilder=class{claimsMapping;claimsResolver;relationshipResolver;constructor(options={}){this.claimsMapping=options.claimsMapping;this.claimsResolver=options.claimsResolver;this.relationshipResolver=options.relationshipResolver??noopRelationshipResolver}build(authInfo,input={},env=runtimeEnv){if(this.claimsResolver){const resolved=this.claimsResolver(authInfo);return{user:{sub:signedInSubject(resolveAuthUser(authInfo).sub),roles:resolved.roles,permissions:resolved.permissions,claims:resolved.claims},input,env,relationships:this.relationshipResolver}}const user=resolveAuthUser(authInfo);const authorization=authInfo?.extra?.["authorization"];const authorizationClaims=authorization?.["claims"]??{};const rawClaims={...authorizationClaims,...user};let roles;if(this.claimsMapping?.roles){roles=toStringArray(resolveDotPath(rawClaims,this.claimsMapping.roles))}else{roles=toStringArray(user["roles"]??authorization?.["scopes"]??[])}let permissions;if(this.claimsMapping?.permissions){permissions=toStringArray(resolveDotPath(rawClaims,this.claimsMapping.permissions))}else{permissions=toStringArray(user["permissions"]??[])}const mappedSub=this.claimsMapping?.userId?resolveDotPath(rawClaims,this.claimsMapping.userId):void 0;return{user:{sub:signedInSubject(user.sub,mappedSub),roles,permissions,claims:rawClaims},input,env,relationships:this.relationshipResolver}}};function toStringArray2(value){if(Array.isArray(value)){return value.filter(v=>typeof v==="string")}if(typeof value==="string"){return value.split(/\s+/).filter(Boolean)}return[]}var FrontMcpAuthContextImpl=class{user;isAnonymous;mode;sessionId;scopes;claims;roles;permissions;constructor(source,claimsMapping,claimsResolver){const rawUser=resolveAuthUser(source);const mappedSub=!claimsResolver&&claimsMapping?.userId?resolveDotPath(this.buildRawClaims(source),claimsMapping.userId):void 0;const signedInSub=signedInSubject(rawUser.sub,mappedSub);const sub=signedInSub??(typeof rawUser.sub==="string"?rawUser.sub:"");this.user=Object.freeze({sub,name:rawUser.name,email:rawUser.email,picture:rawUser.picture});this.isAnonymous=signedInSub===void 0;const extraAuth=source.extra?.["authorization"];this.mode=String(source.extra?.["authMode"]??extraAuth?.["mode"]??(source.extra?.["isPublic"]===true||rawUser["anonymous"]===true?"public":"authenticated"));this.sessionId=typeof source.sessionId==="string"?source.sessionId:"";this.scopes=Object.freeze(Array.isArray(source.scopes)?source.scopes.filter(s=>typeof s==="string"):[]);if(claimsResolver){const resolved=claimsResolver(source);this.claims=Object.freeze({...resolved.claims});this.roles=Object.freeze([...toStringArray2(resolved.roles)]);this.permissions=Object.freeze([...toStringArray2(resolved.permissions)]);return}const rawClaims=this.buildRawClaims(source);this.claims=Object.freeze({...rawClaims});if(claimsMapping?.roles){this.roles=Object.freeze([...toStringArray2(resolveDotPath(rawClaims,claimsMapping.roles))])}else{this.roles=Object.freeze([...toStringArray2(rawUser["roles"]??extraAuth?.["scopes"]??[])])}if(claimsMapping?.permissions){this.permissions=Object.freeze([...toStringArray2(resolveDotPath(rawClaims,claimsMapping.permissions))])}else{this.permissions=Object.freeze([...toStringArray2(rawUser["permissions"]??[])])}}hasRole(role){return this.roles.includes(role)}hasAllRoles(roles){return roles.every(r=>this.roles.includes(r))}hasAnyRole(roles){return roles.some(r=>this.roles.includes(r))}hasPermission(permission){return this.permissions.includes(permission)}hasAllPermissions(permissions){return permissions.every(p=>this.permissions.includes(p))}hasAnyPermission(permissions){return permissions.some(p=>this.permissions.includes(p))}hasScope(scope){return this.scopes.includes(scope)}hasAllScopes(scopes){return scopes.every(s=>this.scopes.includes(s))}hasAnyScope(scopes){return scopes.some(s=>this.scopes.includes(s))}buildRawClaims(source){const rawUser=resolveAuthUser(source);const extraAuth=source.extra?.["authorization"];const authorizationClaims=extraAuth?.["claims"]??{};return{...authorizationClaims,...rawUser}}};function buildAuthContext(authInfo,claimsMapping,pipes,claimsResolver){const base=new FrontMcpAuthContextImpl(authInfo,claimsMapping,claimsResolver);if(!pipes||pipes.length===0){return base}return runPipes(base,pipes)}async function runPipes(base,pipes){const extensions={};for(const pipe of pipes){try{const result=await pipe(base.claims);if(result&&typeof result==="object"){Object.assign(extensions,result)}}catch(error){const message=error instanceof Error?error.message:String(error);console.warn(`[FrontMcpAuth] pipe failed: ${message}`)}}const merged=Object.create(Object.getPrototypeOf(base));Object.assign(merged,base,extensions);return Object.freeze(merged)}function resolveRequiredScopes(denial,mapping,authorities){const scopes=new Set;if(typeof authorities==="string"&&mapping.profiles?.[authorities]){mapping.profiles[authorities].forEach(s=>scopes.add(s))}if(Array.isArray(authorities)){for(const profileName of authorities){if(typeof profileName==="string"&&mapping.profiles?.[profileName]){mapping.profiles[profileName].forEach(s=>scopes.add(s))}}}if(denial.kind==="roles"&&denial.missing&&mapping.roles){for(const role of denial.missing){const mapped=mapping.roles[role];if(mapped)mapped.forEach(s=>scopes.add(s))}}if(denial.kind==="permissions"&&denial.missing&&mapping.permissions){for(const perm of denial.missing){const mapped=mapping.permissions[perm];if(mapped)mapped.forEach(s=>scopes.add(s))}}return scopes.size>0?[...scopes].sort():void 0}var import_lazy_zod20=require("@frontmcp/lazy-zod");var rbacRolesPolicySchema=import_lazy_zod20.z.object({all:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional(),any:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional()}).refine(data=>data.all!==void 0||data.any!==void 0,{message:'Roles policy must have at least "all" or "any"'});var rbacPermissionsPolicySchema=import_lazy_zod20.z.object({all:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional(),any:import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).optional()}).refine(data=>data.all!==void 0||data.any!==void 0,{message:'Permissions policy must have at least "all" or "any"'});var abacOperatorSchema=import_lazy_zod20.z.enum(["eq","neq","in","notIn","gt","gte","lt","lte","contains","startsWith","endsWith","exists","matches"]);var abacConditionSchema=import_lazy_zod20.z.object({path:import_lazy_zod20.z.string().min(1),op:abacOperatorSchema,value:import_lazy_zod20.z.unknown()});var abacPolicySchema=import_lazy_zod20.z.object({match:import_lazy_zod20.z.record(import_lazy_zod20.z.string(),import_lazy_zod20.z.unknown()).optional(),conditions:import_lazy_zod20.z.array(abacConditionSchema).optional()}).refine(data=>data.match!==void 0||data.conditions!==void 0,{message:'Attributes policy must have at least "match" or "conditions"'});var resourceIdRefSchema=import_lazy_zod20.z.union([import_lazy_zod20.z.string().min(1),import_lazy_zod20.z.object({fromInput:import_lazy_zod20.z.string().min(1)}).strict(),import_lazy_zod20.z.object({fromClaims:import_lazy_zod20.z.string().min(1)}).strict()]);var rebacPolicySchema=import_lazy_zod20.z.object({type:import_lazy_zod20.z.string().min(1),resource:import_lazy_zod20.z.string().min(1),resourceId:resourceIdRefSchema});var basePolicyShape={roles:rbacRolesPolicySchema.optional(),permissions:rbacPermissionsPolicySchema.optional(),attributes:abacPolicySchema.optional(),relationships:import_lazy_zod20.z.union([rebacPolicySchema,import_lazy_zod20.z.array(rebacPolicySchema)]).optional(),custom:import_lazy_zod20.z.record(import_lazy_zod20.z.string(),import_lazy_zod20.z.unknown()).optional(),guards:import_lazy_zod20.z.array(import_lazy_zod20.z.instanceof(Function)).optional(),operator:import_lazy_zod20.z.enum(["AND","OR"]).optional()};var authoritiesPolicySchema=import_lazy_zod20.z.lazy(()=>import_lazy_zod20.z.object({...basePolicyShape,not:authoritiesPolicySchema.optional(),anyOf:import_lazy_zod20.z.array(authoritiesPolicySchema).optional(),allOf:import_lazy_zod20.z.array(authoritiesPolicySchema).optional()}));var authoritiesMetadataSchema=import_lazy_zod20.z.union([import_lazy_zod20.z.string().min(1),import_lazy_zod20.z.array(import_lazy_zod20.z.string().min(1)).min(1),authoritiesPolicySchema]);var authoritiesClaimsMappingSchema=import_lazy_zod20.z.record(import_lazy_zod20.z.string(),import_lazy_zod20.z.string().optional()).refine(data=>Object.values(data).some(v=>v!==void 0),{message:"Claims mapping must have at least one mapping"});var authoritiesConfigSchema=import_lazy_zod20.z.object({claimsMapping:authoritiesClaimsMappingSchema.optional(),profiles:import_lazy_zod20.z.record(import_lazy_zod20.z.string().min(1),authoritiesPolicySchema).optional()});function evaluateRbacRoles(policy,ctx){const userRoles=ctx.user.roles;if(policy.all){const missing=policy.all.filter(r=>!userRoles.includes(r));if(missing.length>0){return{granted:false,deniedBy:`roles.all: missing ${missing.map(r=>`'${r}'`).join(", ")}`,denial:{kind:"roles",path:"roles.all",missing},evaluatedPolicies:["roles.all"]}}}if(policy.any){const hasAny=policy.any.some(r=>userRoles.includes(r));if(!hasAny){return{granted:false,deniedBy:`roles.any: user has none of ${policy.any.map(r=>`'${r}'`).join(", ")}`,denial:{kind:"roles",path:"roles.any",missing:policy.any},evaluatedPolicies:["roles.any"]}}}return{granted:true,evaluatedPolicies:["roles"]}}function evaluateRbacPermissions(policy,ctx){const userPerms=ctx.user.permissions;if(policy.all){const missing=policy.all.filter(p=>!userPerms.includes(p));if(missing.length>0){return{granted:false,deniedBy:`permissions.all: missing ${missing.map(p=>`'${p}'`).join(", ")}`,denial:{kind:"permissions",path:"permissions.all",missing},evaluatedPolicies:["permissions.all"]}}}if(policy.any){const hasAny=policy.any.some(p=>userPerms.includes(p));if(!hasAny){return{granted:false,deniedBy:`permissions.any: user has none of ${policy.any.map(p=>`'${p}'`).join(", ")}`,denial:{kind:"permissions",path:"permissions.any",missing:policy.any},evaluatedPolicies:["permissions.any"]}}}return{granted:true,evaluatedPolicies:["permissions"]}}function buildContextEnvelope(ctx){return{user:ctx.user,claims:ctx.user.claims,input:ctx.input,env:ctx.env}}function resolveValue(value,ctx){if(value!==null&&typeof value==="object"&&!Array.isArray(value)){const obj=value;if("fromInput"in obj&&typeof obj["fromInput"]==="string"){return ctx.input[obj["fromInput"]]}if("fromClaims"in obj&&typeof obj["fromClaims"]==="string"){return resolveDotPath(ctx.user.claims,obj["fromClaims"])}}return value}function applyOperator(actual,op,expected){switch(op){case"eq":return expected!==void 0&&actual===expected;case"neq":return actual!==expected;case"in":return Array.isArray(expected)&&expected.includes(actual);case"notIn":return Array.isArray(expected)&&!expected.includes(actual);case"gt":return typeof actual==="number"&&typeof expected==="number"&&actual>expected;case"gte":return typeof actual==="number"&&typeof expected==="number"&&actual>=expected;case"lt":return typeof actual==="number"&&typeof expected==="number"&&actual<expected;case"lte":return typeof actual==="number"&&typeof expected==="number"&&actual<=expected;case"contains":if(typeof actual==="string"&&typeof expected==="string")return actual.includes(expected);if(Array.isArray(actual))return actual.includes(expected);return false;case"startsWith":return typeof actual==="string"&&typeof expected==="string"&&actual.startsWith(expected);case"endsWith":return typeof actual==="string"&&typeof expected==="string"&&actual.endsWith(expected);case"exists":return expected?actual!==void 0&&actual!==null:actual===void 0||actual===null;case"matches":if(typeof actual!=="string"||typeof expected!=="string")return false;if(expected.length>256)return false;if(/(\+\+|\*\*|\{\d+,\d*\}\{)/.test(expected))return false;try{return new RegExp(expected).test(actual)}catch{return false}default:return false}}function evaluateCondition(condition,envelope,ctx){const actual=resolveDotPath(envelope,condition.path);const expected=resolveValue(condition.value,ctx);return applyOperator(actual,condition.op,expected)}var REDACTED_ENV_VALUE="[redacted]";function reportableActual(path,actual){return path==="env"||path.startsWith("env.")?REDACTED_ENV_VALUE:actual}function evaluateAbac(policy,ctx){const envelope=buildContextEnvelope(ctx);if(policy.match){for(const[path,expectedRaw]of Object.entries(policy.match)){const actual=resolveDotPath(envelope,path);const expected=resolveValue(expectedRaw,ctx);if(expected===void 0||actual!==expected){const reported=reportableActual(path,actual);return{granted:false,deniedBy:`attributes.match: '${path}' expected '${String(expected)}' but got '${String(reported)}'`,denial:{kind:"attributes",path:"attributes.match",expected,actual:reported},evaluatedPolicies:["attributes.match"]}}}}if(policy.conditions){for(let i=0;i<policy.conditions.length;i++){const condition=policy.conditions[i];if(!evaluateCondition(condition,envelope,ctx)){const expected=resolveValue(condition.value,ctx);const actual=reportableActual(condition.path,resolveDotPath(envelope,condition.path));return{granted:false,deniedBy:`attributes.conditions: '${condition.path}' failed '${condition.op}' check against '${String(expected)}'`,denial:{kind:"attributes",path:`attributes.conditions[${i}]`,expected,actual},evaluatedPolicies:["attributes.conditions"]}}}}return{granted:true,evaluatedPolicies:["attributes"]}}function resolveResourceId(ref,ctx){if(typeof ref==="string")return ref;if("fromInput"in ref){const val=ctx.input[ref.fromInput];return typeof val==="string"?val:void 0}if("fromClaims"in ref){const val=resolveDotPath(ctx.user.claims,ref.fromClaims);return typeof val==="string"?val:void 0}return void 0}async function evaluateSingleRebac(policy,ctx){const userSub=ctx.user.sub;if(userSub===void 0||isAnonymousSubject(userSub)){return{granted:false,deniedBy:`relationships: an anonymous caller cannot be '${policy.type}' of ${policy.resource}`,denial:{kind:"relationships",path:"user.sub",expected:"a signed-in caller",actual:void 0},evaluatedPolicies:["relationships"]}}const resourceId=resolveResourceId(policy.resourceId,ctx);if(resourceId===void 0){return{granted:false,deniedBy:`relationships: could not resolve resourceId for ${policy.resource}`,denial:{kind:"relationships",path:"relationships",expected:`${policy.resource}:resourceId`,actual:void 0},evaluatedPolicies:["relationships"]}}const hasRelationship=await ctx.relationships.check(policy.type,policy.resource,resourceId,userSub,ctx);if(!hasRelationship){return{granted:false,deniedBy:`relationships: user '${userSub}' is not '${policy.type}' of ${policy.resource}:${resourceId}`,denial:{kind:"relationships",path:"relationships",expected:`${policy.type}:${policy.resource}:${resourceId}`},evaluatedPolicies:["relationships"]}}return{granted:true,evaluatedPolicies:["relationships"]}}async function evaluateRebac(policy,ctx){const policies=Array.isArray(policy)?policy:[policy];for(const p of policies){const result=await evaluateSingleRebac(p,ctx);if(!result.granted)return result}return{granted:true,evaluatedPolicies:["relationships"]}}var ABAC_OPERATORS=new Set(["eq","neq","in","notIn","gt","gte","lt","lte","contains","startsWith","endsWith","exists","matches"]);var CHECK_FIELDS=["roles","permissions","attributes","relationships","custom","guards","allOf","anyOf","not"];var RULE_FIELDS=new Set([...CHECK_FIELDS,"operator"]);function isPlainObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function isNonEmptyString(value){return typeof value==="string"&&value.length>0}function unknownFields(value,known,path){const prefix=path?`${path} has`:"has";return Object.keys(value).filter(key=>!known.has(key)).map(key=>`${prefix} an unknown field "${key}"`)}function checkStringList(value,path){if(!Array.isArray(value))return[`${path} must be a list of names`];if(value.length===0)return[`${path} is empty`];return value.every(isNonEmptyString)?[]:[`${path} must contain only non-empty names`]}var ALL_OR_ANY=new Set(["all","any"]);function checkAllOrAny(value,path){if(!isPlainObject(value))return[`${path} must be an object with "all" or "any"`];const problems=unknownFields(value,ALL_OR_ANY,path);if(value["all"]===void 0&&value["any"]===void 0){problems.push(`${path} needs "all" or "any"`)}if(value["all"]!==void 0)problems.push(...checkStringList(value["all"],`${path}.all`));if(value["any"]!==void 0)problems.push(...checkStringList(value["any"],`${path}.any`));return problems}var ATTRIBUTE_FIELDS=new Set(["match","conditions"]);var CONDITION_FIELDS=new Set(["path","op","value"]);function isValueReference(value){return isPlainObject(value)&&("fromInput"in value||"fromClaims"in value)}function checkValueReference(value,path){const ref=value["fromInput"]??value["fromClaims"];return Object.keys(value).length===1&&isNonEmptyString(ref)?[]:[`${path} must be { fromInput: "<name>" } or { fromClaims: "<path>" }`]}var OPERATOR_VALUES={in:{accepts:Array.isArray,needs:"a list"},notIn:{accepts:Array.isArray,needs:"a list"},gt:{accepts:value=>typeof value==="number",needs:"a number"},gte:{accepts:value=>typeof value==="number",needs:"a number"},lt:{accepts:value=>typeof value==="number",needs:"a number"},lte:{accepts:value=>typeof value==="number",needs:"a number"},startsWith:{accepts:value=>typeof value==="string",needs:"a string"},endsWith:{accepts:value=>typeof value==="string",needs:"a string"},matches:{accepts:value=>typeof value==="string",needs:"a string"}};function checkConditionValue(op,condition,path){const value=condition["value"];if(value===void 0)return[`${path} is missing`];if(op==="exists"){return typeof value==="boolean"?[]:[`${path} must be true or false for "exists"`]}if(isValueReference(value))return checkValueReference(value,path);const expected=OPERATOR_VALUES[op];if(expected&&!expected.accepts(value))return[`${path} must be ${expected.needs} for "${op}"`];if(Array.isArray(value)&&value.length===0&&(op==="in"||op==="notIn"))return[`${path} is empty`];return[]}function checkAttributes(value,path){if(!isPlainObject(value))return[`${path} must be an object with "match" or "conditions"`];const problems=unknownFields(value,ATTRIBUTE_FIELDS,path);const{match,conditions}=value;if(match===void 0&&conditions===void 0){problems.push(`${path} needs "match" or "conditions"`)}if(match!==void 0){if(!isPlainObject(match))problems.push(`${path}.match must be an object`);else if(Object.keys(match).length===0)problems.push(`${path}.match is empty`);else{for(const[attribute,expected]of Object.entries(match)){const at=`${path}.match[${JSON.stringify(attribute)}]`;if(expected===void 0)problems.push(`${at} has no value`);else if(isValueReference(expected))problems.push(...checkValueReference(expected,at))}}}if(conditions!==void 0){if(!Array.isArray(conditions))problems.push(`${path}.conditions must be a list`);else if(conditions.length===0)problems.push(`${path}.conditions is empty`);else{conditions.forEach((condition,index)=>{const at=`${path}.conditions[${index}]`;if(!isPlainObject(condition)){problems.push(`${at} must be an object with "path" and "op"`);return}problems.push(...unknownFields(condition,CONDITION_FIELDS,at));if(!isNonEmptyString(condition["path"]))problems.push(`${at}.path must be a non-empty string`);const op=condition["op"];if(!ABAC_OPERATORS.has(op)){problems.push(`${at}.op "${String(condition["op"])}" is not an operator`)}else{problems.push(...checkConditionValue(op,condition,`${at}.value`))}})}}return problems}var RELATIONSHIP_FIELDS=new Set(["type","resource","resourceId"]);function checkResourceId(value,path){if(isNonEmptyString(value))return[];if(isPlainObject(value)&&Object.keys(value).length===1){const ref=value["fromInput"]??value["fromClaims"];if(isNonEmptyString(ref))return[]}return[`${path} must be a string, { fromInput } or { fromClaims }`]}function checkRelationship(value,path){if(!isPlainObject(value))return[`${path} must be an object with "type", "resource" and "resourceId"`];const problems=unknownFields(value,RELATIONSHIP_FIELDS,path);if(!isNonEmptyString(value["type"]))problems.push(`${path}.type must be a non-empty string`);if(!isNonEmptyString(value["resource"]))problems.push(`${path}.resource must be a non-empty string`);problems.push(...checkResourceId(value["resourceId"],`${path}.resourceId`));return problems}function checkRelationships(value,path){if(!Array.isArray(value))return checkRelationship(value,path);if(value.length===0)return[`${path} is empty`];return value.flatMap((relationship,index)=>checkRelationship(relationship,`${path}[${index}]`))}function checkRuleList(value,path){if(!Array.isArray(value))return[`${path} must be a list of rules`];if(value.length===0)return[`${path} is empty`];return value.flatMap((rule,index)=>checkRule(rule,`${path}[${index}]`))}function checkRule(rule,path){if(!isPlainObject(rule)){return[`${path||"the rule"} must be a rule object${typeof rule==="string"?", not a profile name":""}`]}const problems=unknownFields(rule,RULE_FIELDS,path);if(!CHECK_FIELDS.some(field=>rule[field]!==void 0)){problems.push(`${path?`${path} `:""}checks nothing`)}if(rule["operator"]!==void 0&&rule["operator"]!=="AND"&&rule["operator"]!=="OR"){problems.push(`${path}.operator must be "AND" or "OR"`)}if(rule["roles"]!==void 0)problems.push(...checkAllOrAny(rule["roles"],`${path}.roles`));if(rule["permissions"]!==void 0)problems.push(...checkAllOrAny(rule["permissions"],`${path}.permissions`));if(rule["attributes"]!==void 0)problems.push(...checkAttributes(rule["attributes"],`${path}.attributes`));if(rule["relationships"]!==void 0){problems.push(...checkRelationships(rule["relationships"],`${path}.relationships`))}if(rule["custom"]!==void 0){if(!isPlainObject(rule["custom"]))problems.push(`${path}.custom must be an object`);else if(Object.keys(rule["custom"]).length===0)problems.push(`${path}.custom is empty`)}if(rule["guards"]!==void 0){const guards=rule["guards"];if(!Array.isArray(guards))problems.push(`${path}.guards must be a list of functions`);else if(guards.length===0)problems.push(`${path}.guards is empty`);else if(!guards.every(guard=>typeof guard==="function")){problems.push(`${path}.guards must contain only functions`)}}if(rule["allOf"]!==void 0)problems.push(...checkRuleList(rule["allOf"],`${path}.allOf`));if(rule["anyOf"]!==void 0)problems.push(...checkRuleList(rule["anyOf"],`${path}.anyOf`));if(rule["not"]!==void 0)problems.push(...checkRule(rule["not"],`${path}.not`));return problems}function findAuthoritiesRuleProblems(authorities){if(typeof authorities==="string"){return authorities.length>0?[]:["the profile name is empty"]}if(Array.isArray(authorities)){if(authorities.length===0)return["the list of profiles is empty"];return authorities.every(isNonEmptyString)?[]:["a list of profiles must contain only non-empty profile names"]}if(!isPlainObject(authorities)){return["must be a profile name, a list of profile names, or a rule object"]}return checkRule(authorities,"")}function findAuthoritiesProfileProblems(name,policy){return checkRule(policy,"").map(problem=>`profile "${name}": ${problem.replace(/^\./,"")}`)}function mergeResult(base,...others){const evaluatedPolicies=[...base.evaluatedPolicies];for(const other of others){evaluatedPolicies.push(...other.evaluatedPolicies)}return{...base,evaluatedPolicies}}function invalidRule(problems,policies=[]){return{granted:false,deniedBy:`invalid authorities rule: ${problems.join("; ")}`,evaluatedPolicies:policies}}var AuthoritiesEngine=class{constructor(profiles,evaluators){this.profiles=profiles;this.evaluators=evaluators}profiles;evaluators;ruleProblems=new WeakMap;findRuleProblems(authorities){const problems=findAuthoritiesRuleProblems(authorities);if(problems.length>0)return problems;const names=typeof authorities==="string"?[authorities]:Array.isArray(authorities)?authorities:[];return names.filter(name=>typeof name==="string"&&!this.profiles.has(name)).map(name=>`names an unknown profile "${name}"`)}findProfileProblems(){return Object.entries(this.profiles.getAll()).flatMap(([name,policy])=>findAuthoritiesProfileProblems(name,policy))}async evaluate(authorities,ctx){const problems=this.problemsOf(authorities,findAuthoritiesRuleProblems);if(problems.length>0)return invalidRule(problems);if(typeof authorities==="string"){return this.evaluateProfile(authorities,ctx)}if(Array.isArray(authorities)){return this.evaluateProfileArray(authorities,ctx)}return this.evaluatePolicy(authorities,ctx)}async evaluateProfile(name,ctx){const policy=this.profiles.resolve(name);if(!policy){return{granted:false,deniedBy:`profile '${name}' is not registered`,evaluatedPolicies:[`profile:${name}`]}}const problems=this.problemsOf(policy,rule=>findAuthoritiesProfileProblems(name,rule));if(problems.length>0)return invalidRule(problems,[`profile:${name}`]);const result=await this.evaluatePolicy(policy,ctx);if(!result.granted){return{...result,deniedBy:`profile:${name}: ${result.deniedBy}`,evaluatedPolicies:[`profile:${name}`,...result.evaluatedPolicies]}}return mergeResult(result,{granted:true,evaluatedPolicies:[`profile:${name}`]})}problemsOf(rule,find){if(typeof rule!=="object"||rule===null)return find(rule);let problems=this.ruleProblems.get(rule);if(!problems){problems=find(rule);this.ruleProblems.set(rule,problems)}return problems}async evaluateProfileArray(names,ctx){const allPolicies=[];for(const name of names){const result=await this.evaluateProfile(name,ctx);allPolicies.push(...result.evaluatedPolicies);if(!result.granted){return{...result,evaluatedPolicies:allPolicies}}}return{granted:true,evaluatedPolicies:allPolicies}}async evaluatePolicy(policy,ctx){const operator=policy.operator??"AND";const results=[];if(policy.roles){results.push(evaluateRbacRoles(policy.roles,ctx))}if(policy.permissions){results.push(evaluateRbacPermissions(policy.permissions,ctx))}if(policy.attributes){results.push(evaluateAbac(policy.attributes,ctx))}if(policy.relationships){results.push(await evaluateRebac(policy.relationships,ctx))}if(policy.custom){results.push(await this.evaluateCustom(policy.custom,ctx))}if(policy.guards&&policy.guards.length>0){results.push(await this.evaluateGuards(policy.guards,ctx))}if(policy.allOf){results.push(await this.evaluateAllOf(policy.allOf,ctx))}if(policy.anyOf){results.push(await this.evaluateAnyOf(policy.anyOf,ctx))}if(policy.not){results.push(await this.evaluateNot(policy.not,ctx))}if(results.length===0){return invalidRule(["checks nothing"])}return this.combineResults(results,operator)}combineResults(results,operator){const allPolicies=results.flatMap(r=>r.evaluatedPolicies);if(operator==="AND"){const denied=results.find(r=>!r.granted);if(denied){return{...denied,evaluatedPolicies:allPolicies}}return{granted:true,evaluatedPolicies:allPolicies}}const anyGranted=results.some(r=>r.granted);if(anyGranted){return{granted:true,evaluatedPolicies:allPolicies}}const firstDenied=results.find(r=>!r.granted);return{granted:false,deniedBy:firstDenied?.deniedBy??"all policies denied (OR)",evaluatedPolicies:allPolicies}}async evaluateCustom(custom,ctx){const allPolicies=[];for(const[name,config]of Object.entries(custom)){const evaluator=this.evaluators.get(name);if(!evaluator){return{granted:false,deniedBy:`custom evaluator '${name}' is not registered`,evaluatedPolicies:[...allPolicies,`custom.${name}`]}}const result=await evaluator.evaluate(config,ctx);allPolicies.push(`custom.${name}`,...result.evaluatedPolicies);if(!result.granted){return{...result,evaluatedPolicies:allPolicies}}}return{granted:true,evaluatedPolicies:allPolicies}}async evaluateGuards(guards,ctx){for(let i=0;i<guards.length;i++){const guard=guards[i];const result=await guard(ctx);if(result!==true){const denialMessage=typeof result==="string"?result:result===false?`guard[${i}] denied`:`guard[${i}] did not return true (returned ${result===null?"null":typeof result})`;return{granted:false,deniedBy:`guards[${i}]: ${denialMessage}`,denial:{kind:"custom",path:`guards[${i}]`},evaluatedPolicies:["guards"]}}}return{granted:true,evaluatedPolicies:["guards"]}}async evaluateAllOf(policies,ctx){const allPolicies=["allOf"];for(const policy of policies){const result=await this.evaluatePolicy(policy,ctx);allPolicies.push(...result.evaluatedPolicies);if(!result.granted){return{...result,evaluatedPolicies:allPolicies}}}return{granted:true,evaluatedPolicies:allPolicies}}async evaluateAnyOf(policies,ctx){const allPolicies=["anyOf"];let lastDenied;for(const policy of policies){const result=await this.evaluatePolicy(policy,ctx);allPolicies.push(...result.evaluatedPolicies);if(result.granted){return{granted:true,evaluatedPolicies:allPolicies}}lastDenied=result}return{granted:false,deniedBy:lastDenied?.deniedBy??"no policies in anyOf",denial:lastDenied?.denial??{kind:"anyOf",path:"anyOf"},evaluatedPolicies:allPolicies}}async evaluateNot(policy,ctx){const result=await this.evaluatePolicy(policy,ctx);return{granted:!result.granted,deniedBy:result.granted?"not: inner policy was granted (negated to denied)":void 0,denial:result.granted?{kind:"not",path:"not"}:void 0,evaluatedPolicies:["not",...result.evaluatedPolicies]}}resolveProfile(name){return this.profiles.resolve(name)}};var AuthoritiesProfileRegistry=class{profiles=new Map;register(name,policy){this.profiles.set(name,policy)}registerAll(profiles){for(const[name,policy]of Object.entries(profiles)){this.profiles.set(name,policy)}}resolve(name){return this.profiles.get(name)}has(name){return this.profiles.has(name)}getAll(){const result={};for(const[name,policy]of this.profiles){result[name]=policy}return result}get size(){return this.profiles.size}remove(name){return this.profiles.delete(name)}clear(){this.profiles.clear()}};var AuthoritiesEvaluatorRegistry=class{evaluators=new Map;register(name,evaluator){this.evaluators.set(name,evaluator)}registerAll(evaluators){for(const[name,evaluator]of Object.entries(evaluators)){this.evaluators.set(name,evaluator)}}get(name){return this.evaluators.get(name)}has(name){return this.evaluators.has(name)}get size(){return this.evaluators.size}remove(name){return this.evaluators.delete(name)}clear(){this.evaluators.clear()}};var import_utils50=require("@frontmcp/utils");var FORBIDDEN_CODE=-32003;var AuthorityDeniedError=class extends Error{static[Symbol.hasInstance](value){return(0,import_utils50.isBrandedInstance)(this,value)}mcpErrorCode=FORBIDDEN_CODE;statusCode=403;code="AUTHORITY_DENIED";entryType;entryName;deniedBy;denial;requiredScopes;constructor(params){const msg=params.message??`Access denied to ${params.entryType} "${params.entryName}": ${params.deniedBy}`;super(msg);this.name="AuthorityDeniedError";this.entryType=params.entryType;this.entryName=params.entryName;this.deniedBy=params.deniedBy;this.denial=params.denial;this.requiredScopes=params.requiredScopes}toJsonRpcError(){const data={entryType:this.entryType,entryName:this.entryName,deniedBy:this.deniedBy};if(this.denial!==void 0)data["denial"]=this.denial;if(this.requiredScopes!==void 0)data["requiredScopes"]=this.requiredScopes;return{code:this.mcpErrorCode,message:this.message,data}}};(0,import_utils50.brandClass)(AuthorityDeniedError,"@frontmcp/auth:AuthorityDeniedError");var bearerApplier={apply(token,_url,init){const headers=new Headers(init.headers);headers.set("Authorization",`Bearer ${token}`);return{init:{...init,headers}}}};function headerApplier(headerName,prefix){return{apply(token,_url,init){const headers=new Headers(init.headers);headers.set(headerName,prefix?`${prefix} ${token}`:token);return{init:{...init,headers}}}}}function queryApplier(paramName){return{apply(token,url,init){const urlObj=new URL(url);urlObj.searchParams.set(paramName,token);return{init,url:urlObj.toString()}}}}var basicApplier={apply(token,_url,init){const headers=new Headers(init.headers);const encoded=typeof btoa==="function"?btoa(token):Buffer.from(token).toString("base64");headers.set("Authorization",`Basic ${encoded}`);return{init:{...init,headers}}}};function isFrontMcpCredentials(creds){return typeof creds==="object"&&creds!==null&&"provider"in creds&&typeof creds.provider==="string"&&creds.provider.length>0}function providerHeadersCredentials(resolveHeaders){return{async applyCredentials(_url,init){const{credentials,...cleanInit}=init;if(!isFrontMcpCredentials(credentials)){return{init:typeof credentials==="string"?init:cleanInit}}const headers=new Headers(cleanInit.headers);for(const[name,value]of Object.entries(await resolveHeaders(credentials.provider))){headers.set(name,value)}return{init:{...cleanInit,headers}}}}}var FetchCredentialMiddleware=class{constructor(tokenAccessor,appliers){this.tokenAccessor=tokenAccessor;this.appliers=new Map(Object.entries(appliers??{}))}tokenAccessor;appliers;async applyCredentials(url,init){const creds=init.credentials;if(!creds||typeof creds==="string"){return{init}}if(!isFrontMcpCredentials(creds)){const{credentials:_removed2,...rest}=init;return{init:rest}}const token=await this.tokenAccessor.getToken(creds.provider);if(!token){const{credentials:_removed2,...rest}=init;return{init:rest}}const applier=this.appliers.get(creds.provider)??bearerApplier;const{credentials:_removed,...cleanInit}=init;return applier.apply(token,url,cleanInit)}};var import_lazy_zod21=require("@frontmcp/lazy-zod");var MINUTE_MS=6e4;function milliseconds(field){return import_lazy_zod21.internalZ.number({message:`${field} must be a number of milliseconds`}).int(`${field} must be a whole number of milliseconds`).positive(`${field} must be greater than 0`)}function createPeopleAuthOptionsSchema(){const loopbackToken=import_lazy_zod21.internalZ.object({mode:import_lazy_zod21.internalZ.literal("loopback-token"),codeTtlMs:milliseconds("codeTtlMs").max(10*MINUTE_MS,"codeTtlMs must be at most 600000 (10 minutes): a sign-in code is for one hand-off").optional(),sessionTtlMs:milliseconds("sessionTtlMs").optional(),maxFailedAttempts:import_lazy_zod21.internalZ.number({message:"maxFailedAttempts must be a number"}).int("maxFailedAttempts must be a whole number").positive("maxFailedAttempts must be greater than 0").optional(),lockoutMs:milliseconds("lockoutMs").optional(),cookiePath:import_lazy_zod21.internalZ.string().startsWith("/",'cookiePath must start with "/"').optional()}).strict();return import_lazy_zod21.internalZ.union([import_lazy_zod21.internalZ.literal("loopback-token"),loopbackToken],{message:"http.auth.people must be 'loopback-token' or { mode: 'loopback-token', ... }"}).transform(value=>{const settings=typeof value==="string"?{}:value;return{mode:"loopback-token",codeTtlMs:settings.codeTtlMs??MINUTE_MS,sessionTtlMs:settings.sessionTtlMs??12*60*MINUTE_MS,maxFailedAttempts:settings.maxFailedAttempts??5,lockoutMs:settings.lockoutMs??MINUTE_MS,cookiePath:settings.cookiePath??"/"}})}var schema;function peopleAuthOptionsSchema(){schema??=createPeopleAuthOptionsSchema();return schema}var import_utils51=require("@frontmcp/utils");var PEOPLE_SESSION_COOKIE="frontmcp_people";var INVALID={ok:false,reason:"invalid"};var LOCKED={ok:false,reason:"locked"};var MAX_TRACKED_CLIENTS=1024;function newSecret(){return(0,import_utils51.base64urlEncode)((0,import_utils51.randomBytes)(32))}function matches(presented,digest){return(0,import_utils51.timingSafeEqual)((0,import_utils51.sha256)(presented),digest)}function unexpired(secrets){const now=Date.now();return secrets.filter(secret=>secret.expiresAt>now)}var LoopbackTokenAuth=class{constructor(options){this.options=options;const token=newSecret();this.token=token;this.tokenDigest=(0,import_utils51.sha256)(token)}options;token;tokenDigest;codes=[];sessions=[];failures=new Map;takeToken(){const token=this.token;this.token=void 0;return token}createCode(options={}){const code=newSecret();const expiresAt=Date.now()+this.options.codeTtlMs;const{subject}=options;this.codes=[...unexpired(this.codes),{digest:(0,import_utils51.sha256)(code),expiresAt,...subject?{subject}:{}}];return{code,expiresAt}}exchangeToken(presented,client){if(this.isLocked(client))return LOCKED;if(presented===void 0||!matches(presented,this.tokenDigest))return this.refuse(client);this.failures.delete(client);return{ok:true,...this.createCode()}}exchangeCode(presented,client){if(this.isLocked(client))return LOCKED;this.codes=unexpired(this.codes);const index=presented===void 0?-1:this.codes.findIndex(code=>matches(presented,code.digest));if(index===-1)return this.refuse(client);const[{subject}]=this.codes.splice(index,1);this.failures.delete(client);const cookieValue=newSecret();const expiresAt=Date.now()+this.options.sessionTtlMs;this.sessions=[...unexpired(this.sessions),{digest:(0,import_utils51.sha256)(cookieValue),expiresAt,...subject?{subject}:{}}];return{ok:true,cookieValue,expiresAt}}verifySession(presented){if(!presented)return void 0;this.sessions=unexpired(this.sessions);const session=this.sessions.find(stored=>matches(presented,stored.digest));if(!session)return void 0;return session.subject?{expiresAt:session.expiresAt,subject:session.subject}:{expiresAt:session.expiresAt}}endSession(presented){if(!presented)return;this.sessions=this.sessions.filter(stored=>!matches(presented,stored.digest))}isLocked(client){return(this.failures.get(client)?.lockedUntil??0)>Date.now()}refuse(client){const now=Date.now();const{maxFailedAttempts,lockoutMs}=this.options;const previous=this.failures.get(client);const count=previous&&now-previous.lastAt<=lockoutMs?previous.count+1:1;const locked=count>=maxFailedAttempts;if(!previous&&this.failures.size>=MAX_TRACKED_CLIENTS)this.forgetIdleClients(now);this.failures.set(client,{count:locked?0:count,lastAt:now,lockedUntil:locked?now+lockoutMs:0});return locked?LOCKED:INVALID}forgetIdleClients(now){for(const[client,failures]of this.failures){if(failures.lockedUntil<=now&&now-failures.lastAt>this.options.lockoutMs)this.failures.delete(client)}}};function peopleSessionCookie(value,options){return{name:PEOPLE_SESSION_COOKIE,value,path:options.path,httpOnly:true,sameSite:"strict",secure:options.secure,maxAge:Math.floor(options.maxAgeMs/1e3)}}var import_utils52=require("@frontmcp/utils");var SECRET_BYTES=32;var BASE64URL_32_BYTES=/^[A-Za-z0-9_-]{43}$/;var KEY_SALT="frontmcp shared server";var PROOF_LABEL="frontmcp shared server identity v1";var encoder=new TextEncoder;function createSharedServerSecret(){return(0,import_utils52.base64urlEncode)((0,import_utils52.randomBytes)(SECRET_BYTES))}function createSharedServerNonce(){return(0,import_utils52.base64urlEncode)((0,import_utils52.randomBytes)(SECRET_BYTES))}function isBase64url32Bytes(value){return typeof value==="string"&&BASE64URL_32_BYTES.test(value)}function isSharedServerNonce(value){return isBase64url32Bytes(value)}function deriveSharedServerKeys(secret){if(!isBase64url32Bytes(secret))throw new TypeError("a shared server secret is 32 bytes of base64url");const bytes=(0,import_utils52.base64urlDecode)(secret);const salt=encoder.encode(KEY_SALT);return{proofKey:(0,import_utils52.hkdfSha256)(bytes,salt,encoder.encode("proof"),32),token:(0,import_utils52.base64urlEncode)((0,import_utils52.hkdfSha256)(bytes,salt,encoder.encode("token"),32))}}function proofBytes(proofKey,{endpoint,nonce,version}){return(0,import_utils52.hmacSha256)(proofKey,encoder.encode(JSON.stringify([PROOF_LABEL,endpoint,nonce,version])))}function proveSharedServerIdentity(proofKey,statement){return(0,import_utils52.base64urlEncode)(proofBytes(proofKey,statement))}function verifySharedServerIdentity(proofKey,statement,proof){if(!isBase64url32Bytes(proof))return false;const expected=proofBytes(proofKey,statement);const presented=(0,import_utils52.base64urlDecode)(proof);return presented.length===expected.length&&(0,import_utils52.timingSafeEqual)(presented,expected)}0&&(module.exports={AUTH_PROVIDERS_ACCESSOR,AUTH_PROVIDERS_REGISTRY,AUTH_PROVIDERS_VAULT,AppAuthState,AudienceValidator,AuthInternalError,AuthInvalidInputError,AuthProvidersAccessorImpl,AuthProvidersNotConfiguredError,AuthProvidersRegistry,AuthProvidersVault,AuthoritiesContextBuilder,AuthoritiesEngine,AuthoritiesEvaluatorRegistry,AuthoritiesProfileRegistry,AuthorityDeniedError,AuthorizationBase,BUILT_IN_AUTH_PAGE_CSP,CDN,CREDENTIALS_ACCESSOR,CimdClientIdMismatchError,CimdDisabledError,CimdError,CimdFetchError,CimdResponseTooLargeError,CimdSecurityError,CimdService,CimdValidationError,CredentialCache,CredentialProviderAlreadyRegisteredError,CredentialStorageError,CredentialsAccessorImpl,DEFAULT_ALLOWED_SCOPES,DEFAULT_INCREMENTAL_TICKET_TTL_MS,DEFAULT_RESUME_TTL_MS,DEFAULT_THEME,DcrClientRegistry,EagerCredentialLoader,ElicitationSecretRequiredError,EncryptedRedisVault,EncryptedStorageError,EncryptedStorageSecureStoreBackend,EncryptedTypedStorage,EncryptionContextNotSetError,EncryptionKeyNotConfiguredError,FetchCredentialMiddleware,FrontMcpAuthContextImpl,InMemoryAuthorizationStore,InMemoryAuthorizationVault,InMemoryCimdCache,InMemoryConsentStore,InMemoryFederatedAuthSessionStore,InMemoryOrchestratedTokenStore,InMemoryStoreRequiredError,InvalidClientIdUrlError,JwksService,JwtSecretRequiredError,JwtSecretWeakError,LazyCredentialLoader,LoopbackTokenAuth,NoProviderIdError,NullOrchestratedAuthAccessor,ORCHESTRATED_AUTH_ACCESSOR,OrchestratedAuthAccessorAdapter,OrchestratedAuthNotAvailableError,OrchestratedAuthorization,OrchestratorJwksNotAvailableError,PEOPLE_SESSION_COOKIE,PublicAuthorization,RedirectUriMismatchError,RedisAuthorizationStore,RedisSessionStore,SECURE_STORE_ACCESSOR,SIGNIN_BINDING_COOKIE_PREFIX,SIGNIN_BINDING_MAX_AGE_SECONDS,SIGNIN_BINDING_SECURE_COOKIE_PREFIX,ScopeDeniedError,SecureStoreAccessorImpl,SecureStoreConfigError,SessionCredentialVault,SessionIdEmptyError,SessionRateLimiter,SessionSecretRequiredError,StorageAuthorizationStore,StorageAuthorizationVault,StorageConsentStore,StorageFederatedAuthSessionStore,StorageOrchestratedTokenStore,StorageTokenStore,TinyTtlCache,TokenLeakDetectedError,TokenNotAvailableError,TokenStoreRequiredError,TokenVault,TransparentAuthorization,TransportIdGenerator,TypedStorage,VaultEncryption,VaultLoadError,VaultNotFoundError,VercelKvSessionStore,abacConditionSchema,abacOperatorSchema,abacPolicySchema,advertisedScopes,aiPlatformTypeSchema,allowsPublicAccess,anonymousCallerClaims,apiKeyCredentialSchema,appAuthOptionsSchema,appAuthStateSchema,appAuthorizationRecordSchema,appCredentialSchema,appRequiresOrchestration,authLayout,authModeSchema,authOptionsSchema,authProviderDetectionResultSchema,authProviderMappingSchema,authProvidersVaultOptionsSchema,authUserSchema,authenticateFnSchema,authoritiesClaimsMappingSchema,authoritiesConfigSchema,authoritiesMetadataSchema,authoritiesPolicySchema,authorizationCodeRecordSchema,authorizationVaultEntrySchema,authorizedPromptSchema,authorizedToolSchema,baseLayout,basicApplier,basicAuthCredentialSchema,bearerApplier,bearerCredentialSchema,buildAuthContext,buildCodeRecord,buildConnectPage,buildConnectSuccessPage,buildConsentPage,buildCredentialResumeUrl,buildErrorPage,buildFederatedLoginPage,buildIncrementalAuthPage,buildInsufficientScopeHeader,buildInvalidRequestHeader,buildInvalidTokenHeader,buildLoginPage,buildPendingRecord,buildPrmUrl,buildRefreshTokenRecord,buildToolConsentPage,buildUnauthorizedHeader,buildWwwAuthenticate,builtInAuthPageHeaders,centeredCardLayout,checkSsrfProtection,cimdCacheConfigSchema,cimdConfigSchema,cimdNetworkConfigSchema,cimdSecurityConfigSchema,clientMetadataDocumentSchema,completeCurrentProvider,consentConfigSchema,consentRecordKey,consentSelectionSchema,consentStateSchema,consentToolItemSchema,createAudienceValidator,createEncryptedVault,createFederatedAuthSession,createLayout,createSecureStore,createSessionCredentialVault,createSharedServerNonce,createSharedServerSecret,createSigninBinding,createTokenStorageAdapter,credentialProviderConfigSchema,credentialSchema,credentialScopeSchema,credentialTypeSchema,customCredentialSchema,decodeJwtPayloadSafe,decryptAesGcm,decryptSessionJson,decryptValue,defaultSessionRateLimiter,deriveAuthorizationId,deriveExpectedAudience,deriveProviderId,deriveSharedServerKeys,deriveTypedUser,detectAuthProviders,detectedAuthProviderSchema,encryptAesGcm,encryptJson,encryptValue,encryptedBlobSchema,encryptedDataSchema,encryptedVaultEntrySchema,escapeHtml,extraWideLayout,extractBearerToken,extractCacheHeaders,extractCredentialExpiry,federatedAuthConfigSchema,federatedLoginStateSchema,federatedProviderItemSchema,federatedSelectionSchema,findAuthoritiesProfileProblems,findAuthoritiesRuleProblems,flatRemoteProviderFields,fromSessionRecord,generateAuthorizationCode,generatePkceChallenge,generateRefreshTokenValue,getCredentialOptionsSchema,getKey,getNextProvider,getProviderApps,getProviderScopes,getTokenSignatureFingerprint,grantScopes,hasOnlyLocalhostRedirectUris,headerApplier,hkdfSha256,incrementalAuthConfigSchema,isAnonymousSubject,isCimdClientId,isFrontMcpCredentials,isJwt,isLocalMode,isLoopbackRedirectUri,isOrchestratedLocal,isOrchestratedMode,isOrchestratedRemote,isPersistentTokenStorage,isPublicMode,isRedisTokenStorage,isRemoteMode,isSessionComplete,isSharedServerNonce,isSignedSession,isSoonExpiring,isSoonExpiringProvider,isSqliteTokenStorage,isStaticMode,isTransparentMode,jsonWebKeySetSchema,jwkParametersSchema,jwkSchema,legacySseTransportStateSchema,llmSafeAuthContextSchema,loadingStrategySchema,localAuthSchema,localDcrClientSchema,localDcrConfigSchema,localSigningConfigSchema,loginConfigSchema,mtlsCredentialSchema,noopLogger,normalizeIssuer,oauthCredentialSchema,openPendingLogin,orchestratedLocalSchema,orchestratedRemoteSchema,parseAuthOptions,parseCacheHeaders,parseWwwAuthenticate,pendingIncrementalAuthSchema,peopleAuthOptionsSchema,peopleSessionCookie,pkceChallengeSchema,pkceOAuthCredentialSchema,privateKeyCredentialSchema,progressiveAuthStateSchema,proveSharedServerIdentity,providerConfigSchema,providerHeadersCredentials,publicAccessConfigSchema,publicAuthOptionsSchema,queryApplier,rbacPermissionsPolicySchema,rbacRolesPolicySchema,rebacPolicySchema,redisConfigSchema,redisVaultEntrySchema,remoteAuthSchema,remoteProviderConfigSchema,renderLocalLoginPage,renderToHtml,resetCachedKey,resolveRequiredScopes,resourceIdRefSchema,resourceScopesFor,safeDecrypt,scopesFromClaims,sealPendingLogin,secureStoreConfigSchema,secureStoreCustomBackendSchema,secureStoreEncryptionSchema,secureStoreScopeSchema,serviceAccountCredentialSchema,sessionIdPayloadSchema,sessionJwtPayloadSchema,signCredentialResumeToken,signIncrementalAuthTicket,signSession,signinBindingCookieName,signinBindingMatches,skippedAppBehaviorSchema,sseTransportStateSchema,sshKeyCredentialSchema,startNextProvider,statefulHttpTransportStateSchema,statelessHttpTransportStateSchema,staticAuthOptionsSchema,storedSessionSchema,streamableHttpTransportStateSchema,toEpochSeconds,toLoginExtraFields,toSessionRecord,tokenRefreshConfigSchema,tokenStorageConfigSchema,tokenStorageSqliteSchema,transparentAuthOptionsSchema,transportProtocolSchema,transportSessionSchema,transportStateSchema,trimSlash,tryJwtExp,upstreamProviderSchema,userClaimSchema,validateAudience,validateClientIdUrl,vaultConsentRecordSchema,vaultFederatedRecordSchema,verifyCredentialResumeToken,verifyIncrementalAuthTicket,verifyOrParseSession,verifyPkce,verifySession,verifySharedServerIdentity,wideLayout,withoutSecretFieldValues});