@kya-os/agentshield-nextjs 0.2.13 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/api-client.d.mts +6 -1
  2. package/dist/api-client.d.ts +6 -1
  3. package/dist/api-client.js.map +1 -1
  4. package/dist/api-client.mjs.map +1 -1
  5. package/dist/api-middleware.d.mts +13 -0
  6. package/dist/api-middleware.d.ts +13 -0
  7. package/dist/api-middleware.js +149 -19
  8. package/dist/api-middleware.js.map +1 -1
  9. package/dist/api-middleware.mjs +149 -19
  10. package/dist/api-middleware.mjs.map +1 -1
  11. package/dist/create-middleware.js +565 -487
  12. package/dist/create-middleware.js.map +1 -1
  13. package/dist/create-middleware.mjs +565 -487
  14. package/dist/create-middleware.mjs.map +1 -1
  15. package/dist/edge/index.js +69 -46
  16. package/dist/edge/index.js.map +1 -1
  17. package/dist/edge/index.mjs +69 -46
  18. package/dist/edge/index.mjs.map +1 -1
  19. package/dist/edge-detector-wrapper.js +9 -1
  20. package/dist/edge-detector-wrapper.js.map +1 -1
  21. package/dist/edge-detector-wrapper.mjs +9 -1
  22. package/dist/edge-detector-wrapper.mjs.map +1 -1
  23. package/dist/edge-runtime-loader.d.mts +1 -0
  24. package/dist/edge-runtime-loader.d.ts +1 -0
  25. package/dist/edge-runtime-loader.js +19 -3
  26. package/dist/edge-runtime-loader.js.map +1 -1
  27. package/dist/edge-runtime-loader.mjs +19 -3
  28. package/dist/edge-runtime-loader.mjs.map +1 -1
  29. package/dist/edge-wasm-middleware.d.mts +1 -0
  30. package/dist/edge-wasm-middleware.d.ts +1 -0
  31. package/dist/edge-wasm-middleware.js +10 -2
  32. package/dist/edge-wasm-middleware.js.map +1 -1
  33. package/dist/edge-wasm-middleware.mjs +11 -3
  34. package/dist/edge-wasm-middleware.mjs.map +1 -1
  35. package/dist/enhanced-middleware.js +48 -20
  36. package/dist/enhanced-middleware.js.map +1 -1
  37. package/dist/enhanced-middleware.mjs +49 -21
  38. package/dist/enhanced-middleware.mjs.map +1 -1
  39. package/dist/index.d.mts +1 -1
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.js +263 -102
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +264 -103
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/middleware.js +565 -487
  46. package/dist/middleware.js.map +1 -1
  47. package/dist/middleware.mjs +565 -487
  48. package/dist/middleware.mjs.map +1 -1
  49. package/dist/policy.d.mts +16 -4
  50. package/dist/policy.d.ts +16 -4
  51. package/dist/policy.js +14 -10
  52. package/dist/policy.js.map +1 -1
  53. package/dist/policy.mjs +14 -10
  54. package/dist/policy.mjs.map +1 -1
  55. package/dist/session-tracker.js +13 -19
  56. package/dist/session-tracker.js.map +1 -1
  57. package/dist/session-tracker.mjs +13 -19
  58. package/dist/session-tracker.mjs.map +1 -1
  59. package/dist/signature-verifier.js +9 -1
  60. package/dist/signature-verifier.js.map +1 -1
  61. package/dist/signature-verifier.mjs +9 -1
  62. package/dist/signature-verifier.mjs.map +1 -1
  63. package/dist/wasm-middleware.d.mts +1 -0
  64. package/dist/wasm-middleware.d.ts +1 -0
  65. package/dist/wasm-middleware.js +15 -15
  66. package/dist/wasm-middleware.js.map +1 -1
  67. package/dist/wasm-middleware.mjs +15 -15
  68. package/dist/wasm-middleware.mjs.map +1 -1
  69. package/package.json +3 -3
  70. package/wasm/agentshield_wasm.d.ts +379 -21
  71. package/wasm/agentshield_wasm.js +1409 -506
  72. package/wasm/agentshield_wasm_bg.wasm +0 -0
  73. package/dist/.tsbuildinfo +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api-client.ts","../src/api-middleware.ts"],"names":["NextResponse","client"],"mappings":"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","file":"api-middleware.js","sourcesContent":["/**\n * AgentShield API Client\n *\n * Lightweight client for calling the AgentShield enforce API from middleware.\n * Designed for Edge Runtime compatibility (no Node.js-specific APIs).\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * API client configuration\n */\nexport interface AgentShieldClientConfig {\n /** API key for authentication */\n apiKey: string;\n /** API base URL (defaults to production) */\n baseUrl?: string;\n /**\n * Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.\n * Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)\n * that the pixel cannot detect since they don't execute JavaScript.\n * @default true\n */\n useEdge?: boolean;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Enforcement action\n */\nexport type EnforcementAction = 'allow' | 'block' | 'redirect' | 'challenge' | 'log';\n\n/**\n * Enforcement decision from the API\n */\nexport interface EnforcementDecision {\n action: EnforcementAction;\n reason: string;\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n redirectUrl?: string;\n message?: string;\n metadata?: {\n policyVersion?: string;\n signatureVerified?: boolean;\n denyListMatch?: {\n clientDid?: string;\n agentDid?: string;\n clientName?: string;\n reason?: string;\n };\n };\n}\n\n/**\n * Detection result (optional in response)\n */\nexport interface DetectionResult {\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n /** Detection class: 'human', 'ai_agent', 'bot', 'incomplete_data' */\n detectionClass?: string;\n verificationMethod?: string;\n reasons?: string[];\n /** Detection engine used: 'wasm' or 'javascript-fallback' */\n detectionMethod?: string;\n}\n\n/**\n * Enforce API response\n */\nexport interface EnforceResponse {\n success: boolean;\n data?: {\n decision: EnforcementDecision;\n processingTimeMs: number;\n requestId: string;\n detection?: DetectionResult;\n };\n error?: {\n code: string;\n message: string;\n };\n}\n\n/**\n * Request input for enforce API\n */\nexport interface EnforceInput {\n /** HTTP headers from the incoming request */\n headers?: Record<string, string>;\n /** User-Agent header */\n userAgent?: string;\n /** Client IP address */\n ipAddress?: string;\n /** Request path */\n path?: string;\n /** Request URL */\n url?: string;\n /** HTTP method */\n method?: string;\n /** Request ID for tracing */\n requestId?: string;\n /** Options */\n options?: {\n /** Include full detection result */\n includeDetectionResult?: boolean;\n /** Cache TTL override */\n cacheTTL?: number;\n };\n}\n\n/**\n * Input for logging a detection result\n */\nexport interface LogDetectionInput {\n /** Detection result from Gateway */\n detection: DetectionResult;\n /** Request context */\n context: {\n userAgent?: string;\n ipAddress?: string;\n path?: string;\n url?: string;\n method?: string;\n };\n /** Source of the detection */\n source?: 'gateway' | 'middleware';\n}\n\n// ============================================================================\n// Client Implementation\n// ============================================================================\n\nconst DEFAULT_BASE_URL = 'https://kya.vouched.id';\nconst EDGE_DETECT_URL = 'https://detect.checkpoint-gateway.ai';\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * AgentShield API Client\n *\n * @example\n * ```typescript\n * const client = new AgentShieldClient({\n * apiKey: process.env.AGENTSHIELD_API_KEY!,\n * });\n *\n * const result = await client.enforce({\n * headers: Object.fromEntries(request.headers),\n * path: request.nextUrl.pathname,\n * method: request.method,\n * });\n *\n * if (result.decision.action === 'block') {\n * return new Response('Access denied', { status: 403 });\n * }\n * ```\n */\nexport class AgentShieldClient {\n private apiKey: string;\n private baseUrl: string;\n private useEdge: boolean;\n private timeout: number;\n private debug: boolean;\n\n constructor(config: AgentShieldClientConfig) {\n if (!config.apiKey) {\n throw new Error('AgentShield API key is required');\n }\n\n this.apiKey = config.apiKey;\n // Default to edge detection for better coverage (detects non-JS clients)\n this.useEdge = config.useEdge !== false; // true by default\n this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n this.debug = config.debug || false;\n }\n\n /**\n * Call the enforce API to check if a request should be allowed\n */\n async enforce(input: EnforceInput): Promise<EnforceResponse> {\n const startTime = Date.now();\n\n try {\n // Create abort controller for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Use edge endpoint or Vercel API based on configuration\n const endpoint = this.useEdge\n ? `${this.baseUrl}/__detect/enforce`\n : `${this.baseUrl}/api/v1/enforce`;\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n 'X-Request-ID': input.requestId || crypto.randomUUID(),\n },\n body: JSON.stringify(input),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Parse response\n const data = (await response.json()) as EnforceResponse;\n\n if (this.debug) {\n console.log('[AgentShield] Enforce response:', {\n status: response.status,\n action: data.data?.decision.action,\n processingTimeMs: Date.now() - startTime,\n });\n }\n\n // Handle non-2xx responses\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: `HTTP_${response.status}`,\n message: data.error?.message || `HTTP error: ${response.status}`,\n },\n };\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Handle timeout\n if (error instanceof Error && error.name === 'AbortError') {\n if (this.debug) {\n console.warn('[AgentShield] Request timed out');\n }\n return {\n success: false,\n error: {\n code: 'TIMEOUT',\n message: `Request timed out after ${this.timeout}ms`,\n },\n };\n }\n\n // Handle network errors\n if (this.debug) {\n console.error('[AgentShield] Request failed:', error);\n }\n\n return {\n success: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Network request failed',\n },\n };\n }\n }\n\n /**\n * Quick check - returns just the action without full response parsing\n * Useful for very fast middleware that just needs allow/block\n */\n async quickCheck(input: EnforceInput): Promise<{\n action: EnforcementAction;\n error?: string;\n }> {\n const result = await this.enforce(input);\n\n if (!result.success || !result.data) {\n // On error, default to allow (fail-open)\n return {\n action: 'allow',\n error: result.error?.message,\n };\n }\n\n return {\n action: result.data.decision.action,\n };\n }\n\n /**\n * Check if this client is using edge detection (Gateway Worker)\n */\n isUsingEdge(): boolean {\n return this.useEdge;\n }\n\n /**\n * Log a detection result to AgentShield database.\n * Use after Gateway Worker detection to persist results.\n * Fire-and-forget - returns immediately without waiting for DB write.\n *\n * @example\n * ```typescript\n * // After receiving Gateway response\n * if (client.isUsingEdge() && response.data?.detection) {\n * client.logDetection({\n * detection: response.data.detection,\n * context: { userAgent, ipAddress, path, url, method }\n * }).catch(err => console.error('Log failed:', err));\n * }\n * ```\n */\n async logDetection(input: LogDetectionInput): Promise<void> {\n // Don't await - fire and forget\n // Use the base URL (not edge) for logging since this goes to the main API\n const logEndpoint = this.useEdge\n ? `${DEFAULT_BASE_URL}/api/v1/log-detection`\n : `${this.baseUrl}/api/v1/log-detection`;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(logEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n detection: {\n isAgent: input.detection.isAgent,\n confidence: input.detection.confidence,\n agentName: input.detection.agentName,\n agentType: input.detection.agentType,\n detectionClass: input.detection.detectionClass,\n verificationMethod: input.detection.verificationMethod,\n reasons: input.detection.reasons,\n },\n context: input.context,\n source: input.source || 'gateway',\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok && this.debug) {\n console.warn('[AgentShield] Log detection returned non-2xx:', response.status);\n }\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Silently fail for fire-and-forget, but log in debug mode\n if (this.debug) {\n console.error('[AgentShield] Log detection failed:', error);\n }\n // Re-throw so caller can catch if needed\n throw error;\n }\n }\n}\n\n/**\n * Create a singleton client instance\n *\n * @example\n * ```typescript\n * // In middleware.ts\n * import { getAgentShieldClient } from '@kya-os/agentshield-nextjs';\n *\n * const client = getAgentShieldClient();\n * ```\n */\nlet clientInstance: AgentShieldClient | null = null;\n\nexport function getAgentShieldClient(config?: Partial<AgentShieldClientConfig>): AgentShieldClient {\n if (!clientInstance) {\n const apiKey = config?.apiKey || process.env.AGENTSHIELD_API_KEY;\n\n if (!apiKey) {\n throw new Error(\n 'AgentShield API key is required. Set AGENTSHIELD_API_KEY environment variable or pass apiKey in config.'\n );\n }\n\n clientInstance = new AgentShieldClient({\n apiKey,\n baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL,\n // Default to edge detection unless explicitly disabled\n useEdge: config?.useEdge ?? process.env.AGENTSHIELD_USE_EDGE !== 'false',\n timeout: config?.timeout,\n debug: config?.debug || process.env.AGENTSHIELD_DEBUG === 'true',\n });\n }\n\n return clientInstance;\n}\n\n/**\n * Reset the singleton client (useful for testing)\n */\nexport function resetAgentShieldClient(): void {\n clientInstance = null;\n}\n","/**\n * API-based AgentShield Middleware for Next.js\n *\n * This middleware uses the AgentShield API for detection and enforcement,\n * instead of running detection locally. This approach:\n *\n * 1. Works reliably in Edge Runtime (no WASM loading issues)\n * 2. Ensures consistent detection across all platforms\n * 3. Applies centralized policies from the dashboard\n * 4. Supports deny lists, thresholds, and path rules\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware';\n *\n * export default withAgentShield({\n * apiKey: process.env.AGENTSHIELD_API_KEY!,\n * // Optional overrides:\n * onBlock: 'redirect', // 'block' | 'redirect' | 'challenge'\n * redirectUrl: '/blocked',\n * skipPaths: ['/api/health', '/_next/*'],\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next/static|favicon.ico).*)'],\n * };\n * ```\n */\n\nimport { NextRequest, NextResponse } from 'next/server';\nimport { AgentShieldClient, getAgentShieldClient, type EnforcementDecision } from './api-client';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Middleware configuration\n */\nexport interface AgentShieldMiddlewareConfig {\n /** API key (or use AGENTSHIELD_API_KEY env var) */\n apiKey?: string;\n /** API base URL (defaults to production) */\n apiUrl?: string;\n /**\n * Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.\n * Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)\n * that the pixel cannot detect since they don't execute JavaScript.\n * Set to false to use the Vercel API instead.\n * @default true\n */\n useEdge?: boolean;\n /** Request timeout in ms (default: 5000) */\n timeout?: number;\n\n /**\n * Action to take when an agent should be blocked\n * - 'block': Return 403 response\n * - 'redirect': Redirect to redirectUrl\n * - 'challenge': Show a challenge page (future)\n * Default: uses policy from dashboard\n */\n onBlock?: 'block' | 'redirect' | 'challenge';\n\n /**\n * URL to redirect to when blocking (if onBlock is 'redirect')\n * Default: uses redirectUrl from dashboard policy\n */\n redirectUrl?: string;\n\n /**\n * Custom blocked response\n */\n blockedResponse?: {\n status?: number;\n message?: string;\n headers?: Record<string, string>;\n };\n\n /**\n * Paths to skip (in addition to dashboard policy)\n * Supports glob patterns: '/api/*', '/_next/*'\n */\n skipPaths?: string[];\n\n /**\n * Only enforce on these paths (overrides dashboard policy)\n */\n includePaths?: string[];\n\n /**\n * Callback when an agent is detected\n */\n onAgentDetected?: (request: NextRequest, decision: EnforcementDecision) => void | Promise<void>;\n\n /**\n * Callback to customize the blocked response\n */\n customBlockedResponse?: (\n request: NextRequest,\n decision: EnforcementDecision\n ) => NextResponse | Promise<NextResponse>;\n\n /**\n * Whether to fail open (allow) on API errors\n * Default: true (recommended for production)\n */\n failOpen?: boolean;\n\n /**\n * Enable debug logging\n */\n debug?: boolean;\n}\n\n// ============================================================================\n// Path Matching\n// ============================================================================\n\n/**\n * Check if a path matches a pattern\n */\nfunction matchPath(path: string, pattern: string): boolean {\n // Handle exact match\n if (pattern === path) return true;\n\n // Handle glob patterns\n if (pattern.includes('*')) {\n const regexPattern = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex chars\n .replace(/\\*/g, '.*'); // Convert * to .*\n return new RegExp(`^${regexPattern}$`).test(path);\n }\n\n // Handle prefix match\n if (pattern.endsWith('/')) {\n return path.startsWith(pattern) || path === pattern.slice(0, -1);\n }\n\n return path.startsWith(pattern);\n}\n\n/**\n * Check if path should be skipped\n */\nfunction shouldSkipPath(path: string, skipPaths: string[]): boolean {\n return skipPaths.some((pattern) => matchPath(path, pattern));\n}\n\n/**\n * Check if path should be included (if includePaths is set)\n */\nfunction shouldIncludePath(path: string, includePaths?: string[]): boolean {\n if (!includePaths || includePaths.length === 0) return true;\n return includePaths.some((pattern) => matchPath(path, pattern));\n}\n\n// ============================================================================\n// Response Builders\n// ============================================================================\n\n/**\n * Build blocked response\n */\nfunction buildBlockedResponse(\n decision: EnforcementDecision,\n config: AgentShieldMiddlewareConfig\n): NextResponse {\n const status = config.blockedResponse?.status ?? 403;\n const message = config.blockedResponse?.message ?? decision.message ?? 'Access denied';\n\n const response = NextResponse.json(\n {\n error: message,\n code: 'AGENT_BLOCKED',\n reason: decision.reason,\n agentType: decision.agentType,\n },\n { status }\n );\n\n // Add custom headers\n if (config.blockedResponse?.headers) {\n for (const [key, value] of Object.entries(config.blockedResponse.headers)) {\n response.headers.set(key, value);\n }\n }\n\n // Add AgentShield headers\n response.headers.set('X-AgentShield-Action', decision.action);\n response.headers.set('X-AgentShield-Reason', decision.reason);\n\n return response;\n}\n\n/**\n * Build redirect response\n */\nfunction buildRedirectResponse(\n request: NextRequest,\n decision: EnforcementDecision,\n config: AgentShieldMiddlewareConfig\n): NextResponse {\n const redirectUrl = config.redirectUrl || decision.redirectUrl || '/blocked';\n const url = new URL(redirectUrl, request.url);\n\n // Add query params with detection info\n url.searchParams.set('reason', decision.reason);\n if (decision.agentType) {\n url.searchParams.set('agent', decision.agentType);\n }\n\n return NextResponse.redirect(url);\n}\n\n// ============================================================================\n// Middleware Factory\n// ============================================================================\n\n/**\n * Create AgentShield middleware with API-based detection\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware';\n *\n * export default withAgentShield({\n * onBlock: 'block',\n * skipPaths: ['/api/health'],\n * });\n * ```\n */\nexport function withAgentShield(config: AgentShieldMiddlewareConfig = {}) {\n // Initialize client (will use AGENTSHIELD_API_KEY env var if not provided)\n let client: AgentShieldClient | null = null;\n\n const getClient = () => {\n if (!client) {\n client = getAgentShieldClient({\n apiKey: config.apiKey,\n baseUrl: config.apiUrl,\n useEdge: config.useEdge,\n timeout: config.timeout,\n debug: config.debug,\n });\n }\n return client;\n };\n\n // Default skip paths (static assets, etc.)\n const defaultSkipPaths = [\n '/_next/static/*',\n '/_next/image/*',\n '/favicon.ico',\n '/robots.txt',\n '/sitemap.xml',\n ];\n\n const skipPaths = [...defaultSkipPaths, ...(config.skipPaths || [])];\n const failOpen = config.failOpen ?? true;\n\n return async function middleware(request: NextRequest): Promise<NextResponse> {\n const path = request.nextUrl.pathname;\n const startTime = Date.now();\n\n // Check skip paths\n if (shouldSkipPath(path, skipPaths)) {\n return NextResponse.next();\n }\n\n // Check include paths\n if (!shouldIncludePath(path, config.includePaths)) {\n return NextResponse.next();\n }\n\n try {\n const client = getClient();\n\n // Extract request context for potential logging\n const userAgent = request.headers.get('user-agent') || undefined;\n const ipAddress =\n request.ip ||\n request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ||\n request.headers.get('x-real-ip') ||\n undefined;\n\n // Call enforce API\n const result = await client.enforce({\n headers: Object.fromEntries(request.headers.entries()),\n userAgent,\n ipAddress,\n path,\n url: request.url,\n method: request.method,\n requestId: request.headers.get('x-request-id') || undefined,\n options: {\n // Always include detection results for logging (needed when using edge)\n includeDetectionResult: true,\n },\n });\n\n // Handle API error\n if (!result.success || !result.data) {\n if (config.debug) {\n console.warn('[AgentShield] API error:', result.error);\n }\n\n if (failOpen) {\n return NextResponse.next();\n }\n\n // Fail closed - block on error\n return NextResponse.json(\n { error: 'Security check failed', code: 'API_ERROR' },\n { status: 503 }\n );\n }\n\n const decision = result.data.decision;\n\n // Log if debug enabled\n if (config.debug) {\n console.log('[AgentShield] Decision:', {\n path,\n action: decision.action,\n isAgent: decision.isAgent,\n confidence: decision.confidence,\n agentName: decision.agentName,\n detectionMethod: result.data.detection?.detectionMethod || 'not-included',\n processingTimeMs: Date.now() - startTime,\n });\n }\n\n // Fire-and-forget logging - ONLY when using Gateway Worker (edge detection)\n // When useEdge: false, the /api/v1/enforce endpoint already logs to the database\n // This prevents double-logging while ensuring Gateway detections are persisted\n if (client.isUsingEdge() && result.data.detection) {\n client\n .logDetection({\n detection: result.data.detection,\n context: { userAgent, ipAddress, path, url: request.url, method: request.method },\n })\n .catch((err) => {\n if (config.debug) {\n console.error('[AgentShield] Log detection failed:', err);\n }\n });\n }\n\n // Handle agent detection callback\n if (decision.isAgent && config.onAgentDetected) {\n await config.onAgentDetected(request, decision);\n }\n\n // Handle enforcement action\n switch (decision.action) {\n case 'block': {\n // Use custom response if provided\n if (config.customBlockedResponse) {\n return config.customBlockedResponse(request, decision);\n }\n\n // Check if config overrides to redirect\n if (config.onBlock === 'redirect') {\n return buildRedirectResponse(request, decision, config);\n }\n\n return buildBlockedResponse(decision, config);\n }\n\n case 'redirect': {\n return buildRedirectResponse(request, decision, config);\n }\n\n case 'challenge': {\n // Future: implement challenge page\n // For now, treat as redirect\n return buildRedirectResponse(request, decision, config);\n }\n\n case 'log':\n case 'allow':\n default: {\n // Allow the request to proceed\n const response = NextResponse.next();\n\n // Add detection headers for downstream use\n if (decision.isAgent) {\n response.headers.set('X-AgentShield-Detected', 'true');\n response.headers.set('X-AgentShield-Confidence', decision.confidence.toString());\n if (decision.agentName) {\n response.headers.set('X-AgentShield-Agent', decision.agentName);\n }\n }\n\n return response;\n }\n }\n } catch (error) {\n // Unexpected error\n if (config.debug) {\n console.error('[AgentShield] Middleware error:', error);\n }\n\n if (failOpen) {\n return NextResponse.next();\n }\n\n return NextResponse.json(\n { error: 'Security check failed', code: 'MIDDLEWARE_ERROR' },\n { status: 503 }\n );\n }\n };\n}\n\n/**\n * Convenience export for simple setup\n *\n * @example\n * ```typescript\n * // middleware.ts\n * export { agentShieldMiddleware as default } from '@kya-os/agentshield-nextjs/api-middleware';\n * ```\n */\nexport const agentShieldMiddleware = withAgentShield();\n"]}
1
+ {"version":3,"sources":["../src/api-client.ts","../src/utils.ts","../src/responses/agent-instruction.ts","../src/api-middleware.ts"],"names":["NextResponse","client"],"mappings":"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","file":"api-middleware.js","sourcesContent":["/**\n * AgentShield API Client\n *\n * Lightweight client for calling the AgentShield enforce API from middleware.\n * Designed for Edge Runtime compatibility (no Node.js-specific APIs).\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * API client configuration\n */\nexport interface AgentShieldClientConfig {\n /** API key for authentication */\n apiKey: string;\n /** API base URL (defaults to production) */\n baseUrl?: string;\n /**\n * Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.\n * Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)\n * that the pixel cannot detect since they don't execute JavaScript.\n * @default true\n */\n useEdge?: boolean;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Enforcement action\n *\n * Must stay in sync with `EnforcementConfig.defaultAction` in\n * `packages/agentshield-shared/src/core/enforcement.ts` and the dashboard\n * policy builder. `'instruct'` tells the middleware to emit a 401 with an\n * MCP-I Link header pointing the agent at a connect/consent URL.\n */\nexport type EnforcementAction = 'allow' | 'block' | 'redirect' | 'instruct' | 'challenge' | 'log';\n\n/**\n * Enforcement decision from the API\n */\nexport interface EnforcementDecision {\n action: EnforcementAction;\n reason: string;\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n redirectUrl?: string;\n message?: string;\n metadata?: {\n policyVersion?: string;\n signatureVerified?: boolean;\n denyListMatch?: {\n clientDid?: string;\n agentDid?: string;\n clientName?: string;\n reason?: string;\n };\n };\n}\n\n/**\n * Detection result (optional in response)\n */\nexport interface DetectionResult {\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n /** Detection class: 'human', 'ai_agent', 'bot', 'incomplete_data' */\n detectionClass?: string;\n verificationMethod?: string;\n reasons?: string[];\n /** Detection engine used: 'wasm' or 'javascript-fallback' */\n detectionMethod?: string;\n}\n\n/**\n * Enforce API response\n */\nexport interface EnforceResponse {\n success: boolean;\n data?: {\n decision: EnforcementDecision;\n processingTimeMs: number;\n requestId: string;\n detection?: DetectionResult;\n };\n error?: {\n code: string;\n message: string;\n };\n}\n\n/**\n * Request input for enforce API\n */\nexport interface EnforceInput {\n /** HTTP headers from the incoming request */\n headers?: Record<string, string>;\n /** User-Agent header */\n userAgent?: string;\n /** Client IP address */\n ipAddress?: string;\n /** Request path */\n path?: string;\n /** Request URL */\n url?: string;\n /** HTTP method */\n method?: string;\n /** Request ID for tracing */\n requestId?: string;\n /** Options */\n options?: {\n /** Include full detection result */\n includeDetectionResult?: boolean;\n /** Cache TTL override */\n cacheTTL?: number;\n };\n}\n\n/**\n * Input for logging a detection result\n */\nexport interface LogDetectionInput {\n /** Detection result from Gateway */\n detection: DetectionResult;\n /** Request context */\n context: {\n userAgent?: string;\n ipAddress?: string;\n path?: string;\n url?: string;\n method?: string;\n };\n /** Source of the detection */\n source?: 'gateway' | 'middleware';\n}\n\n// ============================================================================\n// Client Implementation\n// ============================================================================\n\nconst DEFAULT_BASE_URL = 'https://kya.vouched.id';\nconst EDGE_DETECT_URL = 'https://detect.checkpoint-gateway.ai';\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * AgentShield API Client\n *\n * @example\n * ```typescript\n * const client = new AgentShieldClient({\n * apiKey: process.env.AGENTSHIELD_API_KEY!,\n * });\n *\n * const result = await client.enforce({\n * headers: Object.fromEntries(request.headers),\n * path: request.nextUrl.pathname,\n * method: request.method,\n * });\n *\n * if (result.decision.action === 'block') {\n * return new Response('Access denied', { status: 403 });\n * }\n * ```\n */\nexport class AgentShieldClient {\n private apiKey: string;\n private baseUrl: string;\n private useEdge: boolean;\n private timeout: number;\n private debug: boolean;\n\n constructor(config: AgentShieldClientConfig) {\n if (!config.apiKey) {\n throw new Error('AgentShield API key is required');\n }\n\n this.apiKey = config.apiKey;\n // Default to edge detection for better coverage (detects non-JS clients)\n this.useEdge = config.useEdge !== false; // true by default\n this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n this.debug = config.debug || false;\n }\n\n /**\n * Call the enforce API to check if a request should be allowed\n */\n async enforce(input: EnforceInput): Promise<EnforceResponse> {\n const startTime = Date.now();\n\n try {\n // Create abort controller for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Use edge endpoint or Vercel API based on configuration\n const endpoint = this.useEdge\n ? `${this.baseUrl}/__detect/enforce`\n : `${this.baseUrl}/api/v1/enforce`;\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n 'X-Request-ID': input.requestId || crypto.randomUUID(),\n },\n body: JSON.stringify(input),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Parse response\n const data = (await response.json()) as EnforceResponse;\n\n if (this.debug) {\n console.log('[AgentShield] Enforce response:', {\n status: response.status,\n action: data.data?.decision.action,\n processingTimeMs: Date.now() - startTime,\n });\n }\n\n // Handle non-2xx responses\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: `HTTP_${response.status}`,\n message: data.error?.message || `HTTP error: ${response.status}`,\n },\n };\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Handle timeout\n if (error instanceof Error && error.name === 'AbortError') {\n if (this.debug) {\n console.warn('[AgentShield] Request timed out');\n }\n return {\n success: false,\n error: {\n code: 'TIMEOUT',\n message: `Request timed out after ${this.timeout}ms`,\n },\n };\n }\n\n // Handle network errors\n if (this.debug) {\n console.error('[AgentShield] Request failed:', error);\n }\n\n return {\n success: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Network request failed',\n },\n };\n }\n }\n\n /**\n * Quick check - returns just the action without full response parsing\n * Useful for very fast middleware that just needs allow/block\n */\n async quickCheck(input: EnforceInput): Promise<{\n action: EnforcementAction;\n error?: string;\n }> {\n const result = await this.enforce(input);\n\n if (!result.success || !result.data) {\n // On error, default to allow (fail-open)\n return {\n action: 'allow',\n error: result.error?.message,\n };\n }\n\n return {\n action: result.data.decision.action,\n };\n }\n\n /**\n * Check if this client is using edge detection (Gateway Worker)\n */\n isUsingEdge(): boolean {\n return this.useEdge;\n }\n\n /**\n * Log a detection result to AgentShield database.\n * Use after Gateway Worker detection to persist results.\n * Fire-and-forget - returns immediately without waiting for DB write.\n *\n * @example\n * ```typescript\n * // After receiving Gateway response\n * if (client.isUsingEdge() && response.data?.detection) {\n * client.logDetection({\n * detection: response.data.detection,\n * context: { userAgent, ipAddress, path, url, method }\n * }).catch(err => console.error('Log failed:', err));\n * }\n * ```\n */\n async logDetection(input: LogDetectionInput): Promise<void> {\n // Don't await - fire and forget\n // Use the base URL (not edge) for logging since this goes to the main API\n const logEndpoint = this.useEdge\n ? `${DEFAULT_BASE_URL}/api/v1/log-detection`\n : `${this.baseUrl}/api/v1/log-detection`;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(logEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n detection: {\n isAgent: input.detection.isAgent,\n confidence: input.detection.confidence,\n agentName: input.detection.agentName,\n agentType: input.detection.agentType,\n detectionClass: input.detection.detectionClass,\n verificationMethod: input.detection.verificationMethod,\n reasons: input.detection.reasons,\n },\n context: input.context,\n source: input.source || 'gateway',\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok && this.debug) {\n console.warn('[AgentShield] Log detection returned non-2xx:', response.status);\n }\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Silently fail for fire-and-forget, but log in debug mode\n if (this.debug) {\n console.error('[AgentShield] Log detection failed:', error);\n }\n // Re-throw so caller can catch if needed\n throw error;\n }\n }\n}\n\n/**\n * Create a singleton client instance\n *\n * @example\n * ```typescript\n * // In middleware.ts\n * import { getAgentShieldClient } from '@kya-os/agentshield-nextjs';\n *\n * const client = getAgentShieldClient();\n * ```\n */\nlet clientInstance: AgentShieldClient | null = null;\n\nexport function getAgentShieldClient(config?: Partial<AgentShieldClientConfig>): AgentShieldClient {\n if (!clientInstance) {\n const apiKey = config?.apiKey || process.env.AGENTSHIELD_API_KEY;\n\n if (!apiKey) {\n throw new Error(\n 'AgentShield API key is required. Set AGENTSHIELD_API_KEY environment variable or pass apiKey in config.'\n );\n }\n\n clientInstance = new AgentShieldClient({\n apiKey,\n baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL,\n // Default to edge detection unless explicitly disabled\n useEdge: config?.useEdge ?? process.env.AGENTSHIELD_USE_EDGE !== 'false',\n timeout: config?.timeout,\n debug: config?.debug || process.env.AGENTSHIELD_DEBUG === 'true',\n });\n }\n\n return clientInstance;\n}\n\n/**\n * Reset the singleton client (useful for testing)\n */\nexport function resetAgentShieldClient(): void {\n clientInstance = null;\n}\n","/**\n * Utility functions for agentshield-nextjs\n */\n\nimport type { NextRequest } from 'next/server';\n\n/**\n * Extract client IP address from a NextRequest.\n * In Next.js 15+, the `ip` property was removed from NextRequest.\n * This function uses headers to determine the client IP.\n *\n * @param request - The NextRequest object\n * @returns The client IP address or undefined if not available\n */\nexport function getClientIp(request: NextRequest): string | undefined {\n // Check x-forwarded-for header (standard for proxies/load balancers)\n const forwardedFor = request.headers.get('x-forwarded-for');\n if (forwardedFor) {\n // Take the first IP in the chain (original client)\n const ip = forwardedFor.split(',')[0]?.trim();\n if (ip) return ip;\n }\n\n // Check x-real-ip header (commonly used by nginx)\n const realIp = request.headers.get('x-real-ip');\n if (realIp) return realIp;\n\n // Check cf-connecting-ip header (Cloudflare)\n const cfIp = request.headers.get('cf-connecting-ip');\n if (cfIp) return cfIp;\n\n // Check x-client-ip header (some proxies use this)\n const clientIp = request.headers.get('x-client-ip');\n if (clientIp) return clientIp;\n\n return undefined;\n}\n\n/**\n * Safely extract the hostname from a URL string.\n * Returns a friendly fallback when parsing fails so UX copy doesn't leak\n * \"undefined\" or similar to end users.\n */\nexport function safeHostname(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return 'this site';\n }\n}\n","/**\n * Agent Instruction Response Builder (Next.js)\n *\n * Returns a 401 response with a machine-parseable Link header + JSON body\n * telling an AI agent where to send its user to complete consent / connect.\n *\n * This is the in-app counterpart to the Cloudflare Gateway's builder at\n * `apps/web/workers/gateway/src/responses/agent-instruction.ts`. The response\n * shape is kept in sync so LLM and MCP clients see identical behavior whether\n * a site is protected by the gateway or by the Next.js middleware.\n *\n * Implements:\n * - RFC 7235 (WWW-Authenticate header)\n * - RFC 8288 (Link header for discovery)\n *\n * @see ../../apps/web/workers/gateway/src/responses/agent-instruction.ts\n */\n\nimport { NextResponse, type NextRequest } from 'next/server';\nimport type { EnforcementDecision } from '../api-client';\nimport { safeHostname } from '../utils';\n\nconst MCP_I_DOCS_URL = 'https://docs.knowthat.ai/mcp-i/getting-started';\nconst DEFAULT_CONNECT_PATH = '/connect';\n\n/**\n * Build a 401 \"agent must connect\" response for the Next.js middleware.\n *\n * The caller is responsible for deciding *when* to call this (typically when\n * `decision.action === 'redirect'` or `'instruct'`). This helper only owns the\n * response shape.\n */\nexport function buildAgentInstructionResponse(\n request: NextRequest,\n decision: EnforcementDecision,\n redirectUrl: string | undefined\n): NextResponse {\n // Resolve the target to an absolute URL against the incoming request so the\n // Link header is dereferenceable by strict clients (some LLM fetchers refuse\n // relative URIs in Link).\n const resolved = resolveUrl(redirectUrl ?? DEFAULT_CONNECT_PATH, request.url);\n\n // Match gateway's \"connect page\" branch: attach ?agent= for client-specific\n // install cards on the landing page.\n const agentName = decision.agentName || decision.agentType || 'unknown';\n if (!resolved.searchParams.has('agent')) {\n resolved.searchParams.set('agent', agentName.toLowerCase());\n }\n\n const authUrl = resolved.toString();\n const hostname = safeHostname(request.url);\n\n const body = {\n // Markdown-formatted so clients that render markdown (Claude Desktop,\n // ChatGPT web) surface the URL as a clickable link. Tone mirrors the\n // gateway response so messaging stays consistent across platforms.\n message:\n `I can't access ${hostname} yet — this site checks AI assistants at the front door.\\n\\n` +\n `**To give me access, open this link:**\\n` +\n `[Connect securely to ${hostname}](${authUrl})\\n\\n` +\n `It only takes a moment and you won't need to do it again. ` +\n `Once you're done, ask me to try again and I'll connect through the verified channel automatically.`,\n\n user_action_required: {\n action: `Connect securely to ${hostname}`,\n url: authUrl,\n reason: `${hostname} checks AI assistants before they connect. Open the link to give your assistant a verified key.`,\n },\n\n mcp_i: {\n version: '1.0' as const,\n action: 'authenticate' as const,\n authorization_url: authUrl,\n flow: {\n type: 'oauth2_delegation' as const,\n steps: [\n '1. Direct your user to the authorization_url',\n '2. User reviews requested scopes and grants consent',\n '3. Receive delegation credential (JWT)',\n '4. Include credential in KYA-Delegation header',\n '5. Retry this request with the proof',\n ],\n },\n retry_instructions: {\n header: 'KYA-Delegation' as const,\n format: 'JWT delegation credential from authorization flow',\n },\n documentation: MCP_I_DOCS_URL,\n },\n\n error: 'mcp_authentication_required',\n code: 'AGENT_REQUIRES_DELEGATION',\n\n detection: {\n agent_type: decision.agentType || 'ai_agent',\n agent_name: decision.agentName || 'Unknown Agent',\n confidence: decision.confidence,\n },\n };\n\n const response = NextResponse.json(body, { status: 401 });\n\n // RFC 7235: tells strict clients this is an auth challenge.\n response.headers.set('WWW-Authenticate', `KYA realm=\"api\", authorization_uri=\"${authUrl}\"`);\n\n // RFC 8288: discovery pointer. `rel=\"kya-authorize\"` is the same value\n // the CF gateway emits — keep in sync.\n response.headers.set(\n 'Link',\n `<${authUrl}>; rel=\"kya-authorize\", <${MCP_I_DOCS_URL}>; rel=\"help\"`\n );\n\n // Headers read by MCP-I clients + our own tooling.\n response.headers.set('KYA-Auth-Required', 'true');\n response.headers.set('KYA-Auth-Url', authUrl);\n response.headers.set('KYA-Action', 'instruct');\n response.headers.set('KYA-Detected-Agent', agentName);\n response.headers.set('KYA-Confidence', decision.confidence.toString());\n response.headers.set('Cache-Control', 'no-store');\n\n return response;\n}\n\n/**\n * Resolve a URL that may be absolute or a same-origin path.\n * Falls back to `/connect` on the request origin if parsing fails.\n */\nfunction resolveUrl(target: string, baseUrl: string): URL {\n try {\n return new URL(target, baseUrl);\n } catch {\n return new URL(DEFAULT_CONNECT_PATH, baseUrl);\n }\n}\n","/**\n * API-based AgentShield Middleware for Next.js\n *\n * This middleware uses the AgentShield API for detection and enforcement,\n * instead of running detection locally. This approach:\n *\n * 1. Works reliably in Edge Runtime (no WASM loading issues)\n * 2. Ensures consistent detection across all platforms\n * 3. Applies centralized policies from the dashboard\n * 4. Supports deny lists, thresholds, and path rules\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware';\n *\n * export default withAgentShield({\n * apiKey: process.env.AGENTSHIELD_API_KEY!,\n * // Optional overrides:\n * onBlock: 'redirect', // 'block' | 'redirect' | 'challenge'\n * redirectUrl: '/blocked',\n * skipPaths: ['/api/health', '/_next/*'],\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next/static|favicon.ico).*)'],\n * };\n * ```\n */\n\nimport { NextRequest, NextResponse } from 'next/server';\nimport { AgentShieldClient, getAgentShieldClient, type EnforcementDecision } from './api-client';\nimport { buildAgentInstructionResponse } from './responses/agent-instruction';\nimport { getClientIp, safeHostname } from './utils';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Middleware configuration\n */\nexport interface AgentShieldMiddlewareConfig {\n /** API key (or use AGENTSHIELD_API_KEY env var) */\n apiKey?: string;\n /** API base URL (defaults to production) */\n apiUrl?: string;\n /**\n * Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.\n * Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)\n * that the pixel cannot detect since they don't execute JavaScript.\n * Set to false to use the Vercel API instead.\n * @default true\n */\n useEdge?: boolean;\n /** Request timeout in ms (default: 5000) */\n timeout?: number;\n\n /**\n * Action to take when an agent should be blocked\n * - 'block': Return 403 response\n * - 'redirect': Redirect to redirectUrl\n * - 'challenge': Show a challenge page (future)\n * Default: uses policy from dashboard\n */\n onBlock?: 'block' | 'redirect' | 'challenge';\n\n /**\n * URL to redirect to when blocking (if onBlock is 'redirect')\n * Default: uses redirectUrl from dashboard policy\n */\n redirectUrl?: string;\n\n /**\n * How the middleware handles a `redirect` / `instruct` action.\n *\n * - `'instruct'` (default): return HTTP 401 with an MCP-I Link header + JSON\n * body pointing the agent at the redirect URL. LLMs surface the URL as a\n * clickable link for the user. Matches the Cloudflare Gateway contract.\n * - `'http'`: legacy behavior — return HTTP 302 with `Location`. Most LLM\n * fetchers won't follow the redirect, so this is only useful when your\n * traffic is real browsers.\n *\n * @default 'instruct'\n */\n redirectMode?: 'instruct' | 'http';\n\n /**\n * Custom blocked response\n */\n blockedResponse?: {\n status?: number;\n message?: string;\n headers?: Record<string, string>;\n };\n\n /**\n * Paths to skip (in addition to dashboard policy)\n * Supports glob patterns: '/api/*', '/_next/*'\n */\n skipPaths?: string[];\n\n /**\n * Only enforce on these paths (overrides dashboard policy)\n */\n includePaths?: string[];\n\n /**\n * Callback when an agent is detected\n */\n onAgentDetected?: (request: NextRequest, decision: EnforcementDecision) => void | Promise<void>;\n\n /**\n * Callback to customize the blocked response\n */\n customBlockedResponse?: (\n request: NextRequest,\n decision: EnforcementDecision\n ) => NextResponse | Promise<NextResponse>;\n\n /**\n * Whether to fail open (allow) on API errors\n * Default: true (recommended for production)\n */\n failOpen?: boolean;\n\n /**\n * Enable debug logging\n */\n debug?: boolean;\n}\n\n// ============================================================================\n// Path Matching\n// ============================================================================\n\n/**\n * Check if a path matches a pattern\n */\nfunction matchPath(path: string, pattern: string): boolean {\n // Handle exact match\n if (pattern === path) return true;\n\n // Handle glob patterns\n if (pattern.includes('*')) {\n const regexPattern = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex chars\n .replace(/\\*/g, '.*'); // Convert * to .*\n return new RegExp(`^${regexPattern}$`).test(path);\n }\n\n // Handle prefix match\n if (pattern.endsWith('/')) {\n return path.startsWith(pattern) || path === pattern.slice(0, -1);\n }\n\n return path.startsWith(pattern);\n}\n\n/**\n * Check if path should be skipped\n */\nfunction shouldSkipPath(path: string, skipPaths: string[]): boolean {\n return skipPaths.some((pattern) => matchPath(path, pattern));\n}\n\n/**\n * Check if path should be included (if includePaths is set)\n */\nfunction shouldIncludePath(path: string, includePaths?: string[]): boolean {\n if (!includePaths || includePaths.length === 0) return true;\n return includePaths.some((pattern) => matchPath(path, pattern));\n}\n\n// ============================================================================\n// Response Builders\n// ============================================================================\n\n/**\n * Build blocked response.\n *\n * When the policy attaches a `redirectUrl` (e.g. the dashboard's hosted\n * /connect page), we still respect the `block` action but surface the URL to\n * LLM clients so the user can recover: `Link` header + `user_action_required`\n * in the JSON body. Status stays 403 — this is not an auth challenge, it's a\n * blocked request with a recovery hint.\n */\nfunction buildBlockedResponse(\n request: NextRequest,\n decision: EnforcementDecision,\n config: AgentShieldMiddlewareConfig\n): NextResponse {\n const status = config.blockedResponse?.status ?? 403;\n const message = config.blockedResponse?.message ?? decision.message ?? 'Access denied';\n\n const recoveryUrl = resolveRecoveryUrl(request, config.redirectUrl || decision.redirectUrl);\n\n const body: Record<string, unknown> = {\n error: message,\n code: 'AGENT_BLOCKED',\n reason: decision.reason,\n agentType: decision.agentType,\n };\n\n if (recoveryUrl) {\n const hostname = safeHostname(request.url);\n body.user_action_required = {\n action: `Connect securely to ${hostname}`,\n url: recoveryUrl,\n reason: `${hostname} blocks unverified AI assistants. Open the link to give your assistant a verified key and try again.`,\n };\n body.message =\n `I can't access ${hostname} — this site blocks unverified AI assistants.\\n\\n` +\n `**To give me access, open this link:**\\n` +\n `[Connect securely to ${hostname}](${recoveryUrl})\\n\\n` +\n `Once you're done, ask me to try again.`;\n }\n\n const response = NextResponse.json(body, { status });\n\n // Add custom headers\n if (config.blockedResponse?.headers) {\n for (const [key, value] of Object.entries(config.blockedResponse.headers)) {\n response.headers.set(key, value);\n }\n }\n\n if (recoveryUrl) {\n // RFC 8288 discovery pointer — same rel value the 401 instruct path uses\n // so LLM clients can parse it uniformly.\n response.headers.set('Link', `<${recoveryUrl}>; rel=\"kya-authorize\"`);\n response.headers.set('KYA-Auth-Url', recoveryUrl);\n }\n\n // Add AgentShield headers\n response.headers.set('KYA-Action', decision.action);\n response.headers.set('KYA-Reason', decision.reason);\n\n return response;\n}\n\nfunction resolveRecoveryUrl(request: NextRequest, target: string | undefined): string | undefined {\n if (!target) return undefined;\n try {\n return new URL(target, request.url).toString();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Build redirect response\n */\nfunction buildRedirectResponse(\n request: NextRequest,\n decision: EnforcementDecision,\n config: AgentShieldMiddlewareConfig\n): NextResponse {\n const redirectUrl = config.redirectUrl || decision.redirectUrl || '/blocked';\n const url = new URL(redirectUrl, request.url);\n\n // Add query params with detection info\n url.searchParams.set('reason', decision.reason);\n if (decision.agentType) {\n url.searchParams.set('agent', decision.agentType);\n }\n\n return NextResponse.redirect(url);\n}\n\n// ============================================================================\n// Middleware Factory\n// ============================================================================\n\n/**\n * Create AgentShield middleware with API-based detection\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware';\n *\n * export default withAgentShield({\n * onBlock: 'block',\n * skipPaths: ['/api/health'],\n * });\n * ```\n */\nexport function withAgentShield(config: AgentShieldMiddlewareConfig = {}) {\n // Initialize client (will use AGENTSHIELD_API_KEY env var if not provided)\n let client: AgentShieldClient | null = null;\n\n const getClient = () => {\n if (!client) {\n client = getAgentShieldClient({\n apiKey: config.apiKey,\n baseUrl: config.apiUrl,\n useEdge: config.useEdge,\n timeout: config.timeout,\n debug: config.debug,\n });\n }\n return client;\n };\n\n // Default skip paths (static assets, etc.)\n const defaultSkipPaths = [\n '/_next/static/*',\n '/_next/image/*',\n '/favicon.ico',\n '/robots.txt',\n '/sitemap.xml',\n ];\n\n const skipPaths = [...defaultSkipPaths, ...(config.skipPaths || [])];\n const failOpen = config.failOpen ?? true;\n\n return async function middleware(request: NextRequest): Promise<NextResponse> {\n const path = request.nextUrl.pathname;\n const startTime = Date.now();\n\n // Check skip paths\n if (shouldSkipPath(path, skipPaths)) {\n return NextResponse.next();\n }\n\n // Check include paths\n if (!shouldIncludePath(path, config.includePaths)) {\n return NextResponse.next();\n }\n\n try {\n const client = getClient();\n\n // Extract request context for potential logging\n const userAgent = request.headers.get('user-agent') || undefined;\n const ipAddress = getClientIp(request);\n\n // Call enforce API\n const result = await client.enforce({\n headers: Object.fromEntries(request.headers.entries()),\n userAgent,\n ipAddress,\n path,\n url: request.url,\n method: request.method,\n requestId: request.headers.get('x-request-id') || undefined,\n options: {\n // Always include detection results for logging (needed when using edge)\n includeDetectionResult: true,\n },\n });\n\n // Handle API error\n if (!result.success || !result.data) {\n if (config.debug) {\n console.warn('[AgentShield] API error:', result.error);\n }\n\n if (failOpen) {\n return NextResponse.next();\n }\n\n // Fail closed - block on error\n return NextResponse.json(\n { error: 'Security check failed', code: 'API_ERROR' },\n { status: 503 }\n );\n }\n\n const decision = result.data.decision;\n\n // Log if debug enabled\n if (config.debug) {\n console.log('[AgentShield] Decision:', {\n path,\n action: decision.action,\n isAgent: decision.isAgent,\n confidence: decision.confidence,\n agentName: decision.agentName,\n detectionMethod: result.data.detection?.detectionMethod || 'not-included',\n processingTimeMs: Date.now() - startTime,\n });\n }\n\n // Fire-and-forget logging - ONLY when using Gateway Worker (edge detection)\n // When useEdge: false, the /api/v1/enforce endpoint already logs to the database\n // This prevents double-logging while ensuring Gateway detections are persisted\n if (client.isUsingEdge() && result.data.detection) {\n client\n .logDetection({\n detection: result.data.detection,\n context: { userAgent, ipAddress, path, url: request.url, method: request.method },\n })\n .catch((err) => {\n if (config.debug) {\n console.error('[AgentShield] Log detection failed:', err);\n }\n });\n }\n\n // Handle agent detection callback\n if (decision.isAgent && config.onAgentDetected) {\n await config.onAgentDetected(request, decision);\n }\n\n // Handle enforcement action\n const redirectMode = config.redirectMode ?? 'instruct';\n switch (decision.action) {\n case 'block': {\n // Use custom response if provided\n if (config.customBlockedResponse) {\n return config.customBlockedResponse(request, decision);\n }\n\n // Check if config overrides to redirect\n if (config.onBlock === 'redirect') {\n return buildRedirectResponse(request, decision, config);\n }\n\n return buildBlockedResponse(request, decision, config);\n }\n\n case 'redirect':\n case 'instruct': {\n // Default behavior: 401 + Link header + JSON body so LLM clients can\n // surface the /connect URL as a link for the user to open. This\n // matches `buildAgentInstructionResponse` in the CF gateway, so\n // hostname-routed and self-hosted deployments behave the same.\n //\n // Legacy 302 behavior is available under `redirectMode: 'http'` for\n // customers who want a plain browser redirect.\n if (redirectMode === 'http' && decision.action === 'redirect') {\n return buildRedirectResponse(request, decision, config);\n }\n\n const targetUrl = config.redirectUrl || decision.redirectUrl;\n return buildAgentInstructionResponse(request, decision, targetUrl);\n }\n\n case 'challenge': {\n // Future: implement challenge page\n // For now, treat as redirect\n return buildRedirectResponse(request, decision, config);\n }\n\n case 'log':\n case 'allow':\n default: {\n // Allow the request to proceed\n const response = NextResponse.next();\n\n // Add detection headers for downstream use\n if (decision.isAgent) {\n response.headers.set('KYA-Detected', 'true');\n response.headers.set('KYA-Confidence', decision.confidence.toString());\n if (decision.agentName) {\n response.headers.set('KYA-Agent', decision.agentName);\n }\n }\n\n return response;\n }\n }\n } catch (error) {\n // Unexpected error\n if (config.debug) {\n console.error('[AgentShield] Middleware error:', error);\n }\n\n if (failOpen) {\n return NextResponse.next();\n }\n\n return NextResponse.json(\n { error: 'Security check failed', code: 'MIDDLEWARE_ERROR' },\n { status: 503 }\n );\n }\n };\n}\n\n/**\n * Convenience export for simple setup\n *\n * @example\n * ```typescript\n * // middleware.ts\n * export { agentShieldMiddleware as default } from '@kya-os/agentshield-nextjs/api-middleware';\n * ```\n */\nexport const agentShieldMiddleware = withAgentShield();\n"]}
@@ -192,6 +192,105 @@ function getAgentShieldClient(config) {
192
192
  return clientInstance;
193
193
  }
194
194
 
195
+ // src/utils.ts
196
+ function getClientIp(request) {
197
+ const forwardedFor = request.headers.get("x-forwarded-for");
198
+ if (forwardedFor) {
199
+ const ip = forwardedFor.split(",")[0]?.trim();
200
+ if (ip) return ip;
201
+ }
202
+ const realIp = request.headers.get("x-real-ip");
203
+ if (realIp) return realIp;
204
+ const cfIp = request.headers.get("cf-connecting-ip");
205
+ if (cfIp) return cfIp;
206
+ const clientIp = request.headers.get("x-client-ip");
207
+ if (clientIp) return clientIp;
208
+ return void 0;
209
+ }
210
+ function safeHostname(url) {
211
+ try {
212
+ return new URL(url).hostname;
213
+ } catch {
214
+ return "this site";
215
+ }
216
+ }
217
+
218
+ // src/responses/agent-instruction.ts
219
+ var MCP_I_DOCS_URL = "https://docs.knowthat.ai/mcp-i/getting-started";
220
+ var DEFAULT_CONNECT_PATH = "/connect";
221
+ function buildAgentInstructionResponse(request, decision, redirectUrl) {
222
+ const resolved = resolveUrl(redirectUrl ?? DEFAULT_CONNECT_PATH, request.url);
223
+ const agentName = decision.agentName || decision.agentType || "unknown";
224
+ if (!resolved.searchParams.has("agent")) {
225
+ resolved.searchParams.set("agent", agentName.toLowerCase());
226
+ }
227
+ const authUrl = resolved.toString();
228
+ const hostname = safeHostname(request.url);
229
+ const body = {
230
+ // Markdown-formatted so clients that render markdown (Claude Desktop,
231
+ // ChatGPT web) surface the URL as a clickable link. Tone mirrors the
232
+ // gateway response so messaging stays consistent across platforms.
233
+ message: `I can't access ${hostname} yet \u2014 this site checks AI assistants at the front door.
234
+
235
+ **To give me access, open this link:**
236
+ [Connect securely to ${hostname}](${authUrl})
237
+
238
+ It only takes a moment and you won't need to do it again. Once you're done, ask me to try again and I'll connect through the verified channel automatically.`,
239
+ user_action_required: {
240
+ action: `Connect securely to ${hostname}`,
241
+ url: authUrl,
242
+ reason: `${hostname} checks AI assistants before they connect. Open the link to give your assistant a verified key.`
243
+ },
244
+ mcp_i: {
245
+ version: "1.0",
246
+ action: "authenticate",
247
+ authorization_url: authUrl,
248
+ flow: {
249
+ type: "oauth2_delegation",
250
+ steps: [
251
+ "1. Direct your user to the authorization_url",
252
+ "2. User reviews requested scopes and grants consent",
253
+ "3. Receive delegation credential (JWT)",
254
+ "4. Include credential in KYA-Delegation header",
255
+ "5. Retry this request with the proof"
256
+ ]
257
+ },
258
+ retry_instructions: {
259
+ header: "KYA-Delegation",
260
+ format: "JWT delegation credential from authorization flow"
261
+ },
262
+ documentation: MCP_I_DOCS_URL
263
+ },
264
+ error: "mcp_authentication_required",
265
+ code: "AGENT_REQUIRES_DELEGATION",
266
+ detection: {
267
+ agent_type: decision.agentType || "ai_agent",
268
+ agent_name: decision.agentName || "Unknown Agent",
269
+ confidence: decision.confidence
270
+ }
271
+ };
272
+ const response = NextResponse.json(body, { status: 401 });
273
+ response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
274
+ response.headers.set(
275
+ "Link",
276
+ `<${authUrl}>; rel="kya-authorize", <${MCP_I_DOCS_URL}>; rel="help"`
277
+ );
278
+ response.headers.set("KYA-Auth-Required", "true");
279
+ response.headers.set("KYA-Auth-Url", authUrl);
280
+ response.headers.set("KYA-Action", "instruct");
281
+ response.headers.set("KYA-Detected-Agent", agentName);
282
+ response.headers.set("KYA-Confidence", decision.confidence.toString());
283
+ response.headers.set("Cache-Control", "no-store");
284
+ return response;
285
+ }
286
+ function resolveUrl(target, baseUrl) {
287
+ try {
288
+ return new URL(target, baseUrl);
289
+ } catch {
290
+ return new URL(DEFAULT_CONNECT_PATH, baseUrl);
291
+ }
292
+ }
293
+
195
294
  // src/api-middleware.ts
196
295
  function matchPath(path, pattern) {
197
296
  if (pattern === path) return true;
@@ -211,27 +310,52 @@ function shouldIncludePath(path, includePaths) {
211
310
  if (!includePaths || includePaths.length === 0) return true;
212
311
  return includePaths.some((pattern) => matchPath(path, pattern));
213
312
  }
214
- function buildBlockedResponse(decision, config) {
313
+ function buildBlockedResponse(request, decision, config) {
215
314
  const status = config.blockedResponse?.status ?? 403;
216
315
  const message = config.blockedResponse?.message ?? decision.message ?? "Access denied";
217
- const response = NextResponse.json(
218
- {
219
- error: message,
220
- code: "AGENT_BLOCKED",
221
- reason: decision.reason,
222
- agentType: decision.agentType
223
- },
224
- { status }
225
- );
316
+ const recoveryUrl = resolveRecoveryUrl(request, config.redirectUrl || decision.redirectUrl);
317
+ const body = {
318
+ error: message,
319
+ code: "AGENT_BLOCKED",
320
+ reason: decision.reason,
321
+ agentType: decision.agentType
322
+ };
323
+ if (recoveryUrl) {
324
+ const hostname = safeHostname(request.url);
325
+ body.user_action_required = {
326
+ action: `Connect securely to ${hostname}`,
327
+ url: recoveryUrl,
328
+ reason: `${hostname} blocks unverified AI assistants. Open the link to give your assistant a verified key and try again.`
329
+ };
330
+ body.message = `I can't access ${hostname} \u2014 this site blocks unverified AI assistants.
331
+
332
+ **To give me access, open this link:**
333
+ [Connect securely to ${hostname}](${recoveryUrl})
334
+
335
+ Once you're done, ask me to try again.`;
336
+ }
337
+ const response = NextResponse.json(body, { status });
226
338
  if (config.blockedResponse?.headers) {
227
339
  for (const [key, value] of Object.entries(config.blockedResponse.headers)) {
228
340
  response.headers.set(key, value);
229
341
  }
230
342
  }
231
- response.headers.set("X-AgentShield-Action", decision.action);
232
- response.headers.set("X-AgentShield-Reason", decision.reason);
343
+ if (recoveryUrl) {
344
+ response.headers.set("Link", `<${recoveryUrl}>; rel="kya-authorize"`);
345
+ response.headers.set("KYA-Auth-Url", recoveryUrl);
346
+ }
347
+ response.headers.set("KYA-Action", decision.action);
348
+ response.headers.set("KYA-Reason", decision.reason);
233
349
  return response;
234
350
  }
351
+ function resolveRecoveryUrl(request, target) {
352
+ if (!target) return void 0;
353
+ try {
354
+ return new URL(target, request.url).toString();
355
+ } catch {
356
+ return void 0;
357
+ }
358
+ }
235
359
  function buildRedirectResponse(request, decision, config) {
236
360
  const redirectUrl = config.redirectUrl || decision.redirectUrl || "/blocked";
237
361
  const url = new URL(redirectUrl, request.url);
@@ -276,7 +400,7 @@ function withAgentShield(config = {}) {
276
400
  try {
277
401
  const client2 = getClient();
278
402
  const userAgent = request.headers.get("user-agent") || void 0;
279
- const ipAddress = request.ip || request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || request.headers.get("x-real-ip") || void 0;
403
+ const ipAddress = getClientIp(request);
280
404
  const result = await client2.enforce({
281
405
  headers: Object.fromEntries(request.headers.entries()),
282
406
  userAgent,
@@ -327,6 +451,7 @@ function withAgentShield(config = {}) {
327
451
  if (decision.isAgent && config.onAgentDetected) {
328
452
  await config.onAgentDetected(request, decision);
329
453
  }
454
+ const redirectMode = config.redirectMode ?? "instruct";
330
455
  switch (decision.action) {
331
456
  case "block": {
332
457
  if (config.customBlockedResponse) {
@@ -335,10 +460,15 @@ function withAgentShield(config = {}) {
335
460
  if (config.onBlock === "redirect") {
336
461
  return buildRedirectResponse(request, decision, config);
337
462
  }
338
- return buildBlockedResponse(decision, config);
463
+ return buildBlockedResponse(request, decision, config);
339
464
  }
340
- case "redirect": {
341
- return buildRedirectResponse(request, decision, config);
465
+ case "redirect":
466
+ case "instruct": {
467
+ if (redirectMode === "http" && decision.action === "redirect") {
468
+ return buildRedirectResponse(request, decision, config);
469
+ }
470
+ const targetUrl = config.redirectUrl || decision.redirectUrl;
471
+ return buildAgentInstructionResponse(request, decision, targetUrl);
342
472
  }
343
473
  case "challenge": {
344
474
  return buildRedirectResponse(request, decision, config);
@@ -348,10 +478,10 @@ function withAgentShield(config = {}) {
348
478
  default: {
349
479
  const response = NextResponse.next();
350
480
  if (decision.isAgent) {
351
- response.headers.set("X-AgentShield-Detected", "true");
352
- response.headers.set("X-AgentShield-Confidence", decision.confidence.toString());
481
+ response.headers.set("KYA-Detected", "true");
482
+ response.headers.set("KYA-Confidence", decision.confidence.toString());
353
483
  if (decision.agentName) {
354
- response.headers.set("X-AgentShield-Agent", decision.agentName);
484
+ response.headers.set("KYA-Agent", decision.agentName);
355
485
  }
356
486
  }
357
487
  return response;