@kya-os/agentshield-nextjs 0.1.46 → 0.1.48

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api-client.ts","../src/api-middleware.ts"],"names":[],"mappings":"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","file":"api-middleware.mjs","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 /** 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 verificationMethod?: string;\n reasons?: 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// Client Implementation\n// ============================================================================\n\nconst DEFAULT_BASE_URL = 'https://kya.vouched.id';\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 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 this.baseUrl = config.baseUrl || 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 const response = await fetch(`${this.baseUrl}/api/v1/enforce`, {\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/**\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 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 /** 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 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 // Call enforce API\n const result = await getClient().enforce({\n headers: Object.fromEntries(request.headers.entries()),\n userAgent: request.headers.get('user-agent') || undefined,\n ipAddress:\n request.ip ||\n request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ||\n request.headers.get('x-real-ip') ||\n undefined,\n path,\n url: request.url,\n method: request.method,\n requestId: request.headers.get('x-request-id') || undefined,\n options: {\n includeDetectionResult: config.debug,\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 processingTimeMs: Date.now() - startTime,\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/api-middleware.ts"],"names":[],"mappings":"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","file":"api-middleware.mjs","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)\n * When enabled, calls detect.kya-os.ai instead of the Vercel API\n * @default false\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 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// Client Implementation\n// ============================================================================\n\nconst DEFAULT_BASE_URL = 'https://kya.vouched.id';\nconst EDGE_DETECT_URL = 'https://detect.kya-os.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 this.useEdge = config.useEdge || false;\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/**\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 useEdge: config?.useEdge || process.env.AGENTSHIELD_USE_EDGE === 'true',\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)\n * When enabled, calls detect.kya-os.ai instead of the Vercel API\n * @default false\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 // Call enforce API\n const result = await getClient().enforce({\n headers: Object.fromEntries(request.headers.entries()),\n userAgent: request.headers.get('user-agent') || undefined,\n ipAddress:\n request.ip ||\n request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ||\n request.headers.get('x-real-ip') ||\n undefined,\n path,\n url: request.url,\n method: request.method,\n requestId: request.headers.get('x-request-id') || undefined,\n options: {\n includeDetectionResult: config.debug,\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 // 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"]}
package/dist/index.js CHANGED
@@ -2012,10 +2012,12 @@ function createEnhancedAgentShieldMiddleware(config = {}) {
2012
2012
 
2013
2013
  // src/api-client.ts
2014
2014
  var DEFAULT_BASE_URL = "https://kya.vouched.id";
2015
+ var EDGE_DETECT_URL = "https://detect.kya-os.ai";
2015
2016
  var DEFAULT_TIMEOUT = 5e3;
2016
2017
  var AgentShieldClient = class {
2017
2018
  apiKey;
2018
2019
  baseUrl;
2020
+ useEdge;
2019
2021
  timeout;
2020
2022
  debug;
2021
2023
  constructor(config) {
@@ -2023,7 +2025,8 @@ var AgentShieldClient = class {
2023
2025
  throw new Error("AgentShield API key is required");
2024
2026
  }
2025
2027
  this.apiKey = config.apiKey;
2026
- this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
2028
+ this.useEdge = config.useEdge || false;
2029
+ this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL);
2027
2030
  this.timeout = config.timeout || DEFAULT_TIMEOUT;
2028
2031
  this.debug = config.debug || false;
2029
2032
  }
@@ -2036,7 +2039,8 @@ var AgentShieldClient = class {
2036
2039
  const controller = new AbortController();
2037
2040
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2038
2041
  try {
2039
- const response = await fetch(`${this.baseUrl}/api/v1/enforce`, {
2042
+ const endpoint = this.useEdge ? `${this.baseUrl}/__detect/enforce` : `${this.baseUrl}/api/v1/enforce`;
2043
+ const response = await fetch(endpoint, {
2040
2044
  method: "POST",
2041
2045
  headers: {
2042
2046
  "Content-Type": "application/json",
@@ -2123,6 +2127,7 @@ function getAgentShieldClient(config) {
2123
2127
  clientInstance = new AgentShieldClient({
2124
2128
  apiKey,
2125
2129
  baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL,
2130
+ useEdge: config?.useEdge || process.env.AGENTSHIELD_USE_EDGE === "true",
2126
2131
  timeout: config?.timeout,
2127
2132
  debug: config?.debug || process.env.AGENTSHIELD_DEBUG === "true"
2128
2133
  });
@@ -2189,6 +2194,7 @@ function withAgentShield(config = {}) {
2189
2194
  client = getAgentShieldClient({
2190
2195
  apiKey: config.apiKey,
2191
2196
  baseUrl: config.apiUrl,
2197
+ useEdge: config.useEdge,
2192
2198
  timeout: config.timeout,
2193
2199
  debug: config.debug
2194
2200
  });
@@ -2246,6 +2252,7 @@ function withAgentShield(config = {}) {
2246
2252
  isAgent: decision.isAgent,
2247
2253
  confidence: decision.confidence,
2248
2254
  agentName: decision.agentName,
2255
+ detectionMethod: result.data.detection?.detectionMethod || "not-included",
2249
2256
  processingTimeMs: Date.now() - startTime
2250
2257
  });
2251
2258
  }