@burdenoff/be-sdk 2026.703.5 → 2026.705.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.
- package/dist/{chunk-YNUFPUZ6.js → chunk-5BCCI2FV.js} +3 -3
- package/dist/{chunk-YNUFPUZ6.js.map → chunk-5BCCI2FV.js.map} +1 -1
- package/dist/{chunk-TRBTYM6S.js → chunk-5WRBQUS3.js} +3 -3
- package/dist/{chunk-TRBTYM6S.js.map → chunk-5WRBQUS3.js.map} +1 -1
- package/dist/{chunk-JOJNTJQS.js → chunk-IDKU7OGF.js} +3 -3
- package/dist/{chunk-JOJNTJQS.js.map → chunk-IDKU7OGF.js.map} +1 -1
- package/dist/{chunk-IIUYANNF.js → chunk-WHSIZCJX.js} +6 -8
- package/dist/chunk-WHSIZCJX.js.map +1 -0
- package/dist/export/index.js +3 -3
- package/dist/gateway/index.js +2 -2
- package/dist/gateway/security/index.js +1 -1
- package/dist/index.js +10 -10
- package/dist/init/index.js +3 -3
- package/dist/sharding/index.d.ts +59 -0
- package/dist/sharding/index.js +152 -0
- package/dist/sharding/index.js.map +1 -0
- package/package.json +3 -3
- package/dist/chunk-IIUYANNF.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/gateway/index.ts","../src/gateway/types.ts","../src/gateway/client.ts"],"names":["CircuitState","GatewayErrorType","GatewayError","Error","type","gatewayUrl","statusCode","graphqlErrors","cause","message","options","name","Object","setPrototypeOf","prototype","uuidv4","crypto","randomUUID","hasAuthorizationHeader","headers","key","keys","toLowerCase","resolveBypassPermissionValue","token","process","env","normalizedToken","trim","CircuitBreaker","state","CLOSED","failures","successes","consecutiveFailures","lastFailureTime","lastSuccessTime","openedAt","failureTimestamps","config","getState","checkStateTransition","recordSuccess","Date","now","HALF_OPEN","logger","info","recordFailure","push","windowStart","failureWindow","filter","t","length","failureThreshold","OPEN","warn","threshold","allowRequest","forceOpen","forceClose","getStats","elapsed","resetTimeout","GatewayClient","layerManager","internalCircuitBreaker","crossLayerCircuitBreaker","retryConfig","defaultHeaders","timeout","enableLogging","LayerManager","layer","serviceName","serviceIdentity","internalGatewayUrl","crossLayerGatewayUrl","cbConfig","DEFAULT_CIRCUIT_BREAKER_CONFIG","circuitBreaker","DEFAULT_GATEWAY_RETRY_CONFIG","retry","getServiceIdentity","debug","internalUrl","getInternalUrl","crossLayerUrl","getCrossLayerUrl","getInternalGatewayUrl","getCrossLayerGatewayUrl","internalQuery","context","createRequestContext","executeWithRetry","bypassPermission","crossLayerQuery","query","getInternalCircuitBreaker","getCrossLayerCircuitBreaker","getHealthStatus","internal","url","circuitState","stats","crossLayer","updateDefaultHeaders","callType","requestId","actorId","workspaceId","startTime","shouldRetryError","error","GRAPHQL_ERROR","CIRCUIT_OPEN","calculateRetryDelay","attempt","Math","min","initialDelay","pow","backoffMultiplier","maxDelay","logRetryAttempt","maxAttempts","delay","settings","skipCircuitBreaker","skipRetry","lastError","result","executeRequest","String","sleep","UNKNOWN_ERROR","buildRequestHeaders","cfHeaders","ContextManager","getCfAccessHeaders","assign","value","entries","undefined","toString","cfCookie","existing","split","some","c","handleGraphQLErrors","duration","errors","errorMessages","map","e","join","handleFetchError","TIMEOUT_ERROR","NETWORK_ERROR","serviceActorId","serviceJwt","signServiceJwt","body","JSON","stringify","variables","operationName","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","signal","clearTimeout","ok","status","statusText","json","hasData","data","ms","Promise","resolve","createGatewayClient","createGatewayClientFromEnv"],"mappings":"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","file":"chunk-JOJNTJQS.js","sourcesContent":["/**\n * Gateway Module\n *\n * Provides unified gateway client for layer-aware M2M communication\n * with circuit breaker and retry logic.\n *\n * @module gateway\n * @category Gateway\n *\n * @example\n * ```typescript\n * import { GatewayClient, createGatewayClientFromEnv } from '@burdenoff/be-sdk/gateway';\n *\n * // Create from environment variables\n * const client = createGatewayClientFromEnv();\n *\n * // Or create manually\n * const client = new GatewayClient({\n * layer: 'wspace',\n * serviceName: 'wspace-tags-svc',\n * });\n *\n * // Internal call (same layer, uses int-gateway with bypass)\n * const internalResult = await client.internalQuery({\n * query: `query { getTag(id: \"123\") { id name } }`,\n * });\n *\n * // Cross-layer call (via public gateway)\n * const crossLayerResult = await client.crossLayerQuery({\n * query: `query { getCurrentUser { id email } }`,\n * });\n * ```\n */\n\n// Client exports\nexport { GatewayClient, createGatewayClient, createGatewayClientFromEnv } from './client.js';\n\n// Service-JWT minting for cross-layer M2M auth. Exposed so non-GatewayClient\n// callers (e.g. bespoke graphql-request clients) can authenticate identically.\nexport { signServiceJwt } from './service-jwt.js';\n\n// Type exports\nexport {\n CircuitState,\n GatewayErrorType,\n GatewayError,\n type GatewayClientConfig,\n type GraphQLRequestOptions,\n type GraphQLResponse,\n type GraphQLError,\n type IGatewayClient,\n type ICircuitBreaker,\n type CircuitBreakerStats,\n type GatewayClientHealth,\n type RequestContext,\n} from './types.js';\n\n// Gateway-side security plugin stack (for public gateways).\n// Imported by consumers as `@burdenoff/be-sdk/gateway/security` — this\n// re-export lets `@burdenoff/be-sdk/gateway` also resolve the namespace.\nexport * as Security from './security/index.js';\n","/**\n * Gateway Client Types\n *\n * Type definitions for the unified gateway client with\n * circuit breaker and retry logic.\n *\n * @module gateway/types\n * @category Gateway\n */\n\nimport type { ServiceLayer, CircuitBreakerConfig, GatewayRetryConfig, GatewayRequestHeaders } from '../types/layer.js';\n\n/**\n * Gateway client configuration\n */\nexport interface GatewayClientConfig {\n /**\n * Layer this client belongs to\n */\n layer: ServiceLayer;\n\n /**\n * Service name (for logging and headers)\n */\n serviceName: string;\n\n /**\n * Service identity for bypass headers\n * @default serviceName\n */\n serviceIdentity?: string;\n\n /**\n * Internal gateway URL (same layer M2M)\n * @default Resolved from layer defaults or environment\n */\n internalGatewayUrl?: string;\n\n /**\n * Cross-layer gateway URL (cross layer via public gateway)\n * @default Resolved from layer defaults or environment\n */\n crossLayerGatewayUrl?: string;\n\n /**\n * Request timeout in milliseconds\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n\n /**\n * Circuit breaker configuration\n */\n circuitBreaker?: Partial<CircuitBreakerConfig>;\n\n /**\n * Retry configuration\n */\n retry?: Partial<GatewayRetryConfig>;\n\n /**\n * Enable request logging\n * @default true\n */\n enableLogging?: boolean;\n\n /**\n * Default headers to include in all requests\n */\n defaultHeaders?: GatewayRequestHeaders;\n}\n\n/**\n * Circuit breaker states\n */\nexport enum CircuitState {\n CLOSED = 'CLOSED',\n OPEN = 'OPEN',\n HALF_OPEN = 'HALF_OPEN',\n}\n\n/**\n * Circuit breaker instance interface\n */\nexport interface ICircuitBreaker {\n /**\n * Get current circuit state\n */\n getState(): CircuitState;\n\n /**\n * Record a successful call\n */\n recordSuccess(): void;\n\n /**\n * Record a failed call\n */\n recordFailure(): void;\n\n /**\n * Check if circuit allows calls\n */\n allowRequest(): boolean;\n\n /**\n * Force open the circuit\n */\n forceOpen(): void;\n\n /**\n * Force close the circuit\n */\n forceClose(): void;\n\n /**\n * Get circuit statistics\n */\n getStats(): CircuitBreakerStats;\n}\n\n/**\n * Circuit breaker statistics\n */\nexport interface CircuitBreakerStats {\n state: CircuitState;\n failures: number;\n successes: number;\n consecutiveFailures: number;\n lastFailureTime: number | null;\n lastSuccessTime: number | null;\n openedAt: number | null;\n}\n\n/**\n * GraphQL request options\n */\nexport interface GraphQLRequestOptions {\n /**\n * GraphQL query or mutation string\n */\n query: string;\n\n /**\n * GraphQL variables\n */\n variables?: Record<string, unknown>;\n\n /**\n * Operation name (for multi-operation documents)\n */\n operationName?: string;\n\n /**\n * Additional headers for this request\n */\n headers?: GatewayRequestHeaders;\n\n /**\n * Override timeout for this request\n */\n timeout?: number;\n\n /**\n * Skip circuit breaker for this request\n * @default false\n */\n skipCircuitBreaker?: boolean;\n\n /**\n * Skip retry logic for this request\n * @default false\n */\n skipRetry?: boolean;\n}\n\n/**\n * GraphQL response\n */\nexport interface GraphQLResponse<T = unknown> {\n /**\n * Response data\n */\n data?: T;\n\n /**\n * GraphQL errors\n */\n errors?: GraphQLError[];\n}\n\n/**\n * GraphQL error structure\n */\nexport interface GraphQLError {\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n}\n\n/**\n * Gateway client interface\n */\nexport interface IGatewayClient {\n /**\n * Execute internal (same layer) GraphQL query/mutation\n *\n * Uses internal gateway with bypass headers for M2M communication.\n *\n * @param options - Request options\n * @returns GraphQL response\n */\n internalQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Execute cross-layer GraphQL query/mutation\n *\n * Uses public gateway for cross-layer communication.\n *\n * @param options - Request options\n * @returns GraphQL response\n */\n crossLayerQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Execute GraphQL query/mutation with explicit gateway URL\n *\n * @param gatewayUrl - Gateway URL to use\n * @param options - Request options\n * @returns GraphQL response\n */\n query<T = unknown>(gatewayUrl: string, options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Get internal gateway circuit breaker\n */\n getInternalCircuitBreaker(): ICircuitBreaker;\n\n /**\n * Get cross-layer gateway circuit breaker\n */\n getCrossLayerCircuitBreaker(): ICircuitBreaker;\n\n /**\n * Get client health status\n */\n getHealthStatus(): GatewayClientHealth;\n\n /**\n * Update default headers\n */\n updateDefaultHeaders(headers: Partial<GatewayRequestHeaders>): void;\n}\n\n/**\n * Gateway client health status\n */\nexport interface GatewayClientHealth {\n /**\n * Internal gateway status\n */\n internal: {\n url: string;\n circuitState: CircuitState;\n stats: CircuitBreakerStats;\n };\n\n /**\n * Cross-layer gateway status\n */\n crossLayer: {\n url: string;\n circuitState: CircuitState;\n stats: CircuitBreakerStats;\n };\n}\n\n/**\n * Gateway error types\n */\nexport enum GatewayErrorType {\n NETWORK_ERROR = 'NETWORK_ERROR',\n TIMEOUT_ERROR = 'TIMEOUT_ERROR',\n CIRCUIT_OPEN = 'CIRCUIT_OPEN',\n GRAPHQL_ERROR = 'GRAPHQL_ERROR',\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\n/**\n * Gateway error class\n */\nexport class GatewayError extends Error {\n type: GatewayErrorType;\n gatewayUrl: string;\n statusCode?: number;\n graphqlErrors?: GraphQLError[];\n override cause?: Error;\n\n constructor(\n message: string,\n type: GatewayErrorType,\n gatewayUrl: string,\n options?: {\n statusCode?: number;\n graphqlErrors?: GraphQLError[];\n cause?: Error;\n }\n ) {\n super(message);\n this.name = 'GatewayError';\n this.type = type;\n this.gatewayUrl = gatewayUrl;\n this.statusCode = options?.statusCode;\n this.graphqlErrors = options?.graphqlErrors;\n this.cause = options?.cause;\n Object.setPrototypeOf(this, GatewayError.prototype);\n }\n}\n\n/**\n * Request context for logging and tracing\n */\nexport interface RequestContext {\n /**\n * Request ID for tracing\n */\n requestId: string;\n\n /**\n * Actor ID making the request\n */\n actorId?: string;\n\n /**\n * Workspace ID context\n */\n workspaceId?: string;\n\n /**\n * Timestamp when request started\n */\n startTime: number;\n\n /**\n * Call type\n */\n callType: 'internal' | 'cross-layer' | 'direct';\n}\n","/**\n * Unified Gateway Client\n *\n * Provides a layer-aware GraphQL client with circuit breaker,\n * retry logic, and automatic header management for M2M communication.\n *\n * @module gateway/client\n * @category Gateway\n *\n * @example\n * ```typescript\n * import { GatewayClient } from '@burdenoff/be-sdk/gateway';\n *\n * const client = new GatewayClient({\n * layer: 'wspace',\n * serviceName: 'wspace-tags-svc',\n * });\n *\n * // Internal call (same layer)\n * const result = await client.internalQuery({\n * query: `query { getTag(id: \"123\") { id name } }`,\n * });\n *\n * // Cross-layer call\n * const authResult = await client.crossLayerQuery({\n * query: `query { getCurrentUser { id email } }`,\n * });\n * ```\n */\n\nimport { ContextManager } from '../context/index.js';\nimport { LayerManager } from '../layer/index.js';\nimport { logger } from '../logger/index.js';\nimport { signServiceJwt } from './service-jwt.js';\nimport {\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n DEFAULT_GATEWAY_RETRY_CONFIG,\n type CircuitBreakerConfig,\n type GatewayRequestHeaders,\n type GatewayRetryConfig,\n type ServiceLayer,\n} from '../types/layer.js';\nimport {\n CircuitState,\n GatewayError,\n GatewayErrorType,\n type CircuitBreakerStats,\n type GatewayClientConfig,\n type GatewayClientHealth,\n type GraphQLError,\n type GraphQLRequestOptions,\n type GraphQLResponse,\n type ICircuitBreaker,\n type IGatewayClient,\n type RequestContext,\n} from './types.js';\n\nconst uuidv4 = (): string => crypto.randomUUID();\n\n/**\n * Case-insensitive presence check for the `Authorization` header. HTTP header\n * names are case-insensitive (RFC 7230), and while the outbound `fetch` will\n * preserve whatever casing the caller supplies, callers may legitimately set\n * `authorization` / `Authorization` / even `AUTHORIZATION` via defaultHeaders\n * or options.headers. We must not overwrite an already-supplied token.\n */\nfunction hasAuthorizationHeader(headers: Record<string, string>): boolean {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === 'authorization') return true;\n }\n return false;\n}\n\nexport function resolveBypassPermissionValue(\n token: string | undefined = process.env['INTERNAL_SERVICE_TOKEN']\n): string {\n const normalizedToken = token?.trim();\n\n if (!normalizedToken) {\n throw new Error('INTERNAL_SERVICE_TOKEN must be configured for bypass-enabled gateway calls');\n }\n\n return normalizedToken;\n}\n\n/**\n * Circuit Breaker Implementation\n */\nclass CircuitBreaker implements ICircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failures = 0;\n private successes = 0;\n private consecutiveFailures = 0;\n private lastFailureTime: number | null = null;\n private lastSuccessTime: number | null = null;\n private openedAt: number | null = null;\n private failureTimestamps: number[] = [];\n private config: CircuitBreakerConfig;\n\n constructor(config: CircuitBreakerConfig) {\n this.config = config;\n }\n\n getState(): CircuitState {\n this.checkStateTransition();\n return this.state;\n }\n\n recordSuccess(): void {\n this.successes++;\n this.consecutiveFailures = 0;\n this.lastSuccessTime = Date.now();\n\n if (this.state === CircuitState.HALF_OPEN) {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.failureTimestamps = [];\n this.openedAt = null;\n logger.info('[CircuitBreaker] Circuit closed after successful test');\n }\n }\n\n recordFailure(): void {\n this.failures++;\n this.consecutiveFailures++;\n this.lastFailureTime = Date.now();\n this.failureTimestamps.push(Date.now());\n\n // Clean up old timestamps\n const windowStart = Date.now() - this.config.failureWindow;\n this.failureTimestamps = this.failureTimestamps.filter((t) => t > windowStart);\n\n // Check if we should open the circuit\n if (this.state === CircuitState.CLOSED && this.failureTimestamps.length >= this.config.failureThreshold) {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.warn('[CircuitBreaker] Circuit opened due to failures', {\n failures: this.failureTimestamps.length,\n threshold: this.config.failureThreshold,\n });\n }\n\n // If we're half-open and fail, go back to open\n if (this.state === CircuitState.HALF_OPEN) {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.warn('[CircuitBreaker] Circuit re-opened after failed test');\n }\n }\n\n allowRequest(): boolean {\n this.checkStateTransition();\n\n switch (this.state) {\n case CircuitState.CLOSED:\n return true;\n case CircuitState.OPEN:\n return false;\n case CircuitState.HALF_OPEN:\n // Allow one test request\n return true;\n default:\n return true;\n }\n }\n\n forceOpen(): void {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.info('[CircuitBreaker] Circuit force-opened');\n }\n\n forceClose(): void {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.consecutiveFailures = 0;\n this.failureTimestamps = [];\n this.openedAt = null;\n logger.info('[CircuitBreaker] Circuit force-closed');\n }\n\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n consecutiveFailures: this.consecutiveFailures,\n lastFailureTime: this.lastFailureTime,\n lastSuccessTime: this.lastSuccessTime,\n openedAt: this.openedAt,\n };\n }\n\n private checkStateTransition(): void {\n if (this.state === CircuitState.OPEN && this.openedAt) {\n const elapsed = Date.now() - this.openedAt;\n if (elapsed >= this.config.resetTimeout) {\n this.state = CircuitState.HALF_OPEN;\n logger.info('[CircuitBreaker] Circuit transitioning to half-open');\n }\n }\n }\n}\n\n/**\n * Unified Gateway Client\n */\nexport class GatewayClient implements IGatewayClient {\n private config: GatewayClientConfig;\n private layerManager: LayerManager;\n private internalCircuitBreaker: CircuitBreaker;\n private crossLayerCircuitBreaker: CircuitBreaker;\n private retryConfig: GatewayRetryConfig;\n private defaultHeaders: GatewayRequestHeaders;\n\n constructor(config: GatewayClientConfig) {\n this.config = {\n timeout: 30000,\n enableLogging: true,\n ...config,\n };\n\n // Initialize layer manager\n this.layerManager = new LayerManager({\n layer: config.layer,\n serviceName: config.serviceName,\n serviceIdentity: config.serviceIdentity,\n });\n\n // Override URLs if provided\n if (config.internalGatewayUrl) {\n // Use getter internally, but we'll store the override\n }\n if (config.crossLayerGatewayUrl) {\n // Use getter internally, but we'll store the override\n }\n\n // Initialize circuit breakers\n const cbConfig: CircuitBreakerConfig = {\n ...DEFAULT_CIRCUIT_BREAKER_CONFIG,\n ...config.circuitBreaker,\n };\n this.internalCircuitBreaker = new CircuitBreaker(cbConfig);\n this.crossLayerCircuitBreaker = new CircuitBreaker(cbConfig);\n\n // Initialize retry config\n this.retryConfig = {\n ...DEFAULT_GATEWAY_RETRY_CONFIG,\n ...config.retry,\n };\n\n // Initialize default headers\n this.defaultHeaders = {\n 'x-service-identity': this.layerManager.getServiceIdentity(),\n 'x-actor-type': 'service',\n ...config.defaultHeaders,\n };\n\n logger.debug('[GatewayClient] Initialized', {\n layer: config.layer,\n serviceName: config.serviceName,\n internalUrl: this.getInternalUrl(),\n crossLayerUrl: this.getCrossLayerUrl(),\n });\n }\n\n private getInternalUrl(): string {\n return this.config.internalGatewayUrl || this.layerManager.getInternalGatewayUrl();\n }\n\n private getCrossLayerUrl(): string {\n return this.config.crossLayerGatewayUrl || this.layerManager.getCrossLayerGatewayUrl();\n }\n\n /**\n * Execute internal (same layer) GraphQL query/mutation\n */\n async internalQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('internal', options);\n\n return this.executeWithRetry(this.getInternalUrl(), options, this.internalCircuitBreaker, context, {\n bypassPermission: true,\n });\n }\n\n /**\n * Execute cross-layer GraphQL query/mutation\n */\n async crossLayerQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('cross-layer', options);\n\n return this.executeWithRetry(\n this.getCrossLayerUrl(),\n options,\n this.crossLayerCircuitBreaker,\n context,\n { bypassPermission: false } // Cross-layer calls go through public gateway\n );\n }\n\n /**\n * Execute GraphQL query/mutation with explicit gateway URL\n */\n async query<T = unknown>(gatewayUrl: string, options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('direct', options);\n\n // Use internal circuit breaker for direct calls\n return this.executeWithRetry(gatewayUrl, options, this.internalCircuitBreaker, context, {\n bypassPermission: false,\n });\n }\n\n getInternalCircuitBreaker(): ICircuitBreaker {\n return this.internalCircuitBreaker;\n }\n\n getCrossLayerCircuitBreaker(): ICircuitBreaker {\n return this.crossLayerCircuitBreaker;\n }\n\n getHealthStatus(): GatewayClientHealth {\n return {\n internal: {\n url: this.getInternalUrl(),\n circuitState: this.internalCircuitBreaker.getState(),\n stats: this.internalCircuitBreaker.getStats(),\n },\n crossLayer: {\n url: this.getCrossLayerUrl(),\n circuitState: this.crossLayerCircuitBreaker.getState(),\n stats: this.crossLayerCircuitBreaker.getStats(),\n },\n };\n }\n\n updateDefaultHeaders(headers: Partial<GatewayRequestHeaders>): void {\n this.defaultHeaders = { ...this.defaultHeaders, ...headers };\n }\n\n private createRequestContext(\n callType: 'internal' | 'cross-layer' | 'direct',\n options: GraphQLRequestOptions\n ): RequestContext {\n return {\n requestId: uuidv4(),\n actorId: options.headers?.['x-actor-id'] || this.defaultHeaders['x-actor-id'],\n workspaceId: options.headers?.['x-workspace-id'] || this.defaultHeaders['x-workspace-id'],\n startTime: Date.now(),\n callType,\n };\n }\n\n /**\n * Check if an error should be retried\n */\n private shouldRetryError(error: unknown): boolean {\n if (!(error instanceof GatewayError)) {\n return true;\n }\n // Don't retry GraphQL errors or circuit open errors\n return error.type !== GatewayErrorType.GRAPHQL_ERROR && error.type !== GatewayErrorType.CIRCUIT_OPEN;\n }\n\n /**\n * Calculate retry delay with exponential backoff\n */\n private calculateRetryDelay(attempt: number): number {\n return Math.min(\n this.retryConfig.initialDelay * Math.pow(this.retryConfig.backoffMultiplier, attempt - 1),\n this.retryConfig.maxDelay\n );\n }\n\n /**\n * Log retry attempt if logging is enabled\n */\n private logRetryAttempt(\n context: RequestContext,\n attempt: number,\n maxAttempts: number,\n delay: number,\n error: Error\n ): void {\n if (this.config.enableLogging) {\n logger.warn('[GatewayClient] Request failed, retrying', {\n requestId: context.requestId,\n attempt,\n maxAttempts,\n delay,\n error: error.message,\n });\n }\n }\n\n private async executeWithRetry<T>(\n gatewayUrl: string,\n options: GraphQLRequestOptions,\n circuitBreaker: CircuitBreaker,\n context: RequestContext,\n settings: { bypassPermission: boolean }\n ): Promise<GraphQLResponse<T>> {\n // Check circuit breaker\n if (!options.skipCircuitBreaker && !circuitBreaker.allowRequest()) {\n throw new GatewayError(`Circuit breaker is open for ${gatewayUrl}`, GatewayErrorType.CIRCUIT_OPEN, gatewayUrl);\n }\n\n const maxAttempts = options.skipRetry ? 1 : this.retryConfig.maxAttempts;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const result = await this.executeRequest<T>(gatewayUrl, options, context, settings.bypassPermission);\n if (!options.skipCircuitBreaker) {\n circuitBreaker.recordSuccess();\n }\n return result;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (!options.skipCircuitBreaker) {\n circuitBreaker.recordFailure();\n }\n\n if (!this.shouldRetryError(error)) {\n throw error;\n }\n\n if (attempt < maxAttempts) {\n const delay = this.calculateRetryDelay(attempt);\n this.logRetryAttempt(context, attempt, maxAttempts, delay, lastError);\n await this.sleep(delay);\n }\n }\n }\n\n throw lastError || new GatewayError('Request failed after retries', GatewayErrorType.UNKNOWN_ERROR, gatewayUrl);\n }\n\n /**\n * Build headers for a request\n */\n private buildRequestHeaders(\n context: RequestContext,\n options: GraphQLRequestOptions,\n bypassPermission: boolean\n ): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-request-id': context.requestId,\n 'x-call-type': context.callType,\n };\n\n // Cross-layer calls transit the peer layer's PUBLIC gateway, which on alpha\n // sits behind Cloudflare Access. Re-present the inbound request's CF creds\n // (service token and/or the CF_Authorization cookie) so the call passes the\n // CF edge. Added before default/request headers so a caller may still\n // override the non-cookie CF headers explicitly; the CF cookie is reconciled\n // after the merges below so it is never silently clobbered. No-op when the\n // inbound request carried no CF creds (local dev, production) — returns {}.\n const cfHeaders = context.callType === 'cross-layer' ? ContextManager.getCfAccessHeaders() : {};\n Object.assign(headers, cfHeaders);\n\n // Add default headers\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value !== undefined) {\n headers[key] = String(value);\n }\n }\n\n // Add request-specific headers\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n if (value !== undefined) {\n headers[key] = String(value);\n }\n }\n }\n\n // Add bypass headers for internal calls\n if (bypassPermission) {\n headers['x-bypass-permission'] = resolveBypassPermissionValue();\n headers['x-bypass-source'] = this.layerManager.getServiceIdentity();\n headers['x-bypass-timestamp'] = Date.now().toString();\n }\n\n // Reconcile the CF_Authorization cookie: the default/request-header merges\n // above may set their own `cookie`, which would otherwise clobber the CF\n // cookie applied earlier (or vice versa). Merge so both survive, without\n // duplicating if it's already present.\n const cfCookie = cfHeaders['cookie'];\n if (cfCookie) {\n const existing = headers['cookie'];\n if (!existing) {\n headers['cookie'] = cfCookie;\n } else if (!existing.split(';').some((c) => c.trim() === cfCookie)) {\n headers['cookie'] = `${existing}; ${cfCookie}`;\n }\n }\n\n return headers;\n }\n\n /**\n * Handle GraphQL errors in response\n */\n private handleGraphQLErrors<T>(\n result: GraphQLResponse<T>,\n context: RequestContext,\n gatewayUrl: string,\n duration: number\n ): void {\n if (!result.errors || result.errors.length === 0) {\n return;\n }\n\n const errorMessages = result.errors.map((e: GraphQLError) => e.message).join(', ');\n\n if (this.config.enableLogging) {\n logger.warn('[GatewayClient] GraphQL errors', {\n requestId: context.requestId,\n errors: result.errors,\n duration,\n });\n }\n\n throw new GatewayError(`GraphQL error: ${errorMessages}`, GatewayErrorType.GRAPHQL_ERROR, gatewayUrl, {\n graphqlErrors: result.errors,\n });\n }\n\n /**\n * Handle fetch errors\n */\n private handleFetchError(\n error: unknown,\n context: RequestContext,\n gatewayUrl: string,\n timeout: number,\n duration: number\n ): never {\n if (error instanceof GatewayError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new GatewayError(`Request timed out after ${timeout}ms`, GatewayErrorType.TIMEOUT_ERROR, gatewayUrl, {\n cause: error,\n });\n }\n\n if (this.config.enableLogging) {\n logger.error('[GatewayClient] Request failed', {\n requestId: context.requestId,\n error: error.message,\n duration,\n });\n }\n\n throw new GatewayError(error.message, GatewayErrorType.NETWORK_ERROR, gatewayUrl, {\n cause: error,\n });\n }\n\n throw new GatewayError(String(error), GatewayErrorType.UNKNOWN_ERROR, gatewayUrl);\n }\n\n private async executeRequest<T>(\n gatewayUrl: string,\n options: GraphQLRequestOptions,\n context: RequestContext,\n bypassPermission: boolean\n ): Promise<GraphQLResponse<T>> {\n const timeout = options.timeout || this.config.timeout || 30000;\n const headers = this.buildRequestHeaders(context, options, bypassPermission);\n\n // Cross-layer calls transit the peer layer's PUBLIC gateway, which\n // requires JWT auth to propagate actor context. Mint a short-lived\n // service-actor JWT so the gateway admits the call and preserves\n // `x-actor-type: service` downstream. Skipped when the caller has\n // already supplied an Authorization header (e.g., user-originated\n // cross-layer flows) or when SERVICE_JWT_SECRET is unset.\n if (context.callType === 'cross-layer' && !hasAuthorizationHeader(headers)) {\n const serviceActorId = this.layerManager.getServiceIdentity();\n const serviceJwt = await signServiceJwt(serviceActorId);\n if (serviceJwt) {\n headers['Authorization'] = `Bearer ${serviceJwt}`;\n } else if (this.config.enableLogging) {\n // Subtle failure mode: without the JWT the public gateway strips\n // actor headers and the subgraph rejects with `authenticationRequired`.\n // Surface the root cause so operators rolling out a new caller don't\n // spend time debugging the downstream error.\n logger.debug(\n '[GatewayClient] SERVICE_JWT_SECRET not configured — cross-layer call will proceed without service JWT',\n { requestId: context.requestId, gatewayUrl }\n );\n }\n }\n\n const body = JSON.stringify({\n query: options.query,\n variables: options.variables || {},\n operationName: options.operationName,\n });\n\n if (this.config.enableLogging) {\n logger.debug('[GatewayClient] Executing request', {\n requestId: context.requestId,\n gatewayUrl,\n operationName: options.operationName,\n callType: context.callType,\n bypassPermission,\n });\n }\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n const response = await fetch(gatewayUrl, {\n method: 'POST',\n headers,\n body,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const duration = Date.now() - context.startTime;\n\n if (!response.ok) {\n throw new GatewayError(\n `HTTP ${response.status}: ${response.statusText}`,\n GatewayErrorType.NETWORK_ERROR,\n gatewayUrl,\n { statusCode: response.status }\n );\n }\n\n const result = (await response.json()) as GraphQLResponse<T>;\n this.handleGraphQLErrors(result, context, gatewayUrl, duration);\n\n if (this.config.enableLogging) {\n logger.debug('[GatewayClient] Request completed', {\n requestId: context.requestId,\n duration,\n hasData: !!result.data,\n });\n }\n\n return result;\n } catch (error) {\n const duration = Date.now() - context.startTime;\n this.handleFetchError(error, context, gatewayUrl, timeout, duration);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Create a gateway client for a specific layer\n */\nexport function createGatewayClient(config: GatewayClientConfig): GatewayClient {\n return new GatewayClient(config);\n}\n\n/**\n * Create a gateway client from environment variables\n *\n * Required environment variables:\n * - SERVICE_LAYER: 'wspace' | 'global'\n * - SERVICE_NAME: Service name\n *\n * Optional:\n * - SERVICE_IDENTITY: Service identity (defaults to SERVICE_NAME)\n * - {LAYER}_INT_GATEWAY_URL: Internal gateway URL\n * - {OPPOSITE_LAYER}_PUBLIC_GATEWAY_URL: Cross-layer gateway URL\n */\nexport function createGatewayClientFromEnv(): GatewayClient {\n const layer = process.env['SERVICE_LAYER'] as ServiceLayer;\n\n if (!layer || (layer !== 'wspace' && layer !== 'global')) {\n throw new Error(`[GatewayClient] Invalid or missing SERVICE_LAYER. Expected 'wspace' or 'global', got '${layer}'`);\n }\n\n const serviceName = process.env['SERVICE_NAME'];\n if (!serviceName) {\n throw new Error('[GatewayClient] SERVICE_NAME environment variable is required');\n }\n\n const serviceIdentity = process.env['SERVICE_IDENTITY'] || serviceName;\n\n return new GatewayClient({\n layer,\n serviceName,\n serviceIdentity,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/gateway/index.ts","../src/gateway/types.ts","../src/gateway/client.ts"],"names":["CircuitState","GatewayErrorType","GatewayError","Error","type","gatewayUrl","statusCode","graphqlErrors","cause","message","options","name","Object","setPrototypeOf","prototype","uuidv4","crypto","randomUUID","hasAuthorizationHeader","headers","key","keys","toLowerCase","resolveBypassPermissionValue","token","process","env","normalizedToken","trim","CircuitBreaker","state","CLOSED","failures","successes","consecutiveFailures","lastFailureTime","lastSuccessTime","openedAt","failureTimestamps","config","getState","checkStateTransition","recordSuccess","Date","now","HALF_OPEN","logger","info","recordFailure","push","windowStart","failureWindow","filter","t","length","failureThreshold","OPEN","warn","threshold","allowRequest","forceOpen","forceClose","getStats","elapsed","resetTimeout","GatewayClient","layerManager","internalCircuitBreaker","crossLayerCircuitBreaker","retryConfig","defaultHeaders","timeout","enableLogging","LayerManager","layer","serviceName","serviceIdentity","internalGatewayUrl","crossLayerGatewayUrl","cbConfig","DEFAULT_CIRCUIT_BREAKER_CONFIG","circuitBreaker","DEFAULT_GATEWAY_RETRY_CONFIG","retry","getServiceIdentity","debug","internalUrl","getInternalUrl","crossLayerUrl","getCrossLayerUrl","getInternalGatewayUrl","getCrossLayerGatewayUrl","internalQuery","context","createRequestContext","executeWithRetry","bypassPermission","crossLayerQuery","query","getInternalCircuitBreaker","getCrossLayerCircuitBreaker","getHealthStatus","internal","url","circuitState","stats","crossLayer","updateDefaultHeaders","callType","requestId","actorId","workspaceId","startTime","shouldRetryError","error","GRAPHQL_ERROR","CIRCUIT_OPEN","calculateRetryDelay","attempt","Math","min","initialDelay","pow","backoffMultiplier","maxDelay","logRetryAttempt","maxAttempts","delay","settings","skipCircuitBreaker","skipRetry","lastError","result","executeRequest","String","sleep","UNKNOWN_ERROR","buildRequestHeaders","cfHeaders","ContextManager","getCfAccessHeaders","assign","value","entries","undefined","toString","cfCookie","existing","split","some","c","handleGraphQLErrors","duration","errors","errorMessages","map","e","join","handleFetchError","TIMEOUT_ERROR","NETWORK_ERROR","serviceActorId","serviceJwt","signServiceJwt","body","JSON","stringify","variables","operationName","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","signal","clearTimeout","ok","status","statusText","json","hasData","data","ms","Promise","resolve","createGatewayClient","createGatewayClientFromEnv"],"mappings":"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","file":"chunk-IDKU7OGF.js","sourcesContent":["/**\n * Gateway Module\n *\n * Provides unified gateway client for layer-aware M2M communication\n * with circuit breaker and retry logic.\n *\n * @module gateway\n * @category Gateway\n *\n * @example\n * ```typescript\n * import { GatewayClient, createGatewayClientFromEnv } from '@burdenoff/be-sdk/gateway';\n *\n * // Create from environment variables\n * const client = createGatewayClientFromEnv();\n *\n * // Or create manually\n * const client = new GatewayClient({\n * layer: 'wspace',\n * serviceName: 'wspace-tags-svc',\n * });\n *\n * // Internal call (same layer, uses int-gateway with bypass)\n * const internalResult = await client.internalQuery({\n * query: `query { getTag(id: \"123\") { id name } }`,\n * });\n *\n * // Cross-layer call (via public gateway)\n * const crossLayerResult = await client.crossLayerQuery({\n * query: `query { getCurrentUser { id email } }`,\n * });\n * ```\n */\n\n// Client exports\nexport { GatewayClient, createGatewayClient, createGatewayClientFromEnv } from './client.js';\n\n// Service-JWT minting for cross-layer M2M auth. Exposed so non-GatewayClient\n// callers (e.g. bespoke graphql-request clients) can authenticate identically.\nexport { signServiceJwt } from './service-jwt.js';\n\n// Type exports\nexport {\n CircuitState,\n GatewayErrorType,\n GatewayError,\n type GatewayClientConfig,\n type GraphQLRequestOptions,\n type GraphQLResponse,\n type GraphQLError,\n type IGatewayClient,\n type ICircuitBreaker,\n type CircuitBreakerStats,\n type GatewayClientHealth,\n type RequestContext,\n} from './types.js';\n\n// Gateway-side security plugin stack (for public gateways).\n// Imported by consumers as `@burdenoff/be-sdk/gateway/security` — this\n// re-export lets `@burdenoff/be-sdk/gateway` also resolve the namespace.\nexport * as Security from './security/index.js';\n","/**\n * Gateway Client Types\n *\n * Type definitions for the unified gateway client with\n * circuit breaker and retry logic.\n *\n * @module gateway/types\n * @category Gateway\n */\n\nimport type { ServiceLayer, CircuitBreakerConfig, GatewayRetryConfig, GatewayRequestHeaders } from '../types/layer.js';\n\n/**\n * Gateway client configuration\n */\nexport interface GatewayClientConfig {\n /**\n * Layer this client belongs to\n */\n layer: ServiceLayer;\n\n /**\n * Service name (for logging and headers)\n */\n serviceName: string;\n\n /**\n * Service identity for bypass headers\n * @default serviceName\n */\n serviceIdentity?: string;\n\n /**\n * Internal gateway URL (same layer M2M)\n * @default Resolved from layer defaults or environment\n */\n internalGatewayUrl?: string;\n\n /**\n * Cross-layer gateway URL (cross layer via public gateway)\n * @default Resolved from layer defaults or environment\n */\n crossLayerGatewayUrl?: string;\n\n /**\n * Request timeout in milliseconds\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n\n /**\n * Circuit breaker configuration\n */\n circuitBreaker?: Partial<CircuitBreakerConfig>;\n\n /**\n * Retry configuration\n */\n retry?: Partial<GatewayRetryConfig>;\n\n /**\n * Enable request logging\n * @default true\n */\n enableLogging?: boolean;\n\n /**\n * Default headers to include in all requests\n */\n defaultHeaders?: GatewayRequestHeaders;\n}\n\n/**\n * Circuit breaker states\n */\nexport enum CircuitState {\n CLOSED = 'CLOSED',\n OPEN = 'OPEN',\n HALF_OPEN = 'HALF_OPEN',\n}\n\n/**\n * Circuit breaker instance interface\n */\nexport interface ICircuitBreaker {\n /**\n * Get current circuit state\n */\n getState(): CircuitState;\n\n /**\n * Record a successful call\n */\n recordSuccess(): void;\n\n /**\n * Record a failed call\n */\n recordFailure(): void;\n\n /**\n * Check if circuit allows calls\n */\n allowRequest(): boolean;\n\n /**\n * Force open the circuit\n */\n forceOpen(): void;\n\n /**\n * Force close the circuit\n */\n forceClose(): void;\n\n /**\n * Get circuit statistics\n */\n getStats(): CircuitBreakerStats;\n}\n\n/**\n * Circuit breaker statistics\n */\nexport interface CircuitBreakerStats {\n state: CircuitState;\n failures: number;\n successes: number;\n consecutiveFailures: number;\n lastFailureTime: number | null;\n lastSuccessTime: number | null;\n openedAt: number | null;\n}\n\n/**\n * GraphQL request options\n */\nexport interface GraphQLRequestOptions {\n /**\n * GraphQL query or mutation string\n */\n query: string;\n\n /**\n * GraphQL variables\n */\n variables?: Record<string, unknown>;\n\n /**\n * Operation name (for multi-operation documents)\n */\n operationName?: string;\n\n /**\n * Additional headers for this request\n */\n headers?: GatewayRequestHeaders;\n\n /**\n * Override timeout for this request\n */\n timeout?: number;\n\n /**\n * Skip circuit breaker for this request\n * @default false\n */\n skipCircuitBreaker?: boolean;\n\n /**\n * Skip retry logic for this request\n * @default false\n */\n skipRetry?: boolean;\n}\n\n/**\n * GraphQL response\n */\nexport interface GraphQLResponse<T = unknown> {\n /**\n * Response data\n */\n data?: T;\n\n /**\n * GraphQL errors\n */\n errors?: GraphQLError[];\n}\n\n/**\n * GraphQL error structure\n */\nexport interface GraphQLError {\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n}\n\n/**\n * Gateway client interface\n */\nexport interface IGatewayClient {\n /**\n * Execute internal (same layer) GraphQL query/mutation\n *\n * Uses internal gateway with bypass headers for M2M communication.\n *\n * @param options - Request options\n * @returns GraphQL response\n */\n internalQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Execute cross-layer GraphQL query/mutation\n *\n * Uses public gateway for cross-layer communication.\n *\n * @param options - Request options\n * @returns GraphQL response\n */\n crossLayerQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Execute GraphQL query/mutation with explicit gateway URL\n *\n * @param gatewayUrl - Gateway URL to use\n * @param options - Request options\n * @returns GraphQL response\n */\n query<T = unknown>(gatewayUrl: string, options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Get internal gateway circuit breaker\n */\n getInternalCircuitBreaker(): ICircuitBreaker;\n\n /**\n * Get cross-layer gateway circuit breaker\n */\n getCrossLayerCircuitBreaker(): ICircuitBreaker;\n\n /**\n * Get client health status\n */\n getHealthStatus(): GatewayClientHealth;\n\n /**\n * Update default headers\n */\n updateDefaultHeaders(headers: Partial<GatewayRequestHeaders>): void;\n}\n\n/**\n * Gateway client health status\n */\nexport interface GatewayClientHealth {\n /**\n * Internal gateway status\n */\n internal: {\n url: string;\n circuitState: CircuitState;\n stats: CircuitBreakerStats;\n };\n\n /**\n * Cross-layer gateway status\n */\n crossLayer: {\n url: string;\n circuitState: CircuitState;\n stats: CircuitBreakerStats;\n };\n}\n\n/**\n * Gateway error types\n */\nexport enum GatewayErrorType {\n NETWORK_ERROR = 'NETWORK_ERROR',\n TIMEOUT_ERROR = 'TIMEOUT_ERROR',\n CIRCUIT_OPEN = 'CIRCUIT_OPEN',\n GRAPHQL_ERROR = 'GRAPHQL_ERROR',\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\n/**\n * Gateway error class\n */\nexport class GatewayError extends Error {\n type: GatewayErrorType;\n gatewayUrl: string;\n statusCode?: number;\n graphqlErrors?: GraphQLError[];\n override cause?: Error;\n\n constructor(\n message: string,\n type: GatewayErrorType,\n gatewayUrl: string,\n options?: {\n statusCode?: number;\n graphqlErrors?: GraphQLError[];\n cause?: Error;\n }\n ) {\n super(message);\n this.name = 'GatewayError';\n this.type = type;\n this.gatewayUrl = gatewayUrl;\n this.statusCode = options?.statusCode;\n this.graphqlErrors = options?.graphqlErrors;\n this.cause = options?.cause;\n Object.setPrototypeOf(this, GatewayError.prototype);\n }\n}\n\n/**\n * Request context for logging and tracing\n */\nexport interface RequestContext {\n /**\n * Request ID for tracing\n */\n requestId: string;\n\n /**\n * Actor ID making the request\n */\n actorId?: string;\n\n /**\n * Workspace ID context\n */\n workspaceId?: string;\n\n /**\n * Timestamp when request started\n */\n startTime: number;\n\n /**\n * Call type\n */\n callType: 'internal' | 'cross-layer' | 'direct';\n}\n","/**\n * Unified Gateway Client\n *\n * Provides a layer-aware GraphQL client with circuit breaker,\n * retry logic, and automatic header management for M2M communication.\n *\n * @module gateway/client\n * @category Gateway\n *\n * @example\n * ```typescript\n * import { GatewayClient } from '@burdenoff/be-sdk/gateway';\n *\n * const client = new GatewayClient({\n * layer: 'wspace',\n * serviceName: 'wspace-tags-svc',\n * });\n *\n * // Internal call (same layer)\n * const result = await client.internalQuery({\n * query: `query { getTag(id: \"123\") { id name } }`,\n * });\n *\n * // Cross-layer call\n * const authResult = await client.crossLayerQuery({\n * query: `query { getCurrentUser { id email } }`,\n * });\n * ```\n */\n\nimport { ContextManager } from '../context/index.js';\nimport { LayerManager } from '../layer/index.js';\nimport { logger } from '../logger/index.js';\nimport { signServiceJwt } from './service-jwt.js';\nimport {\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n DEFAULT_GATEWAY_RETRY_CONFIG,\n type CircuitBreakerConfig,\n type GatewayRequestHeaders,\n type GatewayRetryConfig,\n type ServiceLayer,\n} from '../types/layer.js';\nimport {\n CircuitState,\n GatewayError,\n GatewayErrorType,\n type CircuitBreakerStats,\n type GatewayClientConfig,\n type GatewayClientHealth,\n type GraphQLError,\n type GraphQLRequestOptions,\n type GraphQLResponse,\n type ICircuitBreaker,\n type IGatewayClient,\n type RequestContext,\n} from './types.js';\n\nconst uuidv4 = (): string => crypto.randomUUID();\n\n/**\n * Case-insensitive presence check for the `Authorization` header. HTTP header\n * names are case-insensitive (RFC 7230), and while the outbound `fetch` will\n * preserve whatever casing the caller supplies, callers may legitimately set\n * `authorization` / `Authorization` / even `AUTHORIZATION` via defaultHeaders\n * or options.headers. We must not overwrite an already-supplied token.\n */\nfunction hasAuthorizationHeader(headers: Record<string, string>): boolean {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === 'authorization') return true;\n }\n return false;\n}\n\nexport function resolveBypassPermissionValue(\n token: string | undefined = process.env['INTERNAL_SERVICE_TOKEN']\n): string {\n const normalizedToken = token?.trim();\n\n if (!normalizedToken) {\n throw new Error('INTERNAL_SERVICE_TOKEN must be configured for bypass-enabled gateway calls');\n }\n\n return normalizedToken;\n}\n\n/**\n * Circuit Breaker Implementation\n */\nclass CircuitBreaker implements ICircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failures = 0;\n private successes = 0;\n private consecutiveFailures = 0;\n private lastFailureTime: number | null = null;\n private lastSuccessTime: number | null = null;\n private openedAt: number | null = null;\n private failureTimestamps: number[] = [];\n private config: CircuitBreakerConfig;\n\n constructor(config: CircuitBreakerConfig) {\n this.config = config;\n }\n\n getState(): CircuitState {\n this.checkStateTransition();\n return this.state;\n }\n\n recordSuccess(): void {\n this.successes++;\n this.consecutiveFailures = 0;\n this.lastSuccessTime = Date.now();\n\n if (this.state === CircuitState.HALF_OPEN) {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.failureTimestamps = [];\n this.openedAt = null;\n logger.info('[CircuitBreaker] Circuit closed after successful test');\n }\n }\n\n recordFailure(): void {\n this.failures++;\n this.consecutiveFailures++;\n this.lastFailureTime = Date.now();\n this.failureTimestamps.push(Date.now());\n\n // Clean up old timestamps\n const windowStart = Date.now() - this.config.failureWindow;\n this.failureTimestamps = this.failureTimestamps.filter((t) => t > windowStart);\n\n // Check if we should open the circuit\n if (this.state === CircuitState.CLOSED && this.failureTimestamps.length >= this.config.failureThreshold) {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.warn('[CircuitBreaker] Circuit opened due to failures', {\n failures: this.failureTimestamps.length,\n threshold: this.config.failureThreshold,\n });\n }\n\n // If we're half-open and fail, go back to open\n if (this.state === CircuitState.HALF_OPEN) {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.warn('[CircuitBreaker] Circuit re-opened after failed test');\n }\n }\n\n allowRequest(): boolean {\n this.checkStateTransition();\n\n switch (this.state) {\n case CircuitState.CLOSED:\n return true;\n case CircuitState.OPEN:\n return false;\n case CircuitState.HALF_OPEN:\n // Allow one test request\n return true;\n default:\n return true;\n }\n }\n\n forceOpen(): void {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.info('[CircuitBreaker] Circuit force-opened');\n }\n\n forceClose(): void {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.consecutiveFailures = 0;\n this.failureTimestamps = [];\n this.openedAt = null;\n logger.info('[CircuitBreaker] Circuit force-closed');\n }\n\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n consecutiveFailures: this.consecutiveFailures,\n lastFailureTime: this.lastFailureTime,\n lastSuccessTime: this.lastSuccessTime,\n openedAt: this.openedAt,\n };\n }\n\n private checkStateTransition(): void {\n if (this.state === CircuitState.OPEN && this.openedAt) {\n const elapsed = Date.now() - this.openedAt;\n if (elapsed >= this.config.resetTimeout) {\n this.state = CircuitState.HALF_OPEN;\n logger.info('[CircuitBreaker] Circuit transitioning to half-open');\n }\n }\n }\n}\n\n/**\n * Unified Gateway Client\n */\nexport class GatewayClient implements IGatewayClient {\n private config: GatewayClientConfig;\n private layerManager: LayerManager;\n private internalCircuitBreaker: CircuitBreaker;\n private crossLayerCircuitBreaker: CircuitBreaker;\n private retryConfig: GatewayRetryConfig;\n private defaultHeaders: GatewayRequestHeaders;\n\n constructor(config: GatewayClientConfig) {\n this.config = {\n timeout: 30000,\n enableLogging: true,\n ...config,\n };\n\n // Initialize layer manager\n this.layerManager = new LayerManager({\n layer: config.layer,\n serviceName: config.serviceName,\n serviceIdentity: config.serviceIdentity,\n });\n\n // Override URLs if provided\n if (config.internalGatewayUrl) {\n // Use getter internally, but we'll store the override\n }\n if (config.crossLayerGatewayUrl) {\n // Use getter internally, but we'll store the override\n }\n\n // Initialize circuit breakers\n const cbConfig: CircuitBreakerConfig = {\n ...DEFAULT_CIRCUIT_BREAKER_CONFIG,\n ...config.circuitBreaker,\n };\n this.internalCircuitBreaker = new CircuitBreaker(cbConfig);\n this.crossLayerCircuitBreaker = new CircuitBreaker(cbConfig);\n\n // Initialize retry config\n this.retryConfig = {\n ...DEFAULT_GATEWAY_RETRY_CONFIG,\n ...config.retry,\n };\n\n // Initialize default headers\n this.defaultHeaders = {\n 'x-service-identity': this.layerManager.getServiceIdentity(),\n 'x-actor-type': 'service',\n ...config.defaultHeaders,\n };\n\n logger.debug('[GatewayClient] Initialized', {\n layer: config.layer,\n serviceName: config.serviceName,\n internalUrl: this.getInternalUrl(),\n crossLayerUrl: this.getCrossLayerUrl(),\n });\n }\n\n private getInternalUrl(): string {\n return this.config.internalGatewayUrl || this.layerManager.getInternalGatewayUrl();\n }\n\n private getCrossLayerUrl(): string {\n return this.config.crossLayerGatewayUrl || this.layerManager.getCrossLayerGatewayUrl();\n }\n\n /**\n * Execute internal (same layer) GraphQL query/mutation\n */\n async internalQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('internal', options);\n\n return this.executeWithRetry(this.getInternalUrl(), options, this.internalCircuitBreaker, context, {\n bypassPermission: true,\n });\n }\n\n /**\n * Execute cross-layer GraphQL query/mutation\n */\n async crossLayerQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('cross-layer', options);\n\n return this.executeWithRetry(\n this.getCrossLayerUrl(),\n options,\n this.crossLayerCircuitBreaker,\n context,\n { bypassPermission: false } // Cross-layer calls go through public gateway\n );\n }\n\n /**\n * Execute GraphQL query/mutation with explicit gateway URL\n */\n async query<T = unknown>(gatewayUrl: string, options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('direct', options);\n\n // Use internal circuit breaker for direct calls\n return this.executeWithRetry(gatewayUrl, options, this.internalCircuitBreaker, context, {\n bypassPermission: false,\n });\n }\n\n getInternalCircuitBreaker(): ICircuitBreaker {\n return this.internalCircuitBreaker;\n }\n\n getCrossLayerCircuitBreaker(): ICircuitBreaker {\n return this.crossLayerCircuitBreaker;\n }\n\n getHealthStatus(): GatewayClientHealth {\n return {\n internal: {\n url: this.getInternalUrl(),\n circuitState: this.internalCircuitBreaker.getState(),\n stats: this.internalCircuitBreaker.getStats(),\n },\n crossLayer: {\n url: this.getCrossLayerUrl(),\n circuitState: this.crossLayerCircuitBreaker.getState(),\n stats: this.crossLayerCircuitBreaker.getStats(),\n },\n };\n }\n\n updateDefaultHeaders(headers: Partial<GatewayRequestHeaders>): void {\n this.defaultHeaders = { ...this.defaultHeaders, ...headers };\n }\n\n private createRequestContext(\n callType: 'internal' | 'cross-layer' | 'direct',\n options: GraphQLRequestOptions\n ): RequestContext {\n return {\n requestId: uuidv4(),\n actorId: options.headers?.['x-actor-id'] || this.defaultHeaders['x-actor-id'],\n workspaceId: options.headers?.['x-workspace-id'] || this.defaultHeaders['x-workspace-id'],\n startTime: Date.now(),\n callType,\n };\n }\n\n /**\n * Check if an error should be retried\n */\n private shouldRetryError(error: unknown): boolean {\n if (!(error instanceof GatewayError)) {\n return true;\n }\n // Don't retry GraphQL errors or circuit open errors\n return error.type !== GatewayErrorType.GRAPHQL_ERROR && error.type !== GatewayErrorType.CIRCUIT_OPEN;\n }\n\n /**\n * Calculate retry delay with exponential backoff\n */\n private calculateRetryDelay(attempt: number): number {\n return Math.min(\n this.retryConfig.initialDelay * Math.pow(this.retryConfig.backoffMultiplier, attempt - 1),\n this.retryConfig.maxDelay\n );\n }\n\n /**\n * Log retry attempt if logging is enabled\n */\n private logRetryAttempt(\n context: RequestContext,\n attempt: number,\n maxAttempts: number,\n delay: number,\n error: Error\n ): void {\n if (this.config.enableLogging) {\n logger.warn('[GatewayClient] Request failed, retrying', {\n requestId: context.requestId,\n attempt,\n maxAttempts,\n delay,\n error: error.message,\n });\n }\n }\n\n private async executeWithRetry<T>(\n gatewayUrl: string,\n options: GraphQLRequestOptions,\n circuitBreaker: CircuitBreaker,\n context: RequestContext,\n settings: { bypassPermission: boolean }\n ): Promise<GraphQLResponse<T>> {\n // Check circuit breaker\n if (!options.skipCircuitBreaker && !circuitBreaker.allowRequest()) {\n throw new GatewayError(`Circuit breaker is open for ${gatewayUrl}`, GatewayErrorType.CIRCUIT_OPEN, gatewayUrl);\n }\n\n const maxAttempts = options.skipRetry ? 1 : this.retryConfig.maxAttempts;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const result = await this.executeRequest<T>(gatewayUrl, options, context, settings.bypassPermission);\n if (!options.skipCircuitBreaker) {\n circuitBreaker.recordSuccess();\n }\n return result;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (!options.skipCircuitBreaker) {\n circuitBreaker.recordFailure();\n }\n\n if (!this.shouldRetryError(error)) {\n throw error;\n }\n\n if (attempt < maxAttempts) {\n const delay = this.calculateRetryDelay(attempt);\n this.logRetryAttempt(context, attempt, maxAttempts, delay, lastError);\n await this.sleep(delay);\n }\n }\n }\n\n throw lastError || new GatewayError('Request failed after retries', GatewayErrorType.UNKNOWN_ERROR, gatewayUrl);\n }\n\n /**\n * Build headers for a request\n */\n private buildRequestHeaders(\n context: RequestContext,\n options: GraphQLRequestOptions,\n bypassPermission: boolean\n ): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-request-id': context.requestId,\n 'x-call-type': context.callType,\n };\n\n // Cross-layer calls transit the peer layer's PUBLIC gateway, which on alpha\n // sits behind Cloudflare Access. Re-present the inbound request's CF creds\n // (service token and/or the CF_Authorization cookie) so the call passes the\n // CF edge. Added before default/request headers so a caller may still\n // override the non-cookie CF headers explicitly; the CF cookie is reconciled\n // after the merges below so it is never silently clobbered. No-op when the\n // inbound request carried no CF creds (local dev, production) — returns {}.\n const cfHeaders = context.callType === 'cross-layer' ? ContextManager.getCfAccessHeaders() : {};\n Object.assign(headers, cfHeaders);\n\n // Add default headers\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value !== undefined) {\n headers[key] = String(value);\n }\n }\n\n // Add request-specific headers\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n if (value !== undefined) {\n headers[key] = String(value);\n }\n }\n }\n\n // Add bypass headers for internal calls\n if (bypassPermission) {\n headers['x-bypass-permission'] = resolveBypassPermissionValue();\n headers['x-bypass-source'] = this.layerManager.getServiceIdentity();\n headers['x-bypass-timestamp'] = Date.now().toString();\n }\n\n // Reconcile the CF_Authorization cookie: the default/request-header merges\n // above may set their own `cookie`, which would otherwise clobber the CF\n // cookie applied earlier (or vice versa). Merge so both survive, without\n // duplicating if it's already present.\n const cfCookie = cfHeaders['cookie'];\n if (cfCookie) {\n const existing = headers['cookie'];\n if (!existing) {\n headers['cookie'] = cfCookie;\n } else if (!existing.split(';').some((c) => c.trim() === cfCookie)) {\n headers['cookie'] = `${existing}; ${cfCookie}`;\n }\n }\n\n return headers;\n }\n\n /**\n * Handle GraphQL errors in response\n */\n private handleGraphQLErrors<T>(\n result: GraphQLResponse<T>,\n context: RequestContext,\n gatewayUrl: string,\n duration: number\n ): void {\n if (!result.errors || result.errors.length === 0) {\n return;\n }\n\n const errorMessages = result.errors.map((e: GraphQLError) => e.message).join(', ');\n\n if (this.config.enableLogging) {\n logger.warn('[GatewayClient] GraphQL errors', {\n requestId: context.requestId,\n errors: result.errors,\n duration,\n });\n }\n\n throw new GatewayError(`GraphQL error: ${errorMessages}`, GatewayErrorType.GRAPHQL_ERROR, gatewayUrl, {\n graphqlErrors: result.errors,\n });\n }\n\n /**\n * Handle fetch errors\n */\n private handleFetchError(\n error: unknown,\n context: RequestContext,\n gatewayUrl: string,\n timeout: number,\n duration: number\n ): never {\n if (error instanceof GatewayError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new GatewayError(`Request timed out after ${timeout}ms`, GatewayErrorType.TIMEOUT_ERROR, gatewayUrl, {\n cause: error,\n });\n }\n\n if (this.config.enableLogging) {\n logger.error('[GatewayClient] Request failed', {\n requestId: context.requestId,\n error: error.message,\n duration,\n });\n }\n\n throw new GatewayError(error.message, GatewayErrorType.NETWORK_ERROR, gatewayUrl, {\n cause: error,\n });\n }\n\n throw new GatewayError(String(error), GatewayErrorType.UNKNOWN_ERROR, gatewayUrl);\n }\n\n private async executeRequest<T>(\n gatewayUrl: string,\n options: GraphQLRequestOptions,\n context: RequestContext,\n bypassPermission: boolean\n ): Promise<GraphQLResponse<T>> {\n const timeout = options.timeout || this.config.timeout || 30000;\n const headers = this.buildRequestHeaders(context, options, bypassPermission);\n\n // Cross-layer calls transit the peer layer's PUBLIC gateway, which\n // requires JWT auth to propagate actor context. Mint a short-lived\n // service-actor JWT so the gateway admits the call and preserves\n // `x-actor-type: service` downstream. Skipped when the caller has\n // already supplied an Authorization header (e.g., user-originated\n // cross-layer flows) or when SERVICE_JWT_SECRET is unset.\n if (context.callType === 'cross-layer' && !hasAuthorizationHeader(headers)) {\n const serviceActorId = this.layerManager.getServiceIdentity();\n const serviceJwt = await signServiceJwt(serviceActorId);\n if (serviceJwt) {\n headers['Authorization'] = `Bearer ${serviceJwt}`;\n } else if (this.config.enableLogging) {\n // Subtle failure mode: without the JWT the public gateway strips\n // actor headers and the subgraph rejects with `authenticationRequired`.\n // Surface the root cause so operators rolling out a new caller don't\n // spend time debugging the downstream error.\n logger.debug(\n '[GatewayClient] SERVICE_JWT_SECRET not configured — cross-layer call will proceed without service JWT',\n { requestId: context.requestId, gatewayUrl }\n );\n }\n }\n\n const body = JSON.stringify({\n query: options.query,\n variables: options.variables || {},\n operationName: options.operationName,\n });\n\n if (this.config.enableLogging) {\n logger.debug('[GatewayClient] Executing request', {\n requestId: context.requestId,\n gatewayUrl,\n operationName: options.operationName,\n callType: context.callType,\n bypassPermission,\n });\n }\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n const response = await fetch(gatewayUrl, {\n method: 'POST',\n headers,\n body,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const duration = Date.now() - context.startTime;\n\n if (!response.ok) {\n throw new GatewayError(\n `HTTP ${response.status}: ${response.statusText}`,\n GatewayErrorType.NETWORK_ERROR,\n gatewayUrl,\n { statusCode: response.status }\n );\n }\n\n const result = (await response.json()) as GraphQLResponse<T>;\n this.handleGraphQLErrors(result, context, gatewayUrl, duration);\n\n if (this.config.enableLogging) {\n logger.debug('[GatewayClient] Request completed', {\n requestId: context.requestId,\n duration,\n hasData: !!result.data,\n });\n }\n\n return result;\n } catch (error) {\n const duration = Date.now() - context.startTime;\n this.handleFetchError(error, context, gatewayUrl, timeout, duration);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Create a gateway client for a specific layer\n */\nexport function createGatewayClient(config: GatewayClientConfig): GatewayClient {\n return new GatewayClient(config);\n}\n\n/**\n * Create a gateway client from environment variables\n *\n * Required environment variables:\n * - SERVICE_LAYER: 'wspace' | 'global'\n * - SERVICE_NAME: Service name\n *\n * Optional:\n * - SERVICE_IDENTITY: Service identity (defaults to SERVICE_NAME)\n * - {LAYER}_INT_GATEWAY_URL: Internal gateway URL\n * - {OPPOSITE_LAYER}_PUBLIC_GATEWAY_URL: Cross-layer gateway URL\n */\nexport function createGatewayClientFromEnv(): GatewayClient {\n const layer = process.env['SERVICE_LAYER'] as ServiceLayer;\n\n if (!layer || (layer !== 'wspace' && layer !== 'global')) {\n throw new Error(`[GatewayClient] Invalid or missing SERVICE_LAYER. Expected 'wspace' or 'global', got '${layer}'`);\n }\n\n const serviceName = process.env['SERVICE_NAME'];\n if (!serviceName) {\n throw new Error('[GatewayClient] SERVICE_NAME environment variable is required');\n }\n\n const serviceIdentity = process.env['SERVICE_IDENTITY'] || serviceName;\n\n return new GatewayClient({\n layer,\n serviceName,\n serviceIdentity,\n });\n}\n"]}
|
|
@@ -229,16 +229,14 @@ var resolveSecurityOptionsFromEnv = /* @__PURE__ */ __name((gatewayName, costMap
|
|
|
229
229
|
observeOnly: boolEnv("RATE_LIMIT_OBSERVE_ONLY", true),
|
|
230
230
|
failClosed: boolEnv("RATE_LIMIT_FAIL_CLOSED", false),
|
|
231
231
|
perWorkspace: {
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
// reviewing the tier='workspace' metric + exceed logs. Generous default
|
|
236
|
-
// budget so enforcement (when enabled) never trips normal usage.
|
|
232
|
+
// Per-workspace aggregate limiter. observe-only period ended 2026-07-05
|
|
233
|
+
// (2-day bake verified zero normal-usage trips at 6000 req/min budget).
|
|
234
|
+
// Override with RATE_LIMIT_WS_OBSERVE_ONLY=true to revert to measure-only.
|
|
237
235
|
enabled: boolEnv("RATE_LIMIT_WS_ENABLED", true),
|
|
238
236
|
points: intEnv("RATE_LIMIT_WS_POINTS", 6e3),
|
|
239
237
|
duration: intEnv("RATE_LIMIT_WS_DURATION", 60),
|
|
240
238
|
burst: intEnv("RATE_LIMIT_WS_BURST", 2e3),
|
|
241
|
-
observeOnly: boolEnv("RATE_LIMIT_WS_OBSERVE_ONLY",
|
|
239
|
+
observeOnly: boolEnv("RATE_LIMIT_WS_OBSERVE_ONLY", false)
|
|
242
240
|
}
|
|
243
241
|
},
|
|
244
242
|
operationTimeout: {
|
|
@@ -1372,5 +1370,5 @@ var buildSecurityPlugins = /* @__PURE__ */ __name(async (options) => {
|
|
|
1372
1370
|
}, "buildSecurityPlugins");
|
|
1373
1371
|
|
|
1374
1372
|
export { DEFAULT_ARMOR_CONFIG, DEFAULT_COST_MAP, DEFAULT_TIERS, MemoryValkey, __resetMetricsForTest, __setSecurityValkeyForTest, buildSecurityPlugins, checkRateLimit, createArmorPlugins, createOperationTimeoutPlugin, createOtelPlugin, createQueryComplexityPlugin, createRateLimitPlugin, getMetrics, getSecurityValkey, initializeMetrics, initializeOtel, initializeSecurityValkey, mergeCostMap, resolveActor, resolveSecurityOptionsFromEnv, resolveTiersFromEnv, scrapeMetrics, security_exports, shutdownOtel };
|
|
1375
|
-
//# sourceMappingURL=chunk-
|
|
1376
|
-
//# sourceMappingURL=chunk-
|
|
1373
|
+
//# sourceMappingURL=chunk-WHSIZCJX.js.map
|
|
1374
|
+
//# sourceMappingURL=chunk-WHSIZCJX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gateway/security/index.ts","../src/gateway/security/actor.ts","../src/gateway/security/cost-map.ts","../src/gateway/security/tiers.ts","../src/gateway/security/defaults.ts","../src/gateway/security/valkey.ts","../src/gateway/security/metrics.ts","../src/gateway/security/plugins/armor.ts","../src/gateway/security/plugins/operation-timeout.ts","../src/gateway/security/plugins/otel.ts","../src/gateway/security/plugins/query-complexity.ts","../src/gateway/security/plugins/rate-limit.ts","../src/gateway/security/plugins/index.ts"],"names":["firstIp","header","undefined","split","trim","classify","actorType","actorRole","resolveActor","getHeader","actorId","workspaceId","tenantId","orgId","appId","ip","tier","identity","headers","DEFAULT_COST_MAP","mergeCostMap","base","override","DEFAULT_TIERS","public","points","duration","burst","user","app","service","super_admin","Number","MAX_SAFE_INTEGER","positiveInt","value","fallback","parsed","parseInt","isFinite","resolveTiersFromEnv","out","Object","keys","forEach","upper","toUpperCase","process","env","boolEnv","key","v","intEnv","strEnv","DEFAULT_ARMOR_CONFIG","maxAliases","maxTokens","maxDirectives","characterLimit","costLimit","observe","resolveSecurityOptionsFromEnv","gatewayName","costMapOverride","enabled","armor","queryComplexity","maxCost","costMap","rateLimit","tiers","keyPrefix","observeOnly","failClosed","perWorkspace","operationTimeout","timeoutMs","otel","serviceName","endpoint","environment","version","IoRedisAdapter","client","get","set","options","EX","incrBy","amount","incrby","expire","seconds","result","ttl","ping","buildIoRedisClient","url","spec","mod","Ctor","default","Redis","Error","on","err","e","String","logger","warn","error","message","MemoryValkey","store","Map","prune","expiresAt","Date","now","delete","Promise","resolve","next","Math","max","ceil","singleton","bootPromise","initializeSecurityValkey","required","clientKind","msg","attempts","push","kind","factory","getValkeyClient","lastError","attempt","pong","info","getSecurityValkey","__setSecurityValkeyForTest","metrics","initializing","promMod","noopCounter","inc","noopMetrics","complexityRejected","armorRejected","valkeyFailover","initializeMetrics","imported","Counter","name","help","labelNames","getMetrics","scrapeMetrics","register","body","contentType","__resetMetricsForTest","tryImport","specifier","pickFactory","candidates","fn","createMaxAliasesRule","context","aliases","Field","node","alias","reportError","GraphQLError","nodes","extensions","code","createMaxDirectivesRule","directives","Directive","isLean","loadRules","cfg","lean","aliasesMod","directivesMod","costMod","blockSuggestionsMod","all","loaded","maxAliasesFactory","maxAliasesRule","n","exposeLimits","maxDirectivesFactory","maxDirectivesRule","costLimitFactory","costLimitRule","objectCost","scalarCost","depthCostFactor","ignoreIntrospection","blockSuggestionsFactory","blockSuggestionsPlugin","createArmorPlugins","rules","enabledRules","rule","armorValidationPlugin","onParse","params","source","length","limit","mode","http","status","onValidate","setResult","armorErrors","errs","graphqlValidate","schema","documentAST","wrapped","originalError","plugins","createTimeoutHandle","timerRef","promise","_","reject","setTimeout","timer","createOperationTimeoutPlugin","deps","timeoutError","config","onExecute","executeFn","setExecuteFn","args","handle","race","clearTimeout","shutdownHook","buildResource","resMod","attrs","resourceFromAttributes","Resource","resolveSemanticKeys","semcon","SemanticResourceAttributes","SERVICE_NAME","deploymentEnv","DEPLOYMENT_ENVIRONMENT","serviceVersion","SERVICE_VERSION","ATTR_SERVICE_NAME","ATTR_DEPLOYMENT_ENVIRONMENT_NAME","ATTR_DEPLOYMENT_ENVIRONMENT","ATTR_SERVICE_VERSION","loadOtelPeerDeps","sdkSpec","otlpSpec","resSpec","semSpec","modules","sdkMod","otlpMod","NodeSDK","OTLPTraceExporter","initializeOtel","resourceAttributes","sdk","resource","traceExporter","start","shutdown","shutdownOtel","createOtelPlugin","useOpenTelemetry","spans","execute","parse","validate","subscribe","resolvers","PAGINATION_ARGUMENTS","Set","MAX_LIST_MULTIPLIER","MAX_FAILURE_LOG_VARIANTS","complexityFailureMessages","isRecord","unwrapNamedType","type","current","getSchemaLike","getOperationRootType","operation","schemaLike","getMutationType","getSubscriptionType","getQueryType","getTypeByName","getType","getField","parentType","fieldName","getFields","getCostMapValue","numericValueFromAst","Kind","INT","FLOAT","STRING","listMultiplierFromArgs","arg","has","raw","min","trunc","calculateFieldComplexity","fieldNode","fragments","activeFragments","field","baseCost","namedFieldType","childCost","selectionSet","calculateSelectionSetComplexity","arguments","total","selection","selections","calculateSelectionComplexity","FIELD","INLINE_FRAGMENT","fragmentParent","typeCondition","fragmentName","fragment","add","complexity","calculateDocumentComplexity","operations","definition","definitions","FRAGMENT_DEFINITION","OPERATION_DEFINITION","maxComplexity","rootType","logComplexityFailure","seen","size","suppressedRepeats","debug","createQueryComplexityPlugin","gateway","cost","keyFor","prefix","wsKeyFor","stamp","checkRateLimit","actor","decision","allowed","remaining","resetAtMs","count","valkey","checkWorkspaceRateLimit","createRateLimitPlugin","onRequest","request","fetchAPI","endResponse","__rateLimitResult","__rateLimitActor","wsResult","retryAfterS","JSON","stringify","errors","scope","resetAt","toISOString","Response","floor","response","onResponse","stash","buildSecurityPlugins","otelPlugin","armorPlugins"],"mappings":"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","file":"chunk-WHSIZCJX.js","sourcesContent":["/**\n * Gateway Security Module — public API\n *\n * Plug-in stack for public GraphQL federation gateways:\n * graphql-armor, per-field query complexity, per-actor rate limiting,\n * operation-level AbortController, OpenTelemetry spans.\n *\n * Consumed by each public gateway via:\n * ```ts\n * import { buildSecurityPlugins, resolveSecurityOptionsFromEnv } from '@burdenoff/be-sdk/gateway/security';\n *\n * const plugins = await buildSecurityPlugins(\n * resolveSecurityOptionsFromEnv('wspace-public-gateway', { 'Query.customField': 100 })\n * );\n * // pass plugins into createGatewayRuntime({ plugins })\n * ```\n *\n * @module gateway/security\n * @category Gateway\n */\n\nexport { resolveActor } from './actor.js';\nexport { DEFAULT_COST_MAP, mergeCostMap } from './cost-map.js';\nexport { DEFAULT_ARMOR_CONFIG, resolveSecurityOptionsFromEnv } from './defaults.js';\nexport { DEFAULT_TIERS, resolveTiersFromEnv } from './tiers.js';\nexport type {\n ActorContext,\n ArmorConfig,\n CostMap,\n GatewaySecurityOptions,\n OperationTimeoutConfig,\n OtelConfig,\n QueryComplexityConfig,\n RateLimitConfig,\n RateLimitResult,\n SecurityValkeyClient,\n Tier,\n TierLimits,\n} from './types.js';\nexport { __setSecurityValkeyForTest, getSecurityValkey, initializeSecurityValkey, MemoryValkey } from './valkey.js';\nexport { __resetMetricsForTest, getMetrics, initializeMetrics, scrapeMetrics } from './metrics.js';\n\nexport {\n buildSecurityPlugins,\n createArmorPlugins,\n createOperationTimeoutPlugin,\n createOtelPlugin,\n createQueryComplexityPlugin,\n createRateLimitPlugin,\n checkRateLimit,\n initializeOtel,\n shutdownOtel,\n} from './plugins/index.js';\n","/**\n * Actor Resolver\n *\n * Derives an ActorContext from the headers that the gateway's auth middleware\n * already injects (`x-actor-*`, `x-workspace-id`, `x-tenant-id`, `x-org-id`,\n * `x-forwarded-for`). This is the identity used for rate-limit buckets and\n * OTel span enrichment.\n *\n * @module gateway/security/actor\n * @category Gateway\n */\n\nimport type { ActorContext, Tier } from './types.js';\n\ntype HeaderGetter = (name: string) => string | null | undefined;\n\nconst firstIp = (header: string | null | undefined): string | undefined => {\n if (!header) return undefined;\n // x-forwarded-for is a comma-separated list; take the left-most (client).\n return header.split(',')[0]?.trim() || undefined;\n};\n\nconst classify = (actorType: string | undefined, actorRole: string | undefined): Tier => {\n if (actorRole === 'super_admin') return 'super_admin';\n switch (actorType) {\n case 'user':\n return 'user';\n case 'app':\n return 'app';\n case 'service':\n case 'service_account':\n return 'service';\n case 'super_admin':\n return 'super_admin';\n default:\n return 'public';\n }\n};\n\n/**\n * Resolve the canonical ActorContext for a request.\n * Accepts a `HeaderGetter` so it is trivially testable with a plain function.\n */\nexport const resolveActor = (getHeader: HeaderGetter): ActorContext => {\n const actorId = getHeader('x-actor-id') ?? undefined;\n const actorType = getHeader('x-actor-type') ?? undefined;\n const actorRole = getHeader('x-actor-role') ?? undefined;\n const workspaceId = getHeader('x-workspace-id') ?? undefined;\n const tenantId = getHeader('x-tenant-id') ?? undefined;\n const orgId = getHeader('x-org-id') ?? undefined;\n const appId = getHeader('x-app-id') ?? undefined;\n const ip =\n firstIp(getHeader('x-forwarded-for')) || getHeader('x-real-ip') || getHeader('cf-connecting-ip') || undefined;\n\n const tier = classify(actorType, actorRole);\n\n let identity: string;\n switch (tier) {\n case 'super_admin':\n identity = 'bypass';\n break;\n case 'service':\n identity = `svc:${actorId ?? 'unknown'}`;\n break;\n case 'app':\n identity = `${tenantId ?? 'notenant'}:${appId ?? actorId ?? 'unknown'}`;\n break;\n case 'user':\n identity = `${workspaceId ?? 'nows'}:${actorId ?? 'unknown'}`;\n break;\n case 'public':\n default:\n identity = `ip:${ip ?? 'unknown'}`;\n }\n\n return {\n tier,\n identity,\n headers: {\n actorId,\n actorType,\n actorRole,\n workspaceId,\n tenantId,\n orgId,\n appId,\n ip,\n },\n };\n};\n","/**\n * Default query complexity cost map.\n *\n * Key format: \"TypeName.fieldName\". Values are base costs. List fields multiply\n * by the requested page size (up to 100) via the plugin's list-multiplier.\n *\n * Seeded from known high-cost queries across the Burdenoff federation:\n * search, analytics, reports, enumerations, introspection.\n *\n * Extend via `mergeCostMap(DEFAULT_COST_MAP, override)` in each gateway.\n *\n * @module gateway/security/cost-map\n * @category Gateway\n */\n\nimport type { CostMap } from './types.js';\n\nexport const DEFAULT_COST_MAP: CostMap = {\n // Cross-subgraph search — fanout\n 'Query.searchBigConsole': 200,\n 'Query.searchWorkspaces': 100,\n 'Query.searchTags': 80,\n\n // Aggregations\n 'Query.analyticsReport': 300,\n 'Query.usageReport': 250,\n 'Query.billingReport': 250,\n 'Query.auditLog': 150,\n\n // Enumeration risk (paginated lists)\n 'Query.listUsers': 50,\n 'Query.listWorkspaces': 50,\n 'Query.listFiles': 40,\n 'Query.listTags': 20,\n 'Query.listApps': 40,\n\n // Nested lists\n 'Workspace.members': 5,\n 'User.workspaces': 10,\n 'User.apps': 5,\n 'Tag.appliedTo': 5,\n\n // Introspection — expensive and abuse-prone in prod\n 'Query.__schema': 1000,\n 'Query.__type': 500,\n\n // Heavy writers\n 'Mutation.bulkImport': 500,\n 'Mutation.webhookTrigger': 100,\n};\n\nexport const mergeCostMap = (base: CostMap, override: CostMap): CostMap => ({\n ...base,\n ...override,\n});\n","/**\n * Default rate-limit tiers for public gateways.\n *\n * These defaults target a single pod; cross-pod fairness is provided by the\n * Valkey-backed counter. Tune via `GATEWAY_RATE_LIMIT_*` env vars.\n *\n * @module gateway/security/tiers\n * @category Gateway\n */\n\nimport type { Tier, TierLimits } from './types.js';\n\nexport const DEFAULT_TIERS: Record<Tier, TierLimits> = {\n // Public (anonymous) traffic is keyed per-IP. The previous 60+20=80/60s\n // ceiling (1.33 req/s sustained) was tight enough that a single heavy\n // frontend page load (≈15–30 GraphQL queries) plus a NAT-shared second\n // user could blow the bucket on benign traffic. Bumping to 120+60=180/60s\n // (3 req/s sustained) gives 2× headroom while staying ~40× below the\n // ~130 req/s single-pod compute floor measured under realistic load.\n public: {\n points: 120,\n duration: 60,\n burst: 60,\n },\n user: {\n points: 600,\n duration: 60,\n burst: 120,\n },\n app: {\n points: 3000,\n duration: 60,\n burst: 500,\n },\n service: {\n points: 6000,\n duration: 60,\n burst: 1000,\n },\n super_admin: {\n points: Number.MAX_SAFE_INTEGER,\n duration: 60,\n burst: Number.MAX_SAFE_INTEGER,\n },\n};\n\nconst positiveInt = (value: string | undefined, fallback: number): number => {\n if (!value) return fallback;\n const parsed = parseInt(value, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n};\n\n/**\n * Read tier overrides from env.\n *\n * Env var pattern: `GATEWAY_RL_{TIER}_{POINTS|DURATION|BURST}`\n * Example: `GATEWAY_RL_USER_POINTS=1200`\n */\nexport const resolveTiersFromEnv = (base: Record<Tier, TierLimits> = DEFAULT_TIERS): Record<Tier, TierLimits> => {\n const out: Record<Tier, TierLimits> = { ...base };\n (Object.keys(base) as Tier[]).forEach((tier) => {\n const upper = tier.toUpperCase();\n out[tier] = {\n points: positiveInt(process.env[`GATEWAY_RL_${upper}_POINTS`], base[tier].points),\n duration: positiveInt(process.env[`GATEWAY_RL_${upper}_DURATION`], base[tier].duration),\n burst: positiveInt(process.env[`GATEWAY_RL_${upper}_BURST`], base[tier].burst),\n };\n });\n return out;\n};\n","/**\n * Gateway Security Defaults\n *\n * Production-safe defaults for the security plugin stack, and helpers to\n * assemble `GatewaySecurityOptions` from environment variables. Each field\n * honors an `*_OBSERVE*` flag so the hardening pass can soft-launch\n * observe-only before flipping to enforce.\n *\n * @module gateway/security/defaults\n * @category Gateway\n */\n\nimport { DEFAULT_COST_MAP, mergeCostMap } from './cost-map.js';\nimport { resolveTiersFromEnv } from './tiers.js';\nimport type { ArmorConfig, CostMap, GatewaySecurityOptions } from './types.js';\n\nconst boolEnv = (key: string, fallback: boolean): boolean => {\n const v = process.env[key];\n if (v === undefined) return fallback;\n return v === 'true' || v === '1';\n};\n\nconst intEnv = (key: string, fallback: number): number => {\n const v = process.env[key];\n if (!v) return fallback;\n const parsed = parseInt(v, 10);\n return Number.isFinite(parsed) ? parsed : fallback;\n};\n\nconst strEnv = (key: string, fallback: string): string => process.env[key] ?? fallback;\n\n/**\n * Default armor thresholds for public gateways.\n */\nexport const DEFAULT_ARMOR_CONFIG: ArmorConfig = {\n maxAliases: 15,\n maxTokens: 1000,\n maxDirectives: 50,\n characterLimit: 15000,\n costLimit: 5000,\n observe: true,\n};\n\n/**\n * Build `GatewaySecurityOptions` by reading env vars.\n *\n * All defaults are production-safe but begin in observe-only mode so the\n * first deploy does not reject any traffic. Flip observe flags to `false`\n * after the 48h bake.\n */\nexport const resolveSecurityOptionsFromEnv = (\n gatewayName: string,\n costMapOverride?: CostMap\n): GatewaySecurityOptions => {\n return {\n gatewayName,\n enabled: boolEnv('SECURITY_PLUGINS_ENABLED', true),\n armor: {\n maxAliases: intEnv('ARMOR_MAX_ALIASES', DEFAULT_ARMOR_CONFIG.maxAliases),\n maxTokens: intEnv('ARMOR_MAX_TOKENS', DEFAULT_ARMOR_CONFIG.maxTokens),\n maxDirectives: intEnv('ARMOR_MAX_DIRECTIVES', DEFAULT_ARMOR_CONFIG.maxDirectives),\n characterLimit: intEnv('ARMOR_CHARACTER_LIMIT', DEFAULT_ARMOR_CONFIG.characterLimit),\n costLimit: intEnv('ARMOR_COST_LIMIT', DEFAULT_ARMOR_CONFIG.costLimit),\n observe: boolEnv('ARMOR_OBSERVE', true),\n },\n queryComplexity: {\n enabled: boolEnv('QUERY_COMPLEXITY_ENABLED', true),\n maxCost: intEnv('QUERY_COMPLEXITY_MAX', 2000),\n costMap: costMapOverride ? mergeCostMap(DEFAULT_COST_MAP, costMapOverride) : DEFAULT_COST_MAP,\n observe: boolEnv('QUERY_COMPLEXITY_OBSERVE', true),\n },\n rateLimit: {\n tiers: resolveTiersFromEnv(),\n keyPrefix: strEnv('VALKEY_KEY_PREFIX', gatewayName),\n observeOnly: boolEnv('RATE_LIMIT_OBSERVE_ONLY', true),\n failClosed: boolEnv('RATE_LIMIT_FAIL_CLOSED', false),\n perWorkspace: {\n // Per-workspace aggregate limiter. observe-only period ended 2026-07-05\n // (2-day bake verified zero normal-usage trips at 6000 req/min budget).\n // Override with RATE_LIMIT_WS_OBSERVE_ONLY=true to revert to measure-only.\n enabled: boolEnv('RATE_LIMIT_WS_ENABLED', true),\n points: intEnv('RATE_LIMIT_WS_POINTS', 6000),\n duration: intEnv('RATE_LIMIT_WS_DURATION', 60),\n burst: intEnv('RATE_LIMIT_WS_BURST', 2000),\n observeOnly: boolEnv('RATE_LIMIT_WS_OBSERVE_ONLY', false),\n },\n },\n operationTimeout: {\n // Default 15s — shorter than the 30s request-limiter queueTimeout, and\n // aligned with typical client-side timeouts so load-shedding fires at\n // the same edge a saturated client would already give up. Mutations\n // that legitimately take longer can override per-deployment via the\n // OPERATION_TIMEOUT_MS env var.\n timeoutMs: intEnv('OPERATION_TIMEOUT_MS', 15000),\n },\n otel: {\n enabled: boolEnv('OTEL_ENABLED', true),\n serviceName: strEnv('OTEL_SERVICE_NAME', gatewayName),\n // LEGACY default: `tempo.tooling.internal.burdenoff.com` is the retired\n // K8s tooling-cluster Tempo. On ACA, gateway metrics flow via the\n // `/metrics` pull path (otel-collector scrape); OTLP push only works when\n // `OTEL_EXPORTER_OTLP_ENDPOINT` points at the env's otel-collector.\n endpoint: strEnv('OTEL_EXPORTER_OTLP_ENDPOINT', 'https://tempo.tooling.internal.burdenoff.com:4318/v1/traces'),\n environment: strEnv('NODE_ENV', 'development'),\n version: process.env['APP_VERSION'],\n },\n };\n};\n","/**\n * Valkey Client Bootstrap for Gateway Security\n *\n * Wraps the SDK's existing getValkeyClient() (@valkey/valkey-glide) to expose a\n * minimal, stable surface for the rate-limit plugin. Falls back to an\n * in-memory stub so unit tests and local dev without Valkey do not error.\n *\n * @module gateway/security/valkey\n * @category Gateway\n */\n\nimport { logger } from '../../logger/index.js';\nimport type { SecurityValkeyClient } from './types.js';\n\n/**\n * `ioredis` adapter. Used when `VALKEY_CLIENT=ioredis` or as the Bun-compat\n * fallback when `@valkey/valkey-glide` throws at runtime (known issue:\n * `util.Buffer.byteLength` under Bun 1.3.x).\n */\ntype IoRedisInstance = {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, mode?: string, duration?: number): Promise<string | null>;\n incrby(key: string, amount: number): Promise<number>;\n expire(key: string, seconds: number): Promise<number>;\n ttl(key: string): Promise<number>;\n ping(): Promise<string>;\n quit(): Promise<string>;\n on(event: string, listener: (...args: unknown[]) => void): void;\n};\n\nclass IoRedisAdapter implements SecurityValkeyClient {\n constructor(private readonly client: IoRedisInstance) {}\n\n get(key: string): Promise<string | null> {\n return this.client.get(key);\n }\n\n set(key: string, value: string, options?: { EX?: number }): Promise<string | null> {\n if (options?.EX) {\n return this.client.set(key, value, 'EX', options.EX);\n }\n return this.client.set(key, value);\n }\n\n incrBy(key: string, amount: number): Promise<number> {\n return this.client.incrby(key, amount);\n }\n\n async expire(key: string, seconds: number): Promise<boolean> {\n const result = await this.client.expire(key, seconds);\n return result === 1;\n }\n\n ttl(key: string): Promise<number> {\n return this.client.ttl(key);\n }\n\n ping(): Promise<string> {\n return this.client.ping();\n }\n}\n\nconst buildIoRedisClient = async (url: string): Promise<SecurityValkeyClient> => {\n const spec = 'ioredis';\n const mod = (await import(/* @vite-ignore */ spec)) as unknown as {\n default?: new (url: string) => IoRedisInstance;\n Redis?: new (url: string) => IoRedisInstance;\n };\n const Ctor = mod.default ?? mod.Redis;\n if (!Ctor) {\n throw new Error('ioredis module has no Redis constructor');\n }\n const client = new Ctor(url);\n client.on('error', (err) => {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] ioredis error event', { error: e.message });\n });\n return new IoRedisAdapter(client);\n};\n\ntype MemoryEntry = {\n value: string;\n expiresAt: number;\n};\n\n/**\n * Tiny in-memory fallback. Not cross-pod safe; used only when Valkey is\n * absent (e.g., unit tests, local dev without `docker compose up`).\n */\nclass MemoryValkey implements SecurityValkeyClient {\n private store = new Map<string, MemoryEntry>();\n\n private prune(key: string): MemoryEntry | undefined {\n const e = this.store.get(key);\n if (!e) return undefined;\n if (e.expiresAt > 0 && e.expiresAt <= Date.now()) {\n this.store.delete(key);\n return undefined;\n }\n return e;\n }\n\n get(key: string): Promise<string | null> {\n const e = this.prune(key);\n return Promise.resolve(e?.value ?? null);\n }\n\n set(key: string, value: string, options?: { EX?: number }): Promise<string | null> {\n this.store.set(key, {\n value,\n expiresAt: options?.EX ? Date.now() + options.EX * 1000 : 0,\n });\n return Promise.resolve('OK');\n }\n\n incrBy(key: string, amount: number): Promise<number> {\n const e = this.prune(key);\n const next = (e ? parseInt(e.value, 10) || 0 : 0) + amount;\n this.store.set(key, { value: String(next), expiresAt: e?.expiresAt ?? 0 });\n return Promise.resolve(next);\n }\n\n expire(key: string, seconds: number): Promise<boolean> {\n const e = this.store.get(key);\n if (!e) return Promise.resolve(false);\n e.expiresAt = Date.now() + seconds * 1000;\n return Promise.resolve(true);\n }\n\n ttl(key: string): Promise<number> {\n const e = this.prune(key);\n if (!e) return Promise.resolve(-2);\n if (e.expiresAt === 0) return Promise.resolve(-1);\n return Promise.resolve(Math.max(0, Math.ceil((e.expiresAt - Date.now()) / 1000)));\n }\n\n ping(): Promise<string> {\n return Promise.resolve('PONG');\n }\n}\n\nlet singleton: SecurityValkeyClient | null = null;\nlet bootPromise: Promise<SecurityValkeyClient> | null = null;\n\n/**\n * Initialize the Valkey client for the gateway. Reads `VALKEY_URL` (or\n * `REDIS_URL`) + `VALKEY_PASSWORD` from env. On failure: if `VALKEY_REQUIRED`\n * is set to `\"true\"`, throws; otherwise logs a warning and returns the memory\n * fallback so the gateway still boots.\n *\n * Safe to call multiple times — the result is memoized.\n */\nexport const initializeSecurityValkey = async (gatewayName: string): Promise<SecurityValkeyClient> => {\n if (singleton) return singleton;\n if (bootPromise) return bootPromise;\n\n bootPromise = (async (): Promise<SecurityValkeyClient> => {\n const url = process.env['VALKEY_URL'] || process.env['REDIS_URL'];\n const required = process.env['VALKEY_REQUIRED'] === 'true';\n const clientKind = process.env['VALKEY_CLIENT'] ?? 'ioredis';\n\n if (!url) {\n const msg = '[gateway-security] VALKEY_URL not set';\n if (required) throw new Error(`${msg} and VALKEY_REQUIRED=true`);\n logger.warn(`${msg} — using in-memory fallback (not cross-pod safe)`, {\n gatewayName,\n });\n singleton = new MemoryValkey();\n return singleton;\n }\n\n const attempts: Array<{\n kind: string;\n factory: () => Promise<SecurityValkeyClient>;\n }> = [];\n\n if (clientKind === 'ioredis') {\n attempts.push({ kind: 'ioredis', factory: () => buildIoRedisClient(url) });\n attempts.push({\n kind: 'glide (fallback)',\n factory: async () => {\n const { getValkeyClient } = await import('../../cache/index.js');\n return getValkeyClient();\n },\n });\n } else {\n attempts.push({\n kind: 'glide',\n factory: async () => {\n const { getValkeyClient } = await import('../../cache/index.js');\n return getValkeyClient();\n },\n });\n attempts.push({ kind: 'ioredis (fallback)', factory: () => buildIoRedisClient(url) });\n }\n\n let lastError: Error | null = null;\n for (const attempt of attempts) {\n try {\n const client = await attempt.factory();\n const pong = await client.ping();\n if (pong !== 'PONG') {\n throw new Error(`ping returned ${pong}`);\n }\n logger.info('[gateway-security] Valkey connected', {\n gatewayName,\n url,\n client: attempt.kind,\n });\n singleton = client;\n return client;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] Valkey client init failed, will try next', {\n gatewayName,\n client: attempt.kind,\n error: lastError.message,\n });\n }\n }\n\n if (required) {\n logger.error('[gateway-security] Valkey connection failed and required=true', {\n gatewayName,\n error: lastError?.message ?? 'all attempts failed',\n });\n throw lastError ?? new Error('Valkey connection failed');\n }\n logger.warn('[gateway-security] All Valkey clients failed — using in-memory fallback', {\n gatewayName,\n error: lastError?.message ?? 'unknown',\n });\n singleton = new MemoryValkey();\n return singleton;\n })();\n\n return bootPromise;\n};\n\n/**\n * Return the initialized client. Throws if `initializeSecurityValkey` was not\n * called first — keeps the plugin wiring explicit.\n */\nexport const getSecurityValkey = (): SecurityValkeyClient => {\n if (!singleton) {\n throw new Error('[gateway-security] Valkey not initialized — call initializeSecurityValkey() first');\n }\n return singleton;\n};\n\n/**\n * Test-only seam. Replaces the singleton with a stub.\n * Do NOT use in production code.\n */\nexport const __setSecurityValkeyForTest = (client: SecurityValkeyClient | null): void => {\n singleton = client;\n bootPromise = client ? Promise.resolve(client) : null;\n};\n\nexport { MemoryValkey };\n","/**\n * Prometheus Metrics for Gateway Security Plugins\n *\n * Thin wrapper over `prom-client` — optional peer dep. When prom-client is\n * not installed or `PROMETHEUS_METRICS_ENABLED !== 'true'`, every emit is a\n * no-op so the SDK remains consumable without pulling the dependency.\n *\n * Metrics:\n * - `gateway_security_rate_limit_total{gateway,tier,decision}`\n * decision ∈ allowed | rejected | observed_reject\n * - `gateway_security_complexity_rejected_total{gateway,observe}`\n * - `gateway_security_armor_rejected_total{gateway,rule}` (reserved —\n * wiring depends on armor plugin emitting hooks)\n * - `gateway_security_valkey_failover_total{gateway}`\n * - `gateway_security_operation_timeout_total{gateway}`\n *\n * Labels:\n * - `gateway` — gateway name (wspace-public-gateway | global-public-gateway)\n * - `tier` — public | user | app | service | super_admin\n * - `decision` — allowed | rejected | observed_reject\n * - `observe` — 'true' | 'false'\n * - `rule` — armor rule ref (max_aliases, max_tokens, …)\n *\n * All metrics are global singletons across plugin instances. Safe to call\n * `initializeMetrics()` multiple times; subsequent calls are no-ops.\n *\n * @module gateway/security/metrics\n * @category Gateway\n */\n\nimport { logger } from '../../logger/index.js';\n\n// Lightweight type shims for prom-client — keeps this file usable without\n// the peer dep installed.\ntype CounterLike = {\n inc(labels?: Record<string, string>, value?: number): void;\n};\n\ntype CounterCtor = new (opts: { name: string; help: string; labelNames?: string[] }) => CounterLike;\n\ntype PromClientModule = {\n Counter?: CounterCtor;\n register?: { metrics(): Promise<string>; contentType: string };\n};\n\ninterface Metrics {\n rateLimit: CounterLike;\n complexityRejected: CounterLike;\n armorRejected: CounterLike;\n valkeyFailover: CounterLike;\n operationTimeout: CounterLike;\n}\n\nlet metrics: Metrics | null = null;\nlet initializing = false;\nlet promMod: PromClientModule | null = null;\n\nconst noopCounter: CounterLike = {\n inc: () => undefined,\n};\n\nconst noopMetrics: Metrics = {\n rateLimit: noopCounter,\n complexityRejected: noopCounter,\n armorRejected: noopCounter,\n valkeyFailover: noopCounter,\n operationTimeout: noopCounter,\n};\n\n/**\n * Initialize the metrics registry. Safe to call multiple times.\n * Returns a no-op metrics object if prom-client is unavailable.\n */\nexport const initializeMetrics = async (): Promise<Metrics> => {\n if (metrics) return metrics;\n if (initializing) {\n // Another caller is mid-init; return noop to avoid races.\n return noopMetrics;\n }\n if (process.env['PROMETHEUS_METRICS_ENABLED'] !== 'true') {\n logger.info('[gateway-security] Prometheus metrics disabled (PROMETHEUS_METRICS_ENABLED!=true)');\n metrics = noopMetrics;\n return metrics;\n }\n\n initializing = true;\n try {\n const spec = 'prom-client';\n const imported = (await import(/* @vite-ignore */ spec)) as unknown as PromClientModule;\n promMod = imported;\n if (typeof imported.Counter !== 'function') {\n logger.warn('[gateway-security] prom-client has unexpected shape — metrics disabled');\n metrics = noopMetrics;\n return metrics;\n }\n\n const { Counter } = imported;\n metrics = {\n rateLimit: new Counter({\n name: 'gateway_security_rate_limit_total',\n help: 'Rate-limit plugin decisions by tier + gateway',\n labelNames: ['gateway', 'tier', 'decision'],\n }),\n complexityRejected: new Counter({\n name: 'gateway_security_complexity_rejected_total',\n help: 'Query complexity plugin rejections',\n labelNames: ['gateway', 'observe'],\n }),\n armorRejected: new Counter({\n name: 'gateway_security_armor_rejected_total',\n help: 'graphql-armor rule rejections',\n labelNames: ['gateway', 'rule', 'mode'],\n }),\n valkeyFailover: new Counter({\n name: 'gateway_security_valkey_failover_total',\n help: 'Rate-limit plugin fail-open events due to Valkey unreachable',\n labelNames: ['gateway'],\n }),\n operationTimeout: new Counter({\n name: 'gateway_security_operation_timeout_total',\n help: 'Operation timeout plugin aborts',\n labelNames: ['gateway'],\n }),\n };\n logger.info('[gateway-security] Prometheus metrics initialized');\n return metrics;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] prom-client not installed — metrics disabled', {\n error: e.message,\n });\n metrics = noopMetrics;\n return metrics;\n } finally {\n initializing = false;\n }\n};\n\n/**\n * Get the current metrics handle. Returns a noop object if\n * `initializeMetrics()` has not been called or prom-client is unavailable.\n * Always safe to call.\n */\nexport const getMetrics = (): Metrics => metrics ?? noopMetrics;\n\n/**\n * Return the Prometheus registry's default `/metrics` output. Returns\n * `null` if prom-client is not installed.\n */\nexport const scrapeMetrics = async (): Promise<{ body: string; contentType: string } | null> => {\n if (!promMod?.register) return null;\n const body = await promMod.register.metrics();\n return { body, contentType: promMod.register.contentType };\n};\n\n/**\n * Test-only reset. Drops the initialized counters. Do NOT use in production.\n */\nexport const __resetMetricsForTest = (): void => {\n metrics = null;\n initializing = false;\n promMod = null;\n};\n","/**\n * GraphQL Armor Plugin Bundle\n *\n * Wraps the `@escape.tech/graphql-armor-*` validation rules into a single\n * Envelop plugin that runs them inside `onValidate` and sets rejection via\n * `setResult(errors)` — the same pattern that `query-complexity` uses and\n * that Hive Gateway Runtime is confirmed to honor.\n *\n * Why not just use each armor package's own `plugin` factory (which wraps\n * the rule via `addValidationRule`)? Because Hive Gateway Runtime's plugin\n * system does not honor the `addValidationRule` registration path during\n * query validation — rules registered that way are silently dropped. Nor\n * does Hive honor `afterValidate` hooks returned from `onValidate`, which\n * was the first workaround we tried. Only `setResult(errors)` called\n * synchronously inside `onValidate` actually propagates to the client.\n *\n * Rule coverage:\n * - max-aliases (graphql-armor rule)\n * - max-directives (graphql-armor rule)\n * - cost-limit (graphql-armor rule; heuristic pre-pass)\n * - character-limit (implemented inline via `onParse.source.length`\n * because the armor package hooks `onParams` which\n * is not exposed by Envelop — equivalent protection)\n * - block-field-suggestions (still uses the armor plugin — hooks onValidate\n * via `setResult`, which does work)\n * - max-tokens (covered by query-complexity, not re-implemented;\n * token blowup shows up as high cost)\n *\n * In observe mode, rule errors are logged but not attached to the final\n * result — the query proceeds as if nothing happened.\n *\n * @module gateway/security/plugins/armor\n * @category Gateway\n */\n\nimport { GraphQLError, validate as graphqlValidate, type ValidationContext, type ValidationRule } from 'graphql';\nimport type { Plugin } from 'graphql-yoga';\n\nimport { logger } from '../../../logger/index.js';\nimport { getMetrics } from '../metrics.js';\nimport type { ArmorConfig } from '../types.js';\n\ntype RuleFactory = (options: Record<string, unknown>) => ValidationRule;\n\ntype ArmorModule = Record<string, unknown>;\n\nconst tryImport = async (specifier: string): Promise<ArmorModule | null> => {\n try {\n return (await import(specifier)) as ArmorModule;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] armor package not installed — rule skipped', {\n specifier,\n error: e.message,\n });\n return null;\n }\n};\n\nconst pickFactory = (mod: ArmorModule | null, candidates: string[]): RuleFactory | null => {\n if (!mod) return null;\n for (const name of candidates) {\n const fn = mod[name];\n if (typeof fn === 'function') return fn as RuleFactory;\n }\n return null;\n};\n\nconst createMaxAliasesRule = (maxAliases: number): ValidationRule => {\n return (context: ValidationContext) => {\n let aliases = 0;\n\n return {\n Field(node) {\n if (!node.alias) return;\n aliases += 1;\n if (aliases > maxAliases) {\n context.reportError(\n new GraphQLError('Too many field aliases.', {\n nodes: node,\n extensions: { code: 'ARMOR_MAX_ALIASES' },\n })\n );\n }\n },\n };\n };\n};\n\nconst createMaxDirectivesRule = (maxDirectives: number): ValidationRule => {\n return (context: ValidationContext) => {\n let directives = 0;\n\n return {\n Directive(node) {\n directives += 1;\n if (directives > maxDirectives) {\n context.reportError(\n new GraphQLError('Too many directives.', {\n nodes: node,\n extensions: { code: 'ARMOR_MAX_DIRECTIVES' },\n })\n );\n }\n },\n };\n };\n};\n\ninterface LoadedRules {\n maxAliasesRule?: ValidationRule;\n maxDirectivesRule?: ValidationRule;\n costLimitRule?: ValidationRule;\n blockSuggestionsPlugin?: Plugin;\n}\n\n/**\n * When `ARMOR_LEAN=true` (default: false), the gateway loads only the cost-limit\n * rule and skips `max-aliases`, `max-directives`, and `block-field-suggestions`.\n *\n * Rationale: each `@escape.tech/graphql-armor-*` rule runs its own\n * `graphqlValidate(document, [rule])` — a full AST traversal per request. On\n * busy public gateways this shows up as a measurable fraction of total CPU.\n * The cost-limit rule already covers the DoS surface (it rejects expensive\n * aliased-or-deeply-nested queries via the heuristic cost function), and\n * character-limit is handled inline in `onParse`, so the other three rules\n * are refinements rather than load-bearing defences.\n *\n * Opt-in via env so existing services see no behavior change.\n */\nconst isLean = (): boolean => {\n const v = process.env['ARMOR_LEAN'];\n return v === 'true' || v === '1';\n};\n\nconst loadRules = async (cfg: ArmorConfig): Promise<LoadedRules> => {\n const lean = isLean();\n\n const [aliasesMod, directivesMod, costMod, blockSuggestionsMod] = await Promise.all([\n lean ? Promise.resolve(null) : tryImport('@escape.tech/graphql-armor-max-aliases'),\n lean ? Promise.resolve(null) : tryImport('@escape.tech/graphql-armor-max-directives'),\n tryImport('@escape.tech/graphql-armor-cost-limit'),\n lean ? Promise.resolve(null) : tryImport('@escape.tech/graphql-armor-block-field-suggestions'),\n ]);\n\n const loaded: LoadedRules = {};\n\n const maxAliasesFactory = pickFactory(aliasesMod, ['maxAliasesRule']);\n loaded.maxAliasesRule = maxAliasesFactory\n ? maxAliasesFactory({ n: cfg.maxAliases, exposeLimits: cfg.observe })\n : createMaxAliasesRule(cfg.maxAliases);\n\n const maxDirectivesFactory = pickFactory(directivesMod, ['maxDirectivesRule']);\n loaded.maxDirectivesRule = maxDirectivesFactory\n ? maxDirectivesFactory({\n n: cfg.maxDirectives,\n exposeLimits: cfg.observe,\n })\n : createMaxDirectivesRule(cfg.maxDirectives);\n\n const costLimitFactory = pickFactory(costMod, ['costLimitRule']);\n if (costLimitFactory) {\n loaded.costLimitRule = costLimitFactory({\n maxCost: cfg.costLimit,\n objectCost: 2,\n scalarCost: 1,\n depthCostFactor: 1.5,\n ignoreIntrospection: true,\n exposeLimits: cfg.observe,\n });\n }\n\n const blockSuggestionsFactory = pickFactory(blockSuggestionsMod, ['blockFieldSuggestionsPlugin', 'default']);\n if (blockSuggestionsFactory) {\n loaded.blockSuggestionsPlugin = blockSuggestionsFactory({}) as unknown as Plugin;\n }\n\n if (lean) {\n logger.info('[gateway-security] ARMOR_LEAN enabled — running only cost-limit + character-limit', {});\n }\n\n return loaded;\n};\n\n/**\n * Build the Envelop/Yoga plugin list for graphql-armor. Returns the\n * block-field-suggestions plugin (armor's own — this one actually works via\n * `setResult`) plus a custom `onValidate` plugin that runs the rule-based\n * armor checks (max-aliases, max-directives, cost-limit) manually inside\n * `AfterValidate.setResult`.\n *\n * The custom plugin also handles character-limit inline via `onParse`.\n */\nexport const createArmorPlugins = async (cfg: ArmorConfig): Promise<Plugin[]> => {\n const rules = await loadRules(cfg);\n\n const metrics = getMetrics();\n\n // Collect the ValidationRule array once per plugin creation. Envelop's\n // `validateFn` takes an array of rules, but we're bypassing that path and\n // running the rules ourselves inside the afterValidate hook. Each rule is\n // a factory returning a visitor, so this reuse is safe.\n const enabledRules: Array<{ name: string; rule: ValidationRule }> = [];\n if (rules.maxAliasesRule) {\n enabledRules.push({ name: 'max-aliases', rule: rules.maxAliasesRule });\n }\n if (rules.maxDirectivesRule) {\n enabledRules.push({ name: 'max-directives', rule: rules.maxDirectivesRule });\n }\n if (rules.costLimitRule) {\n enabledRules.push({ name: 'cost-limit', rule: rules.costLimitRule });\n }\n\n const armorValidationPlugin: Plugin = {\n onParse({ params }) {\n // Character limit — rejects oversized raw queries before parse even\n // starts. Doing it here is equivalent to graphql-armor-character-limit\n // hooking `onParams`, which is not exposed by Envelop.\n const source = typeof params.source === 'string' ? params.source : params.source?.body;\n if (typeof source === 'string' && source.length > cfg.characterLimit) {\n if (cfg.observe) {\n logger.warn('[gateway-security] armor character-limit exceeded (observe)', {\n length: source.length,\n limit: cfg.characterLimit,\n });\n metrics.armorRejected.inc({ rule: 'character-limit', mode: 'observe' }, 1);\n return;\n }\n metrics.armorRejected.inc({ rule: 'character-limit', mode: 'enforce' }, 1);\n throw new GraphQLError('Syntax Error: Query exceeds maximum character limit.', {\n extensions: {\n code: 'CHARACTER_LIMIT_EXCEEDED',\n http: { status: 400 },\n },\n });\n }\n },\n onValidate({ params, setResult }) {\n if (enabledRules.length === 0) return;\n // Run armor rules manually inside `onValidate`. We initially tried\n // returning an `afterValidate` hook here, but Hive Gateway Runtime\n // silently drops those callbacks — the same class of bug that causes\n // `addValidationRule` not to fire. Doing the work in the synchronous\n // body of `onValidate` + calling `setResult` directly is the pattern\n // that query-complexity uses and it is confirmed to work end-to-end\n // against Hive Gateway.\n //\n // IMPORTANT: graphql-armor rules throw `GraphQLError` synchronously\n // when a limit is exceeded, instead of using the conventional\n // `context.reportError()` path. This propagates as an exception out\n // of `graphqlValidate`, which is why we wrap each rule in an\n // isolated try/catch — otherwise the first throwing rule would hide\n // any subsequent rule failures.\n const armorErrors: GraphQLError[] = [];\n for (const { name, rule } of enabledRules) {\n try {\n const errs = graphqlValidate(params.schema, params.documentAST, [rule]);\n armorErrors.push(...errs);\n } catch (err) {\n // `err instanceof GraphQLError` is NOT reliable here because\n // `@escape.tech/graphql-armor-*` bundles its own copy of\n // `graphql`, so the thrown error's prototype chain does not\n // match the `GraphQLError` class we imported at the top of this\n // file even when both resolve to the same package semver range.\n // We therefore detect armor rule violations by looking at the\n // error shape (either GraphQLError-like or Error-like with a\n // message). Any thrown value from a rule is treated as a\n // violation — rules don't throw for any other reason.\n const message = err instanceof Error ? err.message : String(err);\n const wrapped = new GraphQLError(message, {\n originalError: err instanceof Error ? err : undefined,\n extensions: {\n code: 'ARMOR_VIOLATION',\n rule: name,\n },\n });\n armorErrors.push(wrapped);\n }\n }\n\n if (armorErrors.length === 0) return;\n\n for (const err of armorErrors) {\n logger.warn('[gateway-security] armor rule triggered', {\n message: err.message,\n observe: cfg.observe,\n });\n }\n\n metrics.armorRejected.inc(\n {\n rule: 'armor',\n mode: cfg.observe ? 'observe' : 'enforce',\n },\n armorErrors.length\n );\n\n if (cfg.observe) return;\n\n // Calling `setResult` inside `onValidate` replaces the validation\n // result and skips envelop's own validate invocation. That is exactly\n // what we want — armor violations are fatal, no point running the\n // default graphql-js validation afterwards.\n setResult(armorErrors);\n },\n };\n\n const plugins: Plugin[] = [armorValidationPlugin];\n if (rules.blockSuggestionsPlugin) {\n plugins.push(rules.blockSuggestionsPlugin);\n }\n return plugins;\n};\n","/**\n * Operation Timeout Plugin\n *\n * Races each operation against a configurable timer (default 15s, aligned\n * with typical client-side timeouts and shorter than the 30s request-limiter\n * cap). When the timer fires, the execution errors out with a proper\n * GraphQL error (`OPERATION_TIMEOUT`) rather than the client seeing an\n * abrupt TCP drop.\n *\n * This is implemented via `onExecute` with a promise race — the subgraph\n * fetch already honors AbortController from Yoga, so upstream work is\n * cancelled naturally.\n *\n * @module gateway/security/plugins/operation-timeout\n * @category Gateway\n */\n\nimport { GraphQLError } from 'graphql';\nimport type { Plugin } from 'graphql-yoga';\n\nimport type { OperationTimeoutConfig } from '../types.js';\n\nexport interface OperationTimeoutPluginDeps {\n config: OperationTimeoutConfig;\n}\n\ninterface TimerHandle {\n timer: ReturnType<typeof setTimeout>;\n promise: Promise<never>;\n}\n\nconst createTimeoutHandle = (timeoutMs: number, error: GraphQLError): TimerHandle => {\n let timerRef: ReturnType<typeof setTimeout> | undefined;\n const promise = new Promise<never>((_, reject) => {\n timerRef = setTimeout(() => reject(error), timeoutMs);\n });\n return { timer: timerRef as ReturnType<typeof setTimeout>, promise };\n};\n\nexport const createOperationTimeoutPlugin = (deps: OperationTimeoutPluginDeps): Plugin => {\n const timeoutError = new GraphQLError('Operation timeout', {\n extensions: { code: 'OPERATION_TIMEOUT', timeoutMs: deps.config.timeoutMs },\n });\n\n return {\n onExecute: ({ executeFn, setExecuteFn }) => {\n setExecuteFn(async (args) => {\n const handle = createTimeoutHandle(deps.config.timeoutMs, timeoutError);\n try {\n return await Promise.race([executeFn(args), handle.promise]);\n } finally {\n clearTimeout(handle.timer);\n }\n });\n },\n };\n};\n","/**\n * OpenTelemetry Plugin\n *\n * Initializes an OTLP HTTP exporter pointed at Tempo (or any OTLP/HTTP\n * endpoint) and installs `@envelop/opentelemetry` spans around `parse`,\n * `validate`, and `execute`. Imports are dynamic so the SDK stays usable\n * when OTel is disabled or the peer packages are absent.\n *\n * Enrichment: spans carry `gateway.name`, `deployment.environment`, and\n * `service.version` resource attrs. Per-request context (actor, workspace)\n * is propagated via headers because the SDK does not yet wire\n * `propagators` — see the gateway handler edits for `traceparent` forwarding.\n *\n * @module gateway/security/plugins/otel\n * @category Gateway\n */\n\nimport type { Plugin } from 'graphql-yoga';\n\nimport { logger } from '../../../logger/index.js';\nimport type { OtelConfig } from '../types.js';\n\nlet shutdownHook: (() => Promise<void>) | null = null;\n\n// Structural types for the optional OTel peer deps. Constructors accept\n// `unknown` opts because we only need the start/shutdown surface here.\ntype ResourceCtor = new (attrs: Record<string, string>) => unknown;\ntype ResourceFactory = (attrs: Record<string, string>) => unknown;\ntype OtlpExporterCtor = new (opts: { url: string }) => unknown;\ntype NodeSdkInstance = { start(): void; shutdown(): Promise<void> };\ntype NodeSdkCtor = new (opts: { resource: unknown; traceExporter: unknown }) => NodeSdkInstance;\n\ntype ResourceModule = {\n // v1 API\n Resource?: ResourceCtor;\n // v2 API\n resourceFromAttributes?: ResourceFactory;\n};\n\ntype SemanticAttrs = {\n // v1 API\n SemanticResourceAttributes?: {\n SERVICE_NAME: string;\n DEPLOYMENT_ENVIRONMENT: string;\n SERVICE_VERSION: string;\n };\n // v2 API — string constants directly\n ATTR_SERVICE_NAME?: string;\n ATTR_SERVICE_VERSION?: string;\n ATTR_DEPLOYMENT_ENVIRONMENT?: string;\n ATTR_DEPLOYMENT_ENVIRONMENT_NAME?: string;\n};\n\n/**\n * Build an OTel Resource across the v1 → v2 API migration.\n * - v1 (`@opentelemetry/resources` 1.x): `new Resource(attrs)`\n * - v2 (`@opentelemetry/resources` 2.x): `resourceFromAttributes(attrs)`\n */\nconst buildResource = (resMod: ResourceModule, attrs: Record<string, string>): unknown => {\n if (typeof resMod.resourceFromAttributes === 'function') {\n return resMod.resourceFromAttributes(attrs);\n }\n if (typeof resMod.Resource === 'function') {\n return new resMod.Resource(attrs);\n }\n throw new Error('@opentelemetry/resources module exposes neither Resource nor resourceFromAttributes');\n};\n\n/**\n * Resolve semantic attribute keys across the v1 → v2 API migration.\n * - v1: `semcon.SemanticResourceAttributes.SERVICE_NAME` etc.\n * - v2: top-level `ATTR_SERVICE_NAME` string constants. Deployment\n * environment was renamed to `ATTR_DEPLOYMENT_ENVIRONMENT_NAME`.\n */\nconst resolveSemanticKeys = (\n semcon: SemanticAttrs\n): { serviceName: string; deploymentEnv: string; serviceVersion: string } => {\n if (semcon.SemanticResourceAttributes) {\n return {\n serviceName: semcon.SemanticResourceAttributes.SERVICE_NAME,\n deploymentEnv: semcon.SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT,\n serviceVersion: semcon.SemanticResourceAttributes.SERVICE_VERSION,\n };\n }\n return {\n serviceName: semcon.ATTR_SERVICE_NAME ?? 'service.name',\n deploymentEnv:\n semcon.ATTR_DEPLOYMENT_ENVIRONMENT_NAME ?? semcon.ATTR_DEPLOYMENT_ENVIRONMENT ?? 'deployment.environment',\n serviceVersion: semcon.ATTR_SERVICE_VERSION ?? 'service.version',\n };\n};\n\nconst loadOtelPeerDeps = async (): Promise<{\n NodeSDK: NodeSdkCtor;\n OTLPTraceExporter: OtlpExporterCtor;\n resMod: ResourceModule;\n semcon: SemanticAttrs;\n}> => {\n // Optional peer deps — indirect specifiers so TS does not try to resolve.\n const sdkSpec = '@opentelemetry/sdk-node';\n const otlpSpec = '@opentelemetry/exporter-trace-otlp-http';\n const resSpec = '@opentelemetry/resources';\n const semSpec = '@opentelemetry/semantic-conventions';\n const modules = (await Promise.all([\n import(/* @vite-ignore */ sdkSpec),\n import(/* @vite-ignore */ otlpSpec),\n import(/* @vite-ignore */ resSpec),\n import(/* @vite-ignore */ semSpec),\n ])) as [{ NodeSDK: NodeSdkCtor }, { OTLPTraceExporter: OtlpExporterCtor }, ResourceModule, SemanticAttrs];\n const [sdkMod, otlpMod, resMod, semcon] = modules;\n return {\n NodeSDK: sdkMod.NodeSDK,\n OTLPTraceExporter: otlpMod.OTLPTraceExporter,\n resMod,\n semcon,\n };\n};\n\nexport const initializeOtel = async (cfg: OtelConfig): Promise<void> => {\n if (!cfg.enabled) {\n logger.info('[gateway-security] OTel disabled by config');\n return;\n }\n if (shutdownHook) {\n return; // already initialized\n }\n\n try {\n const { NodeSDK, OTLPTraceExporter, resMod, semcon } = await loadOtelPeerDeps();\n const keys = resolveSemanticKeys(semcon);\n\n const resourceAttributes: Record<string, string> = {\n [keys.serviceName]: cfg.serviceName,\n [keys.deploymentEnv]: cfg.environment,\n };\n if (cfg.version) {\n resourceAttributes[keys.serviceVersion] = cfg.version;\n }\n\n const sdk = new NodeSDK({\n resource: buildResource(resMod, resourceAttributes),\n traceExporter: new OTLPTraceExporter({ url: cfg.endpoint }),\n });\n\n sdk.start();\n shutdownHook = (): Promise<void> => sdk.shutdown();\n logger.info('[gateway-security] OTel initialized', {\n serviceName: cfg.serviceName,\n endpoint: cfg.endpoint,\n });\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] OTel init failed — continuing without tracing', {\n error: e.message,\n });\n }\n};\n\nexport const shutdownOtel = async (): Promise<void> => {\n if (shutdownHook) {\n try {\n await shutdownHook();\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] OTel shutdown error', { error: e.message });\n }\n shutdownHook = null;\n }\n};\n\n/**\n * Returns an Envelop plugin that adds spans around parse/validate/execute.\n * Returns an empty plugin when @envelop/opentelemetry is absent.\n */\nexport const createOtelPlugin = async (cfg: OtelConfig): Promise<Plugin> => {\n if (!cfg.enabled) return {};\n try {\n const spec = '@envelop/opentelemetry';\n const mod = (await import(/* @vite-ignore */ spec)) as unknown as {\n useOpenTelemetry?: (opts: {\n spans?: { execute?: boolean; parse?: boolean; validate?: boolean; subscribe?: boolean };\n resolvers?: boolean;\n }) => Plugin;\n };\n if (typeof mod.useOpenTelemetry !== 'function') {\n logger.warn('[gateway-security] @envelop/opentelemetry has unexpected shape — plugin skipped');\n return {};\n }\n return mod.useOpenTelemetry({\n spans: { execute: true, parse: true, validate: true, subscribe: true },\n resolvers: false,\n });\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] @envelop/opentelemetry not installed — plugin skipped', {\n error: e.message,\n });\n return {};\n }\n};\n","/**\n * Query Complexity Plugin\n *\n * Scores each incoming query against a per-field cost map. Scoring happens in\n * the validate phase so rejection is cheap and subgraph fanout is prevented.\n *\n * Observe mode logs the computed cost without rejecting — used during the\n * 48h bake of the hardening pass.\n *\n * @module gateway/security/plugins/query-complexity\n * @category Gateway\n */\n\nimport { GraphQLError, Kind } from 'graphql';\nimport type {\n ArgumentNode,\n FieldNode,\n FragmentDefinitionNode,\n GraphQLSchema,\n OperationDefinitionNode,\n SelectionNode,\n SelectionSetNode,\n ValueNode,\n} from 'graphql';\nimport type { Plugin } from 'graphql-yoga';\n\nimport { logger } from '../../../logger/index.js';\nimport { getMetrics } from '../metrics.js';\nimport type { CostMap, QueryComplexityConfig } from '../types.js';\n\nconst PAGINATION_ARGUMENTS = new Set(['first', 'limit', 'pageSize']);\nconst MAX_LIST_MULTIPLIER = 100;\nconst MAX_FAILURE_LOG_VARIANTS = 5;\nconst complexityFailureMessages = new Set<string>();\n\ninterface GraphQLNamedTypeLike {\n name?: string;\n getFields?: () => Record<string, GraphQLFieldLike | undefined>;\n}\n\ninterface GraphQLFieldLike {\n name?: string;\n type?: unknown;\n}\n\ninterface GraphQLSchemaLike {\n getQueryType?: () => GraphQLNamedTypeLike | null;\n getMutationType?: () => GraphQLNamedTypeLike | null;\n getSubscriptionType?: () => GraphQLNamedTypeLike | null;\n getType?: (name: string) => GraphQLNamedTypeLike | undefined | null;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;\n\nconst unwrapNamedType = (type: unknown): GraphQLNamedTypeLike | null => {\n let current = type;\n while (isRecord(current) && current['ofType'] !== undefined) {\n current = current['ofType'];\n }\n return isRecord(current) ? current : null;\n};\n\nconst getSchemaLike = (schema: GraphQLSchema): GraphQLSchemaLike => schema as unknown as GraphQLSchemaLike;\n\nconst getOperationRootType = (\n schema: GraphQLSchema,\n operation: OperationDefinitionNode\n): GraphQLNamedTypeLike | null => {\n const schemaLike = getSchemaLike(schema);\n if (operation.operation === 'mutation') return schemaLike.getMutationType?.() ?? null;\n if (operation.operation === 'subscription') return schemaLike.getSubscriptionType?.() ?? null;\n return schemaLike.getQueryType?.() ?? null;\n};\n\nconst getTypeByName = (schema: GraphQLSchema, name: string): GraphQLNamedTypeLike | null => {\n return getSchemaLike(schema).getType?.(name) ?? null;\n};\n\nconst getField = (parentType: GraphQLNamedTypeLike, fieldName: string): GraphQLFieldLike | undefined => {\n return parentType.getFields?.()[fieldName];\n};\n\nconst getCostMapValue = (costMap: CostMap, parentType: GraphQLNamedTypeLike, fieldName: string): number => {\n if (!parentType.name) return 1;\n return costMap[`${parentType.name}.${fieldName}`] ?? 1;\n};\n\nconst numericValueFromAst = (value: ValueNode): number | undefined => {\n if (value.kind === Kind.INT || value.kind === Kind.FLOAT) {\n const parsed = Number(value.value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n if (value.kind === Kind.STRING) {\n const parsed = Number(value.value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n};\n\nconst listMultiplierFromArgs = (args: readonly ArgumentNode[] | undefined): number => {\n if (!args) return 1;\n for (const arg of args) {\n if (!PAGINATION_ARGUMENTS.has(arg.name.value)) continue;\n const raw = numericValueFromAst(arg.value);\n if (typeof raw !== 'number') return 1;\n return Math.min(Math.max(1, Math.trunc(raw)), MAX_LIST_MULTIPLIER);\n }\n return 1;\n};\n\nconst calculateFieldComplexity = (\n schema: GraphQLSchema,\n fieldNode: FieldNode,\n parentType: GraphQLNamedTypeLike,\n fragments: ReadonlyMap<string, FragmentDefinitionNode>,\n costMap: CostMap,\n activeFragments: Set<string>\n): number => {\n const fieldName = fieldNode.name.value;\n const field = getField(parentType, fieldName);\n const baseCost = getCostMapValue(costMap, parentType, fieldName);\n const namedFieldType = unwrapNamedType(field?.type);\n const childCost =\n fieldNode.selectionSet && namedFieldType\n ? calculateSelectionSetComplexity(\n schema,\n fieldNode.selectionSet,\n namedFieldType,\n fragments,\n costMap,\n activeFragments\n )\n : 0;\n return (baseCost + childCost) * listMultiplierFromArgs(fieldNode.arguments);\n};\n\nconst calculateSelectionSetComplexity = (\n schema: GraphQLSchema,\n selectionSet: SelectionSetNode,\n parentType: GraphQLNamedTypeLike,\n fragments: ReadonlyMap<string, FragmentDefinitionNode>,\n costMap: CostMap,\n activeFragments: Set<string>\n): number => {\n let total = 0;\n\n for (const selection of selectionSet.selections) {\n total += calculateSelectionComplexity(schema, selection, parentType, fragments, costMap, activeFragments);\n }\n\n return total;\n};\n\nconst calculateSelectionComplexity = (\n schema: GraphQLSchema,\n selection: SelectionNode,\n parentType: GraphQLNamedTypeLike,\n fragments: ReadonlyMap<string, FragmentDefinitionNode>,\n costMap: CostMap,\n activeFragments: Set<string>\n): number => {\n if (selection.kind === Kind.FIELD) {\n return calculateFieldComplexity(schema, selection, parentType, fragments, costMap, activeFragments);\n }\n\n if (selection.kind === Kind.INLINE_FRAGMENT) {\n const fragmentParent = selection.typeCondition\n ? (getTypeByName(schema, selection.typeCondition.name.value) ?? parentType)\n : parentType;\n return calculateSelectionSetComplexity(\n schema,\n selection.selectionSet,\n fragmentParent,\n fragments,\n costMap,\n activeFragments\n );\n }\n\n const fragmentName = selection.name.value;\n if (activeFragments.has(fragmentName)) return 0;\n const fragment = fragments.get(fragmentName);\n if (!fragment) return 0;\n\n activeFragments.add(fragmentName);\n const fragmentParent = getTypeByName(schema, fragment.typeCondition.name.value) ?? parentType;\n const complexity = calculateSelectionSetComplexity(\n schema,\n fragment.selectionSet,\n fragmentParent,\n fragments,\n costMap,\n activeFragments\n );\n activeFragments.delete(fragmentName);\n return complexity;\n};\n\nconst calculateDocumentComplexity = (\n schema: GraphQLSchema,\n documentAST: { definitions: readonly unknown[] },\n costMap: CostMap\n): number => {\n const fragments = new Map<string, FragmentDefinitionNode>();\n const operations: OperationDefinitionNode[] = [];\n\n for (const definition of documentAST.definitions) {\n if (!isRecord(definition) || typeof definition['kind'] !== 'string') continue;\n if (definition['kind'] === Kind.FRAGMENT_DEFINITION) {\n const fragment = definition as unknown as FragmentDefinitionNode;\n fragments.set(fragment.name.value, fragment);\n } else if (definition['kind'] === Kind.OPERATION_DEFINITION) {\n operations.push(definition as unknown as OperationDefinitionNode);\n }\n }\n\n let maxComplexity = 0;\n for (const operation of operations) {\n const rootType = getOperationRootType(schema, operation);\n if (!rootType) continue;\n const complexity = calculateSelectionSetComplexity(\n schema,\n operation.selectionSet,\n rootType,\n fragments,\n costMap,\n new Set<string>()\n );\n maxComplexity = Math.max(maxComplexity, complexity);\n }\n\n return maxComplexity;\n};\n\nconst logComplexityFailure = (error: Error): void => {\n const seen = complexityFailureMessages.has(error.message);\n if (!seen && complexityFailureMessages.size < MAX_FAILURE_LOG_VARIANTS) {\n complexityFailureMessages.add(error.message);\n logger.warn('[gateway-security] complexity scoring failed — fail-open', {\n error: error.message,\n suppressedRepeats: true,\n });\n return;\n }\n\n logger.debug('[gateway-security] repeated complexity scoring failure suppressed', {\n error: error.message,\n });\n};\n\nexport interface QueryComplexityPluginDeps {\n config: QueryComplexityConfig;\n}\n\nexport const createQueryComplexityPlugin = (deps: QueryComplexityPluginDeps): Plugin => {\n return {\n onValidate: ({ params, setResult }) => {\n try {\n const complexity = calculateDocumentComplexity(params.schema, params.documentAST, deps.config.costMap);\n\n if (complexity > deps.config.maxCost) {\n getMetrics().complexityRejected.inc({\n gateway: 'unknown',\n observe: deps.config.observe ? 'true' : 'false',\n });\n if (deps.config.observe) {\n logger.info('[gateway-security] complexity would_reject (observe)', {\n complexity,\n maxCost: deps.config.maxCost,\n });\n return;\n }\n setResult([\n new GraphQLError(`Query too expensive (cost ${complexity} > limit ${deps.config.maxCost})`, {\n extensions: {\n code: 'COMPLEXITY_TOO_HIGH',\n cost: complexity,\n maxCost: deps.config.maxCost,\n },\n }),\n ]);\n }\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logComplexityFailure(e);\n }\n },\n };\n};\n","/**\n * Rate-Limit Plugin\n *\n * Per-actor token-bucket rate limiter backed by Valkey. Tier classification\n * from ActorContext. Increments a counter with a window-scoped TTL and\n * rejects when the bucket is exhausted. Emits rate-limit response headers\n * on every request (X-RateLimit-Limit / Remaining / Reset).\n *\n * Failure policy: **fail open** by default (availability > strictness during\n * Valkey outages). Flip with `failClosed: true`.\n *\n * Observe mode: when `observeOnly: true`, counts and logs but never rejects.\n * Used during the 48h bake of this hardening pass.\n *\n * @module gateway/security/plugins/rate-limit\n * @category Gateway\n */\n\nimport type { Plugin } from 'graphql-yoga';\n\nimport { logger } from '../../../logger/index.js';\nimport { resolveActor } from '../actor.js';\nimport { getMetrics } from '../metrics.js';\nimport type { ActorContext, RateLimitConfig, RateLimitResult, SecurityValkeyClient } from '../types.js';\n\nexport interface RateLimitPluginDeps {\n valkey: SecurityValkeyClient;\n config: RateLimitConfig;\n}\n\nconst keyFor = (prefix: string, tier: string, identity: string): string => `rl:${prefix}:${tier}:${identity}`;\n\nconst wsKeyFor = (prefix: string, workspaceId: string): string => `rl:${prefix}:ws:${workspaceId}`;\n\nconst stamp = (): number => Date.now();\n\n/**\n * Atomic-ish INCR + EXPIRE. Valkey does not guarantee atomicity between the\n * two without a Lua script; the race window here loses at most 1 event per\n * window-start collision, which is acceptable for a limiter and avoids the\n * Lua script registration dance.\n */\nexport const checkRateLimit = async (deps: RateLimitPluginDeps, actor: ActorContext): Promise<RateLimitResult> => {\n const tier = deps.config.tiers[actor.tier];\n const metrics = getMetrics();\n const gateway = deps.config.keyPrefix;\n // Super admin passes through.\n if (tier.points === Number.MAX_SAFE_INTEGER) {\n metrics.rateLimit.inc({ gateway, tier: actor.tier, decision: 'allowed' });\n return { allowed: true, remaining: Number.MAX_SAFE_INTEGER, resetAtMs: 0, limit: tier.points };\n }\n\n const key = keyFor(deps.config.keyPrefix, actor.tier, actor.identity);\n const limit = tier.points + tier.burst;\n\n try {\n const count = await deps.valkey.incrBy(key, 1);\n if (count === 1) {\n await deps.valkey.expire(key, tier.duration);\n }\n const ttl = await deps.valkey.ttl(key);\n const resetAtMs = stamp() + Math.max(0, ttl) * 1000;\n\n if (count > limit) {\n metrics.rateLimit.inc({\n gateway,\n tier: actor.tier,\n decision: deps.config.observeOnly ? 'observed_reject' : 'rejected',\n });\n return { allowed: false, remaining: 0, resetAtMs, limit };\n }\n metrics.rateLimit.inc({ gateway, tier: actor.tier, decision: 'allowed' });\n return { allowed: true, remaining: Math.max(0, limit - count), resetAtMs, limit };\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] rate-limit valkey error — fail-open', {\n key,\n error: e.message,\n });\n metrics.valkeyFailover.inc({ gateway });\n if (deps.config.failClosed) {\n metrics.rateLimit.inc({ gateway, tier: actor.tier, decision: 'rejected' });\n return { allowed: false, remaining: 0, resetAtMs: stamp() + tier.duration * 1000, limit };\n }\n metrics.rateLimit.inc({ gateway, tier: actor.tier, decision: 'allowed' });\n return { allowed: true, remaining: -1, resetAtMs: 0, limit };\n }\n};\n\n/**\n * Per-workspace AGGREGATE rate limit. The per-actor limiter (checkRateLimit)\n * caps each user; this caps the whole workspace so that N users in one workspace\n * cannot collectively starve other workspaces on the shared backend. Runs only\n * when a workspaceId is present. Emits the decision under `tier: 'workspace'`\n * (workspaceId is logged, NOT a metric label, to avoid metric cardinality\n * blow-up). Always fails OPEN on a Valkey error — a fairness signal must never be\n * an availability dependency.\n */\nexport const checkWorkspaceRateLimit = async (\n deps: RateLimitPluginDeps,\n workspaceId: string\n): Promise<RateLimitResult> => {\n const cfg = deps.config.perWorkspace;\n const metrics = getMetrics();\n const gateway = deps.config.keyPrefix;\n const key = wsKeyFor(deps.config.keyPrefix, workspaceId);\n const limit = cfg.points + cfg.burst;\n\n try {\n const count = await deps.valkey.incrBy(key, 1);\n if (count === 1) {\n await deps.valkey.expire(key, cfg.duration);\n }\n const ttl = await deps.valkey.ttl(key);\n const resetAtMs = stamp() + Math.max(0, ttl) * 1000;\n\n if (count > limit) {\n metrics.rateLimit.inc({\n gateway,\n tier: 'workspace',\n decision: cfg.observeOnly ? 'observed_reject' : 'rejected',\n });\n // workspaceId in the LOG (not a metric label) → noisy-neighbor leaderboard\n logger.warn('[gateway-security] workspace rate-limit exceeded', {\n workspaceId,\n count,\n limit,\n observe: cfg.observeOnly,\n });\n return { allowed: false, remaining: 0, resetAtMs, limit };\n }\n metrics.rateLimit.inc({ gateway, tier: 'workspace', decision: 'allowed' });\n return { allowed: true, remaining: Math.max(0, limit - count), resetAtMs, limit };\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n logger.warn('[gateway-security] workspace rate-limit valkey error — fail-open', {\n key,\n error: e.message,\n });\n metrics.valkeyFailover.inc({ gateway });\n return { allowed: true, remaining: -1, resetAtMs: 0, limit };\n }\n};\n\n/**\n * Yoga/Envelop plugin factory.\n */\nexport const createRateLimitPlugin = (deps: RateLimitPluginDeps): Plugin => {\n return {\n onRequest: async ({ request, fetchAPI, endResponse }): Promise<void> => {\n const actor = resolveActor((name) => request.headers.get(name));\n const result = await checkRateLimit(deps, actor);\n\n // Headers are set via onResponse (below). Stash the result on the request\n // so onResponse can read it without re-running the Valkey call.\n (request as unknown as { __rateLimitResult: RateLimitResult; __rateLimitActor: ActorContext }).__rateLimitResult =\n result;\n (request as unknown as { __rateLimitResult: RateLimitResult; __rateLimitActor: ActorContext }).__rateLimitActor =\n actor;\n\n // Per-workspace aggregate limiter (fairness). Independent of the per-actor\n // bucket: measures the whole workspace's request rate so one workspace's\n // many users can't collectively starve others. Observe-only by default →\n // it records + logs but does not reject; enforcement is opt-in.\n const workspaceId = actor.headers.workspaceId;\n if (deps.config.perWorkspace.enabled && workspaceId) {\n const wsResult = await checkWorkspaceRateLimit(deps, workspaceId);\n if (!wsResult.allowed && !deps.config.perWorkspace.observeOnly) {\n const retryAfterS = Math.max(1, Math.ceil((wsResult.resetAtMs - stamp()) / 1000));\n const body = JSON.stringify({\n errors: [\n {\n message: 'Workspace rate limit exceeded',\n extensions: {\n code: 'RATE_LIMITED',\n scope: 'workspace',\n resetAt: new Date(wsResult.resetAtMs).toISOString(),\n },\n },\n ],\n });\n endResponse(\n new fetchAPI.Response(body, {\n status: 429,\n headers: {\n 'content-type': 'application/json',\n 'retry-after': String(retryAfterS),\n 'x-ratelimit-scope': 'workspace',\n 'x-ratelimit-limit': String(wsResult.limit),\n 'x-ratelimit-remaining': '0',\n 'x-ratelimit-reset': String(Math.floor(wsResult.resetAtMs / 1000)),\n },\n })\n );\n return;\n }\n }\n\n if (!result.allowed) {\n if (deps.config.observeOnly) {\n logger.info('[gateway-security] rate-limit would_reject (observe)', {\n tier: actor.tier,\n identity: actor.identity,\n limit: result.limit,\n });\n return;\n }\n const retryAfterS = Math.max(1, Math.ceil((result.resetAtMs - stamp()) / 1000));\n const body = JSON.stringify({\n errors: [\n {\n message: 'Rate limit exceeded',\n extensions: {\n code: 'RATE_LIMITED',\n resetAt: new Date(result.resetAtMs).toISOString(),\n },\n },\n ],\n });\n const response = new fetchAPI.Response(body, {\n status: 429,\n headers: {\n 'content-type': 'application/json',\n 'retry-after': String(retryAfterS),\n 'x-ratelimit-limit': String(result.limit),\n 'x-ratelimit-remaining': '0',\n 'x-ratelimit-reset': String(Math.floor(result.resetAtMs / 1000)),\n },\n });\n endResponse(response);\n }\n },\n onResponse: ({ request, response }): void => {\n const stash = (request as unknown as { __rateLimitResult?: RateLimitResult }).__rateLimitResult;\n if (!stash) return;\n response.headers.set('x-ratelimit-limit', String(stash.limit));\n response.headers.set('x-ratelimit-remaining', String(Math.max(0, stash.remaining)));\n if (stash.resetAtMs > 0) {\n response.headers.set('x-ratelimit-reset', String(Math.floor(stash.resetAtMs / 1000)));\n }\n },\n };\n};\n","/**\n * Gateway Security Plugin Orchestrator\n *\n * Builds the ordered Yoga/Envelop plugin array consumed by each public\n * gateway via `createGatewayRuntime({ plugins: [...] })`.\n *\n * Order (cheapest rejection first, span wrapping everything):\n * otel spans → armor (6 sub-plugins) → query-complexity → rate-limit → timeout\n *\n * @module gateway/security/plugins\n * @category Gateway\n */\n\nimport type { Plugin } from 'graphql-yoga';\n\nimport { logger } from '../../../logger/index.js';\nimport { initializeMetrics } from '../metrics.js';\nimport type { GatewaySecurityOptions } from '../types.js';\nimport { initializeSecurityValkey } from '../valkey.js';\nimport { createArmorPlugins } from './armor.js';\nimport { createOperationTimeoutPlugin } from './operation-timeout.js';\nimport { createOtelPlugin } from './otel.js';\nimport { createQueryComplexityPlugin } from './query-complexity.js';\nimport { createRateLimitPlugin } from './rate-limit.js';\n\n/**\n * Bootstraps Valkey + OTel side effects and returns the ordered plugin list.\n * Safe to call once at gateway boot; subsequent calls reuse the initialized\n * singletons.\n *\n * If `options.enabled === false`, returns an empty array — the master kill\n * switch for instant rollback via env flag.\n */\nexport const buildSecurityPlugins = async (options: GatewaySecurityOptions): Promise<Plugin[]> => {\n if (!options.enabled) {\n logger.warn('[gateway-security] SECURITY_PLUGINS_ENABLED=false — plugins disabled', {\n gatewayName: options.gatewayName,\n });\n return [];\n }\n\n // Side-effect init (both are idempotent). OTel exporter bootstrap belongs to\n // `bootstrapTelemetry()`; this stack only wires Envelop span hooks.\n await initializeMetrics();\n const valkey = await initializeSecurityValkey(options.gatewayName);\n\n const plugins: Plugin[] = [];\n\n const otelPlugin = await createOtelPlugin(options.otel);\n plugins.push(otelPlugin);\n\n const armorPlugins = await createArmorPlugins(options.armor);\n plugins.push(...armorPlugins);\n\n if (options.queryComplexity.enabled) {\n plugins.push(createQueryComplexityPlugin({ config: options.queryComplexity }));\n }\n plugins.push(createRateLimitPlugin({ valkey, config: options.rateLimit }));\n plugins.push(createOperationTimeoutPlugin({ config: options.operationTimeout }));\n\n logger.info('[gateway-security] plugins wired', {\n gatewayName: options.gatewayName,\n count: plugins.length,\n observe: {\n armor: options.armor.observe,\n complexity: options.queryComplexity.observe,\n rateLimit: options.rateLimit.observeOnly,\n },\n enabled: {\n complexity: options.queryComplexity.enabled,\n },\n });\n\n return plugins;\n};\n\nexport { createArmorPlugins } from './armor.js';\nexport { createOperationTimeoutPlugin } from './operation-timeout.js';\nexport { createOtelPlugin, initializeOtel, shutdownOtel } from './otel.js';\nexport { createQueryComplexityPlugin } from './query-complexity.js';\nexport { checkRateLimit, createRateLimitPlugin } from './rate-limit.js';\n"]}
|