@highflame/overwatch 1.0.0

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 (156) hide show
  1. package/README.md +337 -0
  2. package/bin/overwatch +12 -0
  3. package/dist/auth/cli-oauth.d.ts +13 -0
  4. package/dist/auth/cli-oauth.d.ts.map +1 -0
  5. package/dist/auth/html-utils.d.ts +20 -0
  6. package/dist/auth/html-utils.d.ts.map +1 -0
  7. package/dist/auth/index.d.ts +10 -0
  8. package/dist/auth/index.d.ts.map +1 -0
  9. package/dist/auth/oauth.d.ts +81 -0
  10. package/dist/auth/oauth.d.ts.map +1 -0
  11. package/dist/auth/pkce.d.ts +26 -0
  12. package/dist/auth/pkce.d.ts.map +1 -0
  13. package/dist/auth/token-store.d.ts +44 -0
  14. package/dist/auth/token-store.d.ts.map +1 -0
  15. package/dist/bin/overwatch +12 -0
  16. package/dist/cli.d.ts +6 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +5449 -0
  19. package/dist/cli.js.map +7 -0
  20. package/dist/config/index.d.ts +5 -0
  21. package/dist/config/index.d.ts.map +1 -0
  22. package/dist/config/manager.d.ts +54 -0
  23. package/dist/config/manager.d.ts.map +1 -0
  24. package/dist/daemon.d.ts +11 -0
  25. package/dist/daemon.d.ts.map +1 -0
  26. package/dist/daemon.js +6004 -0
  27. package/dist/daemon.js.map +7 -0
  28. package/dist/data/ingestor.d.ts +31 -0
  29. package/dist/data/ingestor.d.ts.map +1 -0
  30. package/dist/data/processor.d.ts +96 -0
  31. package/dist/data/processor.d.ts.map +1 -0
  32. package/dist/data/reader.d.ts +24 -0
  33. package/dist/data/reader.d.ts.map +1 -0
  34. package/dist/data/recorder.d.ts +12 -0
  35. package/dist/data/recorder.d.ts.map +1 -0
  36. package/dist/engines/cedar.d.ts +41 -0
  37. package/dist/engines/cedar.d.ts.map +1 -0
  38. package/dist/engines/remote.d.ts +21 -0
  39. package/dist/engines/remote.d.ts.map +1 -0
  40. package/dist/engines/yara.d.ts +12 -0
  41. package/dist/engines/yara.d.ts.map +1 -0
  42. package/dist/handlers/dashboard-handler.d.ts +7 -0
  43. package/dist/handlers/dashboard-handler.d.ts.map +1 -0
  44. package/dist/handlers/hook-handler.d.ts +23 -0
  45. package/dist/handlers/hook-handler.d.ts.map +1 -0
  46. package/dist/handlers/oauth-handler.d.ts +12 -0
  47. package/dist/handlers/oauth-handler.d.ts.map +1 -0
  48. package/dist/handlers/scan-handler.d.ts +13 -0
  49. package/dist/handlers/scan-handler.d.ts.map +1 -0
  50. package/dist/handlers/utils.d.ts +11 -0
  51. package/dist/handlers/utils.d.ts.map +1 -0
  52. package/dist/hooks/claudecode/hooks.json.template +20 -0
  53. package/dist/hooks/cursor/hooks.json.template +74 -0
  54. package/dist/hooks/universal-hook.sh +36 -0
  55. package/dist/http/server.d.ts +38 -0
  56. package/dist/http/server.d.ts.map +1 -0
  57. package/dist/index.d.ts +8 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +5941 -0
  60. package/dist/index.js.map +7 -0
  61. package/dist/installer.d.ts +25 -0
  62. package/dist/installer.d.ts.map +1 -0
  63. package/dist/javelin/admin-client.d.ts +75 -0
  64. package/dist/javelin/admin-client.d.ts.map +1 -0
  65. package/dist/javelin/client.d.ts +30 -0
  66. package/dist/javelin/client.d.ts.map +1 -0
  67. package/dist/javelin/config-reader.d.ts +70 -0
  68. package/dist/javelin/config-reader.d.ts.map +1 -0
  69. package/dist/javelin/index.d.ts +5 -0
  70. package/dist/javelin/index.d.ts.map +1 -0
  71. package/dist/javelin/types.d.ts +81 -0
  72. package/dist/javelin/types.d.ts.map +1 -0
  73. package/dist/lib/policy-engine.d.ts +34 -0
  74. package/dist/lib/policy-engine.d.ts.map +1 -0
  75. package/dist/lib/policy-manager.d.ts +86 -0
  76. package/dist/lib/policy-manager.d.ts.map +1 -0
  77. package/dist/module.d.ts +52 -0
  78. package/dist/module.d.ts.map +1 -0
  79. package/dist/pipeline/context-mapper.d.ts +16 -0
  80. package/dist/pipeline/context-mapper.d.ts.map +1 -0
  81. package/dist/pipeline/extractors/claude-extractor.d.ts +48 -0
  82. package/dist/pipeline/extractors/claude-extractor.d.ts.map +1 -0
  83. package/dist/pipeline/extractors/cursor-extractor.d.ts +44 -0
  84. package/dist/pipeline/extractors/cursor-extractor.d.ts.map +1 -0
  85. package/dist/pipeline/extractors/github-copilot-extractor.d.ts +49 -0
  86. package/dist/pipeline/extractors/github-copilot-extractor.d.ts.map +1 -0
  87. package/dist/pipeline/extractors/index.d.ts +47 -0
  88. package/dist/pipeline/extractors/index.d.ts.map +1 -0
  89. package/dist/pipeline/extractors/registry.d.ts +38 -0
  90. package/dist/pipeline/extractors/registry.d.ts.map +1 -0
  91. package/dist/pipeline/hook-pipeline.d.ts +25 -0
  92. package/dist/pipeline/hook-pipeline.d.ts.map +1 -0
  93. package/dist/policy.cedar +783 -0
  94. package/dist/rules/pre/command_injection.yar +60 -0
  95. package/dist/rules/pre/cross_origin_escalation.yar +106 -0
  96. package/dist/rules/pre/mcp_config_risk.yar +35 -0
  97. package/dist/rules/pre/path_traversal.yar +50 -0
  98. package/dist/rules/pre/prompt_injection.yar +101 -0
  99. package/dist/rules/pre/secrets_leakage.yar +100 -0
  100. package/dist/rules/pre/sql_injection.yar +65 -0
  101. package/dist/scanner.d.ts +80 -0
  102. package/dist/scanner.d.ts.map +1 -0
  103. package/dist/service.d.ts +18 -0
  104. package/dist/service.d.ts.map +1 -0
  105. package/dist/services/interface.d.ts +11 -0
  106. package/dist/services/interface.d.ts.map +1 -0
  107. package/dist/services/launchd.d.ts +12 -0
  108. package/dist/services/launchd.d.ts.map +1 -0
  109. package/dist/services/systemd.d.ts +12 -0
  110. package/dist/services/systemd.d.ts.map +1 -0
  111. package/dist/services/windows.d.ts +7 -0
  112. package/dist/services/windows.d.ts.map +1 -0
  113. package/dist/skills/index.d.ts +7 -0
  114. package/dist/skills/index.d.ts.map +1 -0
  115. package/dist/skills/scanner.d.ts +44 -0
  116. package/dist/skills/scanner.d.ts.map +1 -0
  117. package/dist/skills/types.d.ts +29 -0
  118. package/dist/skills/types.d.ts.map +1 -0
  119. package/dist/types/config.d.ts +165 -0
  120. package/dist/types/config.d.ts.map +1 -0
  121. package/dist/types/events.d.ts +225 -0
  122. package/dist/types/events.d.ts.map +1 -0
  123. package/dist/types/index.d.ts +6 -0
  124. package/dist/types/index.d.ts.map +1 -0
  125. package/dist/types/remote-policy.d.ts +129 -0
  126. package/dist/types/remote-policy.d.ts.map +1 -0
  127. package/dist/types/requests.d.ts +45 -0
  128. package/dist/types/requests.d.ts.map +1 -0
  129. package/dist/types/responses.d.ts +60 -0
  130. package/dist/types/responses.d.ts.map +1 -0
  131. package/dist/ui/images/highflame-mono.png +0 -0
  132. package/dist/ui/views/dashboard.ejs +301 -0
  133. package/dist/ui/views/dashboard.js +785 -0
  134. package/dist/ui/views/partials/commands-table.ejs +54 -0
  135. package/dist/ui/views/partials/events-table.ejs +36 -0
  136. package/dist/ui/views/partials/filter-dropdown.ejs +12 -0
  137. package/dist/ui/views/partials/overview-charts.ejs +149 -0
  138. package/dist/ui/views/partials/scans-table.ejs +136 -0
  139. package/dist/ui/views/partials/sessions-table.ejs +50 -0
  140. package/dist/ui/views/partials/stats-grid.ejs +23 -0
  141. package/dist/ui/views/partials/threats-table.ejs +60 -0
  142. package/dist/utils/index.d.ts +3 -0
  143. package/dist/utils/index.d.ts.map +1 -0
  144. package/dist/utils/logger.d.ts +28 -0
  145. package/dist/utils/logger.d.ts.map +1 -0
  146. package/dist/utils/performance.d.ts +26 -0
  147. package/dist/utils/performance.d.ts.map +1 -0
  148. package/dist/utils/port-manager.d.ts +6 -0
  149. package/dist/utils/port-manager.d.ts.map +1 -0
  150. package/dist/yara/engine.d.ts +58 -0
  151. package/dist/yara/engine.d.ts.map +1 -0
  152. package/dist/yara/index.d.ts +5 -0
  153. package/dist/yara/index.d.ts.map +1 -0
  154. package/lib/platform-loader.js +210 -0
  155. package/package.json +63 -0
  156. package/scripts/postinstall.js +121 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/auth/pkce.ts", "../src/auth/oauth.ts", "../lib/platform-loader.js", "../node_modules/ejs/lib/utils.js", "../node_modules/ejs/package.json", "../node_modules/ejs/lib/ejs.js", "../src/daemon.ts", "../src/module.ts", "../src/http/server.ts", "../src/utils/logger.ts", "../src/javelin/config-reader.ts", "../src/auth/index.ts", "../src/auth/cli-oauth.ts", "../src/auth/token-store.ts", "../src/auth/html-utils.ts", "../src/config/manager.ts", "../src/types/config.ts", "../src/types/remote-policy.ts", "../src/javelin/client.ts", "../src/javelin/admin-client.ts", "../src/lib/policy-manager.ts", "../src/lib/policy-engine.ts", "../src/scanner.ts", "../src/yara/engine.ts", "../src/engines/yara.ts", "../src/engines/remote.ts", "../src/data/ingestor.ts", "../src/engines/cedar.ts", "../src/pipeline/context-mapper.ts", "../src/handlers/utils.ts", "../src/pipeline/hook-pipeline.ts", "../src/data/recorder.ts", "../src/handlers/hook-handler.ts", "../src/handlers/scan-handler.ts", "../src/handlers/dashboard-handler.ts", "../src/data/reader.ts", "../src/data/processor.ts", "../src/handlers/oauth-handler.ts", "../src/pipeline/extractors/cursor-extractor.ts", "../src/pipeline/extractors/claude-extractor.ts", "../src/pipeline/extractors/github-copilot-extractor.ts", "../src/pipeline/extractors/registry.ts", "../src/skills/scanner.ts", "../src/utils/port-manager.ts"],
4
+ "sourcesContent": ["/**\n * PKCE (Proof Key for Code Exchange) utilities\n * Used for secure OAuth 2.0 flow without client_secret (public client)\n * RFC 7636: https://tools.ietf.org/html/rfc7636\n */\n\nimport * as crypto from \"crypto\";\n\n/**\n * Base64 URL encoding (no padding, URL-safe characters)\n * Per RFC 7636 Appendix A\n */\nfunction base64URLEncode(buffer: Buffer): string {\n return buffer\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=/g, \"\");\n}\n\n/**\n * Generate a cryptographically random code verifier\n * Per RFC 7636: 43-128 characters, using unreserved characters\n * [A-Z] / [a-z] / [0-9] / \"-\" / \".\" / \"_\" / \"~\"\n *\n * We use 32 random bytes \u2192 43 base64url characters\n */\nexport function generateCodeVerifier(): string {\n const buffer = crypto.randomBytes(32);\n return base64URLEncode(buffer);\n}\n\n/**\n * Generate code challenge from verifier using S256 method\n * challenge = BASE64URL(SHA256(verifier))\n *\n * S256 is more secure than plain method and required by most OAuth providers\n */\nexport function generateCodeChallenge(verifier: string): string {\n const hash = crypto.createHash(\"sha256\").update(verifier).digest();\n return base64URLEncode(hash);\n}\n\n/**\n * Generate random state parameter for CSRF protection\n * Returns 32-character hex string (16 random bytes)\n */\nexport function generateState(): string {\n return crypto.randomBytes(16).toString(\"hex\");\n}\n", "/**\n * OAuth 2.0 flow manager for Highflame authentication\n * Uses PKCE for secure public client authentication\n */\n\nimport { generateCodeVerifier, generateState } from \"./pkce\";\n\n/**\n * OAuth configuration for Highflame Studio\n */\nexport const OAUTH_CONFIG = {\n authUrl: \"https://studio.api-dev.highflame.dev/cli-auth\",\n tokenUrl: \"https://studio.api-dev.highflame.dev/api/cli-auth/token\",\n clientId: \"overwatch-cli\",\n scopes: [\"account:read\", \"gateway:read\"],\n};\n\n/**\n * Token expiry: 90 days in seconds\n */\nexport const TOKEN_EXPIRY_SECONDS = 90 * 24 * 60 * 60; // 7,776,000 seconds\n\n/**\n * Pending OAuth flow state\n */\nexport interface OAuthState {\n state: string;\n codeVerifier: string;\n redirectUri: string;\n createdAt: number;\n status: \"pending\" | \"completed\" | \"failed\" | \"expired\";\n tokens?: TokenResponse;\n error?: string;\n userInfo?: UserInfo;\n}\n\n/**\n * Token response from Highflame Studio API\n */\nexport interface TokenResponse {\n access_token: string;\n refresh_token?: string; // Optional, not always returned\n expires_in: number; // seconds\n token_type: \"Bearer\";\n expires_at?: number; // computed Unix timestamp in milliseconds\n scope?: string;\n user?: {\n id: string;\n email: string;\n };\n}\n\n/**\n * User information from Highflame Studio API\n */\nexport interface UserInfo {\n id: string;\n email: string;\n}\n\n/**\n * Build the OAuth authorization URL with PKCE parameters\n */\nexport function buildAuthorizationUrl(\n state: string,\n codeChallenge: string,\n redirectUri: string,\n): string {\n const params = new URLSearchParams({\n response_type: \"code\",\n client_id: OAUTH_CONFIG.clientId,\n redirect_uri: redirectUri,\n code_challenge: codeChallenge,\n code_challenge_method: \"S256\",\n state: state,\n scope: OAUTH_CONFIG.scopes.join(\" \"),\n });\n\n return `${OAUTH_CONFIG.authUrl}?${params.toString()}`;\n}\n\n/**\n * Exchange authorization code for tokens\n * Public client flow - no client_secret required, PKCE verifier proves identity\n */\nexport async function exchangeCodeForTokens(\n code: string,\n codeVerifier: string,\n redirectUri: string,\n): Promise<{ tokens: TokenResponse; userInfo: UserInfo }> {\n console.log(\"[OAuth] Exchanging code for tokens...\");\n console.log(\"[OAuth] Token URL:\", OAUTH_CONFIG.tokenUrl);\n\n const response = await fetch(OAUTH_CONFIG.tokenUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"authorization_code\",\n client_id: OAUTH_CONFIG.clientId,\n code: code,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n }),\n signal: AbortSignal.timeout(30000),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\"[OAuth] Token exchange failed:\", response.status, errorText);\n throw new Error(`Token exchange failed: ${response.status} ${errorText}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n console.log(\"[OAuth] Token exchange successful\");\n\n // Compute absolute expiry timestamp\n // Use provided expires_in or default to 90 days\n const expiresInSeconds = data.expires_in || TOKEN_EXPIRY_SECONDS;\n data.expires_at = Date.now() + expiresInSeconds * 1000;\n\n // Extract user info from token response\n const userInfo: UserInfo = {\n id: data.user?.id || \"\",\n email: data.user?.email || \"\",\n };\n\n return { tokens: data, userInfo };\n}\n\n/**\n * Refresh access token using refresh token\n * Placeholder for future refresh endpoint implementation\n */\nexport async function refreshAccessToken(\n _refreshToken: string,\n): Promise<TokenResponse | null> {\n // TODO: Implement refresh token endpoint when available\n // For now, return null to indicate re-authentication is needed\n return null;\n}\n\n/**\n * Check if tokens are expired or about to expire\n * @param expiresAt Unix timestamp in milliseconds\n * @param bufferSeconds Buffer time before actual expiry (default: 1 day)\n */\nexport function isTokenExpired(\n expiresAt: number,\n bufferSeconds: number = 86400,\n): boolean {\n return Date.now() >= expiresAt - bufferSeconds * 1000;\n}\n\n/**\n * Create a new OAuth flow state\n * @param guardianPort The port Guardian daemon is running on\n */\nexport function createOAuthState(guardianPort: number): OAuthState {\n const state = generateState();\n const codeVerifier = generateCodeVerifier();\n const redirectUri = `http://127.0.0.1:${guardianPort}/oauth/callback`;\n\n return {\n state,\n codeVerifier,\n redirectUri,\n createdAt: Date.now(),\n status: \"pending\",\n };\n}\n", "/**\n * Platform Loader\n *\n * Runtime platform detection and binary/module loading for @highflame/overwatch.\n * Follows the esbuild distribution pattern with platform-specific optionalDependencies.\n *\n * Loading order:\n * 1. Try loading from @highflame/overwatch-{platform} package (npm install)\n * 2. Fall back to local bin/ \n * 3. Fall back to ~/.overwatch/bin/ and system PATH\n */\n\nconst path = require('path');\nconst fs = require('fs');\nconst os = require('os');\n\n// Platform mapping: Node.js platform/arch -> package suffix and Rust target\nconst PLATFORM_MAP = {\n 'darwin-arm64': {\n package: '@highflame/overwatch-darwin-arm64',\n rustTarget: 'aarch64-apple-darwin',\n binaryName: 'ramparts-aarch64-apple-darwin',\n },\n 'darwin-x64': {\n package: '@highflame/overwatch-darwin-x64',\n rustTarget: 'x86_64-apple-darwin',\n binaryName: 'ramparts-x86_64-apple-darwin',\n },\n 'linux-x64': {\n package: '@highflame/overwatch-linux-x64',\n rustTarget: 'x86_64-unknown-linux-gnu',\n binaryName: 'ramparts-x86_64-unknown-linux-gnu',\n },\n 'linux-arm64': {\n package: '@highflame/overwatch-linux-arm64',\n rustTarget: 'aarch64-unknown-linux-gnu',\n binaryName: 'ramparts-aarch64-unknown-linux-gnu',\n },\n};\n\n/**\n * Get current platform key (e.g., \"darwin-arm64\")\n * @returns {string}\n */\nfunction getPlatformKey() {\n return `${process.platform}-${process.arch}`;\n}\n\n/**\n * Get platform configuration for current platform\n * @returns {object|null}\n */\nfunction getPlatformConfig() {\n const key = getPlatformKey();\n return PLATFORM_MAP[key] || null;\n}\n\n/**\n * Try to load the platform-specific package\n * Uses indirect require to prevent bundler analysis (esbuild, webpack)\n * @returns {object|null} The loaded platform package or null\n */\nfunction loadPlatformPackage() {\n const config = getPlatformConfig();\n if (!config) {\n return null;\n }\n\n try {\n // Use indirect require to prevent bundler from analyzing this\n // This allows the optionalDependencies to work correctly\n const dynamicRequire = typeof __non_webpack_require__ !== 'undefined'\n ? __non_webpack_require__\n : require;\n return dynamicRequire(config.package);\n } catch (error) {\n // Package not installed - this is expected when using local dev setup\n return null;\n }\n}\n\n/**\n * Get the guardian package root directory\n * Works from both dist/ and lib/ locations\n * @returns {string}\n */\nfunction getPackageRoot() {\n // This file is in lib/, so go up one level\n // When bundled, __dirname will be dist/, so this still works\n let currentDir = __dirname;\n\n // Handle various directory structures\n const baseName = path.basename(currentDir);\n if (baseName === 'lib' || baseName === 'dist') {\n return path.resolve(currentDir, '..');\n }\n\n // If we're deeply nested (e.g., dist/lib), go up appropriately\n return path.resolve(currentDir, '..');\n}\n\n/**\n * Get the path to the ramparts binary\n *\n * Search order:\n * 1. Platform package (npm optionalDependency)\n * 2. Local bin/ directory (dev mode)\n * 3. ~/.overwatch/bin/\n * 4. System PATH\n *\n * @returns {string|null} Path to binary or null if not found\n */\nfunction getRampartsBinaryPath() {\n const config = getPlatformConfig();\n\n // 1. Try platform package first\n const platformPkg = loadPlatformPackage();\n if (platformPkg && typeof platformPkg.getRampartsBinaryPath === 'function') {\n const binaryPath = platformPkg.getRampartsBinaryPath();\n if (binaryPath && fs.existsSync(binaryPath)) {\n return binaryPath;\n }\n }\n\n // 2. Try local bin/ directory (dev mode)\n const packageRoot = getPackageRoot();\n const localPaths = [];\n\n if (config) {\n // Platform-specific binary name\n localPaths.push(path.join(packageRoot, 'bin', config.binaryName));\n }\n\n // Generic paths\n localPaths.push(\n path.join(packageRoot, 'bin', 'ramparts'),\n path.join(packageRoot, 'dist', 'bin', 'ramparts'),\n );\n\n for (const p of localPaths) {\n if (fs.existsSync(p)) {\n return p;\n }\n }\n\n // 3. Try ~/.overwatch/bin/\n const overwatchPaths = [];\n if (config) {\n overwatchPaths.push(path.join(os.homedir(), '.overwatch', 'bin', config.binaryName));\n }\n overwatchPaths.push(path.join(os.homedir(), '.overwatch', 'bin', 'ramparts'));\n\n for (const p of overwatchPaths) {\n if (fs.existsSync(p)) {\n return p;\n }\n }\n\n // 4. Try PATH as last resort\n try {\n const { execSync } = require('child_process');\n const which = execSync('which ramparts', { encoding: 'utf-8' }).trim();\n if (which && fs.existsSync(which)) {\n return which;\n }\n } catch {\n // Not in PATH\n }\n\n return null;\n}\n\n\n/**\n * Check if the current platform is supported\n * @returns {boolean}\n */\nfunction isPlatformSupported() {\n return getPlatformConfig() !== null;\n}\n\n/**\n * Get a helpful error message when platform binaries are not found\n * @returns {string}\n */\nfunction getPlatformNotFoundMessage() {\n const key = getPlatformKey();\n const config = getPlatformConfig();\n\n if (!config) {\n return `Unsupported platform: ${key}. Supported platforms: ${Object.keys(PLATFORM_MAP).join(', ')}`;\n }\n\n return `Platform binaries not found for ${key}.\\n` +\n `\\n` +\n `To fix this, either:\\n` +\n ` 1. Install the platform package: npm install ${config.package}\\n` +\n ` 2. Run the native deps build: ./scripts/build-native-deps.sh\\n` +\n ` 3. Place binaries in ~/.overwatch/bin/\\n`;\n}\n\nmodule.exports = {\n getPlatformKey,\n getPlatformConfig,\n loadPlatformPackage,\n getRampartsBinaryPath,\n isPlatformSupported,\n getPlatformNotFoundMessage,\n PLATFORM_MAP,\n};\n", "/*\n * EJS Embedded JavaScript templates\n * Copyright 2112 Matthew Eernisse (mde@fleegix.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n*/\n\n/**\n * Private utility functions\n * @module utils\n * @private\n */\n\n'use strict';\n\nvar regExpChars = /[|\\\\{}()[\\]^$+*?.]/g;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };\n\n/**\n * Escape characters reserved in regular expressions.\n *\n * If `string` is `undefined` or `null`, the empty string is returned.\n *\n * @param {String} string Input string\n * @return {String} Escaped string\n * @static\n * @private\n */\nexports.escapeRegExpChars = function (string) {\n // istanbul ignore if\n if (!string) {\n return '';\n }\n return String(string).replace(regExpChars, '\\\\$&');\n};\n\nvar _ENCODE_HTML_RULES = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&#34;',\n \"'\": '&#39;'\n};\nvar _MATCH_HTML = /[&<>'\"]/g;\n\nfunction encode_char(c) {\n return _ENCODE_HTML_RULES[c] || c;\n}\n\n/**\n * Stringified version of constants used by {@link module:utils.escapeXML}.\n *\n * It is used in the process of generating {@link ClientFunction}s.\n *\n * @readonly\n * @type {String}\n */\n\nvar escapeFuncStr =\n 'var _ENCODE_HTML_RULES = {\\n'\n+ ' \"&\": \"&amp;\"\\n'\n+ ' , \"<\": \"&lt;\"\\n'\n+ ' , \">\": \"&gt;\"\\n'\n+ ' , \\'\"\\': \"&#34;\"\\n'\n+ ' , \"\\'\": \"&#39;\"\\n'\n+ ' }\\n'\n+ ' , _MATCH_HTML = /[&<>\\'\"]/g;\\n'\n+ 'function encode_char(c) {\\n'\n+ ' return _ENCODE_HTML_RULES[c] || c;\\n'\n+ '};\\n';\n\n/**\n * Escape characters reserved in XML.\n *\n * If `markup` is `undefined` or `null`, the empty string is returned.\n *\n * @implements {EscapeCallback}\n * @param {String} markup Input string\n * @return {String} Escaped string\n * @static\n * @private\n */\n\nexports.escapeXML = function (markup) {\n return markup == undefined\n ? ''\n : String(markup)\n .replace(_MATCH_HTML, encode_char);\n};\n\nfunction escapeXMLToString() {\n return Function.prototype.toString.call(this) + ';\\n' + escapeFuncStr;\n}\n\ntry {\n if (typeof Object.defineProperty === 'function') {\n // If the Function prototype is frozen, the \"toString\" property is non-writable. This means that any objects which inherit this property\n // cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not using strict\n // mode, attempting that will be silently ignored.\n // However, we can still explicitly shadow the prototype's \"toString\" property by defining a new \"toString\" property on this object.\n Object.defineProperty(exports.escapeXML, 'toString', { value: escapeXMLToString });\n } else {\n // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator.\n exports.escapeXML.toString = escapeXMLToString;\n }\n} catch (err) {\n console.warn('Unable to set escapeXML.toString (is the Function prototype frozen?)');\n}\n\n/**\n * Naive copy of properties from one object to another.\n * Does not recurse into non-scalar properties\n * Does not check to see if the property has a value before copying\n *\n * @param {Object} to Destination object\n * @param {Object} from Source object\n * @return {Object} Destination object\n * @static\n * @private\n */\nexports.shallowCopy = function (to, from) {\n from = from || {};\n if ((to !== null) && (to !== undefined)) {\n for (var p in from) {\n if (!hasOwn(from, p)) {\n continue;\n }\n if (p === '__proto__' || p === 'constructor') {\n continue;\n }\n to[p] = from[p];\n }\n }\n return to;\n};\n\n/**\n * Naive copy of a list of key names, from one object to another.\n * Only copies property if it is actually defined\n * Does not recurse into non-scalar properties\n *\n * @param {Object} to Destination object\n * @param {Object} from Source object\n * @param {Array} list List of properties to copy\n * @return {Object} Destination object\n * @static\n * @private\n */\nexports.shallowCopyFromList = function (to, from, list) {\n list = list || [];\n from = from || {};\n if ((to !== null) && (to !== undefined)) {\n for (var i = 0; i < list.length; i++) {\n var p = list[i];\n if (typeof from[p] != 'undefined') {\n if (!hasOwn(from, p)) {\n continue;\n }\n if (p === '__proto__' || p === 'constructor') {\n continue;\n }\n to[p] = from[p];\n }\n }\n }\n return to;\n};\n\n/**\n * Simple in-process cache implementation. Does not implement limits of any\n * sort.\n *\n * @implements {Cache}\n * @static\n * @private\n */\nexports.cache = {\n _data: {},\n set: function (key, val) {\n this._data[key] = val;\n },\n get: function (key) {\n return this._data[key];\n },\n remove: function (key) {\n delete this._data[key];\n },\n reset: function () {\n this._data = {};\n }\n};\n\n/**\n * Transforms hyphen case variable into camel case.\n *\n * @param {String} string Hyphen case string\n * @return {String} Camel case string\n * @static\n * @private\n */\nexports.hyphenToCamel = function (str) {\n return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); });\n};\n\n/**\n * Returns a null-prototype object in runtimes that support it\n *\n * @return {Object} Object, prototype will be set to null where possible\n * @static\n * @private\n */\nexports.createNullProtoObjWherePossible = (function () {\n if (typeof Object.create == 'function') {\n return function () {\n return Object.create(null);\n };\n }\n if (!({__proto__: null} instanceof Object)) {\n return function () {\n return {__proto__: null};\n };\n }\n // Not possible, just pass through\n return function () {\n return {};\n };\n})();\n\nexports.hasOwnOnlyObject = function (obj) {\n var o = exports.createNullProtoObjWherePossible();\n for (var p in obj) {\n if (hasOwn(obj, p)) {\n o[p] = obj[p];\n }\n }\n return o;\n};\n\n", "{\n \"name\": \"ejs\",\n \"description\": \"Embedded JavaScript templates\",\n \"keywords\": [\n \"template\",\n \"engine\",\n \"ejs\"\n ],\n \"version\": \"3.1.10\",\n \"author\": \"Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)\",\n \"license\": \"Apache-2.0\",\n \"bin\": {\n \"ejs\": \"./bin/cli.js\"\n },\n \"main\": \"./lib/ejs.js\",\n \"jsdelivr\": \"ejs.min.js\",\n \"unpkg\": \"ejs.min.js\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git://github.com/mde/ejs.git\"\n },\n \"bugs\": \"https://github.com/mde/ejs/issues\",\n \"homepage\": \"https://github.com/mde/ejs\",\n \"dependencies\": {\n \"jake\": \"^10.8.5\"\n },\n \"devDependencies\": {\n \"browserify\": \"^16.5.1\",\n \"eslint\": \"^6.8.0\",\n \"git-directory-deploy\": \"^1.5.1\",\n \"jsdoc\": \"^4.0.2\",\n \"lru-cache\": \"^4.0.1\",\n \"mocha\": \"^10.2.0\",\n \"uglify-js\": \"^3.3.16\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n },\n \"scripts\": {\n \"test\": \"npx jake test\"\n }\n}\n", "/*\n * EJS Embedded JavaScript templates\n * Copyright 2112 Matthew Eernisse (mde@fleegix.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n*/\n\n'use strict';\n\n/**\n * @file Embedded JavaScript templating engine. {@link http://ejs.co}\n * @author Matthew Eernisse <mde@fleegix.org>\n * @author Tiancheng \"Timothy\" Gu <timothygu99@gmail.com>\n * @project EJS\n * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0}\n */\n\n/**\n * EJS internal functions.\n *\n * Technically this \"module\" lies in the same file as {@link module:ejs}, for\n * the sake of organization all the private functions re grouped into this\n * module.\n *\n * @module ejs-internal\n * @private\n */\n\n/**\n * Embedded JavaScript templating engine.\n *\n * @module ejs\n * @public\n */\n\n\nvar fs = require('fs');\nvar path = require('path');\nvar utils = require('./utils');\n\nvar scopeOptionWarned = false;\n/** @type {string} */\nvar _VERSION_STRING = require('../package.json').version;\nvar _DEFAULT_OPEN_DELIMITER = '<';\nvar _DEFAULT_CLOSE_DELIMITER = '>';\nvar _DEFAULT_DELIMITER = '%';\nvar _DEFAULT_LOCALS_NAME = 'locals';\nvar _NAME = 'ejs';\nvar _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)';\nvar _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug',\n 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async'];\n// We don't allow 'cache' option to be passed in the data obj for\n// the normal `render` call, but this is where Express 2 & 3 put it\n// so we make an exception for `renderFile`\nvar _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache');\nvar _BOM = /^\\uFEFF/;\nvar _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;\n\n/**\n * EJS template function cache. This can be a LRU object from lru-cache NPM\n * module. By default, it is {@link module:utils.cache}, a simple in-process\n * cache that grows continuously.\n *\n * @type {Cache}\n */\n\nexports.cache = utils.cache;\n\n/**\n * Custom file loader. Useful for template preprocessing or restricting access\n * to a certain part of the filesystem.\n *\n * @type {fileLoader}\n */\n\nexports.fileLoader = fs.readFileSync;\n\n/**\n * Name of the object containing the locals.\n *\n * This variable is overridden by {@link Options}`.localsName` if it is not\n * `undefined`.\n *\n * @type {String}\n * @public\n */\n\nexports.localsName = _DEFAULT_LOCALS_NAME;\n\n/**\n * Promise implementation -- defaults to the native implementation if available\n * This is mostly just for testability\n *\n * @type {PromiseConstructorLike}\n * @public\n */\n\nexports.promiseImpl = (new Function('return this;'))().Promise;\n\n/**\n * Get the path to the included file from the parent file path and the\n * specified path.\n *\n * @param {String} name specified path\n * @param {String} filename parent file path\n * @param {Boolean} [isDir=false] whether the parent file path is a directory\n * @return {String}\n */\nexports.resolveInclude = function(name, filename, isDir) {\n var dirname = path.dirname;\n var extname = path.extname;\n var resolve = path.resolve;\n var includePath = resolve(isDir ? filename : dirname(filename), name);\n var ext = extname(name);\n if (!ext) {\n includePath += '.ejs';\n }\n return includePath;\n};\n\n/**\n * Try to resolve file path on multiple directories\n *\n * @param {String} name specified path\n * @param {Array<String>} paths list of possible parent directory paths\n * @return {String}\n */\nfunction resolvePaths(name, paths) {\n var filePath;\n if (paths.some(function (v) {\n filePath = exports.resolveInclude(name, v, true);\n return fs.existsSync(filePath);\n })) {\n return filePath;\n }\n}\n\n/**\n * Get the path to the included file by Options\n *\n * @param {String} path specified path\n * @param {Options} options compilation options\n * @return {String}\n */\nfunction getIncludePath(path, options) {\n var includePath;\n var filePath;\n var views = options.views;\n var match = /^[A-Za-z]+:\\\\|^\\//.exec(path);\n\n // Abs path\n if (match && match.length) {\n path = path.replace(/^\\/*/, '');\n if (Array.isArray(options.root)) {\n includePath = resolvePaths(path, options.root);\n } else {\n includePath = exports.resolveInclude(path, options.root || '/', true);\n }\n }\n // Relative paths\n else {\n // Look relative to a passed filename first\n if (options.filename) {\n filePath = exports.resolveInclude(path, options.filename);\n if (fs.existsSync(filePath)) {\n includePath = filePath;\n }\n }\n // Then look in any views directories\n if (!includePath && Array.isArray(views)) {\n includePath = resolvePaths(path, views);\n }\n if (!includePath && typeof options.includer !== 'function') {\n throw new Error('Could not find the include file \"' +\n options.escapeFunction(path) + '\"');\n }\n }\n return includePath;\n}\n\n/**\n * Get the template from a string or a file, either compiled on-the-fly or\n * read from cache (if enabled), and cache the template if needed.\n *\n * If `template` is not set, the file specified in `options.filename` will be\n * read.\n *\n * If `options.cache` is true, this function reads the file from\n * `options.filename` so it must be set prior to calling this function.\n *\n * @memberof module:ejs-internal\n * @param {Options} options compilation options\n * @param {String} [template] template source\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `options.client`, either type might be returned.\n * @static\n */\n\nfunction handleCache(options, template) {\n var func;\n var filename = options.filename;\n var hasTemplate = arguments.length > 1;\n\n if (options.cache) {\n if (!filename) {\n throw new Error('cache option requires a filename');\n }\n func = exports.cache.get(filename);\n if (func) {\n return func;\n }\n if (!hasTemplate) {\n template = fileLoader(filename).toString().replace(_BOM, '');\n }\n }\n else if (!hasTemplate) {\n // istanbul ignore if: should not happen at all\n if (!filename) {\n throw new Error('Internal EJS error: no file name or template '\n + 'provided');\n }\n template = fileLoader(filename).toString().replace(_BOM, '');\n }\n func = exports.compile(template, options);\n if (options.cache) {\n exports.cache.set(filename, func);\n }\n return func;\n}\n\n/**\n * Try calling handleCache with the given options and data and call the\n * callback with the result. If an error occurs, call the callback with\n * the error. Used by renderFile().\n *\n * @memberof module:ejs-internal\n * @param {Options} options compilation options\n * @param {Object} data template data\n * @param {RenderFileCallback} cb callback\n * @static\n */\n\nfunction tryHandleCache(options, data, cb) {\n var result;\n if (!cb) {\n if (typeof exports.promiseImpl == 'function') {\n return new exports.promiseImpl(function (resolve, reject) {\n try {\n result = handleCache(options)(data);\n resolve(result);\n }\n catch (err) {\n reject(err);\n }\n });\n }\n else {\n throw new Error('Please provide a callback function');\n }\n }\n else {\n try {\n result = handleCache(options)(data);\n }\n catch (err) {\n return cb(err);\n }\n\n cb(null, result);\n }\n}\n\n/**\n * fileLoader is independent\n *\n * @param {String} filePath ejs file path.\n * @return {String} The contents of the specified file.\n * @static\n */\n\nfunction fileLoader(filePath){\n return exports.fileLoader(filePath);\n}\n\n/**\n * Get the template function.\n *\n * If `options.cache` is `true`, then the template is cached.\n *\n * @memberof module:ejs-internal\n * @param {String} path path for the specified file\n * @param {Options} options compilation options\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `options.client`, either type might be returned\n * @static\n */\n\nfunction includeFile(path, options) {\n var opts = utils.shallowCopy(utils.createNullProtoObjWherePossible(), options);\n opts.filename = getIncludePath(path, opts);\n if (typeof options.includer === 'function') {\n var includerResult = options.includer(path, opts.filename);\n if (includerResult) {\n if (includerResult.filename) {\n opts.filename = includerResult.filename;\n }\n if (includerResult.template) {\n return handleCache(opts, includerResult.template);\n }\n }\n }\n return handleCache(opts);\n}\n\n/**\n * Re-throw the given `err` in context to the `str` of ejs, `filename`, and\n * `lineno`.\n *\n * @implements {RethrowCallback}\n * @memberof module:ejs-internal\n * @param {Error} err Error object\n * @param {String} str EJS source\n * @param {String} flnm file name of the EJS file\n * @param {Number} lineno line number of the error\n * @param {EscapeCallback} esc\n * @static\n */\n\nfunction rethrow(err, str, flnm, lineno, esc) {\n var lines = str.split('\\n');\n var start = Math.max(lineno - 3, 0);\n var end = Math.min(lines.length, lineno + 3);\n var filename = esc(flnm);\n // Error context\n var context = lines.slice(start, end).map(function (line, i){\n var curr = i + start + 1;\n return (curr == lineno ? ' >> ' : ' ')\n + curr\n + '| '\n + line;\n }).join('\\n');\n\n // Alter exception message\n err.path = filename;\n err.message = (filename || 'ejs') + ':'\n + lineno + '\\n'\n + context + '\\n\\n'\n + err.message;\n\n throw err;\n}\n\nfunction stripSemi(str){\n return str.replace(/;(\\s*$)/, '$1');\n}\n\n/**\n * Compile the given `str` of ejs into a template function.\n *\n * @param {String} template EJS template\n *\n * @param {Options} [opts] compilation options\n *\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `opts.client`, either type might be returned.\n * Note that the return type of the function also depends on the value of `opts.async`.\n * @public\n */\n\nexports.compile = function compile(template, opts) {\n var templ;\n\n // v1 compat\n // 'scope' is 'context'\n // FIXME: Remove this in a future version\n if (opts && opts.scope) {\n if (!scopeOptionWarned){\n console.warn('`scope` option is deprecated and will be removed in EJS 3');\n scopeOptionWarned = true;\n }\n if (!opts.context) {\n opts.context = opts.scope;\n }\n delete opts.scope;\n }\n templ = new Template(template, opts);\n return templ.compile();\n};\n\n/**\n * Render the given `template` of ejs.\n *\n * If you would like to include options but not data, you need to explicitly\n * call this function with `data` being an empty object or `null`.\n *\n * @param {String} template EJS template\n * @param {Object} [data={}] template data\n * @param {Options} [opts={}] compilation and rendering options\n * @return {(String|Promise<String>)}\n * Return value type depends on `opts.async`.\n * @public\n */\n\nexports.render = function (template, d, o) {\n var data = d || utils.createNullProtoObjWherePossible();\n var opts = o || utils.createNullProtoObjWherePossible();\n\n // No options object -- if there are optiony names\n // in the data, copy them to options\n if (arguments.length == 2) {\n utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA);\n }\n\n return handleCache(opts, template)(data);\n};\n\n/**\n * Render an EJS file at the given `path` and callback `cb(err, str)`.\n *\n * If you would like to include options but not data, you need to explicitly\n * call this function with `data` being an empty object or `null`.\n *\n * @param {String} path path to the EJS file\n * @param {Object} [data={}] template data\n * @param {Options} [opts={}] compilation and rendering options\n * @param {RenderFileCallback} cb callback\n * @public\n */\n\nexports.renderFile = function () {\n var args = Array.prototype.slice.call(arguments);\n var filename = args.shift();\n var cb;\n var opts = {filename: filename};\n var data;\n var viewOpts;\n\n // Do we have a callback?\n if (typeof arguments[arguments.length - 1] == 'function') {\n cb = args.pop();\n }\n // Do we have data/opts?\n if (args.length) {\n // Should always have data obj\n data = args.shift();\n // Normal passed opts (data obj + opts obj)\n if (args.length) {\n // Use shallowCopy so we don't pollute passed in opts obj with new vals\n utils.shallowCopy(opts, args.pop());\n }\n // Special casing for Express (settings + opts-in-data)\n else {\n // Express 3 and 4\n if (data.settings) {\n // Pull a few things from known locations\n if (data.settings.views) {\n opts.views = data.settings.views;\n }\n if (data.settings['view cache']) {\n opts.cache = true;\n }\n // Undocumented after Express 2, but still usable, esp. for\n // items that are unsafe to be passed along with data, like `root`\n viewOpts = data.settings['view options'];\n if (viewOpts) {\n utils.shallowCopy(opts, viewOpts);\n }\n }\n // Express 2 and lower, values set in app.locals, or people who just\n // want to pass options in their data. NOTE: These values will override\n // anything previously set in settings or settings['view options']\n utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS);\n }\n opts.filename = filename;\n }\n else {\n data = utils.createNullProtoObjWherePossible();\n }\n\n return tryHandleCache(opts, data, cb);\n};\n\n/**\n * Clear intermediate JavaScript cache. Calls {@link Cache#reset}.\n * @public\n */\n\n/**\n * EJS template class\n * @public\n */\nexports.Template = Template;\n\nexports.clearCache = function () {\n exports.cache.reset();\n};\n\nfunction Template(text, optsParam) {\n var opts = utils.hasOwnOnlyObject(optsParam);\n var options = utils.createNullProtoObjWherePossible();\n this.templateText = text;\n /** @type {string | null} */\n this.mode = null;\n this.truncate = false;\n this.currentLine = 1;\n this.source = '';\n options.client = opts.client || false;\n options.escapeFunction = opts.escape || opts.escapeFunction || utils.escapeXML;\n options.compileDebug = opts.compileDebug !== false;\n options.debug = !!opts.debug;\n options.filename = opts.filename;\n options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER;\n options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER;\n options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER;\n options.strict = opts.strict || false;\n options.context = opts.context;\n options.cache = opts.cache || false;\n options.rmWhitespace = opts.rmWhitespace;\n options.root = opts.root;\n options.includer = opts.includer;\n options.outputFunctionName = opts.outputFunctionName;\n options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME;\n options.views = opts.views;\n options.async = opts.async;\n options.destructuredLocals = opts.destructuredLocals;\n options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true;\n\n if (options.strict) {\n options._with = false;\n }\n else {\n options._with = typeof opts._with != 'undefined' ? opts._with : true;\n }\n\n this.opts = options;\n\n this.regex = this.createRegex();\n}\n\nTemplate.modes = {\n EVAL: 'eval',\n ESCAPED: 'escaped',\n RAW: 'raw',\n COMMENT: 'comment',\n LITERAL: 'literal'\n};\n\nTemplate.prototype = {\n createRegex: function () {\n var str = _REGEX_STRING;\n var delim = utils.escapeRegExpChars(this.opts.delimiter);\n var open = utils.escapeRegExpChars(this.opts.openDelimiter);\n var close = utils.escapeRegExpChars(this.opts.closeDelimiter);\n str = str.replace(/%/g, delim)\n .replace(/</g, open)\n .replace(/>/g, close);\n return new RegExp(str);\n },\n\n compile: function () {\n /** @type {string} */\n var src;\n /** @type {ClientFunction} */\n var fn;\n var opts = this.opts;\n var prepended = '';\n var appended = '';\n /** @type {EscapeCallback} */\n var escapeFn = opts.escapeFunction;\n /** @type {FunctionConstructor} */\n var ctor;\n /** @type {string} */\n var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined';\n\n if (!this.source) {\n this.generateSource();\n prepended +=\n ' var __output = \"\";\\n' +\n ' function __append(s) { if (s !== undefined && s !== null) __output += s }\\n';\n if (opts.outputFunctionName) {\n if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) {\n throw new Error('outputFunctionName is not a valid JS identifier.');\n }\n prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\\n';\n }\n if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) {\n throw new Error('localsName is not a valid JS identifier.');\n }\n if (opts.destructuredLocals && opts.destructuredLocals.length) {\n var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\\n';\n for (var i = 0; i < opts.destructuredLocals.length; i++) {\n var name = opts.destructuredLocals[i];\n if (!_JS_IDENTIFIER.test(name)) {\n throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.');\n }\n if (i > 0) {\n destructuring += ',\\n ';\n }\n destructuring += name + ' = __locals.' + name;\n }\n prepended += destructuring + ';\\n';\n }\n if (opts._with !== false) {\n prepended += ' with (' + opts.localsName + ' || {}) {' + '\\n';\n appended += ' }' + '\\n';\n }\n appended += ' return __output;' + '\\n';\n this.source = prepended + this.source + appended;\n }\n\n if (opts.compileDebug) {\n src = 'var __line = 1' + '\\n'\n + ' , __lines = ' + JSON.stringify(this.templateText) + '\\n'\n + ' , __filename = ' + sanitizedFilename + ';' + '\\n'\n + 'try {' + '\\n'\n + this.source\n + '} catch (e) {' + '\\n'\n + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\\n'\n + '}' + '\\n';\n }\n else {\n src = this.source;\n }\n\n if (opts.client) {\n src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\\n' + src;\n if (opts.compileDebug) {\n src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\\n' + src;\n }\n }\n\n if (opts.strict) {\n src = '\"use strict\";\\n' + src;\n }\n if (opts.debug) {\n console.log(src);\n }\n if (opts.compileDebug && opts.filename) {\n src = src + '\\n'\n + '//# sourceURL=' + sanitizedFilename + '\\n';\n }\n\n try {\n if (opts.async) {\n // Have to use generated function for this, since in envs without support,\n // it breaks in parsing\n try {\n ctor = (new Function('return (async function(){}).constructor;'))();\n }\n catch(e) {\n if (e instanceof SyntaxError) {\n throw new Error('This environment does not support async/await');\n }\n else {\n throw e;\n }\n }\n }\n else {\n ctor = Function;\n }\n fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src);\n }\n catch(e) {\n // istanbul ignore else\n if (e instanceof SyntaxError) {\n if (opts.filename) {\n e.message += ' in ' + opts.filename;\n }\n e.message += ' while compiling ejs\\n\\n';\n e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\\n';\n e.message += 'https://github.com/RyanZim/EJS-Lint';\n if (!opts.async) {\n e.message += '\\n';\n e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.';\n }\n }\n throw e;\n }\n\n // Return a callable function which will execute the function\n // created by the source-code, with the passed data as locals\n // Adds a local `include` function which allows full recursive include\n var returnedFn = opts.client ? fn : function anonymous(data) {\n var include = function (path, includeData) {\n var d = utils.shallowCopy(utils.createNullProtoObjWherePossible(), data);\n if (includeData) {\n d = utils.shallowCopy(d, includeData);\n }\n return includeFile(path, opts)(d);\n };\n return fn.apply(opts.context,\n [data || utils.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);\n };\n if (opts.filename && typeof Object.defineProperty === 'function') {\n var filename = opts.filename;\n var basename = path.basename(filename, path.extname(filename));\n try {\n Object.defineProperty(returnedFn, 'name', {\n value: basename,\n writable: false,\n enumerable: false,\n configurable: true\n });\n } catch (e) {/* ignore */}\n }\n return returnedFn;\n },\n\n generateSource: function () {\n var opts = this.opts;\n\n if (opts.rmWhitespace) {\n // Have to use two separate replace here as `^` and `$` operators don't\n // work well with `\\r` and empty lines don't work well with the `m` flag.\n this.templateText =\n this.templateText.replace(/[\\r\\n]+/g, '\\n').replace(/^\\s+|\\s+$/gm, '');\n }\n\n // Slurp spaces and tabs before <%_ and after _%>\n this.templateText =\n this.templateText.replace(/[ \\t]*<%_/gm, '<%_').replace(/_%>[ \\t]*/gm, '_%>');\n\n var self = this;\n var matches = this.parseTemplateText();\n var d = this.opts.delimiter;\n var o = this.opts.openDelimiter;\n var c = this.opts.closeDelimiter;\n\n if (matches && matches.length) {\n matches.forEach(function (line, index) {\n var closing;\n // If this is an opening tag, check for closing tags\n // FIXME: May end up with some false positives here\n // Better to store modes as k/v with openDelimiter + delimiter as key\n // Then this can simply check against the map\n if ( line.indexOf(o + d) === 0 // If it is a tag\n && line.indexOf(o + d + d) !== 0) { // and is not escaped\n closing = matches[index + 2];\n if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) {\n throw new Error('Could not find matching close tag for \"' + line + '\".');\n }\n }\n self.scanLine(line);\n });\n }\n\n },\n\n parseTemplateText: function () {\n var str = this.templateText;\n var pat = this.regex;\n var result = pat.exec(str);\n var arr = [];\n var firstPos;\n\n while (result) {\n firstPos = result.index;\n\n if (firstPos !== 0) {\n arr.push(str.substring(0, firstPos));\n str = str.slice(firstPos);\n }\n\n arr.push(result[0]);\n str = str.slice(result[0].length);\n result = pat.exec(str);\n }\n\n if (str) {\n arr.push(str);\n }\n\n return arr;\n },\n\n _addOutput: function (line) {\n if (this.truncate) {\n // Only replace single leading linebreak in the line after\n // -%> tag -- this is the single, trailing linebreak\n // after the tag that the truncation mode replaces\n // Handle Win / Unix / old Mac linebreaks -- do the \\r\\n\n // combo first in the regex-or\n line = line.replace(/^(?:\\r\\n|\\r|\\n)/, '');\n this.truncate = false;\n }\n if (!line) {\n return line;\n }\n\n // Preserve literal slashes\n line = line.replace(/\\\\/g, '\\\\\\\\');\n\n // Convert linebreaks\n line = line.replace(/\\n/g, '\\\\n');\n line = line.replace(/\\r/g, '\\\\r');\n\n // Escape double-quotes\n // - this will be the delimiter during execution\n line = line.replace(/\"/g, '\\\\\"');\n this.source += ' ; __append(\"' + line + '\")' + '\\n';\n },\n\n scanLine: function (line) {\n var self = this;\n var d = this.opts.delimiter;\n var o = this.opts.openDelimiter;\n var c = this.opts.closeDelimiter;\n var newLineCount = 0;\n\n newLineCount = (line.split('\\n').length - 1);\n\n switch (line) {\n case o + d:\n case o + d + '_':\n this.mode = Template.modes.EVAL;\n break;\n case o + d + '=':\n this.mode = Template.modes.ESCAPED;\n break;\n case o + d + '-':\n this.mode = Template.modes.RAW;\n break;\n case o + d + '#':\n this.mode = Template.modes.COMMENT;\n break;\n case o + d + d:\n this.mode = Template.modes.LITERAL;\n this.source += ' ; __append(\"' + line.replace(o + d + d, o + d) + '\")' + '\\n';\n break;\n case d + d + c:\n this.mode = Template.modes.LITERAL;\n this.source += ' ; __append(\"' + line.replace(d + d + c, d + c) + '\")' + '\\n';\n break;\n case d + c:\n case '-' + d + c:\n case '_' + d + c:\n if (this.mode == Template.modes.LITERAL) {\n this._addOutput(line);\n }\n\n this.mode = null;\n this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0;\n break;\n default:\n // In script mode, depends on type of tag\n if (this.mode) {\n // If '//' is found without a line break, add a line break.\n switch (this.mode) {\n case Template.modes.EVAL:\n case Template.modes.ESCAPED:\n case Template.modes.RAW:\n if (line.lastIndexOf('//') > line.lastIndexOf('\\n')) {\n line += '\\n';\n }\n }\n switch (this.mode) {\n // Just executing code\n case Template.modes.EVAL:\n this.source += ' ; ' + line + '\\n';\n break;\n // Exec, esc, and output\n case Template.modes.ESCAPED:\n this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\\n';\n break;\n // Exec and output\n case Template.modes.RAW:\n this.source += ' ; __append(' + stripSemi(line) + ')' + '\\n';\n break;\n case Template.modes.COMMENT:\n // Do nothing\n break;\n // Literal <%% mode, append as raw output\n case Template.modes.LITERAL:\n this._addOutput(line);\n break;\n }\n }\n // In string mode, just add the output\n else {\n this._addOutput(line);\n }\n }\n\n if (self.opts.compileDebug && newLineCount) {\n this.currentLine += newLineCount;\n this.source += ' ; __line = ' + this.currentLine + '\\n';\n }\n }\n};\n\n/**\n * Escape characters reserved in XML.\n *\n * This is simply an export of {@link module:utils.escapeXML}.\n *\n * If `markup` is `undefined` or `null`, the empty string is returned.\n *\n * @param {String} markup Input string\n * @return {String} Escaped string\n * @public\n * @func\n * */\nexports.escapeXML = utils.escapeXML;\n\n/**\n * Express.js support.\n *\n * This is an alias for {@link module:ejs.renderFile}, in order to support\n * Express.js out-of-the-box.\n *\n * @func\n */\n\nexports.__express = exports.renderFile;\n\n/**\n * Version of EJS.\n *\n * @readonly\n * @type {String}\n * @public\n */\n\nexports.VERSION = _VERSION_STRING;\n\n/**\n * Name for detection of EJS.\n *\n * @readonly\n * @type {String}\n * @public\n */\n\nexports.name = _NAME;\n\n/* istanbul ignore if */\nif (typeof window != 'undefined') {\n window.ejs = exports;\n}\n\n", "/**\n * Guardian Daemon - Standalone entry point\n *\n * Starts Guardian as a background daemon that serves all IDEs.\n * Tries fixed ports in order to avoid port file discovery complexity.\n *\n * Usage:\n * node daemon.js [--debug]\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { GuardianModule } from \"./module\";\nimport { PortManager, GUARDIAN_PORTS } from \"./utils/port-manager\";\n\n// Parse command line arguments\nfunction parseArgs(): { debug: boolean } {\n const args = process.argv.slice(2);\n let debug = false;\n\n for (const arg of args) {\n if (arg === \"--debug\") {\n debug = true;\n }\n }\n\n return { debug };\n}\n\nasync function main(): Promise<void> {\n const { debug } = parseArgs();\n const portFile = path.join(os.homedir(), \".overwatch\", \"guardian_port\");\n\n console.log(\"[Guardian] Starting daemon...\");\n console.log(`[Guardian] Fixed ports: ${GUARDIAN_PORTS.join(\", \")}`);\n console.log(`[Guardian] Debug: ${debug}`);\n\n // Ensure port file directory exists\n const portDir = path.dirname(portFile);\n if (!fs.existsSync(portDir)) {\n fs.mkdirSync(portDir, { recursive: true });\n }\n\n // Find an available port from our fixed list\n const port = await PortManager.findAvailablePort();\n if (!port) {\n console.error(\"[Guardian] All fixed ports are in use:\", GUARDIAN_PORTS);\n process.exit(1);\n }\n\n console.log(`[Guardian] Using port ${port}`);\n\n // Create and start Guardian on the fixed port\n const guardian = new GuardianModule({\n httpPort: port,\n debug,\n });\n\n await guardian.init();\n await guardian.startServer();\n\n // Write port to file for bash scripts to read\n fs.writeFileSync(portFile, String(port));\n console.log(`[Guardian] Server started on port ${port}`);\n console.log(`[Guardian] Port written to ${portFile}`);\n\n // Handle graceful shutdown\n const shutdown = async (signal: string) => {\n console.log(`[Guardian] Received ${signal}, shutting down...`);\n try {\n await guardian.stopServer();\n if (fs.existsSync(portFile)) {\n fs.unlinkSync(portFile);\n }\n console.log(\"[Guardian] Shutdown complete\");\n process.exit(0);\n } catch (error) {\n console.error(\"[Guardian] Error during shutdown:\", error);\n process.exit(1);\n }\n };\n\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n\n // Handle uncaught errors\n process.on(\"uncaughtException\", (error) => {\n console.error(\"[Guardian] Uncaught exception:\", error);\n process.exit(1);\n });\n\n process.on(\"unhandledRejection\", (reason) => {\n console.error(\"[Guardian] Unhandled rejection:\", reason);\n process.exit(1);\n });\n\n // Keep process alive\n console.log(\"[Guardian] Daemon running. Press Ctrl+C to stop.\");\n}\n\n// Run\nmain().catch((error) => {\n console.error(\"[Guardian] Failed to start:\", error);\n process.exit(1);\n});\n", "import * as http from \"http\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\n\nimport { GuardianHttpServer } from \"./http/server\";\nimport { JavelinClient, ConfigReader, AdminClient } from \"./javelin\";\nimport { PolicyManager } from \"./lib/policy-manager\";\nimport { logger, LogLevel } from \"./utils\";\nimport { MCPScanner } from \"./scanner\";\nimport { YaraEngine } from \"./yara\";\nimport {\n createPolicyEngine,\n initPolicyEngine,\n PolicyEngine,\n} from \"./lib/policy-engine\";\n\nimport { IDESource, IDEType, HookEventRecord, ScanRecord } from \"./types\";\nimport { YaraExecutor } from \"./engines/yara\";\nimport { RemoteExecutor } from \"./engines/remote\";\nimport { AdminIngestor } from \"./data/ingestor\";\nimport { OAuthState } from \"./auth\";\n\n// Pipeline & Handlers\nimport { HookPipeline } from \"./pipeline/hook-pipeline\";\nimport { getAuthStatus } from \"./auth/token-store\";\nimport { HookHandler } from \"./handlers/hook-handler\";\nimport { ScanHandler } from \"./handlers/scan-handler\";\nimport { DashboardHandler } from \"./handlers/dashboard-handler\";\nimport { OAuthHandler } from \"./handlers/oauth-handler\";\nimport { ExtractorRegistry } from \"./pipeline/extractors\";\n// Skills Scanner\nimport { SkillsScanner, SkillScanResult } from \"./skills\";\n\nexport class GuardianModule {\n private javelinClients: Map<IDESource, JavelinClient> = new Map();\n private configReader: ConfigReader;\n private httpServer: GuardianHttpServer;\n private scanner: MCPScanner;\n\n // Core Engines\n private yaraEngine: YaraEngine;\n private cedarEngine: PolicyEngine | undefined;\n\n // Executors\n private yaraExecutor: YaraExecutor;\n private remoteExecutor: RemoteExecutor;\n\n // Pipeline\n private hookPipeline: HookPipeline | undefined;\n\n // Handlers\n private hookHandler: HookHandler | undefined;\n private scanHandler: ScanHandler | undefined;\n private dashboardHandler: DashboardHandler = new DashboardHandler();\n private oauthHandler: OAuthHandler | undefined;\n\n // Skills Scanner\n private skillsScanner: SkillsScanner;\n private projectSkillsCache = new Map<string, { timestamp: number }>();\n private static readonly PROJECT_SKILLS_CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n\n // Ingestors\n private eventIngestor: AdminIngestor<HookEventRecord> | null = null;\n private scanIngestor: AdminIngestor<ScanRecord> | null = null;\n private skillsIngestor: AdminIngestor<SkillScanResult> | null = null;\n\n // Policy Manager\n private policyManager: PolicyManager;\n private adminClient: AdminClient | null = null;\n\n private seenInstallations: Set<string> = new Set();\n private pendingOAuthStates: Map<string, OAuthState> = new Map();\n private readonly oauthStateTimeout = 5 * 60 * 1000;\n\n private initialized = false;\n private debug: boolean;\n\n constructor(config: { httpPort?: number; debug?: boolean } = {}) {\n this.debug = config.debug || false;\n this.configReader = new ConfigReader();\n this.scanner = new MCPScanner();\n this.skillsScanner = new SkillsScanner();\n\n this.yaraEngine = new YaraEngine();\n this.yaraExecutor = new YaraExecutor(this.yaraEngine);\n this.remoteExecutor = new RemoteExecutor(this.javelinClients);\n\n const overwatch = this.configReader.getOverwatchConfig();\n const pollIntervalMs =\n (overwatch?.remotePolicy?.pollIntervalMinutes || 5) * 60 * 1000;\n this.policyManager = new PolicyManager(pollIntervalMs);\n\n if (this.debug) logger.setLevel(LogLevel.DEBUG);\n this.httpServer = new GuardianHttpServer(config.httpPort || 0);\n }\n\n async init(): Promise<void> {\n if (this.initialized) return;\n\n logger.info(\"Initializing...\");\n\n await this.loadHighflameConfig();\n await this.loadYaraRules();\n await this.initCedarEngine();\n\n this.remoteExecutor = new RemoteExecutor(this.javelinClients);\n await this.initPolicyManager();\n\n // Set application ID resolver on remote executor after policy manager is initialized\n this.remoteExecutor.setApplicationIdResolver((source) => {\n const mapping = this.policyManager.getPolicyMapping();\n const entry = mapping[source];\n return entry?.applicationId || null;\n });\n\n // Initialize ingestors using JWT token from session\n const highflameConfig = this.configReader.getHighflameConfig();\n const token = this.configReader.getJwtToken();\n\n if (highflameConfig.enabled && token) {\n // Create application ID resolver that looks up from policy mapping\n const applicationIdResolver = (record: HookEventRecord): string | null => {\n const mapping = this.policyManager.getPolicyMapping();\n const entry = mapping[record.source];\n return entry?.applicationId || null;\n };\n\n this.eventIngestor = new AdminIngestor<HookEventRecord>(\n highflameConfig.baseUrl,\n token,\n \"events\",\n applicationIdResolver,\n );\n this.eventIngestor.start();\n this.scanIngestor = new AdminIngestor<ScanRecord>(\n highflameConfig.baseUrl,\n token,\n \"mcp-scans\",\n );\n this.scanIngestor.start();\n\n this.skillsIngestor = new AdminIngestor<SkillScanResult>(\n highflameConfig.baseUrl,\n token,\n \"skills\",\n );\n this.skillsIngestor.start();\n }\n\n // Initialize Extractor Registry\n const extractorRegistry = ExtractorRegistry.createDefault();\n\n // Initialize Pipeline\n this.hookPipeline = new HookPipeline(\n this.yaraExecutor,\n this.remoteExecutor,\n this.policyManager,\n (source) => this.checkInstallation(source),\n extractorRegistry,\n );\n\n // Initialize Handlers\n this.hookHandler = new HookHandler(this.hookPipeline, this.eventIngestor);\n this.hookHandler.setProjectSkillsScanCallback((workspace) => {\n this.scanProjectSkillsIfNeeded(workspace).catch(() => {});\n });\n this.scanHandler = new ScanHandler(this.scanner, this.scanIngestor);\n this.oauthHandler = new OAuthHandler(\n this.httpServer.getPort(),\n this.pendingOAuthStates,\n this.oauthStateTimeout,\n );\n\n this.initialized = true;\n logger.info(\"Initialized\");\n }\n\n private async loadHighflameConfig(): Promise<void> {\n const ides: IDEType[] = [\"cursor\", \"claudecode\", \"github_copilot\"];\n for (const ide of ides) {\n const config = await this.configReader.readHighflameConfig(ide);\n if (config && this.configReader.isValid(config)) {\n this.javelinClients.set(ide, new JavelinClient(config));\n }\n }\n }\n\n private async loadYaraRules(): Promise<void> {\n const rulesDir = this.findRulesDir();\n if (rulesDir) {\n await this.yaraEngine.loadRules(rulesDir);\n }\n }\n\n private findRulesDir(): string | null {\n const locations = [\n path.join(__dirname, \"rules\", \"pre\"),\n path.join(__dirname, \"..\", \"rules\", \"pre\"),\n path.join(os.homedir(), \".overwatch\", \"rules\", \"pre\"),\n ];\n for (const loc of locations) {\n if (fs.existsSync(loc)) return loc;\n }\n return null;\n }\n\n private async initCedarEngine(): Promise<void> {\n try {\n // Initialize policy engine module first (loads @highflame/policy)\n await initPolicyEngine();\n\n this.cedarEngine = createPolicyEngine();\n if (!this.cedarEngine) return;\n\n const policyPath = this.findPolicyFile();\n if (policyPath) {\n this.cedarEngine.loadPoliciesFromFile(policyPath);\n }\n } catch (error) {\n logger.error(\"Failed to initialize Cedar engine:\", {\n error: String(error),\n });\n }\n }\n\n private findPolicyFile(): string | null {\n const locations = [\n path.join(__dirname, \"policy.cedar\"),\n path.join(__dirname, \"..\", \"policy.cedar\"),\n path.join(__dirname, \"..\", \"policy\", \"cedar.policy\"),\n path.join(os.homedir(), \".overwatch\", \"policy.cedar\"),\n ];\n for (const loc of locations) {\n if (fs.existsSync(loc)) return loc;\n }\n return null;\n }\n\n private async initPolicyManager(): Promise<void> {\n const adminConfig = this.configReader.getAdminConfig();\n const token = this.configReader.getAdminToken();\n const overwatch = this.configReader.getOverwatchConfig();\n const remotePolicyEnabled = overwatch?.remotePolicy?.enabled !== false;\n\n if (adminConfig.enabled && token && remotePolicyEnabled) {\n this.adminClient = new AdminClient(adminConfig.baseUrl!, token);\n }\n\n const localPolicyPath = this.findPolicyFile();\n await this.policyManager.init(\n adminConfig.enabled && remotePolicyEnabled\n ? adminConfig.baseUrl || null\n : null,\n token || null,\n localPolicyPath,\n );\n\n if (this.adminClient && remotePolicyEnabled) {\n this.policyManager.startPolling();\n }\n }\n\n private checkInstallation(source: IDESource): void {\n // Get user email from session.json (authenticated user)\n const authStatus = getAuthStatus();\n if (!authStatus.authenticated || !authStatus.email) {\n return;\n }\n\n const userEmail = authStatus.email;\n const installKey = `${userEmail}:${source}`;\n\n if (this.seenInstallations.has(installKey)) {\n return;\n }\n\n this.seenInstallations.add(installKey);\n this.recordInstallation(source, userEmail).catch(() => {});\n }\n\n private async recordInstallation(\n source: IDESource,\n userEmail: string,\n ): Promise<void> {\n if (!this.adminClient) return;\n\n try {\n await this.adminClient.recordInstallation({\n user_id: userEmail,\n user_email: userEmail,\n ide_type: source,\n version: \"2.0.0\",\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(\"Failed to record installation\", { error: String(error) });\n }\n }\n\n async startServer(): Promise<void> {\n if (!this.initialized) await this.init();\n\n this.httpServer.on(\"/hook\", (req, res) =>\n this.hookHandler?.handle(req, res),\n );\n this.httpServer.on(\"/health\", (_req, res) => {\n const policyStatus = this.policyManager.getStatus();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n status: \"ok\",\n version: \"2.0.0\",\n initialized: this.initialized,\n eventCount: this.hookHandler?.getEventCount() || 0,\n configuredIDEs: Array.from(this.javelinClients.keys()),\n policyManager: {\n hasRemotePolicies: policyStatus.remotePolicies.length > 0,\n isPolling: policyStatus.isPolling,\n lastFetchTime: policyStatus.lastFetchTime,\n },\n }),\n );\n });\n this.httpServer.on(\"/policy/refresh\", async (req, res) => {\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n await this.policyManager.refreshPolicies();\n const status = this.policyManager.getStatus();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n status: \"ok\",\n remotePolicies: status.remotePolicies,\n lastFetchTime: status.lastFetchTime,\n }),\n );\n });\n this.httpServer.on(\"/scan\", (req, res) =>\n this.scanHandler?.handle(req, res),\n );\n this.httpServer.on(\"/dashboard\", (req, res) =>\n this.dashboardHandler.handle(req, res),\n );\n this.httpServer.on(\"/dashboard.js\", (req, res) =>\n this.dashboardHandler.handleJs(req, res),\n );\n this.httpServer.on(\"/images\", (req, res) =>\n this.dashboardHandler.handleImage(req, res),\n );\n this.httpServer.on(\"/oauth/start\", (req, res) =>\n this.oauthHandler?.handleStart(req, res),\n );\n this.httpServer.on(\"/oauth/callback\", (req, res) =>\n this.oauthHandler?.handleCallback(req, res),\n );\n this.httpServer.on(\"/oauth/status\", (req, res) =>\n this.oauthHandler?.handleStatus(req, res),\n );\n this.httpServer.on(\"/shutdown\", (req, res) =>\n this.handleShutdown(req, res),\n );\n\n await this.httpServer.start();\n logger.info(`Server started on port ${this.httpServer.getPort()}`);\n\n if (this.scanHandler) this.scanHandler.runInitialScan();\n this.runStartupSkillsScan();\n }\n\n private async runStartupSkillsScan(): Promise<void> {\n try {\n logger.info(\"Running startup skills scan...\");\n const result = await this.skillsScanner.scan();\n\n // Ingest to backend (backend handles change detection via contentHash)\n if (this.skillsIngestor) {\n this.skillsIngestor.ingest(result);\n }\n\n logger.info(\"Startup skills scan completed\", {\n totalSkills: result.totalSkills,\n });\n } catch (error) {\n logger.error(\"Startup skills scan failed\", { error: String(error) });\n }\n }\n\n private handleShutdown(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): void {\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"shutting_down\" }));\n\n // Send SIGTERM to ourselves - this triggers the daemon.ts shutdown handler\n // which properly cleans up the port file and other resources\n setImmediate(() => {\n logger.info(\"Shutdown requested via API, sending SIGTERM...\");\n process.kill(process.pid, \"SIGTERM\");\n });\n }\n\n async stopServer(): Promise<void> {\n this.policyManager.stopPolling();\n this.eventIngestor?.stop();\n this.scanIngestor?.stop();\n this.skillsIngestor?.stop();\n await this.httpServer.stop();\n }\n\n getPort(): number {\n return this.httpServer.getPort();\n }\n\n /**\n * Scan project-level skills if not recently cached\n * Called from hook handler when workspace is present in event\n */\n async scanProjectSkillsIfNeeded(workspace: string): Promise<void> {\n const cached = this.projectSkillsCache.get(workspace);\n const now = Date.now();\n\n if (cached && now - cached.timestamp < GuardianModule.PROJECT_SKILLS_CACHE_TTL) {\n logger.debug(\"Project skills cache hit\", { workspace });\n return;\n }\n\n try {\n const result = await this.skillsScanner.scanProjectSkills(workspace);\n this.projectSkillsCache.set(workspace, { timestamp: now });\n\n if (result.totalSkills > 0 && this.skillsIngestor) {\n this.skillsIngestor.ingest(result);\n }\n } catch (error) {\n logger.error(\"Failed to scan project skills\", {\n workspace,\n error: String(error),\n });\n }\n }\n}\n", "import * as http from \"http\";\nimport { logger } from \"../utils\";\n\ntype RequestListener = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n) => void;\n\n/**\n * Lightweight HTTP server for Guardian\n */\nexport class GuardianHttpServer {\n private server: http.Server;\n private port: number;\n private requestListeners: Map<string, RequestListener> = new Map();\n private requestCount = 0;\n\n constructor(port: number) {\n this.port = port;\n logger.debug(\"Creating server instance\", {\n requestedPort: port,\n isEphemeral: port === 0,\n });\n this.server = http.createServer(this.handleRequest.bind(this));\n }\n\n /**\n * Start the server\n */\n start(): Promise<void> {\n logger.info(\"Starting server...\");\n return new Promise((resolve, reject) => {\n this.server.listen(this.port, \"127.0.0.1\", () => {\n // Get the actual assigned port (important when port 0 is used)\n const address = this.server.address();\n const originalPort = this.port;\n if (address && typeof address === \"object\") {\n this.port = address.port;\n }\n logger.info(\"Server started successfully\", {\n requestedPort: originalPort,\n assignedPort: this.port,\n host: \"127.0.0.1\",\n registeredPaths: Array.from(this.requestListeners.keys()),\n });\n resolve();\n });\n\n this.server.on(\"error\", (error: NodeJS.ErrnoException) => {\n logger.error(\"Server startup error:\", {\n code: error.code,\n message: error.message,\n port: this.port,\n });\n reject(error);\n });\n\n this.server.on(\"close\", () => {\n logger.debug(\"Server closed\");\n });\n\n this.server.on(\"connection\", (socket) => {\n logger.debug(\"New connection\", {\n remoteAddress: socket.remoteAddress,\n remotePort: socket.remotePort,\n });\n });\n });\n }\n\n /**\n * Stop the server\n */\n stop(): Promise<void> {\n logger.info(\"Stopping server...\");\n return new Promise((resolve) => {\n if (this.server.listening) {\n this.server.close(() => {\n logger.info(\"Server stopped\", {\n totalRequestsServed: this.requestCount,\n });\n resolve();\n });\n } else {\n logger.debug(\"Server was not listening\");\n resolve();\n }\n });\n }\n\n /**\n * Register a request handler for a specific path\n */\n on(path: string, listener: RequestListener): void {\n this.requestListeners.set(path, listener);\n logger.debug(\"Registered handler\", {\n path,\n totalHandlers: this.requestListeners.size,\n });\n }\n\n /**\n * Handle incoming requests\n */\n private handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): void {\n const startTime = Date.now();\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n\n logger.debug(\"Incoming request\", {\n method: req.method,\n path: url.pathname,\n query: url.search || \"(none)\",\n userAgent: req.headers[\"user-agent\"],\n contentLength: req.headers[\"content-length\"],\n });\n\n // Find handler - exact match first, then prefix match\n let listener = this.requestListeners.get(url.pathname);\n let matchedPath = url.pathname;\n\n // If no exact match, try prefix matching (e.g., /hook matches /hook/cursor/beforeSubmitPrompt)\n if (!listener) {\n for (const [path, handler] of this.requestListeners.entries()) {\n if (url.pathname.startsWith(path + \"/\") || url.pathname === path) {\n listener = handler;\n matchedPath = path;\n break;\n }\n }\n }\n\n if (listener) {\n logger.debug(`Handler found for ${matchedPath}`);\n\n // Wrap response to log when it finishes\n const originalEnd = res.end.bind(res);\n res.end = ((...args: Parameters<typeof res.end>) => {\n const duration = Date.now() - startTime;\n logger.debug(\"Response sent\", {\n statusCode: res.statusCode,\n duration,\n });\n return originalEnd(...args);\n }) as typeof res.end;\n\n listener(req, res);\n } else {\n const duration = Date.now() - startTime;\n logger.warn(`No handler for path: ${url.pathname}`, {\n availablePaths: Array.from(this.requestListeners.keys()),\n duration,\n });\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not Found\", path: url.pathname }));\n }\n }\n\n /**\n * Get the port the server is listening on\n */\n getPort(): number {\n return this.port;\n }\n\n /**\n * Check if server is currently listening\n */\n isListening(): boolean {\n return this.server.listening;\n }\n}\n", "import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\n\n/**\n * Log levels\n */\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n}\n\n// Log file path\nconst LOG_FILE = path.join(os.homedir(), \".overwatch\", \"guardian.log\");\n\n/**\n * Simple logger utility with file output\n */\nexport class Logger {\n private level: LogLevel;\n private fileEnabled: boolean = true;\n\n constructor(level: LogLevel = LogLevel.INFO) {\n this.level = level;\n this.ensureLogDir();\n }\n\n private ensureLogDir(): void {\n try {\n const dir = path.dirname(LOG_FILE);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n } catch {\n this.fileEnabled = false;\n }\n }\n\n setLevel(level: LogLevel): void {\n this.level = level;\n }\n\n private getCallerFile(offset: number): string {\n const err = new Error();\n const stack = err.stack?.split(\"\\n\");\n if (stack && stack.length > offset) {\n const callerLine = stack[offset] || \"\";\n const match = callerLine.match(/at\\s+(?:.*\\s+\\()?(.+?):\\d+:\\d+\\)?$/);\n if (match && match[1]) {\n return path.basename(match[1]);\n }\n }\n return \"unknown\";\n }\n\n private formatArgs(args: unknown[]): string {\n if (args.length === 0) return \"\";\n\n return args\n .map((arg) => {\n if (typeof arg === \"object\" && arg !== null) {\n try {\n return JSON.stringify(arg)\n .replace(/^{|}$/g, \"\")\n .replace(/\"([^\"]+)\":/g, \"$1=\");\n } catch {\n return String(arg);\n }\n }\n return String(arg);\n })\n .join(\" \");\n }\n\n private writeToFile(level: string, message: string, args: unknown[]): void {\n if (!this.fileEnabled) return;\n\n try {\n const timestamp = new Date().toISOString();\n const callerFile = this.getCallerFile(4); // Error -> getCallerFile -> writeToFile -> info -> caller\n const formattedArgs = this.formatArgs(args);\n const argsStr = formattedArgs ? \" \" + formattedArgs : \"\";\n const line = `${timestamp} [${level.padEnd(5)}] [${callerFile}] ${message}${argsStr}\\n`;\n fs.appendFileSync(LOG_FILE, line);\n } catch {\n // Silently fail file writes\n }\n }\n\n debug(message: string, ...args: unknown[]): void {\n if (this.level <= LogLevel.DEBUG) {\n const callerFile = this.getCallerFile(3); // Error -> getCallerFile -> debug -> caller\n console.debug(`[DEBUG] [${callerFile}] ${message}`, ...args);\n this.writeToFile(\"DEBUG\", message, args);\n }\n }\n\n info(message: string, ...args: unknown[]): void {\n if (this.level <= LogLevel.INFO) {\n const callerFile = this.getCallerFile(3);\n console.info(`[INFO ] [${callerFile}] ${message}`, ...args);\n this.writeToFile(\"INFO\", message, args);\n }\n }\n\n warn(message: string, ...args: unknown[]): void {\n if (this.level <= LogLevel.WARN) {\n const callerFile = this.getCallerFile(3);\n console.warn(`[WARN ] [${callerFile}] ${message}`, ...args);\n this.writeToFile(\"WARN\", message, args);\n }\n }\n\n error(message: string, ...args: unknown[]): void {\n if (this.level <= LogLevel.ERROR) {\n const callerFile = this.getCallerFile(3);\n console.error(`[ERROR] [${callerFile}] ${message}`, ...args);\n this.writeToFile(\"ERROR\", message, args);\n }\n }\n}\n\n// Singleton logger instance\nexport const logger = new Logger();\n", "import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { JavelinConfig } from \"./types\";\nimport { IDEType, OperatingMode, OverwatchConfig, AdminConfig } from \"../types\";\nimport { logger } from \"../utils\";\nimport { loadTokens } from \"../auth\";\nimport { getBaseUrl, getLLMConfig } from \"../config\";\n\n/**\n * Configuration reader for ~/.overwatch/config.json\n * Uses JWT token from session.json for API authentication\n */\nexport class ConfigReader {\n private configPath: string;\n private cachedConfig: Map<IDEType, JavelinConfig> = new Map();\n private rawConfig: OverwatchConfig | null = null;\n\n constructor(configPath?: string) {\n this.configPath =\n configPath || path.join(os.homedir(), \".overwatch\", \"config.json\");\n logger.debug(\"Initialized\", { configPath: this.configPath });\n }\n\n /**\n * JWT token from session.json \n */\n async readHighflameConfig(ide: IDEType): Promise<JavelinConfig | null> {\n logger.info(`Reading config for IDE: ${ide}`);\n\n try {\n // Check cache first\n if (this.cachedConfig.has(ide)) {\n return this.cachedConfig.get(ide)!;\n }\n\n // Load raw config if not already loaded\n if (!this.rawConfig) {\n await this.loadRawConfig();\n }\n\n // Get JWT token from session\n const token = this.getJwtToken();\n\n const javelinConfig: JavelinConfig = {\n baseUrl: getBaseUrl(),\n token: token || \"\",\n timeout: 30000,\n };\n\n this.cachedConfig.set(ide, javelinConfig);\n\n const ideConfig = this.rawConfig?.ides?.[ide];\n logger.info(`Config loaded for ${ide}:`, {\n baseUrl: javelinConfig.baseUrl,\n hasToken: !!token,\n mode: ideConfig?.mode || \"inspect\",\n });\n\n return javelinConfig;\n } catch (error) {\n logger.error(\"Failed to read config:\", {\n error: String(error),\n ide,\n });\n return this.getDefaultConfig();\n }\n }\n\n /**\n * Get operating mode for an IDE (inspect or enforce)\n */\n getMode(ide: IDEType): OperatingMode {\n if (!this.rawConfig) {\n return \"inspect\"; // Default to inspect (safe mode)\n }\n\n const ideConfig = this.rawConfig.ides?.[ide];\n return ideConfig?.mode || \"inspect\";\n }\n\n /**\n * Get the full overwatch config\n */\n getOverwatchConfig(): OverwatchConfig | null {\n return this.rawConfig;\n }\n\n /**\n * Get Highflame API configuration\n */\n getHighflameConfig(): { baseUrl: string; enabled: boolean } {\n const envBaseUrl = process.env.HIGHFLAME_BASE_URL;\n\n return {\n baseUrl: envBaseUrl || getBaseUrl(),\n enabled: this.rawConfig?.engines?.javelin?.enabled !== false,\n };\n }\n\n /**\n * Get JWT token from session.json for API authentication\n */\n getJwtToken(): string | null {\n // Check environment variable first\n const envToken = process.env.HIGHFLAME_TOKEN;\n if (envToken) {\n return envToken;\n }\n\n // Get from session.json\n const authConfig = loadTokens();\n return authConfig?.access_token || null;\n }\n\n /**\n * Get LLM API key from config or environment\n */\n getLLMApiKey(): string | null {\n const llmConfig = getLLMConfig();\n return llmConfig?.apiKey || null;\n }\n\n /**\n * Load raw config from file\n */\n private async loadRawConfig(): Promise<void> {\n if (!fs.existsSync(this.configPath)) {\n logger.warn(`Config file not found: ${this.configPath}`);\n this.rawConfig = null;\n return;\n }\n\n try {\n const configData = await fs.promises.readFile(this.configPath, \"utf-8\");\n this.rawConfig = JSON.parse(configData) as OverwatchConfig;\n logger.info(\"Config loaded:\", {\n version: this.rawConfig.version,\n hasHighflame: !!this.rawConfig.highflame,\n ides: this.rawConfig.ides\n ? Object.keys(this.rawConfig.ides).filter(\n (ide) =>\n this.rawConfig?.ides?.[ide as keyof typeof this.rawConfig.ides]\n ?.enabled,\n )\n : [],\n });\n } catch (error) {\n logger.error(\"Failed to load config:\", {\n error: String(error),\n });\n this.rawConfig = null;\n }\n }\n\n /**\n * Get default configuration\n */\n private getDefaultConfig(): JavelinConfig {\n const token = this.getJwtToken();\n\n const config: JavelinConfig = {\n baseUrl: getBaseUrl(),\n token: token || \"\",\n timeout: 30000,\n };\n\n logger.debug(\"Generated default config:\", {\n baseUrl: config.baseUrl,\n hasToken: !!config.token,\n });\n\n return config;\n }\n\n /**\n * Get cached configuration for an IDE\n */\n getCachedConfig(ide: IDEType): JavelinConfig | null {\n const cached = this.cachedConfig.get(ide) || null;\n logger.debug(`getCachedConfig(${ide}):`, {\n found: !!cached,\n hasToken: cached ? !!cached.token : false,\n });\n return cached;\n }\n\n /**\n * Check if configuration is valid\n */\n isValid(config: JavelinConfig | null): boolean {\n const valid = !!config && !!config.baseUrl && !!config.token;\n logger.debug(\"isValid check:\", {\n hasConfig: !!config,\n hasBaseUrl: !!config?.baseUrl,\n hasToken: !!config?.token,\n result: valid,\n });\n return valid;\n }\n\n /**\n * Get admin API configuration (derived from Highflame config)\n * Used by PolicyManager and AdminClient for remote policy fetching\n */\n getAdminConfig(): AdminConfig {\n const highflameConfig = this.getHighflameConfig();\n return {\n enabled: highflameConfig.enabled,\n baseUrl: highflameConfig.baseUrl || null,\n };\n }\n\n /**\n * Get admin token for API authentication\n * Alias for getJwtToken for backwards compatibility\n */\n getAdminToken(): string | null {\n return this.getJwtToken();\n }\n\n /**\n * Clear cache (useful for config reload)\n */\n clearCache(): void {\n const cacheSize = this.cachedConfig.size;\n this.cachedConfig.clear();\n this.rawConfig = null;\n logger.info(\"Cache cleared\", {\n entriesCleared: cacheSize,\n });\n }\n}\n", "/**\n * OAuth authentication module\n * Provides PKCE-based OAuth 2.0 authentication for Highflame\n */\n\n// PKCE utilities\nexport {\n generateCodeVerifier,\n generateCodeChallenge,\n generateState,\n} from \"./pkce\";\n\n// OAuth flow manager\nexport {\n OAUTH_CONFIG,\n TOKEN_EXPIRY_SECONDS,\n OAuthState,\n TokenResponse,\n UserInfo,\n buildAuthorizationUrl,\n exchangeCodeForTokens,\n refreshAccessToken,\n isTokenExpired,\n createOAuthState,\n} from \"./oauth\";\n\n// CLI OAuth flow\nexport { performCLIOAuthFlow } from \"./cli-oauth\";\n\n// Token persistence\nexport {\n AuthStatus,\n saveTokens,\n loadTokens,\n clearTokens,\n getValidAccessToken,\n needsReauth,\n getAuthStatus,\n} from \"./token-store\";\n\n// HTML utilities\nexport {\n escapeHtml,\n generateSuccessHtml,\n generateErrorHtml,\n} from \"./html-utils\";\n", "/**\n * CLI OAuth 2.0 PKCE flow\n * Handles OAuth authentication flow for CLI commands\n * Starts temporary callback server on ephemeral port\n */\n\nimport * as http from \"http\";\nimport open from \"open\";\nimport {\n generateCodeVerifier,\n generateCodeChallenge,\n generateState,\n} from \"./pkce\";\nimport { buildAuthorizationUrl, exchangeCodeForTokens } from \"./oauth\";\nimport { saveTokens } from \"./token-store\";\nimport { generateSuccessHtml, generateErrorHtml } from \"./html-utils\";\n\n/** OAuth flow timeout: 5 minutes */\nconst OAUTH_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Polling interval for callback check */\nconst CALLBACK_POLL_INTERVAL_MS = 100;\n\n/** OAuth callback data structure */\ninterface OAuthCallbackData {\n code: string;\n state: string;\n}\n\n/** Map to store callback data by server instance */\nconst callbackDataMap = new WeakMap<http.Server, OAuthCallbackData>();\n\n/**\n * Perform OAuth PKCE flow for CLI\n * @param openBrowser Whether to open browser automatically (default: true)\n * @returns User email on success\n * @throws Error on failure\n */\nexport async function performCLIOAuthFlow(\n openBrowser: boolean = true,\n): Promise<string> {\n // Generate PKCE values\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n const state = generateState();\n\n // Start callback server on ephemeral port\n const { server, redirectUri } = await startCallbackServer(state);\n\n try {\n // Build authorization URL\n const authUrl = buildAuthorizationUrl(state, codeChallenge, redirectUri);\n\n // Open browser or print URL\n if (openBrowser) {\n console.log(\"Opening browser for authentication...\");\n console.log(\"(If browser does not open, copy this URL manually)\\n\");\n console.log(` ${authUrl}\\n`);\n await open(authUrl);\n } else {\n console.log(\"Open this URL in your browser:\\n\");\n console.log(` ${authUrl}\\n`);\n }\n\n console.log(\"Waiting for authentication...\");\n\n // Wait for callback\n const { code, callbackState } = await waitForCallback(server, state);\n\n // Verify state matches\n if (callbackState !== state) {\n throw new Error(\"State mismatch - possible CSRF attack\");\n }\n\n // Exchange code for tokens\n const { tokens, userInfo } = await exchangeCodeForTokens(\n code,\n codeVerifier,\n redirectUri,\n );\n\n // Save tokens\n saveTokens(tokens, userInfo);\n\n return userInfo.email;\n } finally {\n // Shutdown callback server\n server.close();\n }\n}\n\n/**\n * Start temporary HTTP server on ephemeral port for OAuth callback\n * @param expectedState The expected state parameter for validation\n */\nfunction startCallbackServer(expectedState: string): Promise<{\n server: http.Server;\n port: number;\n redirectUri: string;\n}> {\n return new Promise((resolve, reject) => {\n const server = http.createServer();\n\n server.on(\"request\", (req, res) => {\n if (!req.url) {\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Bad Request\");\n return;\n }\n\n const parsedUrl = new URL(req.url, `http://${req.headers.host}`);\n\n // Handle OAuth callback\n if (parsedUrl.pathname === \"/oauth/callback\") {\n const code = parsedUrl.searchParams.get(\"code\");\n const state = parsedUrl.searchParams.get(\"state\");\n const error = parsedUrl.searchParams.get(\"error\");\n const errorDescription =\n parsedUrl.searchParams.get(\"error_description\");\n\n if (error) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(errorDescription || error));\n return;\n }\n\n if (!code || !state) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(\"Missing authorization code or state\"));\n return;\n }\n\n // Validate state matches expected\n if (state !== expectedState) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(\"Invalid state parameter\"));\n return;\n }\n\n // Store callback data using WeakMap\n callbackDataMap.set(server, { code, state });\n\n // Send success response\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(\n generateSuccessHtml(\n \"You can close this window and return to the terminal.\",\n ),\n );\n } else {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not Found\");\n }\n });\n\n // Start server on ephemeral port (port 0)\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n if (!address || typeof address === \"string\") {\n reject(new Error(\"Failed to get server address\"));\n return;\n }\n\n const port = address.port;\n const redirectUri = `http://127.0.0.1:${port}/oauth/callback`;\n\n resolve({ server, port, redirectUri });\n });\n\n server.on(\"error\", (err) => {\n reject(err);\n });\n });\n}\n\n/**\n * Wait for OAuth callback with timeout\n * @param server The HTTP server to monitor\n * @param expectedState The expected state parameter\n */\nfunction waitForCallback(\n server: http.Server,\n expectedState: string,\n): Promise<{ code: string; callbackState: string }> {\n return new Promise((resolve, reject) => {\n const startTime = Date.now();\n\n const checkCallback = () => {\n const callback = callbackDataMap.get(server);\n if (callback) {\n // Validate state matches\n if (callback.state !== expectedState) {\n reject(new Error(\"State mismatch in callback\"));\n return;\n }\n resolve({ code: callback.code, callbackState: callback.state });\n return;\n }\n\n if (Date.now() - startTime > OAUTH_TIMEOUT_MS) {\n reject(new Error(\"OAuth flow timed out. Please try again.\"));\n return;\n }\n\n // Check again after polling interval\n setTimeout(checkCallback, CALLBACK_POLL_INTERVAL_MS);\n };\n\n checkCallback();\n });\n}\n", "/**\n * Token storage for OAuth authentication\n * Stores tokens in ~/.overwatch/session.json (separate from config for security)\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport {\n TokenResponse,\n UserInfo,\n isTokenExpired,\n TOKEN_EXPIRY_SECONDS,\n} from \"./oauth\";\nimport { AuthConfig } from \"../types\";\nimport { logger } from \"../utils\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".overwatch\");\nconst SESSION_PATH = path.join(CONFIG_DIR, \"session.json\");\n\n// File permissions: 600 (read/write for owner only)\nconst SESSION_FILE_MODE = 0o600;\n\n/**\n * Auth status response\n */\nexport interface AuthStatus {\n authenticated: boolean;\n email?: string;\n name?: string;\n orgName?: string;\n expiresAt?: number;\n expired?: boolean;\n}\n\n/**\n * Load session data from session.json\n */\nfunction loadSession(): AuthConfig | null {\n try {\n if (fs.existsSync(SESSION_PATH)) {\n const data = fs.readFileSync(SESSION_PATH, \"utf-8\");\n return JSON.parse(data) as AuthConfig;\n }\n } catch (e) {\n logger.debug(\"Failed to load session file\", {\n error: e instanceof Error ? e.message : String(e),\n path: SESSION_PATH,\n });\n }\n return null;\n}\n\n/**\n * Write session data to session.json with restricted permissions\n */\nfunction writeSession(session: AuthConfig): void {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n\n const data = JSON.stringify(session, null, 2);\n fs.writeFileSync(SESSION_PATH, data, { mode: SESSION_FILE_MODE });\n\n // Ensure file permissions are set correctly (in case file already existed)\n try {\n fs.chmodSync(SESSION_PATH, SESSION_FILE_MODE);\n } catch (e) {\n // chmod may not be supported on all platforms (e.g., Windows)\n logger.debug(\"Failed to set session file permissions\", {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n}\n\n/**\n * Save tokens to session.json file\n */\nexport function saveTokens(tokens: TokenResponse, userInfo?: UserInfo): void {\n // Compute expires_at if not already set\n const expiresAt =\n tokens.expires_at ?? Date.now() + TOKEN_EXPIRY_SECONDS * 1000;\n\n const auth: AuthConfig = {\n access_token: tokens.access_token,\n refresh_token: tokens.refresh_token || \"\",\n expires_at: expiresAt,\n token_type: tokens.token_type,\n user: userInfo\n ? {\n email: userInfo.email,\n }\n : undefined,\n authenticated_at: new Date().toISOString(),\n };\n\n writeSession(auth);\n}\n\n/**\n * Load tokens from session.json file\n */\nexport function loadTokens(): AuthConfig | null {\n return loadSession();\n}\n\n/**\n * Clear tokens by deleting session.json file\n */\nexport function clearTokens(): void {\n try {\n if (fs.existsSync(SESSION_PATH)) {\n fs.unlinkSync(SESSION_PATH);\n }\n } catch (e) {\n logger.debug(\"Failed to delete session file\", {\n error: e instanceof Error ? e.message : String(e),\n path: SESSION_PATH,\n });\n }\n}\n\n/**\n * Get access token if valid, null if expired or missing\n * Attempts to refresh token if expired and refresh token is available\n */\nexport async function getValidAccessToken(): Promise<string | null> {\n const auth = loadTokens();\n if (!auth) return null;\n\n // Check if expired (with 1-day buffer)\n if (isTokenExpired(auth.expires_at)) {\n // Try to refresh if refresh token is available\n if (auth.refresh_token) {\n const { refreshAccessToken } = await import(\"./oauth\");\n const refreshed = await refreshAccessToken(auth.refresh_token);\n if (refreshed) {\n // Save new tokens\n saveTokens(refreshed);\n return refreshed.access_token;\n }\n }\n return null;\n }\n\n return auth.access_token;\n}\n\n/**\n * Check if re-authentication is needed\n * Returns true if tokens are expired or missing\n */\nexport function needsReauth(): boolean {\n const auth = loadTokens();\n if (!auth) return true;\n return isTokenExpired(auth.expires_at);\n}\n\n/**\n * Get auth status for display\n */\nexport function getAuthStatus(): AuthStatus {\n const auth = loadTokens();\n if (!auth) {\n return { authenticated: false };\n }\n\n return {\n authenticated: true,\n email: auth.user?.email,\n name: auth.user?.name,\n orgName: auth.user?.org_name,\n expiresAt: auth.expires_at,\n expired: isTokenExpired(auth.expires_at),\n };\n}\n", "/**\n * HTML utilities for OAuth responses\n * Provides secure HTML generation with proper escaping\n */\n\n/**\n * Escape HTML entities to prevent XSS attacks\n */\nexport function escapeHtml(unsafe: string): string {\n return unsafe\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n}\n\n/**\n * Common styles for OAuth response pages\n */\nconst COMMON_STYLES = `\n body {\n font-family: system-ui, -apple-system, sans-serif;\n text-align: center;\n padding: 50px;\n background: #f5f5f5;\n }\n .container {\n background: white;\n padding: 40px;\n border-radius: 10px;\n max-width: 400px;\n margin: 0 auto;\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n }\n h1 {\n margin-bottom: 20px;\n }\n p {\n color: #666;\n margin: 10px 0;\n }\n .success h1 { color: #22c55e; }\n .error h1 { color: #ef4444; }\n .error-message {\n color: #ef4444;\n font-family: monospace;\n background: #fef2f2;\n padding: 10px;\n border-radius: 5px;\n }\n .email {\n font-weight: bold;\n color: #333;\n }\n`;\n\n/**\n * Generate success HTML response for OAuth callback\n * @param message Success message to display\n * @param email Optional user email (will be escaped)\n */\nexport function generateSuccessHtml(message: string, email?: string): string {\n const safeMessage = escapeHtml(message);\n const safeEmail = email ? escapeHtml(email) : \"user\";\n\n return `<!DOCTYPE html>\n<html>\n<head>\n <title>Login Successful</title>\n <style>${COMMON_STYLES}</style>\n</head>\n<body>\n <div class=\"container success\">\n <h1>Login Successful</h1>\n <p>Welcome, <span class=\"email\">${safeEmail}</span>!</p>\n <p>${safeMessage}</p>\n </div>\n</body>\n</html>`;\n}\n\n/**\n * Generate error HTML response for OAuth callback\n * @param error Error message to display (will be escaped)\n */\nexport function generateErrorHtml(error: string): string {\n const safeError = escapeHtml(error);\n\n return `<!DOCTYPE html>\n<html>\n<head>\n <title>Login Failed</title>\n <style>${COMMON_STYLES}</style>\n</head>\n<body>\n <div class=\"container error\">\n <h1>Login Failed</h1>\n <p class=\"error-message\">${safeError}</p>\n <p>Please try again from the terminal.</p>\n </div>\n</body>\n</html>`;\n}\n", "/**\n * Config Manager\n * Handles reading, writing, and updating the overwatch config file\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport {\n OverwatchConfig,\n DEFAULT_OVERWATCH_CONFIG,\n LLMConfig,\n HighflameConfig,\n} from \"../types\";\nimport { loadTokens } from \"../auth\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".overwatch\");\nconst CONFIG_PATH = path.join(CONFIG_DIR, \"config.json\");\n\n/**\n * Load config from file\n */\nexport function loadConfig(): OverwatchConfig | null {\n try {\n if (fs.existsSync(CONFIG_PATH)) {\n const data = fs.readFileSync(CONFIG_PATH, \"utf-8\");\n return JSON.parse(data) as OverwatchConfig;\n }\n } catch (e) {\n console.error(\"Failed to load config:\", e);\n }\n return null;\n}\n\n/**\n * Save config to file\n */\nexport function saveConfig(config: OverwatchConfig): void {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));\n}\n\n/**\n * Initialize config with defaults if not exists\n */\nexport function initConfig(): OverwatchConfig {\n let config = loadConfig();\n\n if (!config) {\n config = { ...DEFAULT_OVERWATCH_CONFIG };\n config.createdAt = new Date().toISOString();\n saveConfig(config);\n }\n\n return config;\n}\n\n/**\n * Update Highflame base URL\n */\nexport function setBaseUrl(url: string): void {\n const config = loadConfig() || { ...DEFAULT_OVERWATCH_CONFIG };\n\n config.highflame = {\n ...config.highflame,\n baseUrl: url,\n };\n\n saveConfig(config);\n}\n\n/**\n * Get Highflame base URL\n */\nexport function getBaseUrl(): string {\n const config = loadConfig();\n return (\n config?.highflame?.baseUrl ||\n process.env.HIGHFLAME_BASE_URL ||\n \"https://api.highflame.app\"\n );\n}\n\n/**\n * Set LLM API key\n */\nexport function setLLMApiKey(apiKey: string, provider?: string): void {\n const config = loadConfig() || { ...DEFAULT_OVERWATCH_CONFIG };\n\n config.llm = {\n ...config.llm,\n apiKey,\n provider: provider || config.llm?.provider || \"openai\",\n };\n\n saveConfig(config);\n}\n\n/**\n * Get LLM config\n */\nexport function getLLMConfig(): LLMConfig | null {\n const config = loadConfig();\n\n // Check environment variable first\n const envKey = process.env.LLM_API_KEY || process.env.OPENAI_API_KEY;\n if (envKey) {\n return {\n apiKey: envKey,\n provider: config?.llm?.provider || \"openai\",\n };\n }\n\n return config?.llm || null;\n}\n\n/**\n * Get Highflame config\n */\nexport function getHighflameConfig(): HighflameConfig {\n const config = loadConfig();\n return {\n baseUrl: config?.highflame?.baseUrl || \"https://api.highflame.app\",\n };\n}\n\n/**\n * Get JWT token from session for API calls\n */\nexport function getJwtToken(): string | null {\n const authConfig = loadTokens();\n return authConfig?.access_token || null;\n}\n\n/**\n * Update IDE config\n */\nexport function updateIDEConfig(\n ide: \"cursor\" | \"claudecode\" | \"github_copilot\",\n enabled: boolean,\n mode: \"inspect\" | \"enforce\" = \"enforce\",\n hooksPath?: string,\n): void {\n const config = loadConfig() || { ...DEFAULT_OVERWATCH_CONFIG };\n\n if (!config.ides) {\n config.ides = {};\n }\n\n config.ides[ide] = {\n enabled,\n mode,\n hooksInstalled: enabled,\n hooksPath,\n };\n\n saveConfig(config);\n}\n\n/**\n * Display current config (formatted for CLI)\n */\nexport function displayConfig(): void {\n const config = loadConfig();\n\n if (!config) {\n console.log(\"No config found. Run 'overwatch start' to create one.\");\n return;\n }\n\n console.log(\"\\n\uD83D\uDCCB Overwatch Configuration\");\n console.log(\"\u2550\".repeat(40));\n\n console.log(`\\nVersion: ${config.version}`);\n if (config.createdAt) {\n console.log(`Created: ${config.createdAt}`);\n }\n\n console.log(\"\\n\uD83D\uDD17 Highflame API:\");\n console.log(` Base URL: ${config.highflame?.baseUrl || \"(not set)\"}`);\n\n console.log(\"\\n\uD83E\uDD16 LLM Config:\");\n const llmConfig = getLLMConfig();\n if (llmConfig?.apiKey) {\n const maskedKey =\n llmConfig.apiKey.substring(0, 7) + \"...\" + llmConfig.apiKey.slice(-4);\n console.log(` API Key: ${maskedKey}`);\n console.log(` Provider: ${llmConfig.provider || \"openai\"}`);\n } else {\n console.log(\" API Key: (not set)\");\n }\n\n console.log(\"\\n\u2699\uFE0F Engines:\");\n console.log(\n ` YARA: ${config.engines?.yara?.enabled !== false ? \"\u2705\" : \"\u274C\"}`,\n );\n console.log(\n ` Cedar: ${config.engines?.cedar?.enabled !== false ? \"\u2705\" : \"\u274C\"}`,\n );\n console.log(\n ` Javelin: ${config.engines?.javelin?.enabled !== false ? \"\u2705\" : \"\u274C\"}`,\n );\n\n console.log(\"\\n\uD83D\uDCBB IDEs:\");\n if (config.ides) {\n for (const [ide, ideConfig] of Object.entries(config.ides)) {\n if (ideConfig) {\n const status = ideConfig.enabled ? \"\u2705\" : \"\u274C\";\n console.log(` ${ide}: ${status} (${ideConfig.mode || \"inspect\"})`);\n }\n }\n } else {\n console.log(\" No IDEs configured\");\n }\n\n console.log(\"\");\n}\n\n/**\n * Get config file path\n */\nexport function getConfigPath(): string {\n return CONFIG_PATH;\n}\n", "/**\n * Supported IDE types\n */\nexport type IDEType = \"cursor\" | \"claudecode\" | \"github_copilot\";\n\n/**\n * IDE source constants - use these instead of hard-coding strings\n */\nexport const IDE_SOURCES = {\n CURSOR: \"cursor\" as const,\n CLAUDE_CODE: \"claudecode\" as const,\n GITHUB_COPILOT: \"github_copilot\" as const,\n} as const;\n\n/**\n * Operating mode\n */\nexport type OperatingMode = \"inspect\" | \"enforce\";\n\n/**\n * Per-IDE configuration (no longer contains token - uses JWT from session)\n */\nexport interface IDEConfig {\n /** Whether this IDE is enabled */\n enabled?: boolean;\n\n /** Operating mode: inspect (allow all, record) or enforce (block threats) */\n mode: OperatingMode;\n\n /** Whether hooks are installed for this IDE */\n hooksInstalled?: boolean;\n\n /** Path to hooks directory */\n hooksPath?: string;\n}\n\n/**\n * LLM configuration for MCP scanning\n */\nexport interface LLMConfig {\n /** LLM API key for evaluation (e.g., OpenAI, Anthropic) */\n apiKey?: string;\n\n /** LLM provider (openai, anthropic, etc.) */\n provider?: string;\n}\n\n/**\n * Engine configuration\n */\nexport interface EnginesConfig {\n /** YARA engine settings */\n yara?: {\n enabled?: boolean;\n rulesDir?: string;\n };\n\n /** Cedar policy engine settings */\n cedar?: {\n enabled?: boolean;\n policyFile?: string;\n };\n\n /** Javelin (Highflame) remote validation */\n javelin?: {\n enabled?: boolean;\n };\n}\n\n/**\n * Daemon configuration\n */\nexport interface DaemonConfig {\n /** Auto-start daemon on boot */\n autoStart?: boolean;\n\n /** Log level */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n\n /** Preferred ports to try (first available will be used) */\n ports?: number[];\n}\n\n/**\n * Highflame API configuration\n */\nexport interface HighflameConfig {\n /** Highflame API base URL */\n baseUrl?: string;\n}\n\n/**\n * OAuth authentication configuration (stored in session.json)\n */\nexport interface AuthConfig {\n /** OAuth access token (JWT) */\n access_token: string;\n\n /** OAuth refresh token for token renewal */\n refresh_token: string;\n\n /** Token expiry timestamp in milliseconds (Unix epoch) */\n expires_at: number;\n\n /** Token type (always Bearer) */\n token_type: \"Bearer\";\n\n /** Authenticated user information */\n user?: {\n email: string;\n name?: string;\n org_id?: string;\n org_name?: string;\n };\n\n /** ISO timestamp when authentication occurred */\n authenticated_at: string;\n}\n\n/**\n * Admin API configuration (derived from Highflame config)\n */\nexport interface AdminConfig {\n /** Whether admin API is enabled */\n enabled: boolean;\n\n /** Admin API base URL */\n baseUrl: string | null;\n}\n\n/**\n * Unified overwatch config file structure (~/.overwatch/config.json)\n */\nexport interface OverwatchConfig {\n /** Config version */\n version: string;\n\n /** Config creation timestamp */\n createdAt?: string;\n\n /** Highflame API settings */\n highflame?: HighflameConfig;\n\n /** LLM configuration for MCP scanning */\n llm?: LLMConfig;\n\n /** Security engines configuration */\n engines?: EnginesConfig;\n\n /** Remote policy settings */\n remotePolicy?: {\n /** Whether remote policy fetching is enabled */\n enabled?: boolean;\n /** Poll interval in minutes for remote policy refresh */\n pollIntervalMinutes?: number;\n };\n\n /** Per-IDE configurations */\n ides?: {\n cursor?: IDEConfig;\n claudecode?: IDEConfig;\n github_copilot?: IDEConfig;\n };\n\n /** Daemon settings */\n daemon?: DaemonConfig;\n\n /** Global enabled flag */\n enabled?: boolean;\n}\n\n/**\n * Guardian daemon configuration (runtime)\n */\nexport interface GuardianConfig {\n /** IDE type - determines which hooks to use */\n ide?: IDEType;\n\n /** HTTP server port */\n httpPort?: number;\n\n /** Enable debug logging */\n debug?: boolean;\n\n /** Highflame API configuration */\n javelin?: {\n /** Javelin API base URL */\n baseUrl?: string;\n\n /** Request timeout in milliseconds */\n timeout?: number;\n };\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: Required<GuardianConfig> = {\n ide: \"cursor\",\n httpPort: 0, // Ephemeral port - OS assigns available port\n debug: false,\n javelin: {\n baseUrl: \"https://api.highflame.app\",\n timeout: 30000,\n },\n};\n\n/**\n * Default Overwatch config structure\n */\nexport const DEFAULT_OVERWATCH_CONFIG: OverwatchConfig = {\n version: \"2.0\",\n createdAt: new Date().toISOString(),\n highflame: {\n baseUrl: \"https://api.highflame.app\",\n },\n engines: {\n yara: {\n enabled: true,\n },\n cedar: {\n enabled: true,\n },\n javelin: {\n enabled: true,\n },\n },\n daemon: {\n autoStart: true,\n logLevel: \"info\",\n },\n enabled: true,\n};\n", "/**\n * Remote policy types for Guardian\n *\n * These types support fetching and managing Cedar policies from the\n * highflame-admin backend, enabling IDE-specific policy configuration.\n */\n\n/**\n * Remote policy configuration\n */\nexport interface RemotePolicyConfig {\n /** Enable remote policy fetching */\n enabled: boolean;\n\n /** Polling interval in milliseconds (default: 5 minutes) */\n pollIntervalMs: number;\n}\n\n/**\n * Application from admin API (code_agent type)\n */\nexport interface CodeAgentApplication {\n /** Application UUID */\n uuid: string;\n\n /** Application name (e.g., \"cursor-guardian\") */\n name: string;\n\n /** Application type (should be \"code_agent\") */\n type: string;\n\n /** IDE type this application is for */\n ide_type?: string;\n\n /** Whether the application is active */\n is_active: boolean;\n\n /** Application description */\n description?: string;\n\n /** Application configuration */\n config?: Record<string, unknown>;\n}\n\n/**\n * Cedar policy from admin API\n */\nexport interface RemoteCedarPolicy {\n /** Policy UUID */\n uuid: string;\n\n /** Policy name */\n name: string;\n\n /** Cedar policy content (the actual policy text) */\n policy_content: string;\n\n /** Associated application ID */\n application_id?: string;\n\n /** IDE type this policy is for */\n ide_type?: string;\n\n /** Policy version */\n version?: string;\n\n /** Last updated timestamp */\n updated_at: string;\n}\n\n/**\n * Installation event payload sent to admin API\n */\nexport interface InstallationEvent {\n /** User identifier */\n user_id: string;\n\n /** User email address */\n user_email: string;\n\n /** IDE type (cursor, claudecode, github_copilot) */\n ide_type: string;\n\n /** Guardian version */\n version: string;\n\n /** Event timestamp (ISO string) */\n timestamp: string;\n}\n\n/**\n * Policy mapping for IDE-specific policies\n * Uses index signature to allow any IDESource string key\n */\nexport interface PolicyMapping {\n cursor?: PolicyMappingEntry;\n claudecode?: PolicyMappingEntry;\n github_copilot?: PolicyMappingEntry;\n [ide: string]: PolicyMappingEntry | undefined; // index by IDE source string\n}\n\n/**\n * Single policy mapping entry\n */\nexport interface PolicyMappingEntry {\n /** Associated application ID */\n applicationId: string;\n\n /** Cedar policy content */\n policyContent: string;\n\n /** Last updated timestamp */\n lastUpdated: string;\n\n /** Policy version */\n version?: string;\n}\n\n/**\n * Admin API response for applications\n */\nexport interface ApplicationsResponse {\n applications: CodeAgentApplication[];\n total: number;\n}\n\n/**\n * Admin API response for policies\n */\nexport interface PoliciesResponse {\n policies: RemoteCedarPolicy[];\n total: number;\n}\n\n/**\n * Admin API response for installations\n */\nexport interface InstallationsResponse {\n installations: InstallationInfo[];\n total: number;\n}\n\n/**\n * Installation info from admin API\n */\nexport interface InstallationInfo {\n id: string;\n user_id: string;\n user_email: string;\n ide_type: string;\n version: string;\n first_seen_at: string;\n last_seen_at: string;\n}\n\n/**\n * Default remote policy configuration\n */\nexport const DEFAULT_REMOTE_POLICY_CONFIG: RemotePolicyConfig = {\n enabled: true,\n pollIntervalMs: 5 * 60 * 1000, // 5 minutes\n};\n", "import { randomUUID } from \"crypto\";\nimport {\n JavelinConfig,\n JavelinValidationResponse,\n HighflameGuardrailsRequest,\n HighflameGuardrailsResponse,\n} from \"./types\";\nimport { logger } from \"../utils\";\n\n/**\n * Guardrail configurations by engine type\n */\nconst GUARDRAIL_CONFIGS: Record<\n string,\n Array<{ name: string; config: { threshold: number } }>\n> = {\n // Full guardrails for prompt validation\n guardrails: [\n { name: \"promptinjectiondetection\", config: { threshold: 0.5 } },\n { name: \"dlp_gcp\", config: { threshold: 0.5 } },\n { name: \"yara\", config: { threshold: 0.5 } },\n ],\n // YARA-only for MCP/Shell (fast)\n yara: [{ name: \"yara\", config: { threshold: 0.5 } }],\n};\n\n/**\n * Highflame HTTP client for guardrails validation\n */\nexport class JavelinClient {\n private config: JavelinConfig;\n private requestCount = 0;\n\n constructor(config: JavelinConfig) {\n this.config = config;\n logger.debug(\n `[JavelinClient] Initialized with baseUrl=${config.baseUrl}, hasToken=${!!config.token}, timeout=${config.timeout}ms`,\n );\n }\n\n /**\n * Get current config\n */\n getConfig(): JavelinConfig {\n return this.config;\n }\n\n /**\n * Validate content using Highflame guardrails API\n * @param engine - Guardrail engine type (guardrails, yara)\n * @param payload - Content to validate\n * @param metadata - Optional metadata to include in request\n * @param applicationId - Optional application ID for x-javelin-application header\n */\n async validateWithGuardrails(\n engine: string,\n payload: string,\n metadata?: Record<string, unknown>,\n applicationId?: string,\n ): Promise<JavelinValidationResponse> {\n const requestId = `req-${++this.requestCount}-${Date.now()}`;\n const startTime = Date.now();\n\n logger.info(\n `[${requestId}] Starting validation: engine=${engine}, payloadLength=${payload.length}`,\n );\n\n // Skip if no token configured\n if (!this.config.token) {\n logger.warn(\n `[${requestId}] No Highflame token configured, skipping API call`,\n );\n return {\n success: true,\n message: \"Skipped - no token configured\",\n results: { findings: [], metadata: { skipped: true, requestId } },\n };\n }\n\n const endpoint = `${this.config.baseUrl}/v1/guardrails/apply`;\n const sessionId = (metadata?.session_id as string) || randomUUID();\n\n // Select guardrails based on engine type\n const guardrails =\n GUARDRAIL_CONFIGS[engine] || GUARDRAIL_CONFIGS.guardrails;\n\n const requestBody: HighflameGuardrailsRequest = {\n input: { text: payload },\n guardrails,\n metadata: {\n direction: \"request\",\n request_source: \"overwatch\",\n session_id: sessionId,\n ...metadata,\n },\n };\n\n logger.debug(\"Request details:\", {\n endpoint,\n engine,\n guardrails: guardrails.map((g) => g.name),\n sessionId,\n payloadPreview:\n payload.substring(0, 100) + (payload.length > 100 ? \"...\" : \"\"),\n });\n\n try {\n logger.debug(`Sending POST to ${endpoint}`);\n const fetchStart = Date.now();\n\n // Build headers\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-javelin-token\": this.config.token,\n \"User-Agent\": \"overwatch/1.0.0\",\n };\n\n // Add application ID header if provided\n if (applicationId) {\n headers[\"x-javelin-application\"] = applicationId;\n }\n\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(requestBody),\n signal: AbortSignal.timeout(this.config.timeout),\n });\n\n const fetchDuration = Date.now() - fetchStart;\n logger.debug(\n `[${requestId}] HTTP response: status=${response.status}, duration=${fetchDuration}ms`,\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n logger.error(\n `[${requestId}] API error response: ${response.status} ${response.statusText}`,\n { body: errorText },\n );\n throw new Error(\n `Highflame API error: ${response.status} ${response.statusText} - ${errorText}`,\n );\n }\n\n const apiResponse =\n (await response.json()) as HighflameGuardrailsResponse;\n logger.debug(\n `[${requestId}] API response body:`,\n JSON.stringify(apiResponse),\n );\n\n // Parse assessments to check for threats\n const findings: Array<{\n severity: string;\n type: string;\n message: string;\n location?: Record<string, unknown>;\n }> = [];\n let threatDetected = false;\n\n // Safely iterate over assessments (may be undefined)\n const assessments = apiResponse?.assessments || [];\n logger.debug(\n `[${requestId}] Processing ${assessments.length} assessments`,\n );\n\n for (const assessment of assessments) {\n for (const [guardrailName, result] of Object.entries(assessment)) {\n const rejected = result?.request_reject === true;\n logger.debug(\n `[${requestId}] Guardrail: ${guardrailName}, request_reject=${rejected}`,\n );\n\n if (rejected) {\n threatDetected = true;\n findings.push({\n severity: \"high\",\n type: guardrailName,\n message: `${guardrailName} triggered rejection`,\n location: result.results,\n });\n logger.warn(\n `[${requestId}] [THREAT] ${guardrailName}: request_reject=true`,\n result.results,\n );\n }\n }\n }\n\n const totalDuration = Date.now() - startTime;\n\n if (threatDetected) {\n logger.warn(\n `[${requestId}] Threats detected: ${findings.length} guardrail(s) triggered (POC: allowing)`,\n );\n findings.forEach((f) =>\n logger.warn(\n `[${requestId}] [${f.severity}] ${f.type}: ${f.message}`,\n ),\n );\n } else {\n logger.info(\n `[${requestId}] Validation passed: no threats detected, duration=${totalDuration}ms`,\n );\n }\n\n return {\n success: true, // POC: Always allow\n message: threatDetected\n ? `${findings.length} threat(s) logged (POC mode - allowed)`\n : \"Validation passed\",\n results: {\n findings,\n metadata: {\n requestId,\n assessments: apiResponse.assessments,\n threatDetected,\n duration: totalDuration,\n },\n },\n };\n } catch (error) {\n const totalDuration = Date.now() - startTime;\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n logger.error(`API call failed after ${totalDuration}ms:`, {\n error: errorMessage,\n stack: errorStack,\n endpoint,\n });\n\n // POC: Return success even on API errors\n return {\n success: true,\n message: `API error (POC mode - allowed): ${errorMessage}`,\n error: {\n code: \"API_ERROR\",\n message: `Failed to call Highflame API: ${errorMessage}`,\n details: { requestId, duration: totalDuration },\n },\n };\n }\n }\n\n /**\n * Test connection to Highflame API\n */\n async testConnection(): Promise<boolean> {\n if (!this.config.token) {\n logger.warn(\"No Highflame token configured\");\n return false;\n }\n logger.debug(\"Connection test: token present\");\n return true;\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: JavelinConfig): void {\n const oldBaseUrl = this.config.baseUrl;\n this.config = config;\n logger.info(\n `[JavelinClient] Configuration updated: baseUrl=${oldBaseUrl} -> ${config.baseUrl}, hasToken=${!!config.token}`,\n );\n }\n}\n", "/**\n * Admin API client for Guardian\n *\n * Handles communication with highflame-admin for:\n * - Recording installation events\n * - Fetching code_agent applications (via existing application API)\n * - Fetching Cedar policies for applications (via existing policy API)\n */\n\nimport { logger } from \"../utils\";\nimport {\n CodeAgentApplication,\n RemoteCedarPolicy,\n InstallationEvent,\n} from \"../types/remote-policy\";\n\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Raw application response from /v1/admin/applications API\n */\ninterface RawApplication {\n uuid: string;\n name: string;\n type: string;\n is_active: boolean;\n description?: string;\n config?: {\n policy_template?: string;\n [key: string]: unknown;\n };\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Raw policy response from /v1/admin/policy/:uuid API\n */\ninterface RawPolicy {\n uuid: string;\n name: string;\n description?: string;\n policy?: {\n code_agent_security?: {\n enabled?: boolean;\n policy_cedar?: string;\n };\n [key: string]: unknown;\n };\n modified_at?: string;\n}\n\n/**\n * Admin API client for Guardian\n * Uses existing application and policy APIs from highflame-admin\n */\nexport class AdminClient {\n private baseUrl: string;\n private token: string;\n private timeout: number;\n\n constructor(\n baseUrl: string,\n token: string,\n timeout: number = DEFAULT_TIMEOUT,\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, \"\"); // Remove trailing slash\n this.token = token;\n this.timeout = timeout;\n\n logger.debug(\"Initialized\", {\n baseUrl: this.baseUrl,\n hasToken: !!token,\n timeout: this.timeout,\n });\n }\n\n /**\n * Record installation event\n * Called on first event from a new user/IDE combination\n */\n async recordInstallation(event: InstallationEvent): Promise<boolean> {\n const url = `${this.baseUrl}/v1/admin/guardian/installations`;\n\n logger.info(\"Recording installation\", {\n ide_type: event.ide_type,\n user_email: event.user_email,\n });\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-javelin-token\": this.token,\n },\n body: JSON.stringify(event),\n signal: AbortSignal.timeout(this.timeout),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n logger.error(\"Failed to record installation\", {\n status: response.status,\n error: errorText,\n });\n return false;\n }\n\n logger.info(\"Installation recorded successfully\");\n return true;\n } catch (error) {\n logger.error(\"Error recording installation\", {\n error: String(error),\n });\n return false;\n }\n }\n\n /**\n * Fetch code_agent applications using existing application API\n * GET /v1/admin/applications?type=code_agent\n */\n async getCodeAgentApplications(): Promise<CodeAgentApplication[]> {\n const url = `${this.baseUrl}/v1/admin/applications?type=code_agent`;\n\n logger.debug(\"Fetching code_agent applications\");\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-javelin-token\": this.token,\n },\n signal: AbortSignal.timeout(this.timeout),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n logger.error(\"Failed to fetch applications\", {\n status: response.status,\n error: errorText,\n });\n return [];\n }\n\n const data = await response.json();\n // Handle both array response and { applications: [...] } wrapper\n const rawApps: RawApplication[] = Array.isArray(data)\n ? (data as RawApplication[])\n : (data as { applications?: RawApplication[] }).applications || [];\n\n // Transform to CodeAgentApplication format\n const apps: CodeAgentApplication[] = rawApps.map((app) => ({\n uuid: app.uuid,\n name: app.name,\n type: app.type,\n is_active: app.is_active ?? true,\n ide_type: app.name, // Use app name as IDE type (cursor, claudecode, etc.)\n description: app.description,\n config: app.config,\n }));\n\n logger.info(`Fetched ${apps.length} code_agent applications`);\n return apps;\n } catch (error) {\n logger.error(\"Error fetching applications\", {\n error: String(error),\n });\n return [];\n }\n }\n\n /**\n * Fetch policy by UUID using existing policy API\n * GET /v1/admin/policy/:uuid\n */\n async getPolicyByUUID(policyUUID: string): Promise<RawPolicy | null> {\n const url = `${this.baseUrl}/v1/admin/policy/${policyUUID}`;\n\n logger.debug(\"Fetching policy\", { policyUUID });\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-javelin-token\": this.token,\n },\n signal: AbortSignal.timeout(this.timeout),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n logger.error(\"Failed to fetch policy\", {\n status: response.status,\n policyUUID,\n error: errorText,\n });\n return null;\n }\n\n const policy = (await response.json()) as RawPolicy;\n logger.info(\"Fetched policy\", {\n policyUUID,\n name: policy.name,\n });\n // Debug: log policy structure\n logger.debug(\"Policy structure\", {\n hasPolicy: !!policy.policy,\n hasCodeAgentSecurity: !!policy.policy?.code_agent_security,\n hasPolicyCedar: !!policy.policy?.code_agent_security?.policy_cedar,\n policyCedarLength:\n policy.policy?.code_agent_security?.policy_cedar?.length || 0,\n });\n return policy;\n } catch (error) {\n logger.error(\"Error fetching policy\", {\n policyUUID,\n error: String(error),\n });\n return null;\n }\n }\n\n /**\n * Get Cedar policy for a specific IDE type\n *\n * Flow:\n * 1. Fetch all code_agent applications\n * 2. Find app matching the IDE name (cursor, claudecode, etc.)\n * 3. Get policy_template UUID from app config\n * 4. Fetch policy by UUID\n * 5. Extract policy_cedar from policy.code_agent_security\n */\n async getCedarPolicyForIDE(\n ideType: string,\n ): Promise<RemoteCedarPolicy | null> {\n logger.debug(\"Getting Cedar policy for IDE\", { ideType });\n\n try {\n // Step 1: Fetch all code_agent applications\n const apps = await this.getCodeAgentApplications();\n if (apps.length === 0) {\n logger.warn(\"No code_agent applications found\");\n return null;\n }\n\n // Step 2: Find app matching IDE name\n const app = apps.find(\n (a) => a.name.toLowerCase() === ideType.toLowerCase() && a.is_active,\n );\n if (!app) {\n logger.debug(\"No application found for IDE\", {\n ideType,\n availableApps: apps.map((a) => a.name),\n });\n return null;\n }\n\n // Step 3: Get policy_template UUID from app config\n const policyTemplateUUID = app.config?.policy_template as\n | string\n | undefined;\n if (!policyTemplateUUID) {\n logger.debug(\"No policy_template in app config\", {\n ideType,\n appName: app.name,\n });\n return null;\n }\n\n // Step 4: Fetch policy by UUID\n const policy = await this.getPolicyByUUID(policyTemplateUUID);\n if (!policy) {\n logger.warn(\"Policy not found\", {\n policyUUID: policyTemplateUUID,\n });\n return null;\n }\n\n // Step 5: Extract policy_cedar from policy.code_agent_security\n const cedarPolicyContent =\n policy.policy?.code_agent_security?.policy_cedar;\n if (!cedarPolicyContent) {\n logger.debug(\"No policy_cedar in policy.code_agent_security\", {\n policyUUID: policyTemplateUUID,\n policyName: policy.name,\n });\n return null;\n }\n\n // Return formatted RemoteCedarPolicy\n const remoteCedarPolicy: RemoteCedarPolicy = {\n uuid: policy.uuid,\n name: policy.name,\n policy_content: cedarPolicyContent,\n application_id: app.uuid,\n ide_type: ideType,\n updated_at: policy.modified_at || new Date().toISOString(),\n };\n\n logger.info(\"Successfully fetched Cedar policy for IDE\", {\n ideType,\n policyName: policy.name,\n policyContentLength: cedarPolicyContent.length,\n });\n\n return remoteCedarPolicy;\n } catch (error) {\n logger.error(\"Error getting Cedar policy for IDE\", {\n ideType,\n error: String(error),\n });\n return null;\n }\n }\n\n /**\n * Fetch Cedar policies for all configured IDEs in one efficient call\n * Returns a map of IDE type to RemoteCedarPolicy\n *\n * This is more efficient than calling getCedarPolicyForIDE() multiple times\n * since it fetches applications only once.\n */\n async getAllIDEPolicies(): Promise<Map<string, RemoteCedarPolicy>> {\n const result = new Map<string, RemoteCedarPolicy>();\n\n logger.debug(\"Fetching all IDE policies\");\n\n try {\n // Step 1: Fetch all code_agent applications (only once!)\n const apps = await this.getCodeAgentApplications();\n if (apps.length === 0) {\n logger.debug(\"No code_agent applications found\");\n return result;\n }\n\n logger.debug(`Found ${apps.length} code_agent applications`);\n\n // Step 2: For each active app, fetch its policy\n for (const app of apps) {\n if (!app.is_active) continue;\n\n const policyTemplateUUID = app.config?.policy_template as\n | string\n | undefined;\n if (!policyTemplateUUID) {\n logger.debug(\"No policy_template for app\", {\n appName: app.name,\n });\n continue;\n }\n\n // Step 3: Fetch policy by UUID\n const policy = await this.getPolicyByUUID(policyTemplateUUID);\n if (!policy) continue;\n\n // Step 4: Extract policy_cedar from policy.code_agent_security\n const cedarPolicyContent =\n policy.policy?.code_agent_security?.policy_cedar;\n if (!cedarPolicyContent) {\n logger.debug(\"No policy_cedar in policy.code_agent_security\", {\n appName: app.name,\n policyName: policy.name,\n });\n continue;\n }\n\n // Step 5: Create RemoteCedarPolicy and add to result\n const remoteCedarPolicy: RemoteCedarPolicy = {\n uuid: policy.uuid,\n name: policy.name,\n policy_content: cedarPolicyContent,\n application_id: app.uuid,\n ide_type: app.name.toLowerCase(), // Use app name as IDE type\n updated_at: policy.modified_at || new Date().toISOString(),\n };\n\n result.set(app.name.toLowerCase(), remoteCedarPolicy);\n logger.info(\"Fetched policy for IDE\", {\n ide: app.name,\n policyName: policy.name,\n });\n }\n\n logger.info(`Fetched ${result.size} IDE policies`);\n return result;\n } catch (error) {\n logger.error(\"Error fetching IDE policies\", {\n error: String(error),\n });\n return result;\n }\n }\n\n /**\n * Health check - verify connection to admin API\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await fetch(\n `${this.baseUrl}/v1/admin/applications?type=code_agent&limit=1`,\n {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-javelin-token\": this.token,\n },\n signal: AbortSignal.timeout(5000), // Short timeout for health check\n },\n );\n\n const healthy = response.ok;\n logger.debug(`Health check: ${healthy ? \"OK\" : \"FAILED\"}`);\n return healthy;\n } catch (error) {\n logger.debug(\"Health check failed\", {\n error: String(error),\n });\n return false;\n }\n }\n}\n", "/**\n * Policy Manager for Guardian\n *\n * Manages Cedar policies with support for:\n * - Remote policy fetching from highflame-admin\n * - IDE-specific policy mapping (cursor, claudecode, github_copilot)\n * - Configurable polling for policy updates\n * - Local policy fallback when remote is unavailable\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { AdminClient } from \"../javelin/admin-client\";\nimport {\n PolicyEngine,\n createPolicyEngine,\n initPolicyEngine,\n} from \"./policy-engine\";\nimport { logger } from \"../utils\";\nimport {\n IDESource,\n RemoteCedarPolicy,\n PolicyMapping,\n PolicyMappingEntry,\n DEFAULT_REMOTE_POLICY_CONFIG,\n} from \"../types\";\n\n/**\n * PolicyManager handles remote policy fetching and local fallback\n * Maintains policy mapping per IDE source\n */\nexport class PolicyManager {\n private adminClient: AdminClient | null = null;\n private policyEngines: Map<IDESource, PolicyEngine> = new Map();\n private localPolicyEngine: PolicyEngine | undefined;\n private policyMapping: PolicyMapping = {};\n private pollTimer: NodeJS.Timeout | null = null;\n private pollIntervalMs: number;\n private _localPolicyPath: string | null = null; // Kept for debugging/status\n private initialized = false;\n private lastFetchTime: number = 0;\n\n constructor(\n pollIntervalMs: number = DEFAULT_REMOTE_POLICY_CONFIG.pollIntervalMs,\n ) {\n this.pollIntervalMs = pollIntervalMs;\n logger.debug(\"Created with poll interval\", {\n pollIntervalMs,\n });\n }\n\n /**\n * Initialize with admin client and local fallback\n */\n async init(\n baseUrl: string | null,\n token: string | null,\n localPolicyPath: string | null,\n ): Promise<void> {\n if (this.initialized) {\n logger.debug(\"Already initialized\");\n return;\n }\n\n // Initialize policy engine module first (loads @highflame/policy)\n await initPolicyEngine();\n\n // Initialize admin client if credentials provided\n if (baseUrl && token) {\n this.adminClient = new AdminClient(baseUrl, token);\n logger.info(\"Admin client initialized\", { baseUrl });\n } else {\n logger.info(\n \"[PolicyManager] No admin credentials, using local policy only\",\n );\n }\n\n // Initialize local policy engine as fallback\n this._localPolicyPath = localPolicyPath;\n if (localPolicyPath && fs.existsSync(localPolicyPath)) {\n try {\n this.localPolicyEngine = createPolicyEngine();\n if (this.localPolicyEngine) {\n this.localPolicyEngine.loadPoliciesFromFile(localPolicyPath);\n logger.info(\"Local policy loaded\", {\n path: localPolicyPath,\n });\n }\n } catch (error) {\n logger.error(\"Failed to load local policy\", {\n path: localPolicyPath,\n error: String(error),\n });\n }\n }\n\n // Fetch remote policies immediately\n await this.fetchRemotePolicies();\n\n this.initialized = true;\n logger.info(\"Initialized\", {\n hasAdminClient: !!this.adminClient,\n hasLocalPolicy: !!this.localPolicyEngine,\n remotePolicies: this.policyEngines.size,\n });\n }\n\n /**\n * Start polling for policy updates\n */\n startPolling(): void {\n if (!this.adminClient) {\n logger.warn(\"No admin client, skipping polling\");\n return;\n }\n\n if (this.pollTimer) {\n logger.debug(\"Already polling\");\n return;\n }\n\n logger.info(\"Starting policy polling\", {\n intervalMs: this.pollIntervalMs,\n intervalMin: Math.round(this.pollIntervalMs / 60000),\n });\n\n this.pollTimer = setInterval(async () => {\n try {\n await this.fetchRemotePolicies();\n } catch (error) {\n logger.error(\"Polling error\", { error: String(error) });\n }\n }, this.pollIntervalMs);\n }\n\n /**\n * Stop polling\n */\n stopPolling(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n logger.info(\"Polling stopped\");\n }\n }\n\n /**\n * Fetch remote policies and update engines\n */\n async fetchRemotePolicies(): Promise<void> {\n if (!this.adminClient) {\n logger.debug(\"No admin client, using local policy\");\n return;\n }\n\n try {\n logger.debug(\"Fetching remote policies...\");\n const startTime = Date.now();\n\n // Fetch all IDE policies in one efficient call (applications fetched only once)\n const policies = await this.adminClient.getAllIDEPolicies();\n let policiesUpdated = 0;\n\n // Update policy engines for each IDE\n for (const [ide, policy] of policies) {\n const updated = await this.updatePolicyForIDE(ide as IDESource, policy);\n if (updated) policiesUpdated++;\n }\n\n this.lastFetchTime = Date.now();\n const duration = this.lastFetchTime - startTime;\n\n logger.info(\"Remote policies fetched\", {\n duration: `${duration}ms`,\n policiesUpdated,\n totalEngines: this.policyEngines.size,\n });\n } catch (error) {\n logger.error(\"Failed to fetch remote policies\", {\n error: String(error),\n });\n }\n }\n\n /**\n * Update policy engine for specific IDE\n */\n private async updatePolicyForIDE(\n ide: IDESource,\n policy: RemoteCedarPolicy,\n ): Promise<boolean> {\n try {\n // Skip if policy content is empty\n if (!policy.policy_content || policy.policy_content.trim() === \"\") {\n logger.warn(\"Empty policy content for IDE\", { ide });\n return false;\n }\n\n // Check if policy has changed\n const existing = this.policyMapping[ide];\n if (existing && existing.policyContent === policy.policy_content) {\n logger.debug(\"Policy unchanged for IDE\", { ide });\n return false;\n }\n\n // Create temporary file with policy content\n const tempDir = path.join(os.tmpdir(), \"guardian-policies\");\n if (!fs.existsSync(tempDir)) {\n fs.mkdirSync(tempDir, { recursive: true });\n }\n\n const policyFile = path.join(tempDir, `${ide}-policy.cedar`);\n fs.writeFileSync(policyFile, policy.policy_content);\n\n // Create new policy engine and load\n const engine = createPolicyEngine();\n if (engine) {\n engine.loadPoliciesFromFile(policyFile);\n this.policyEngines.set(ide, engine);\n\n // Update mapping\n const entry: PolicyMappingEntry = {\n applicationId: policy.application_id || \"\",\n policyContent: policy.policy_content,\n lastUpdated: policy.updated_at,\n version: policy.version,\n };\n this.policyMapping[ide] = entry;\n\n logger.info(\"Updated policy for IDE\", {\n ide,\n policyName: policy.name,\n version: policy.version,\n });\n\n return true;\n }\n } catch (error) {\n logger.error(\"Failed to update policy for IDE\", {\n ide,\n error: String(error),\n });\n }\n\n return false;\n }\n\n /**\n * Get policy engine for IDE source\n * Falls back to local policy if no remote policy available\n */\n getEngineForIDE(ide: IDESource): PolicyEngine | undefined {\n // Check for IDE-specific remote policy first\n const remoteEngine = this.policyEngines.get(ide);\n if (remoteEngine) {\n logger.debug(\"Using remote policy for IDE\", { ide });\n return remoteEngine;\n }\n\n // Fall back to local policy\n if (this.localPolicyEngine) {\n logger.debug(\"Using local fallback policy for IDE\", {\n ide,\n });\n return this.localPolicyEngine;\n }\n\n logger.warn(\"No policy available for IDE\", { ide });\n return undefined;\n }\n\n /**\n * Get policy content for IDE source\n * Returns the Cedar policy string for parsing metadata\n */\n getPolicyContentForIDE(ide: IDESource): string | undefined {\n // Check for IDE-specific remote policy first\n const mapping = this.policyMapping[ide];\n if (mapping && mapping.policyContent) {\n return mapping.policyContent;\n }\n\n // Fall back to local policy file content\n if (this._localPolicyPath && fs.existsSync(this._localPolicyPath)) {\n try {\n return fs.readFileSync(this._localPolicyPath, \"utf-8\");\n } catch (error) {\n logger.error(\"Failed to read local policy content\", {\n path: this._localPolicyPath,\n error: String(error),\n });\n }\n }\n\n return undefined;\n }\n\n /**\n * Check if a specific IDE has remote policy\n */\n hasRemotePolicyForIDE(ide: IDESource): boolean {\n return this.policyEngines.has(ide);\n }\n\n /**\n * Get policy mapping info\n */\n getPolicyMapping(): PolicyMapping {\n return { ...this.policyMapping };\n }\n\n /**\n * Get last fetch time\n */\n getLastFetchTime(): number {\n return this.lastFetchTime;\n }\n\n /**\n * Get status information\n */\n getStatus(): {\n initialized: boolean;\n hasAdminClient: boolean;\n hasLocalPolicy: boolean;\n localPolicyPath: string | null;\n remotePolicies: string[];\n isPolling: boolean;\n lastFetchTime: number;\n } {\n return {\n initialized: this.initialized,\n hasAdminClient: !!this.adminClient,\n hasLocalPolicy: !!this.localPolicyEngine,\n localPolicyPath: this._localPolicyPath,\n remotePolicies: Array.from(this.policyEngines.keys()),\n isPolling: !!this.pollTimer,\n lastFetchTime: this.lastFetchTime,\n };\n }\n\n /**\n * Force refresh policies\n */\n async refreshPolicies(): Promise<void> {\n logger.info(\"Force refreshing policies\");\n await this.fetchRemotePolicies();\n }\n}\n", "/**\n * Policy Engine Loader\n *\n * Uses @highflame/policy npm package for Cedar policy evaluation.\n * The package uses @cedar-policy/cedar-wasm (WebAssembly) for cross-platform support.\n */\n\nimport * as fs from \"fs\";\nimport { logger } from \"../utils\";\n\n// Dynamic import for ESM module\nlet PolicyEngineClass: typeof import(\"@highflame/policy\").PolicyEngine | null =\n null;\nlet moduleLoadAttempted = false;\n\n/**\n * PolicyEngine interface matching the expected API\n */\nexport interface PolicyEngine {\n loadPoliciesFromFile(path: string): void;\n evaluate(\n principalType: string,\n principalId: string,\n action: string,\n resourceType: string,\n resourceId: string,\n context?: Record<string, unknown> | null,\n ): { effect: \"Allow\" | \"Deny\"; determining_policies: string[] };\n}\n\n/**\n * Wrapper class that adapts @highflame/policy API to our expected interface\n */\nclass PolicyEngineWrapper implements PolicyEngine {\n private engine: import(\"@highflame/policy\").PolicyEngine;\n\n constructor(engine: import(\"@highflame/policy\").PolicyEngine) {\n this.engine = engine;\n }\n\n loadPoliciesFromFile(filePath: string): void {\n const content = fs.readFileSync(filePath, \"utf-8\");\n this.engine.loadPolicies(content);\n this.engine.loadHighflameSchema();\n }\n\n evaluate(\n principalType: string,\n principalId: string,\n action: string,\n resourceType: string,\n resourceId: string,\n context?: Record<string, unknown> | null,\n ): { effect: \"Allow\" | \"Deny\"; determining_policies: string[] } {\n // Use evaluateSimple which matches our signature\n const decision = this.engine.evaluateSimple(\n principalType as import(\"@highflame/policy\").EntityType,\n principalId,\n action as import(\"@highflame/policy\").ActionType,\n resourceType as import(\"@highflame/policy\").EntityType,\n resourceId,\n context ?? undefined,\n );\n\n return {\n effect: decision.effect,\n determining_policies: decision.determining_policies,\n };\n }\n}\n\n/**\n * Load the PolicyEngine class from @highflame/policy\n */\nasync function loadPolicyEngineClass(): Promise<\n typeof import(\"@highflame/policy\").PolicyEngine | null\n> {\n if (moduleLoadAttempted) {\n return PolicyEngineClass;\n }\n\n moduleLoadAttempted = true;\n\n try {\n logger.debug(\"Loading @highflame/policy module...\");\n const module = await import(\"@highflame/policy\");\n PolicyEngineClass = module.PolicyEngine;\n logger.info(\"Successfully loaded @highflame/policy module\");\n return PolicyEngineClass;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(\"Failed to load @highflame/policy module\", {\n error: errorMessage,\n });\n return null;\n }\n}\n\n/**\n * Create a new PolicyEngine instance\n * Returns undefined if the module is not available\n *\n * Note: This function is async internally but returns synchronously for compatibility.\n * Call initPolicyEngine() first to ensure the module is loaded.\n */\nexport function createPolicyEngine(): PolicyEngine | undefined {\n if (!PolicyEngineClass) {\n logger.warn(\n \"PolicyEngine class not loaded. Call initPolicyEngine() first.\",\n );\n return undefined;\n }\n\n try {\n logger.debug(\"Creating PolicyEngine instance\");\n const engine = new PolicyEngineClass();\n const wrapper = new PolicyEngineWrapper(engine);\n logger.info(\"Successfully created PolicyEngine instance\");\n return wrapper;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n logger.error(\"Failed to create engine instance\", {\n error: errorMessage,\n stack: errorStack,\n });\n return undefined;\n }\n}\n\n/**\n * Initialize the policy engine module (async)\n * Must be called before createPolicyEngine()\n */\nexport async function initPolicyEngine(): Promise<boolean> {\n const cls = await loadPolicyEngineClass();\n return cls !== null;\n}\n\n/**\n * Check if the policy engine module is available\n */\nexport function isPolicyEngineAvailable(): boolean {\n return PolicyEngineClass !== null;\n}\n", "/**\n * MCP Scanner - Runs bundled ramparts binary for MCP config scanning\n *\n * Supports running ramparts as a child process for local YARA scanning\n * of MCP server configurations.\n *\n * Uses platform-loader for cross-platform binary discovery.\n */\n\nimport { spawn } from \"child_process\";\nimport * as fs from \"fs\";\nimport { logger } from \"./utils\";\nimport { getLLMConfig } from \"./config\";\n\n// Import platform loader (CommonJS module)\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst platformLoader = require(\"../lib/platform-loader\");\n\n/**\n * Scan result from ramparts CLI\n */\nexport interface ScanResult {\n scan_type: string;\n total_servers: number;\n results: ScanServerResult[];\n}\n\nexport interface ScanServerResult {\n server_name: string;\n url?: string;\n server_info?: {\n name?: string;\n metadata?: {\n transport?: string;\n };\n };\n tools?: unknown[];\n prompts?: unknown[];\n resources?: unknown[];\n security_issues?: {\n tool_issues?: unknown[];\n };\n yara_results?: YaraResult[];\n}\n\nexport interface YaraResult {\n status: \"ok\" | \"warning\" | \"error\";\n target_type?: string;\n rule_name?: string;\n rule_metadata?: {\n severity?: string;\n description?: string;\n };\n}\n\n/**\n * MCP Scanner that uses bundled ramparts binary\n */\nexport class MCPScanner {\n private rampartsPath: string | null = null;\n\n constructor() {\n this.rampartsPath = this.findRampartsBinary();\n }\n\n /**\n * Find the ramparts binary based on platform\n * Uses platform-loader for cross-platform discovery.\n *\n * Search order:\n * 1. Platform package (npm optionalDependency)\n * 2. Local bin/ directory (dev mode)\n * 3. ~/.overwatch/bin/\n * 4. System PATH\n */\n private findRampartsBinary(): string | null {\n // Check platform support\n if (!platformLoader.isPlatformSupported()) {\n const key = platformLoader.getPlatformKey();\n logger.warn(`Unsupported platform: ${key}`);\n return null;\n }\n\n // Use platform-loader for binary discovery\n const binaryPath = platformLoader.getRampartsBinaryPath();\n\n if (binaryPath) {\n logger.info(`Found ramparts at: ${binaryPath}`);\n return binaryPath;\n }\n\n logger.warn(\"ramparts binary not found\");\n logger.warn(platformLoader.getPlatformNotFoundMessage());\n return null;\n }\n\n /**\n * Check if scanner is available\n */\n isAvailable(): boolean {\n return this.rampartsPath !== null;\n }\n\n /**\n * Get the path to ramparts binary\n */\n getBinaryPath(): string | null {\n return this.rampartsPath;\n }\n\n /**\n * Run MCP config scan\n * @param rulesDir Optional custom YARA rules directory\n */\n async runScan(rulesDir?: string): Promise<ScanResult> {\n if (!this.rampartsPath) {\n throw new Error(\"ramparts binary not found\");\n }\n\n const args = [\"scan-config\", \"--format\", \"json\"];\n\n // Build environment\n const env: NodeJS.ProcessEnv = {\n ...process.env,\n JAVELIN_BYPASS: \"true\", // Skip Javelin checks during scan\n };\n\n // Set rules directory if provided\n if (rulesDir && fs.existsSync(rulesDir)) {\n env.RAMPARTS_RULES_DIR = rulesDir;\n logger.debug(`Using rules from: ${rulesDir}`);\n }\n\n // Set LLM API key for ramparts evaluation (if configured)\n const llmConfig = getLLMConfig();\n if (llmConfig?.apiKey) {\n env.LLM_API_KEY = llmConfig.apiKey;\n if (llmConfig.provider === \"openai\") {\n env.OPENAI_API_KEY = llmConfig.apiKey;\n } else if (llmConfig.provider === \"anthropic\") {\n env.ANTHROPIC_API_KEY = llmConfig.apiKey;\n }\n logger.debug(\n `LLM API key configured for ramparts (${llmConfig.provider || \"openai\"})`,\n );\n }\n\n logger.info(`Running: ${this.rampartsPath} ${args.join(\" \")}`);\n\n return new Promise((resolve, reject) => {\n const proc = spawn(this.rampartsPath!, args, {\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout?.on(\"data\", (data) => {\n stdout += data.toString();\n });\n\n proc.stderr?.on(\"data\", (data) => {\n stderr += data.toString();\n });\n\n proc.on(\"close\", (code) => {\n if (code !== 0) {\n logger.warn(`ramparts exited with code ${code}`);\n if (stderr) {\n logger.debug(`stderr: ${stderr}`);\n }\n }\n\n try {\n // Try to parse JSON output\n const result = this.parseOutput(stdout);\n resolve(result);\n } catch (error) {\n const errorMsg =\n error instanceof Error ? error.message : String(error);\n logger.error(`Failed to parse output: ${errorMsg}`);\n reject(new Error(`Failed to parse scan output: ${errorMsg}`));\n }\n });\n\n proc.on(\"error\", (err) => {\n logger.error(`Process error: ${err.message}`);\n reject(err);\n });\n\n // Timeout after 600 seconds\n setTimeout(() => {\n proc.kill();\n reject(new Error(\"Scan timed out after 600 seconds\"));\n }, 600000);\n });\n }\n\n /**\n * Parse ramparts CLI output\n * Handles cases where CLI prints banner/logs before JSON\n */\n private parseOutput(output: string): ScanResult {\n // 1. Try simple parse first\n try {\n return JSON.parse(output);\n } catch {\n // Continue to regex extraction\n }\n\n // 2. Remove ANSI codes\n const cleanOutput = output.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n\n // 3. Find specific keys to locate the JSON block\n let searchIndex = cleanOutput.indexOf('\"scan_type\"');\n if (searchIndex === -1) {\n searchIndex = cleanOutput.indexOf('\"results\"');\n }\n\n if (searchIndex === -1) {\n logger.warn(\"Could not find JSON content in output\");\n return this.getEmptyResult();\n }\n\n // 4. Find the opening brace preceding the key\n let startIndex = -1;\n for (let i = searchIndex; i >= 0; i--) {\n if (cleanOutput[i] === \"{\") {\n startIndex = i;\n break;\n }\n }\n\n if (startIndex !== -1) {\n // 5. Use brace counting to find the matching closing brace\n let braceCount = 0;\n let endIndex = -1;\n\n for (let i = startIndex; i < cleanOutput.length; i++) {\n if (cleanOutput[i] === \"{\") braceCount++;\n else if (cleanOutput[i] === \"}\") braceCount--;\n\n if (braceCount === 0) {\n endIndex = i + 1;\n break;\n }\n }\n\n if (endIndex !== -1) {\n const jsonStr = cleanOutput.substring(startIndex, endIndex);\n try {\n return JSON.parse(jsonStr);\n } catch (error) {\n logger.warn(`Failed to parse extracted JSON: $Failed to edit, 0 occurrences found for old_string ( /**\n * Parse ramparts CLI output\n * Handles cases where CLI prints banner/logs before JSON\n */\n private parseOutput(output: string): ScanResult {\n // 1. Try simple parse first\n try {\n return JSON.parse(output);\n } catch {\n // Continue to regex extraction\n }\n\n // 2. Remove ANSI codes\n const cleanOutput = output.replace(/\\x1b\\[[0-9;]*m/g, '');\n\n // 3. Regex to find JSON object\n // We specifically look for our known fields to be safer\n // Matches { ... \"scan_type\": ... } or { ... \"results\": ... }\n // Using [\\s\\S] instead of . with s flag for compatibility\n const jsonRegex = /\\{(?:[^{}]|@)*\"(?:scan_type|results)\"(?:[^{}]|@)*\\}/;\n const match = cleanOutput.match(jsonRegex);\n\n if (match) {\n try {\n const result = JSON.parse(match[0]);\n if (result.scan_type || result.results) {\n return result;\n }\n } catch {\n // Parsing failed\n }\n }\n\n // Return empty result if parsing fails\n logger.warn('Could not parse JSON, returning empty result');\n return {\n scan_type: 'mcp_config',\n total_servers: 0,\n results: [],\n };\n }\n}\n). Original old_string was ( /**\n * Parse ramparts CLI output\n * Handles cases where CLI prints banner/logs before JSON\n */\n private parseOutput(output: string): ScanResult {\n // 1. Try simple parse first\n try {\n return JSON.parse(output);\n } catch {\n // Continue to regex extraction\n }\n\n // 2. Remove ANSI codes\n const cleanOutput = output.replace(/\\x1b\\[[0-9;]*m/g, '');\n\n // 3. Regex to find JSON object\n // We specifically look for our known fields to be safer\n // Matches { ... \"scan_type\": ... } or { ... \"results\": ... }\n // Using [\\s\\S] instead of . with s flag for compatibility\n const jsonRegex = /\\{(?:[^{}]|@)*\"(?:scan_type|results)\"(?:[^{}]|@)*\\}/;\n const match = cleanOutput.match(jsonRegex);\n\n if (match) {\n try {\n const result = JSON.parse(match[0]);\n if (result.scan_type || result.results) {\n return result;\n }\n } catch {\n // Parsing failed\n }\n }\n\n // Return empty result if parsing fails\n logger.warn('Could not parse JSON, returning empty result');\n return {\n scan_type: 'mcp_config',\n total_servers: 0,\n results: [],\n };\n }\n}\n) in /Users/abhishek/office/javelin-rampart/packages/guardian/src/scanner.ts. No edits made. The exact text in old_string was not found. Ensure you're not escaping content incorrectly and check whitespace, indentation, and context. Use read_file tool to verify.`);\n }\n }\n }\n\n // Return empty result if parsing fails\n logger.warn(\"Could not parse JSON, returning empty result\");\n return this.getEmptyResult();\n }\n\n private getEmptyResult(): ScanResult {\n return {\n scan_type: \"mcp_config\",\n total_servers: 0,\n results: [],\n };\n }\n}\n", "/**\n * YARA Engine - Native YARA pattern matching using @litko/yara-x\n *\n * Provides local YARA scanning for content validation without\n * requiring external binaries.\n */\n\nimport { compile, type YaraX, type RuleMatch } from \"@litko/yara-x\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { logger } from \"../utils\";\n\n/**\n * Individual pattern match data from YARA\n */\nexport interface YaraMatchData {\n identifier: string; // Pattern name (e.g., \"$shell_separators\")\n data: string; // Actual matched content\n offset: number; // Position in input\n length: number; // Size of match\n}\n\nexport interface YaraMatch {\n rule: string;\n namespace?: string;\n severity: string;\n category: string;\n description?: string;\n metadata?: Record<string, unknown>;\n tags?: string[];\n matches?: YaraMatchData[]; // Individual pattern matches with positions\n}\n\n/**\n * YARA Engine - compiles and runs YARA rules\n */\nexport class YaraEngine {\n private rules: YaraX | null = null;\n private rulesLoaded = false;\n private rulesCount = 0;\n\n /**\n * Load and compile YARA rules from a directory\n */\n async loadRules(rulesDir: string): Promise<void> {\n const startTime = Date.now();\n\n try {\n // Check if directory exists\n if (!fs.existsSync(rulesDir)) {\n logger.warn(`Rules directory not found: ${rulesDir}`);\n return;\n }\n\n // Read all .yar files\n const ruleFiles = fs\n .readdirSync(rulesDir)\n .filter((f) => f.endsWith(\".yar\"))\n .map((f) => path.join(rulesDir, f));\n\n if (ruleFiles.length === 0) {\n logger.warn(`No .yar files found in ${rulesDir}`);\n return;\n }\n\n // Concatenate all rule contents\n const ruleContent = ruleFiles\n .map((f) => {\n try {\n return fs.readFileSync(f, \"utf-8\");\n } catch (e) {\n logger.warn(`Failed to read ${f}:`, e);\n return \"\";\n }\n })\n .filter((content) => content.length > 0)\n .join(\"\\n\\n\");\n\n if (!ruleContent) {\n logger.warn(\"No rule content to compile\");\n return;\n }\n\n // Compile rules\n this.rules = compile(ruleContent);\n this.rulesLoaded = true;\n this.rulesCount = ruleFiles.length;\n\n logger.info(\n `[YaraEngine] Loaded ${ruleFiles.length} rule files in ${Date.now() - startTime}ms`,\n );\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to load rules: ${errorMsg}`);\n // Don't throw - fail gracefully\n this.rulesLoaded = false;\n }\n }\n\n /**\n * Check if engine is ready for scanning\n */\n isReady(): boolean {\n return this.rulesLoaded && this.rules !== null;\n }\n\n /**\n * Get number of loaded rule files\n */\n getRulesCount(): number {\n return this.rulesCount;\n }\n\n /**\n * Scan content synchronously\n */\n scan(content: string): YaraMatch[] {\n if (!this.rules) {\n return [];\n }\n\n try {\n const buffer = Buffer.from(content, \"utf-8\");\n const matches = this.rules.scan(buffer);\n return this.parseMatches(matches);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`Scan failed: ${errorMsg}`);\n return [];\n }\n }\n\n /**\n * Scan content asynchronously (for large content)\n */\n async scanAsync(content: string): Promise<YaraMatch[]> {\n if (!this.rules) {\n return [];\n }\n\n try {\n const buffer = Buffer.from(content, \"utf-8\");\n const matches = await this.rules.scanAsync(buffer);\n return this.parseMatches(matches);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`Async scan failed: ${errorMsg}`);\n return [];\n }\n }\n\n /**\n * Parse raw matches into structured format\n */\n private parseMatches(matches: RuleMatch[]): YaraMatch[] {\n return matches.map((match) => {\n const meta = match.meta as Record<string, unknown> | undefined;\n\n // Extract individual pattern matches from YARA-X\n const patternMatches: YaraMatchData[] = [];\n if (match.matches && Array.isArray(match.matches)) {\n for (const m of match.matches) {\n patternMatches.push({\n identifier: m.identifier || \"unknown\",\n data: typeof m.data === \"string\" ? m.data : String(m.data || \"\"),\n offset: typeof m.offset === \"number\" ? m.offset : 0,\n length: typeof m.length === \"number\" ? m.length : 0,\n });\n }\n }\n\n return {\n rule: match.ruleIdentifier || \"unknown\",\n namespace: match.namespace,\n severity: String(meta?.severity || \"medium\").toLowerCase(),\n category: String(meta?.category || \"unknown\"),\n description: meta?.description ? String(meta.description) : undefined,\n metadata: meta,\n tags: match.tags,\n matches: patternMatches.length > 0 ? patternMatches : undefined,\n };\n });\n }\n}\n", "import { YaraEngine as CoreYaraEngine, YaraMatchData } from \"../yara\";\nimport { DetectionResult, GuardrailResult } from \"../types\";\nimport { logger } from \"../utils\";\n\n/**\n * Truncate content for fallback matched_content field\n */\nfunction truncateContent(content: string, maxLength: number = 200): string {\n if (content.length <= maxLength) return content;\n return content.substring(0, maxLength) + \"...\";\n}\n\n/**\n * Build matched content string with context around the actual match\n * Shows the first match with surrounding context for clarity\n */\nfunction buildMatchedContent(\n content: string,\n matches?: YaraMatchData[],\n): string {\n if (!matches || matches.length === 0) {\n return truncateContent(content);\n }\n\n // Show first match with context (30 chars before and after)\n const firstMatch = matches[0];\n const contextPadding = 30;\n const contextStart = Math.max(0, firstMatch.offset - contextPadding);\n const contextEnd = Math.min(\n content.length,\n firstMatch.offset + firstMatch.length + contextPadding,\n );\n const context = content.substring(contextStart, contextEnd);\n\n // Add ellipsis indicators for truncation\n const prefix = contextStart > 0 ? \"...\" : \"\";\n const suffix = contextEnd < content.length ? \"...\" : \"\";\n\n return prefix + context + suffix;\n}\n\n/**\n * Extract unique pattern identifiers that triggered the match\n */\nfunction getMatchedPatterns(matches?: YaraMatchData[]): string[] | undefined {\n if (!matches || matches.length === 0) return undefined;\n return [...new Set(matches.map((m) => m.identifier))];\n}\n\n/**\n * Get match location from first pattern match\n */\nfunction getMatchLocation(\n matches?: YaraMatchData[],\n): { offset: number; length: number } | undefined {\n if (!matches || matches.length === 0) return undefined;\n const firstMatch = matches[0];\n return {\n offset: firstMatch.offset,\n length: firstMatch.length,\n };\n}\n\nexport class YaraExecutor {\n constructor(private engine: CoreYaraEngine) {}\n\n /**\n * Run YARA scan on content\n * Returns DetectionResult (no decision field - that's for Cedar)\n */\n async run(content: string): Promise<DetectionResult> {\n const startTime = Date.now();\n\n if (!this.engine.isReady()) {\n return {\n engine: \"yara-local\",\n called: false,\n duration_ms: 0,\n findings: [],\n error: \"YARA engine not ready\",\n };\n }\n\n try {\n const matches = this.engine.scan(content);\n\n // Build enhanced findings with actual matched content and patterns\n const findings: GuardrailResult[] = matches.map((m) => ({\n rule: m.rule,\n namespace: m.namespace,\n severity: m.severity || \"medium\",\n message: m.description || `YARA rule matched: ${m.rule}`,\n category: m.category || \"unknown\",\n\n // Actual matched content with context (not truncated input)\n matched_content: buildMatchedContent(content, m.matches),\n\n // Pattern identifiers that triggered the rule\n matched_patterns: getMatchedPatterns(m.matches),\n\n // Location info (offset and length from first match)\n match_location: getMatchLocation(m.matches),\n\n // Existing fields\n reference: m.metadata?.reference\n ? String(m.metadata.reference)\n : undefined,\n confidence: m.metadata?.confidence\n ? String(m.metadata.confidence)\n : \"medium\",\n\n metadata: m.metadata,\n tags: m.tags,\n }));\n\n return {\n engine: \"yara-local\",\n called: true,\n duration_ms: Date.now() - startTime,\n findings,\n raw_response: matches, // Include raw YARA matches for debugging\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(`Scan failed:`, { error: errorMessage });\n\n return {\n engine: \"yara-local\",\n called: true,\n duration_ms: Date.now() - startTime,\n findings: [],\n error: errorMessage,\n };\n }\n }\n}\n", "import { JavelinClient } from \"../javelin\";\nimport { DetectionResult, GuardrailResult, IDESource } from \"../types\";\nimport { logger } from \"../utils\";\n\n/**\n * Callback to resolve application ID from IDE source\n */\nexport type ApplicationIdResolver = (source: IDESource) => string | null;\n\nexport class RemoteExecutor {\n private applicationIdResolver: ApplicationIdResolver | null = null;\n\n constructor(\n private clients: Map<IDESource, JavelinClient>,\n applicationIdResolver?: ApplicationIdResolver,\n ) {\n this.applicationIdResolver = applicationIdResolver || null;\n }\n\n /**\n * Update the application ID resolver\n */\n setApplicationIdResolver(resolver: ApplicationIdResolver): void {\n this.applicationIdResolver = resolver;\n }\n\n /**\n * Run remote guardrails validation\n * Returns DetectionResult (no decision field - that's for Cedar)\n */\n async run(\n source: IDESource,\n content: string,\n event: string,\n guardrailConfig: string,\n metadata: Record<string, unknown>,\n ): Promise<DetectionResult> {\n const client = this.clients.get(source);\n\n if (!client) {\n return {\n engine: \"javelin-remote\",\n called: false,\n duration_ms: 0,\n findings: [],\n error: `No client configured for ${source}`,\n };\n }\n\n const startTime = Date.now();\n\n // Resolve application ID for this IDE\n const applicationId = this.applicationIdResolver\n ? this.applicationIdResolver(source)\n : null;\n\n try {\n const result = await client.validateWithGuardrails(\n guardrailConfig,\n content,\n { hookEvent: event, source, ...metadata },\n applicationId || undefined,\n );\n\n // Build enhanced findings from remote response\n const findings: GuardrailResult[] =\n result.results?.findings?.map(\n (f: { severity?: string; type?: string; message?: string }) => ({\n rule: f.type || \"unknown\",\n severity: f.severity || \"medium\",\n message: f.message || `Remote guardrail triggered: ${f.type}`,\n category: \"remote-guardrail\",\n confidence: \"high\", // Remote guardrails are high confidence\n }),\n ) || [];\n\n return {\n engine: \"javelin-remote\",\n called: true,\n duration_ms: Date.now() - startTime,\n findings,\n raw_response: result, // Include full API response for debugging\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(`Failed:`, { error: errorMessage });\n\n return {\n engine: \"javelin-remote\",\n called: true,\n duration_ms: Date.now() - startTime,\n findings: [],\n error: errorMessage,\n };\n }\n }\n}\n", "import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { logger } from \"../utils\";\n\nconst MAX_RETRIES = 5;\nconst RETRY_INTERVAL_MS = 30000;\n\ninterface PendingRecord<T> {\n record: T;\n retryCount: number;\n}\n\n/**\n * Callback to resolve application ID from a record\n * Returns the application UUID for the x-javelin-application header\n */\nexport type ApplicationIdResolver<T> = (record: T) => string | null;\n\n/**\n * Generic admin API ingestor with retry support\n * Sends records to configurable admin API endpoints\n */\nexport class AdminIngestor<T> {\n private baseUrl: string;\n private token: string;\n private endpoint: string;\n private pendingFile: string;\n private deadLetterFile: string;\n private retryTimer: NodeJS.Timeout | null = null;\n private applicationIdResolver: ApplicationIdResolver<T> | null = null;\n\n constructor(\n baseUrl: string,\n token: string,\n endpoint: string,\n applicationIdResolver?: ApplicationIdResolver<T>,\n ) {\n this.baseUrl = baseUrl;\n this.token = token;\n this.endpoint = endpoint;\n this.applicationIdResolver = applicationIdResolver || null;\n this.pendingFile = path.join(\n os.homedir(),\n \".overwatch\",\n `pending-${endpoint}.jsonl`,\n );\n this.deadLetterFile = path.join(\n os.homedir(),\n \".overwatch\",\n `dead-letter-${endpoint}.jsonl`,\n );\n\n logger.info(`Initialized`, {\n baseUrl: this.baseUrl,\n endpoint: this.endpoint,\n hasToken: !!this.token,\n tokenLength: this.token?.length || 0,\n pendingFile: this.pendingFile,\n deadLetterFile: this.deadLetterFile,\n });\n }\n\n start(): void {\n if (this.retryTimer) {\n logger.debug(\"Already started\");\n return;\n }\n logger.info(\"Starting\", {\n retryIntervalMs: RETRY_INTERVAL_MS,\n });\n this.processQueue();\n this.retryTimer = setInterval(() => this.processQueue(), RETRY_INTERVAL_MS);\n }\n\n stop(): void {\n if (this.retryTimer) {\n logger.info(\"Stopping\");\n clearInterval(this.retryTimer);\n this.retryTimer = null;\n }\n }\n\n /** Fire-and-forget record ingestion */\n ingest(record: T): void {\n const recordObj = record as Record<string, unknown>;\n logger.debug(\"Ingesting record\", {\n recordSize: JSON.stringify(record).length,\n recordKeys: Object.keys(recordObj),\n hasResults: \"results\" in recordObj,\n resultsType: recordObj.results\n ? Array.isArray(recordObj.results)\n ? \"array\"\n : typeof recordObj.results\n : \"missing\",\n resultsLength: Array.isArray(recordObj.results)\n ? recordObj.results.length\n : \"N/A\",\n });\n this.send(record).catch((error) => {\n logger.warn(\n `[AdminIngestor:${this.endpoint}] Initial send failed, saving for retry`,\n {\n error: String(error),\n errorMessage: error?.message,\n },\n );\n this.saveForRetry(record, 0);\n });\n }\n\n private async send(record: T): Promise<void> {\n const url = `${this.baseUrl}/v1/admin/guardian/${this.endpoint}`;\n const body = JSON.stringify(record);\n\n // Resolve application ID if resolver is provided\n const applicationId = this.applicationIdResolver\n ? this.applicationIdResolver(record)\n : null;\n\n logger.debug(\"Sending record\", {\n url,\n method: \"POST\",\n bodySize: body.length,\n hasToken: !!this.token,\n hasApplicationId: !!applicationId,\n });\n\n // Build headers\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-javelin-token\": this.token,\n };\n\n // Add application ID header if available\n if (applicationId) {\n headers[\"x-javelin-application\"] = applicationId;\n }\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(30000),\n });\n\n if (!res.ok) {\n const errorText = await res.text().catch(() => \"\");\n logger.error(\"Send failed\", {\n status: res.status,\n statusText: res.statusText,\n errorBody: errorText.substring(0, 200),\n url,\n });\n throw new Error(`${res.status} ${res.statusText}`);\n }\n\n logger.info(\"Successfully sent record\", {\n status: res.status,\n url,\n });\n } catch (error) {\n const errorObj = error as Error;\n logger.error(\"Send error\", {\n error: String(error),\n errorMessage: errorObj?.message,\n errorName: errorObj?.name,\n url,\n });\n throw error;\n }\n }\n\n private saveForRetry(record: T, retryCount: number): void {\n try {\n this.ensureDir(this.pendingFile);\n fs.appendFileSync(\n this.pendingFile,\n JSON.stringify({ record, retryCount }) + \"\\n\",\n );\n logger.info(\"Saved record for retry\", {\n retryCount,\n pendingFile: this.pendingFile,\n });\n } catch (e) {\n logger.error(\n `[AdminIngestor:${this.endpoint}] Failed to save for retry`,\n {\n error: String(e),\n retryCount,\n pendingFile: this.pendingFile,\n },\n );\n }\n }\n\n private async processQueue(): Promise<void> {\n if (!fs.existsSync(this.pendingFile)) {\n logger.debug(\n `[AdminIngestor:${this.endpoint}] No pending file, skipping queue processing`,\n );\n return;\n }\n\n const pending = this.loadPending();\n if (pending.length === 0) {\n logger.debug(\n `[AdminIngestor:${this.endpoint}] No pending records to process`,\n );\n return;\n }\n\n logger.info(\"Processing queue\", {\n pendingCount: pending.length,\n });\n\n const remaining: PendingRecord<T>[] = [];\n\n for (const item of pending) {\n try {\n logger.debug(\"Retrying record\", {\n retryCount: item.retryCount,\n });\n await this.send(item.record);\n logger.info(\n `[AdminIngestor:${this.endpoint}] Successfully retried record`,\n {\n retryCount: item.retryCount,\n },\n );\n } catch (e) {\n const newRetryCount = item.retryCount + 1;\n if (newRetryCount >= MAX_RETRIES) {\n logger.error(\n `[AdminIngestor:${this.endpoint}] Max retries reached, moving to dead letter`,\n {\n retryCount: item.retryCount,\n maxRetries: MAX_RETRIES,\n error: String(e),\n },\n );\n this.moveToDeadLetter(item, String(e));\n } else {\n logger.warn(\n `[AdminIngestor:${this.endpoint}] Retry failed, will retry again`,\n {\n retryCount: item.retryCount,\n newRetryCount,\n maxRetries: MAX_RETRIES,\n error: String(e),\n },\n );\n remaining.push({ record: item.record, retryCount: newRetryCount });\n }\n }\n }\n\n if (remaining.length > 0) {\n logger.info(\n `[AdminIngestor:${this.endpoint}] Queue processing complete, ${remaining.length} records remaining`,\n {\n remainingCount: remaining.length,\n processedCount: pending.length - remaining.length,\n },\n );\n } else {\n logger.info(\n `[AdminIngestor:${this.endpoint}] Queue processing complete, all records processed`,\n {\n processedCount: pending.length,\n },\n );\n }\n\n this.savePending(remaining);\n }\n\n private loadPending(): PendingRecord<T>[] {\n try {\n const content = fs.readFileSync(this.pendingFile, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n try {\n return JSON.parse(line);\n } catch {\n return null;\n }\n })\n .filter(Boolean);\n } catch {\n return [];\n }\n }\n\n private savePending(items: PendingRecord<T>[]): void {\n try {\n if (items.length === 0) {\n if (fs.existsSync(this.pendingFile)) fs.unlinkSync(this.pendingFile);\n } else {\n fs.writeFileSync(\n this.pendingFile,\n items.map((i) => JSON.stringify(i)).join(\"\\n\") + \"\\n\",\n );\n }\n } catch (e) {\n logger.error(\"Failed to save pending\", {\n error: String(e),\n });\n }\n }\n\n private moveToDeadLetter(item: PendingRecord<T>, reason: string): void {\n try {\n this.ensureDir(this.deadLetterFile);\n fs.appendFileSync(\n this.deadLetterFile,\n JSON.stringify({\n ...item,\n reason,\n failedAt: new Date().toISOString(),\n }) + \"\\n\",\n );\n logger.error(\n `[AdminIngestor:${this.endpoint}] Moved record to dead letter`,\n {\n retryCount: item.retryCount,\n reason,\n deadLetterFile: this.deadLetterFile,\n },\n );\n } catch (e) {\n logger.error(\n `[AdminIngestor:${this.endpoint}] Failed to write dead letter`,\n {\n error: String(e),\n deadLetterFile: this.deadLetterFile,\n },\n );\n }\n }\n\n private ensureDir(filePath: string): void {\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n }\n}\n", "import { PolicyEngine } from \"../lib/policy-engine\";\nimport { PolicyDecision, PolicyMetadata, CedarRequestContext } from \"../types\";\nimport { logger } from \"../utils\";\n\nexport interface CedarContext {\n principalType: string;\n principalId: string;\n action: string;\n resourceType: string;\n resourceId: string;\n contextData: Record<string, unknown>;\n}\n\n/**\n * Threat context passed to Cedar for decision making\n */\nexport interface ThreatContext {\n threats_detected: number;\n highest_severity: string;\n categories: string[];\n}\n\n/**\n * Parse Cedar policy content to extract policy metadata from comments.\n * Cedar uses @compliance_id, @description, @severity, @category, @frameworks annotations.\n *\n * Returns a mapping from policy index (policy0, policy1, etc.) to PolicyMetadata.\n */\nexport function parsePolicyContent(\n policyContent: string,\n): Record<string, PolicyMetadata> {\n const policyMetadata: Record<string, PolicyMetadata> = {};\n\n // Split content into lines for parsing\n const lines = policyContent.split(\"\\n\");\n\n // Track current metadata being collected\n let currentMetadata: Partial<PolicyMetadata> = {};\n let policyIndex = 0;\n\n // Regex patterns for annotations\n const complianceIdPattern = /@compliance_id:\\s*\"([^\"]+)\"/;\n const descriptionPattern = /@description:\\s*\"([^\"]+)\"/;\n const severityPattern = /@severity:\\s*(\\w+)/;\n const categoryPattern = /@category:\\s*\"([^\"]+)\"/;\n const frameworksPattern = /@frameworks:\\s*\\[([^\\]]+)\\]/;\n const nistPattern = /@nist:\\s*(.+)/;\n const owaspPattern = /@owasp:\\s*(.+)/;\n const mitrePattern = /@mitre:\\s*(.+)/;\n const cisPattern = /@cis:\\s*(.+)/;\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n\n // Check for annotation comments\n if (trimmedLine.startsWith(\"//\")) {\n const commentContent = trimmedLine.substring(2).trim();\n\n // Extract compliance_id\n const complianceMatch = commentContent.match(complianceIdPattern);\n if (complianceMatch) {\n currentMetadata.id = complianceMatch[1];\n }\n\n // Extract description\n const descMatch = commentContent.match(descriptionPattern);\n if (descMatch) {\n currentMetadata.description = descMatch[1];\n }\n\n // Extract severity\n const severityMatch = commentContent.match(severityPattern);\n if (severityMatch) {\n currentMetadata.severity = severityMatch[1];\n }\n\n // Extract category\n const categoryMatch = commentContent.match(categoryPattern);\n if (categoryMatch) {\n currentMetadata.category = categoryMatch[1];\n }\n\n // Extract frameworks array\n const frameworksMatch = commentContent.match(frameworksPattern);\n if (frameworksMatch) {\n const frameworksStr = frameworksMatch[1];\n currentMetadata.frameworks = frameworksStr\n .split(\",\")\n .map((f) => f.trim().replace(/\"/g, \"\"))\n .filter((f) => f.length > 0);\n }\n\n // Also extract individual framework annotations and add to frameworks\n const extractFramework = (\n pattern: RegExp,\n prefix: string,\n content: string,\n ) => {\n const match = content.match(pattern);\n if (match) {\n const values = match[1]\n .split(\",\")\n .map((v) => v.trim())\n .filter((v) => v.length > 0);\n if (!currentMetadata.frameworks) {\n currentMetadata.frameworks = [];\n }\n // Extract the reference ID from formats like \"AC-3 (Access Enforcement)\"\n for (const val of values) {\n const refMatch = val.match(/^([A-Z0-9.-]+)/);\n if (refMatch) {\n currentMetadata.frameworks.push(`${prefix}:${refMatch[1]}`);\n }\n }\n }\n };\n\n extractFramework(nistPattern, \"NIST-800-53\", commentContent);\n extractFramework(owaspPattern, \"OWASP\", commentContent);\n extractFramework(mitrePattern, \"MITRE-ATT&CK\", commentContent);\n extractFramework(cisPattern, \"CIS\", commentContent);\n }\n\n // Check for policy definition (permit or forbid)\n if (trimmedLine.startsWith(\"permit\") || trimmedLine.startsWith(\"forbid\")) {\n // If we have collected metadata with a compliance_id, save it\n if (currentMetadata.id) {\n const policyKey = `policy${policyIndex}`;\n\n // Deduplicate frameworks\n if (currentMetadata.frameworks) {\n currentMetadata.frameworks = [...new Set(currentMetadata.frameworks)];\n }\n\n policyMetadata[policyKey] = {\n id: currentMetadata.id,\n description: currentMetadata.description || \"No description available\",\n severity: currentMetadata.severity || \"MEDIUM\",\n category: currentMetadata.category || \"security\",\n frameworks: currentMetadata.frameworks,\n };\n\n // Also store by compliance_id for direct lookup\n policyMetadata[currentMetadata.id] = policyMetadata[policyKey];\n }\n\n // Move to next policy and reset metadata\n policyIndex++;\n currentMetadata = {};\n }\n }\n\n return policyMetadata;\n}\n\n/**\n * Build human-readable reason for decision\n */\nfunction buildDecisionReason(\n effect: string,\n threatContext: ThreatContext,\n determining_policies: string[],\n policyMetadata: Record<string, PolicyMetadata>,\n): string {\n if (effect === \"Deny\") {\n // Get descriptions from parsed metadata if available\n const descriptions: string[] = [];\n for (const id of determining_policies) {\n if (policyMetadata[id]?.description) {\n descriptions.push(policyMetadata[id].description);\n }\n }\n\n const policyPart = descriptions.length > 0\n ? descriptions.join(\"; \")\n : `policy: ${determining_policies.join(\", \")}`;\n\n if (threatContext.threats_detected > 0) {\n return `Blocked: ${threatContext.threats_detected} threat(s) detected (${threatContext.highest_severity} severity) - ${policyPart}`;\n }\n return `Blocked: ${policyPart}`;\n }\n\n if (threatContext.threats_detected > 0) {\n return `Allowed with ${threatContext.threats_detected} threat(s) logged for monitoring`;\n }\n return \"No threats detected; request allowed\";\n}\n\n/**\n * Get policy details for the given policy IDs from parsed metadata\n */\nfunction getPolicyDetails(\n policyIds: string[],\n policyMetadata: Record<string, PolicyMetadata>,\n): Record<string, PolicyMetadata> | undefined {\n const details: Record<string, PolicyMetadata> = {};\n let hasAny = false;\n\n for (const id of policyIds) {\n if (policyMetadata[id]) {\n details[id] = policyMetadata[id];\n hasAny = true;\n }\n }\n\n return hasAny ? details : undefined;\n}\n\nexport class CedarExecutor {\n private policyMetadata: Record<string, PolicyMetadata> = {};\n\n constructor(\n private engine: PolicyEngine | undefined,\n policyContent?: string,\n ) {\n // Parse policy content to extract metadata if provided\n if (policyContent) {\n this.policyMetadata = parsePolicyContent(policyContent);\n logger.debug(\"Parsed policy metadata\", {\n policyCount: Object.keys(this.policyMetadata).length,\n });\n }\n }\n\n /**\n * Update policy metadata (e.g., when policy content changes)\n */\n updatePolicyContent(policyContent: string): void {\n this.policyMetadata = parsePolicyContent(policyContent);\n logger.debug(\"Updated policy metadata\", {\n policyCount: Object.keys(this.policyMetadata).length,\n });\n }\n\n isAvailable(): boolean {\n return !!this.engine;\n }\n\n /**\n * Run Cedar policy evaluation\n * Returns PolicyDecision (separate from detection results)\n */\n async run(\n ctx: CedarContext,\n threatContext: ThreatContext,\n ): Promise<PolicyDecision> {\n if (!this.engine) {\n return {\n engine: \"cedar-policy\",\n called: false,\n duration_ms: 0,\n effect: \"allow\",\n reason: \"Cedar engine not initialized - allowing by default\",\n determining_policies: [],\n context_used: threatContext,\n error: \"Cedar engine not initialized\",\n };\n }\n\n const startTime = Date.now();\n\n try {\n const decision = this.engine.evaluate(\n ctx.principalType,\n ctx.principalId,\n ctx.action,\n ctx.resourceType,\n ctx.resourceId,\n ctx.contextData,\n );\n\n // Parse decision from native binding\n const effect = (decision as any).effect; // \"Allow\" | \"Deny\"\n const determining_policies = (decision as any).determining_policies || [];\n\n // Build request context for diagnostics\n const requestContext: CedarRequestContext = {\n principal: {\n type: ctx.principalType,\n id: ctx.principalId,\n },\n action: ctx.action,\n resource: {\n type: ctx.resourceType,\n id: ctx.resourceId,\n },\n };\n\n return {\n engine: \"cedar-policy\",\n called: true,\n duration_ms: Date.now() - startTime,\n effect: effect === \"Allow\" ? \"allow\" : \"deny\",\n reason: buildDecisionReason(\n effect,\n threatContext,\n determining_policies,\n this.policyMetadata,\n ),\n determining_policies,\n policy_details: getPolicyDetails(\n determining_policies,\n this.policyMetadata,\n ),\n request_context: requestContext,\n context_used: threatContext,\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(`Evaluation failed:`, { error: errorMessage });\n\n return {\n engine: \"cedar-policy\",\n called: true,\n duration_ms: Date.now() - startTime,\n effect: \"deny\", // Fail closed on error\n reason: `Policy evaluation error: ${errorMessage}`,\n determining_policies: [],\n context_used: threatContext,\n error: errorMessage,\n };\n }\n }\n}\n", "import {\n OverwatchEvent,\n ThreatSummary,\n DetectionResult,\n} from \"../types\";\nimport { getAuthStatus } from \"../auth/token-store\";\n\nexport interface CedarContext {\n principalType: string;\n principalId: string;\n action: string;\n resourceType: string;\n resourceId: string;\n contextData: Record<string, unknown>;\n}\n\n/**\n * Map OverwatchEvent + threat/yara results to Cedar policy context.\n */\nexport class ContextMapper {\n static mapToCedarContext(\n overwatchEvent: OverwatchEvent,\n threatSummary: ThreatSummary,\n yaraResult: DetectionResult,\n ): CedarContext {\n const { type, content, source, context, metadata } = overwatchEvent;\n const event = (metadata.original_event as string) ?? \"unknown\";\n\n let action = \"process_prompt\";\n let resourceType = \"LlmPrompt\";\n let resourceId = \"user_prompt\";\n\n if (type === \"tool\") {\n action = \"call_tool\";\n resourceType = \"Tool\";\n resourceId = context.tool_name ?? \"unknown_tool\";\n } else if (type === \"mcp\") {\n action = \"call_tool\";\n resourceType = \"Tool\";\n resourceId =\n context.mcp_tool ?? context.tool_name ?? \"unknown_tool\";\n }\n // type \"prompt\" | \"session\" \u2192 keep process_prompt / user_prompt defaults\n\n // Use verified identity from session.json (OAuth), fallback to context\n const authStatus = getAuthStatus();\n const userEmail = authStatus.email ?? context.user_email ?? \"anonymous\";\n const originalInput = (metadata.original_input as Record<string, unknown>) ?? {};\n const cedarPrincipal =\n (originalInput.cedar_principal as string) ?? \"mcp_client\";\n\n const toolName =\n type === \"mcp\"\n ? (context.mcp_tool ?? context.tool_name)\n : context.tool_name;\n const serverName = context.mcp_server;\n\n const severityMap: Record<string, number> = {\n low: 1,\n medium: 2,\n high: 3,\n critical: 4,\n };\n const maxThreatSeverity =\n yaraResult.findings.length > 0\n ? Math.max(\n ...yaraResult.findings.map((f: { severity: string }) =>\n severityMap[f.severity.toLowerCase()] ?? 0,\n ),\n )\n : 0;\n\n const contextData: Record<string, unknown> = {\n ...originalInput,\n content,\n source,\n event,\n user_email: userEmail,\n threat_count: threatSummary.total_count,\n highest_severity: threatSummary.highest_severity,\n threat_categories: Object.keys(threatSummary.by_category),\n prompt_text: content,\n tool_name: toolName,\n server_name: serverName,\n path: context.file_path,\n response_content: originalInput.response_content,\n yara_threats: yaraResult.findings.map((f: { rule: string }) => f.rule),\n max_threat_severity: maxThreatSeverity,\n threat_types: yaraResult.findings.map(\n (f: { category: string }) => f.category,\n ),\n contains_secrets: yaraResult.findings.some(\n (f: { category: string }) =>\n f.category.toLowerCase().includes(\"secret\") ||\n f.category.toLowerCase().includes(\"credential\"),\n ),\n };\n\n return {\n principalType: \"User\",\n principalId: cedarPrincipal,\n action,\n resourceType,\n resourceId,\n contextData,\n };\n }\n}\n", "// import { IDESource, HookEvent } from \"../types\";\nimport * as http from \"http\";\n\n/**\n * Parse JSON body from HTTP request\n */\nexport async function parseBody(\n req: http.IncomingMessage,\n): Promise<Record<string, unknown>> {\n return new Promise((resolve) => {\n let body = \"\";\n req.on(\"data\", (chunk) => {\n body += chunk.toString();\n });\n req.on(\"end\", () => {\n try {\n resolve(JSON.parse(body || \"{}\"));\n } catch {\n resolve({});\n }\n });\n req.on(\"error\", () => resolve({}));\n });\n}\n\n/**\n * Get guardrail config name based on hook type\n */\nexport function getGuardrailConfig(event: string): string {\n switch (event) {\n // Cursor - fast path for tool execution\n case \"beforeShellExecution\":\n case \"beforeMCPExecution\":\n return \"yara\"; // YARA-only for speed\n\n // Claude Code - fast path for tool execution\n case \"PreToolUse\":\n case \"PostToolUse\":\n return \"yara\"; // YARA-only for speed\n\n // GitHub Copilot CLI - fast path for tool execution\n case \"preToolUse\":\n case \"postToolUse\":\n return \"yara\"; // YARA-only for speed\n\n // File read events - full guardrails for content\n case \"beforeReadFile\":\n case \"beforeTabFileRead\":\n return \"guardrails\"; // Full guardrails for file content\n\n // Session events - observational only\n case \"sessionStart\":\n case \"sessionEnd\":\n case \"errorOccurred\":\n return \"none\"; // No validation needed\n\n // Prompt validation - full guardrails\n case \"beforeSubmitPrompt\":\n case \"UserPromptSubmit\":\n case \"userPromptSubmitted\":\n default:\n return \"guardrails\"; // Full guardrails\n }\n}\n\nexport function getDefaultResponse(event: string): Record<string, unknown> {\n switch (event) {\n // Cursor hooks\n case \"beforeSubmitPrompt\":\n return { continue: true };\n case \"beforeShellExecution\":\n case \"beforeMCPExecution\":\n case \"beforeTabFileRead\":\n case \"beforeReadFile\":\n case \"afterShellExecution\":\n case \"afterMCPExecution\":\n case \"afterFileEdit\":\n case \"afterTabFileEdit\":\n case \"afterAgentResponse\":\n case \"afterAgentThought\":\n return { permission: \"allow\" };\n case \"stop\":\n return {};\n\n // Claude Code hooks\n case \"UserPromptSubmit\":\n case \"PreToolUse\":\n case \"PostToolUse\":\n return {};\n\n // GitHub Copilot CLI hooks\n case \"userPromptSubmitted\":\n case \"preToolUse\":\n case \"postToolUse\":\n case \"sessionStart\":\n case \"sessionEnd\":\n case \"errorOccurred\":\n return {};\n\n default:\n return {};\n }\n}\n", "import {\n IDESource,\n HookEvent,\n DetectionResult,\n PolicyDecision,\n ThreatSummary,\n ThreatDetail,\n OverwatchEvent,\n} from \"../types\";\nimport { YaraExecutor } from \"../engines/yara\";\nimport { RemoteExecutor } from \"../engines/remote\";\nimport { CedarExecutor, ThreatContext } from \"../engines/cedar\";\nimport { PolicyManager } from \"../lib/policy-manager\";\nimport { ContextMapper } from \"./context-mapper\";\nimport { getGuardrailConfig } from \"../handlers/utils\";\nimport { ExtractorRegistry } from \"./extractors\";\n\nexport interface PipelineResult {\n response: Record<string, unknown>;\n evaluations: DetectionResult[];\n threat_summary: ThreatSummary;\n decision: PolicyDecision;\n allowed: boolean;\n contentLength?: number;\n overwatchEvent?: OverwatchEvent;\n}\n\nexport class HookPipeline {\n constructor(\n private yaraExecutor: YaraExecutor,\n private remoteExecutor: RemoteExecutor,\n private policyManager: PolicyManager,\n private onFirstInstall: (source: IDESource) => void,\n private extractorRegistry: ExtractorRegistry,\n ) { }\n\n async process(\n source: IDESource,\n event: HookEvent,\n input: Record<string, unknown>,\n ): Promise<PipelineResult> {\n const emptyThreatSummary: ThreatSummary = {\n total_count: 0,\n by_severity: { critical: 0, high: 0, medium: 0, low: 0 },\n by_category: {},\n by_source: { yara_local: 0, javelin_remote: 0 },\n highest_severity: \"none\",\n threat_list: [],\n };\n\n const defaultDecision: PolicyDecision = {\n engine: \"cedar-policy\",\n called: false,\n duration_ms: 0,\n effect: \"allow\",\n reason: \"Pass-through hook - no evaluation needed\",\n determining_policies: [],\n context_used: {\n threats_detected: 0,\n highest_severity: \"none\",\n categories: [],\n },\n };\n\n // 1. Find extractor for this source/event\n const extractor = this.extractorRegistry.findExtractor(event, source);\n\n // 2. No extractor = pass through (can't produce overwatchEvent)\n if (!extractor) {\n return {\n response: {},\n evaluations: [],\n threat_summary: emptyThreatSummary,\n decision: defaultDecision,\n allowed: true,\n };\n }\n\n // 3. Extract canonical event (always, for both pass-through and evaluated hooks)\n const overwatchEvent = await extractor.toCanonical(event, input, source);\n if (!overwatchEvent) {\n return {\n response: extractor.getDefaultResponse(event, true),\n evaluations: [],\n threat_summary: emptyThreatSummary,\n decision: defaultDecision,\n allowed: true,\n };\n }\n\n // 4. Check for pass-through hooks (non-blocking events)\n // These get overwatchEvent for recording but skip security evaluation\n if (\n event.startsWith(\"after\") ||\n event === \"stop\" ||\n event === \"PostToolUse\" ||\n // GitHub Copilot pass-through events (camelCase)\n event === \"postToolUse\" ||\n event === \"sessionStart\" ||\n event === \"sessionEnd\" ||\n event === \"errorOccurred\"\n ) {\n return {\n response: extractor.getDefaultResponse(event, true),\n evaluations: [],\n threat_summary: emptyThreatSummary,\n decision: defaultDecision,\n allowed: true,\n overwatchEvent,\n };\n }\n\n const content = overwatchEvent.content;\n const contentLength = content.length;\n\n // 5. Run Detection Engines\n const guardrailConfig = getGuardrailConfig(event);\n const [yaraResult, remoteResult] = await Promise.all([\n this.yaraExecutor.run(content),\n this.remoteExecutor.run(source, content, event, guardrailConfig, input),\n ]);\n\n const evaluations: DetectionResult[] = [yaraResult, remoteResult];\n\n // 6. Build threat summary\n const threatSummary = this.buildThreatSummary(evaluations);\n\n // 7. Build Cedar context\n const threatContext: ThreatContext = {\n threats_detected: threatSummary.total_count,\n highest_severity: threatSummary.highest_severity,\n categories: Object.keys(threatSummary.by_category),\n };\n\n const cedarContext = ContextMapper.mapToCedarContext(\n overwatchEvent,\n threatSummary,\n yaraResult,\n );\n\n // Track installation (side effect)\n this.onFirstInstall(source);\n\n // 8. Get IDE-specific policy engine and content\n const ideEngine = this.policyManager.getEngineForIDE(source);\n const policyContent = this.policyManager.getPolicyContentForIDE(source);\n const cedarExecutor = new CedarExecutor(ideEngine, policyContent);\n\n // 9. Run Decision Engine\n const decision = await cedarExecutor.run(cedarContext, threatContext);\n\n // 10. Final Decision\n let finalAllowed = true;\n let blockReason: string | undefined;\n\n if (decision.called) {\n finalAllowed = decision.effect === \"allow\";\n if (!finalAllowed) {\n blockReason = decision.reason;\n }\n }\n\n // 11. Build Response\n const response = extractor.getDefaultResponse(event, finalAllowed, blockReason);\n\n return {\n response,\n evaluations,\n threat_summary: threatSummary,\n decision,\n allowed: finalAllowed,\n contentLength,\n overwatchEvent,\n };\n }\n\n private buildThreatSummary(evaluations: DetectionResult[]): ThreatSummary {\n const threatList: ThreatDetail[] = [];\n const bySeverity = { critical: 0, high: 0, medium: 0, low: 0 };\n const byCategory: Record<string, number> = {};\n const bySource = { yara_local: 0, javelin_remote: 0 };\n\n for (const evaluation of evaluations) {\n const source =\n evaluation.engine === \"yara-local\" ? \"yara_local\" : \"javelin_remote\";\n\n for (const finding of evaluation.findings || []) {\n const severity = (finding.severity || \"medium\").toLowerCase();\n if (severity in bySeverity) {\n bySeverity[severity as keyof typeof bySeverity]++;\n }\n\n const category = finding.category || \"unknown\";\n byCategory[category] = (byCategory[category] || 0) + 1;\n\n bySource[source]++;\n\n threatList.push({\n rule: finding.rule,\n severity: finding.severity,\n category: finding.category,\n source: evaluation.engine,\n message: finding.message,\n matched_content: finding.matched_content,\n matched_patterns: finding.matched_patterns,\n match_location: finding.match_location,\n reference: finding.reference,\n });\n }\n }\n\n const severityOrder: Record<string, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n };\n threatList.sort(\n (a, b) =>\n (severityOrder[a.severity] || 4) - (severityOrder[b.severity] || 4),\n );\n\n let highestSeverity: \"critical\" | \"high\" | \"medium\" | \"low\" | \"none\" =\n \"none\";\n if (bySeverity.critical > 0) highestSeverity = \"critical\";\n else if (bySeverity.high > 0) highestSeverity = \"high\";\n else if (bySeverity.medium > 0) highestSeverity = \"medium\";\n else if (bySeverity.low > 0) highestSeverity = \"low\";\n\n return {\n total_count: threatList.length,\n by_severity: bySeverity,\n by_category: byCategory,\n by_source: bySource,\n highest_severity: highestSeverity,\n threat_list: threatList,\n };\n }\n}\n", "import * as path from \"path\";\nimport * as os from \"os\";\nimport * as fs from \"fs\";\nimport {\n HookEventRecord,\n IDESource,\n DetectionResult,\n ThreatSummary,\n PolicyDecision,\n HookCategory,\n HookEvent,\n OverwatchEvent,\n} from \"../types\";\nimport { logger } from \"../utils\";\n\nconst EVENTS_FILE = path.join(os.homedir(), \".overwatch\", \"events.jsonl\");\n\nfunction getHookCategory(event: string): HookCategory {\n if (event === \"stop\" || event === \"SessionEnd\") return \"stop\";\n if (event === \"SessionStart\") return \"before\";\n if (event.startsWith(\"after\")) return \"after\";\n if (event === \"PostToolUse\" || event === \"AfterTool\") return \"after\";\n if (event === \"UserPromptSubmit\" || event === \"PreToolUse\" || event === \"BeforeAgent\" || event === \"BeforeTool\") {\n return \"before\";\n }\n return \"before\";\n}\n\n/**\n * Record a hook event with the new evaluation structure\n * - evaluations: Detection engine results (YARA, Javelin)\n * - threat_summary: Aggregated threat data\n * - decision: Cedar policy decision (separate from evaluations)\n *\n * Requires overwatchEvent - all recorded events must go through extractors.\n * Returns the recorded event for ingestion to admin API.\n */\nexport function recordEvent(\n source: IDESource,\n event: HookEvent,\n response: Record<string, unknown>,\n evaluations: DetectionResult[],\n threatSummary: ThreatSummary,\n decision: PolicyDecision,\n finalAllowed: boolean,\n totalDuration: number,\n overwatchEvent: OverwatchEvent,\n contentLength?: number,\n): HookEventRecord {\n // Extract fields directly from overwatchEvent\n const isMcp = overwatchEvent.type === \"mcp\";\n const userEmail = overwatchEvent.context.user_email;\n const workspace = overwatchEvent.context.workspace_root;\n const ideVersion = overwatchEvent.metadata.ide_version as string | undefined;\n const isMcpCall = isMcp;\n const mcpServerName = isMcp ? overwatchEvent.context.mcp_server : undefined;\n const mcpToolName = isMcp ? overwatchEvent.context.mcp_tool : undefined;\n const recordInput = (overwatchEvent.metadata.original_input as Record<string, unknown>) ?? {};\n\n const record: HookEventRecord = {\n id: overwatchEvent.id,\n timestamp: new Date().toISOString(),\n source,\n event,\n hook_category: getHookCategory(event),\n user_email: userEmail,\n workspace,\n ide_version: ideVersion,\n model: recordInput.model as string | undefined,\n\n // MCP-specific fields (only populated for MCP tool calls)\n is_mcp_call: isMcpCall,\n mcp_server_name: mcpServerName,\n mcp_tool_name: mcpToolName,\n\n input: recordInput,\n\n // New structure: detection engines separate from decision engine\n evaluations, // Detection results (YARA, Javelin)\n threat_summary: threatSummary, // Aggregated threats\n decision, // Cedar policy decision\n\n allowed: finalAllowed,\n response,\n total_duration_ms: totalDuration,\n content_length: contentLength,\n };\n\n try {\n const dir = path.dirname(EVENTS_FILE);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.appendFileSync(EVENTS_FILE, JSON.stringify(record) + \"\\n\");\n logger.debug(\"Recorded:\", {\n id: record.id,\n event,\n allowed: finalAllowed,\n threats: threatSummary.total_count,\n decision: decision.effect,\n });\n } catch (error) {\n logger.error(\"Failed to write event:\", { error: String(error) });\n }\n\n return record;\n}\n", "import * as http from \"http\";\nimport { IDESource, HookEvent, HookEventRecord } from \"../types\";\nimport { HookPipeline } from \"../pipeline/hook-pipeline\";\nimport { AdminIngestor } from \"../data/ingestor\";\nimport { logger } from \"../utils\";\nimport { recordEvent } from \"../data/recorder\";\nimport { parseBody } from \"./utils\";\n\nexport class HookHandler {\n private eventCount = 0;\n private onProjectSkillsScan?: (workspace: string) => void;\n\n constructor(\n private pipeline: HookPipeline,\n private ingestor: AdminIngestor<HookEventRecord> | null,\n ) {}\n\n /**\n * Set callback for project skills scanning\n */\n setProjectSkillsScanCallback(callback: (workspace: string) => void): void {\n this.onProjectSkillsScan = callback;\n }\n\n getEventCount(): number {\n return this.eventCount;\n }\n\n async handle(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): Promise<void> {\n const startTime = Date.now();\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n const pathParts = url.pathname.split(\"/\").filter(Boolean);\n const source = (pathParts[1] as IDESource) || \"cursor\";\n const event = (pathParts[2] as HookEvent) || \"unknown\";\n\n logger.info(`${source}/${event} received`);\n\n const body = await parseBody(req);\n\n const result = await this.pipeline.process(source, event, body);\n this.eventCount++;\n const duration = Date.now() - startTime;\n\n // Record event (only if overwatchEvent is available)\n if (result.overwatchEvent) {\n const eventRecord = recordEvent(\n source,\n event,\n result.response,\n result.evaluations,\n result.threat_summary,\n result.decision,\n result.allowed,\n duration,\n result.overwatchEvent,\n result.contentLength,\n );\n\n // Ingest event\n if (this.ingestor) {\n logger.debug(\"Ingesting event to admin API\", {\n source,\n event,\n hasIngestor: !!this.ingestor,\n });\n this.ingestor.ingest(eventRecord);\n } else {\n logger.debug(\"Event ingestor not available, skipping ingestion\", {\n source,\n event,\n });\n }\n } else {\n logger.debug(\"No overwatchEvent, skipping recording\", { source, event });\n }\n\n logger.info(\n `${source}/${event} completed in ${duration}ms`,\n result.response,\n );\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(result.response));\n\n // Trigger project skills scan if workspace is present (fire-and-forget)\n const workspace = this.extractWorkspace(body);\n if (workspace && this.onProjectSkillsScan) {\n try {\n this.onProjectSkillsScan(workspace);\n } catch (error) {\n logger.error(\"Error in project skills scan callback\", {\n workspace,\n error: String(error),\n });\n }\n }\n }\n\n /**\n * Extract workspace path from event body\n * Checks workspace_roots array first, then common fields: cwd, workingDirectory, workspace\n */\n private extractWorkspace(body: Record<string, unknown>): string | null { \n // Check input.workspace_roots (nested in input object) for Cursor format\n if (body && typeof body === \"object\" && body !== null) {\n const input = body as Record<string, unknown>;\n if (input.workspace_roots && Array.isArray(input.workspace_roots)) {\n const roots = input.workspace_roots as string[];\n if (roots.length > 0 && typeof roots[0] === \"string\" && roots[0].length > 0) {\n return roots[0];\n }\n }\n }\n \n // Check other common fields\n const workspaceFields = [\"cwd\", \"workingDirectory\", \"workspace\", \"directory\", \"path\"];\n for (const field of workspaceFields) {\n const value = body[field];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n }\n \n // Also check nested fields (e.g., body.context?.workspace)\n if (body.context && typeof body.context === \"object\" && body.context !== null) {\n const context = body.context as Record<string, unknown>;\n for (const field of workspaceFields) {\n const value = context[field];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n }\n }\n \n return null;\n }\n}\n", "import * as http from \"http\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport * as crypto from \"crypto\";\nimport { IDESource, ScanRecord } from \"../types\";\nimport { MCPScanner } from \"../scanner\";\nimport { AdminIngestor } from \"../data/ingestor\";\nimport { logger } from \"../utils\";\nimport { parseBody } from \"./utils\";\n\nconst SCANS_FILE = path.join(os.homedir(), \".overwatch\", \"scans.jsonl\");\n\nexport class ScanHandler {\n constructor(\n private scanner: MCPScanner,\n private ingestor: AdminIngestor<ScanRecord> | null,\n ) {}\n\n async handle(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): Promise<void> {\n const body = await parseBody(req);\n if (body.action === \"run\") {\n logger.info(\"Running internal scan...\");\n if (!this.scanner.isAvailable()) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({ status: \"error\", error: \"Scanner not available\" }),\n );\n return;\n }\n try {\n const rulesDir = body.rulesDir as string | undefined;\n const results = await this.scanner.runScan(rulesDir);\n this.recordScan(results as unknown as Record<string, unknown>);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"ok\", ...results }));\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(\"Internal scan failed:\", { error: errorMsg });\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"error\", error: errorMsg }));\n }\n return;\n }\n logger.info(\"Received external scan results\");\n this.recordScan(body);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"ok\" }));\n }\n\n // Public so module.ts can use it for initial scan\n async runInitialScan(): Promise<void> {\n if (!this.scanner.isAvailable()) {\n logger.warn(\"Scanner not available, skipping initial MCP scan\");\n return;\n }\n\n try {\n logger.info(\"Running initial MCP scan...\");\n const results = await this.scanner.runScan();\n this.recordScan(results as unknown as Record<string, unknown>);\n logger.info(\"Initial MCP scan completed\");\n } catch (error) {\n logger.error(\"Initial MCP scan failed:\", { error: String(error) });\n }\n }\n\n private recordScan(input: Record<string, unknown>): void {\n const results = (input.results as Array<Record<string, unknown>>) || [];\n const totalServers = (input.total_servers as number) || results.length;\n let totalIssues = 0;\n let maxSeverity: string | undefined;\n const severityOrder: Record<string, number> = {\n low: 1,\n medium: 2,\n high: 3,\n critical: 4,\n };\n\n for (const result of results) {\n const yaraResults =\n (result.yara_results as Array<Record<string, unknown>>) || [];\n for (const yr of yaraResults) {\n if (yr.status === \"warning\") {\n totalIssues++;\n const metadata = yr.rule_metadata as\n | Record<string, unknown>\n | undefined;\n const sev = ((metadata?.severity as string) || \"low\").toLowerCase();\n if (\n !maxSeverity ||\n (severityOrder[sev] || 0) > (severityOrder[maxSeverity] || 0)\n ) {\n maxSeverity = sev;\n }\n }\n }\n }\n\n const source = (results[0]?.ide_source as IDESource) || \"cursor\";\n const record: ScanRecord = {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n source,\n total_servers: totalServers,\n total_issues: totalIssues,\n max_severity: maxSeverity,\n raw: input,\n };\n\n try {\n const dir = path.dirname(SCANS_FILE);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n fs.appendFileSync(SCANS_FILE, JSON.stringify(record) + \"\\n\");\n logger.info(\"Recorded:\", {\n id: record.id,\n servers: totalServers,\n issues: totalIssues,\n });\n\n const serverPayload = {\n id: record.id,\n timestamp: record.timestamp,\n source: record.source,\n total_servers: record.total_servers,\n total_issues: record.total_issues,\n max_severity: record.max_severity,\n results: input.results,\n scan_type: input.scan_type,\n ...(input.total_servers !== undefined && {\n total_servers_raw: input.total_servers,\n }),\n };\n\n logger.debug(\"Ingesting scan with results at top level\", {\n id: record.id,\n resultsCount: Array.isArray(input.results) ? input.results.length : 0,\n });\n\n this.ingestor?.ingest(serverPayload as unknown as ScanRecord);\n } catch (error) {\n logger.error(\"Failed to write scan:\", { error: String(error) });\n }\n }\n}\n", "import * as http from \"http\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as ejs from \"ejs\";\nimport { readEvents, readScans } from \"../data/reader\";\nimport { processDashboardData } from \"../data/processor\";\nimport { logger } from \"../utils\";\n\nexport class DashboardHandler {\n handle(_req: http.IncomingMessage, res: http.ServerResponse): void {\n try {\n const events = readEvents();\n const scans = readScans();\n const dashboardData = processDashboardData(events, scans);\n\n const possiblePaths = [\n // Bundled (dist/daemon.js -> dist/ui/views/dashboard.ejs)\n path.join(__dirname, \"ui\", \"views\", \"dashboard.ejs\"),\n // Unbundled (dist/handlers/dashboard-handler.js -> dist/ui/views/dashboard.ejs)\n path.join(__dirname, \"..\", \"ui\", \"views\", \"dashboard.ejs\"),\n // Source (src/handlers/dashboard-handler.ts -> src/ui/views/dashboard.ejs)\n path.join(__dirname, \"..\", \"ui\", \"views\", \"dashboard.ejs\"),\n ];\n\n let templatePath = \"\";\n for (const p of possiblePaths) {\n if (fs.existsSync(p)) {\n templatePath = p;\n break;\n }\n }\n\n let template: string;\n if (templatePath) {\n template = fs.readFileSync(templatePath, \"utf-8\");\n } else {\n // Last resort: try require.resolve\n try {\n const modPath = require.resolve(\"@highflame/overwatch\");\n templatePath = path.join(\n path.dirname(modPath),\n \"ui\",\n \"views\",\n \"dashboard.ejs\",\n );\n template = fs.readFileSync(templatePath, \"utf-8\");\n } catch {\n throw new Error(\"Could not find dashboard.ejs template\");\n }\n }\n\n const lightweightSessions = dashboardData.sessions.map((s) => ({\n id: s.id,\n source: s.source,\n startTime: s.startTime,\n eventCount: s.eventCount,\n threatCount: s.threatCount,\n allowed: s.allowed,\n }));\n\n const safeJson = (obj: unknown): string => {\n return JSON.stringify(obj).replace(/<\\/script/g, \"<\\\\/script\");\n };\n\n const templateData = {\n ...dashboardData,\n sessions: lightweightSessions,\n sessionsJson: safeJson(lightweightSessions),\n sessionsWithEventsJson: safeJson(dashboardData.sessions),\n threatsJson: safeJson(dashboardData.threats.map((t) => t.rawEvent)),\n commandsJson: safeJson(dashboardData.commands.map((c) => c.rawEvent)),\n eventsJson: safeJson(dashboardData.events),\n activityLabelsJson: safeJson(\n dashboardData.activityTimeline.map((d) => d.date),\n ),\n cursorDataJson: safeJson(\n dashboardData.activityTimeline.map((d) => d.cursor),\n ),\n claudeDataJson: safeJson(\n dashboardData.activityTimeline.map((d) => d.claude),\n ),\n githubCopilotDataJson: safeJson(\n dashboardData.activityTimeline.map((d) => d.github_copilot),\n ),\n };\n\n const viewsDir = path.dirname(templatePath);\n const html = ejs.render(\n template,\n { data: templateData },\n {\n filename: templatePath,\n views: [viewsDir],\n },\n );\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(html);\n } catch (error) {\n logger.error(\"Error:\", { error: String(error) });\n res.writeHead(500, { \"Content-Type\": \"text/html\" });\n res.end(\"<h1>Dashboard Error</h1>\");\n }\n }\n\n handleJs(_req: http.IncomingMessage, res: http.ServerResponse): void {\n try {\n const possiblePaths = [\n // Bundled (dist/daemon.js -> dist/ui/views/dashboard.js)\n path.join(__dirname, \"ui\", \"views\", \"dashboard.js\"),\n // Unbundled (dist/handlers/dashboard-handler.js -> dist/ui/views/dashboard.js)\n path.join(__dirname, \"..\", \"ui\", \"views\", \"dashboard.js\"),\n ];\n\n let jsPath = \"\";\n for (const p of possiblePaths) {\n if (fs.existsSync(p)) {\n jsPath = p;\n break;\n }\n }\n\n if (!jsPath) {\n try {\n const modPath = require.resolve(\"@highflame/overwatch\");\n jsPath = path.join(\n path.dirname(modPath),\n \"ui\",\n \"views\",\n \"dashboard.js\",\n );\n } catch {\n throw new Error(\"Could not find dashboard.js asset\");\n }\n }\n\n const jsContent = fs.readFileSync(jsPath, \"utf-8\");\n res.writeHead(200, {\n \"Content-Type\": \"application/javascript\",\n \"Cache-Control\": \"public, max-age=3600\",\n });\n res.end(jsContent);\n } catch (error) {\n logger.error(\"Error:\", { error: String(error) });\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n }\n }\n\n handleImage(req: http.IncomingMessage, res: http.ServerResponse): void {\n try {\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n const imageName = path.basename(url.pathname);\n\n // Security: Only allow specific image files\n const allowedImages = [\n \"highflame-mono.png\",\n ];\n if (!allowedImages.includes(imageName)) {\n res.writeHead(403, { \"Content-Type\": \"text/plain\" });\n res.end(\"Forbidden\");\n return;\n }\n\n const possiblePaths = [\n // Bundled (dist/daemon.js -> dist/ui/images/)\n path.join(__dirname, \"ui\", \"images\", imageName),\n // Unbundled (dist/handlers/dashboard-handler.js -> dist/ui/images/)\n path.join(__dirname, \"..\", \"ui\", \"images\", imageName),\n ];\n\n let imagePath = \"\";\n for (const p of possiblePaths) {\n if (fs.existsSync(p)) {\n imagePath = p;\n break;\n }\n }\n\n if (!imagePath) {\n try {\n const modPath = require.resolve(\"@highflame/overwatch\");\n imagePath = path.join(\n path.dirname(modPath),\n \"ui\",\n \"images\",\n imageName,\n );\n } catch {\n throw new Error(`Could not find image: ${imageName}`);\n }\n }\n\n if (!fs.existsSync(imagePath)) {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n return;\n }\n\n const ext = path.extname(imageName).toLowerCase();\n const contentType =\n ext === \".png\"\n ? \"image/png\"\n : ext === \".jpg\" || ext === \".jpeg\"\n ? \"image/jpeg\"\n : ext === \".svg\"\n ? \"image/svg+xml\"\n : \"application/octet-stream\";\n\n res.writeHead(200, {\n \"Content-Type\": contentType,\n \"Cache-Control\": \"public, max-age=3600\",\n });\n\n // Use streams for better memory efficiency\n const fileStream = fs.createReadStream(imagePath);\n fileStream.pipe(res);\n fileStream.on(\"error\", (err) => {\n logger.error(\"Error streaming image:\", { error: String(err) });\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal server error\");\n }\n });\n } catch (error) {\n logger.error(\"Error serving image:\", { error: String(error) });\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n }\n }\n}\n", "import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { HookEventRecord } from \"../types\";\n\nconst OVERWATCH_DIR = path.join(os.homedir(), \".overwatch\");\nconst EVENTS_FILE = path.join(OVERWATCH_DIR, \"events.jsonl\");\nconst SCANS_FILE = path.join(OVERWATCH_DIR, \"scans.jsonl\");\n\n// Alias for compatibility with existing code\nexport type EventRecord = HookEventRecord & {\n blocked_reason?: string;\n // Add legacy guardrail field if missing from HookEventRecord but still needed for parsing old logs\n guardrail?: {\n called: boolean;\n engine?: string;\n duration_ms?: number;\n response?: any;\n threats?: string[];\n error?: string;\n };\n};\n\nexport interface ScanRecord {\n id: string;\n timestamp: string;\n source?: string;\n total_servers: number;\n total_issues: number;\n max_severity?: string;\n raw?: any;\n}\n\nexport function readEvents(): EventRecord[] {\n try {\n if (!fs.existsSync(EVENTS_FILE)) {\n return [];\n }\n\n const content = fs.readFileSync(EVENTS_FILE, \"utf-8\").trim();\n if (!content) {\n return [];\n }\n\n const lines = content.split(\"\\n\");\n const events: EventRecord[] = [];\n\n for (const line of lines) {\n try {\n const event = JSON.parse(line);\n events.push(event);\n } catch (err) {\n // Skip invalid JSON lines\n continue;\n }\n }\n\n return events;\n } catch (err) {\n return [];\n }\n}\n\nexport function readScans(): ScanRecord[] {\n try {\n if (!fs.existsSync(SCANS_FILE)) {\n return [];\n }\n\n const content = fs.readFileSync(SCANS_FILE, \"utf-8\").trim();\n if (!content) {\n return [];\n }\n\n const lines = content.split(\"\\n\");\n const scans: ScanRecord[] = [];\n\n for (const line of lines) {\n try {\n const scan = JSON.parse(line);\n scans.push(scan);\n } catch (err) {\n // Skip invalid JSON lines\n continue;\n }\n }\n\n return scans;\n } catch (err) {\n return [];\n }\n}\n", "import { EventRecord, ScanRecord } from \"./reader\";\n\nexport interface DashboardData {\n stats: {\n totalEvents: number;\n blockedCalls: number;\n totalThreats: number;\n serversScanned: number;\n activeSessions: number;\n };\n installation: {\n cursor: { installed: boolean; version?: string; lastSeen?: string };\n claudecode: { installed: boolean; version?: string; lastSeen?: string };\n github_copilot: { installed: boolean; version?: string; lastSeen?: string };\n };\n activityTimeline: Array<{\n date: string;\n cursor: number;\n claude: number;\n github_copilot: number;\n }>;\n sessions: Array<{\n id: string;\n source: string;\n startTime: string;\n eventCount: number;\n threatCount: number;\n allowed: boolean;\n events: EventRecord[];\n }>;\n threats: Array<{\n id: string;\n timestamp: string;\n source: string;\n rule: string;\n severity: string;\n category: string;\n content?: string;\n rawEvent: EventRecord;\n }>;\n commands: Array<{\n id: string;\n timestamp: string;\n source: string;\n command: string;\n risk: \"critical\" | \"high\" | \"medium\" | \"low\";\n reason: string;\n allowed: boolean;\n rawEvent: EventRecord;\n }>;\n topCursorHooks: Array<{\n event: string;\n count: number;\n }>;\n topClaudeTools: Array<{\n tool: string;\n count: number;\n }>;\n topGitHubCopilotHooks: Array<{\n event: string;\n count: number;\n }>;\n events: EventRecord[]; // Full list for the master log\n scans: Array<{\n id: string;\n timestamp: string;\n source?: string;\n total_servers: number;\n total_issues: number;\n max_severity?: string;\n servers: Array<{\n server_name: string;\n url?: string;\n issues: Array<{\n severity: string;\n rule_name?: string;\n description?: string;\n target_type?: string;\n status?: string;\n }>;\n }>;\n }>;\n}\n\nfunction isBlocked(event: EventRecord): boolean {\n return (\n event.allowed === false ||\n event.response?.permission === \"deny\" ||\n event.response?.continue === false ||\n event.decision?.effect === \"deny\"\n );\n}\n\nfunction getRiskLevel(\n event: EventRecord,\n): \"critical\" | \"high\" | \"medium\" | \"low\" {\n const blocked = isBlocked(event);\n const highestSeverity = event.threat_summary?.highest_severity?.toLowerCase();\n\n if (highestSeverity === \"critical\") return \"critical\";\n if (blocked || highestSeverity === \"high\") return \"high\";\n if (highestSeverity === \"medium\") return \"medium\";\n return \"low\";\n}\n\nfunction getReason(event: EventRecord): string {\n if (event.decision?.reason) return event.decision.reason;\n if (event.blocked_reason) return event.blocked_reason;\n\n const threats = event.threat_summary?.total_count || 0;\n if (threats > 0) return `${threats} threat(s) detected`;\n\n return \"No threats detected\";\n}\n\n/** Unwrap Cursor/Claude body.input when present. Stored record.input = raw body. */\nfunction getPayload(e: EventRecord): Record<string, unknown> {\n const in_ = (e.input as Record<string, unknown> | undefined) ?? {};\n return (in_.input as Record<string, unknown> | undefined) ?? in_;\n}\n\nfunction getSessionKey(p: Record<string, unknown>): string {\n const v =\n (p.conversation_id as string) ??\n (p.conversationId as string) ??\n (p.session_id as string) ??\n (p.sessionId as string);\n return typeof v === \"string\" && v ? v : \"unknown\";\n}\n\nexport function processDashboardData(\n events: EventRecord[],\n scans: ScanRecord[],\n): DashboardData {\n const sortedEvents = [...events].sort(\n (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n );\n\n // Stats\n const totalEvents = events.length;\n const blockedCalls = events.filter(isBlocked).length;\n const totalThreats = events.reduce(\n (sum, e) => sum + (e.threat_summary?.total_count || 0),\n 0,\n );\n const serversScanned = scans.reduce(\n (sum, scan) => sum + (scan.total_servers || 0),\n 0,\n );\n\n // Installation info\n const cursorEvents = events.filter((e) => e.source === \"cursor\");\n const claudeEvents = events.filter((e) => e.source === \"claudecode\");\n const githubCopilotEvents = events.filter((e) => e.source === \"github_copilot\");\n\n const installation = {\n cursor: {\n installed: cursorEvents.length > 0,\n version: cursorEvents[0]?.ide_version,\n lastSeen: cursorEvents[0]?.timestamp,\n },\n claudecode: {\n installed: claudeEvents.length > 0,\n lastSeen: claudeEvents[0]?.timestamp,\n },\n github_copilot: {\n installed: githubCopilotEvents.length > 0,\n version: githubCopilotEvents[0]?.ide_version,\n lastSeen: githubCopilotEvents[0]?.timestamp,\n },\n };\n\n // Activity Timeline (Last 14 days for more detail)\n const now = new Date();\n const timelineDays = 14;\n const activityMap = new Map<\n string,\n { cursor: number; claude: number; github_copilot: number }\n >();\n\n for (let i = 0; i < timelineDays; i++) {\n const d = new Date(now);\n d.setDate(d.getDate() - i);\n const dateStr = d.toISOString().split(\"T\")[0];\n activityMap.set(dateStr, { cursor: 0, claude: 0, github_copilot: 0 });\n }\n\n events.forEach((e) => {\n const dateStr = e.timestamp.split(\"T\")[0];\n if (activityMap.has(dateStr)) {\n const counts = activityMap.get(dateStr)!;\n if (e.source === \"cursor\") counts.cursor++;\n if (e.source === \"claudecode\") counts.claude++;\n if (e.source === \"github_copilot\") counts.github_copilot++;\n }\n });\n\n const activityTimeline = Array.from(activityMap.entries())\n .map(([date, counts]) => ({ date, ...counts }))\n .reverse();\n\n // Sessions\n interface SessionInfo {\n id: string;\n source: string;\n startTime: string;\n eventCount: number;\n threatCount: number;\n allowed: boolean;\n events: EventRecord[];\n }\n\n const sessionsMap = new Map<string, SessionInfo>();\n\n events.forEach((e) => {\n const payload = getPayload(e);\n const sid = getSessionKey(payload);\n const key = `${sid}::${e.source}`;\n if (!sessionsMap.has(key)) {\n sessionsMap.set(key, {\n id: key,\n source: e.source,\n startTime: e.timestamp,\n eventCount: 0,\n threatCount: 0,\n allowed: true,\n events: [],\n });\n }\n const s = sessionsMap.get(key)!;\n s.eventCount++;\n s.threatCount += e.threat_summary?.total_count || 0;\n s.events.push(e);\n if (isBlocked(e)) s.allowed = false;\n });\n\n // Sort sessions by start time desc, and their events by timestamp desc\n const sessions = Array.from(sessionsMap.values())\n .map((s) => ({\n ...s,\n events: s.events.sort(\n (a, b) =>\n new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n ),\n }))\n .sort(\n (a, b) =>\n new Date(b.startTime).getTime() - new Date(a.startTime).getTime(),\n );\n\n // Threats\n const threats: DashboardData[\"threats\"] = [];\n events.forEach((e) => {\n if (e.threat_summary && e.threat_summary.total_count > 0) {\n e.threat_summary.threat_list.forEach((t) => {\n threats.push({\n id: e.id,\n timestamp: e.timestamp,\n source: e.source,\n rule: t.rule,\n severity: t.severity,\n category: t.category,\n content: t.matched_content,\n rawEvent: e,\n });\n });\n }\n });\n\n // Commands\n const commands: DashboardData[\"commands\"] = events\n .filter(\n (e) =>\n e.event === \"beforeShellExecution\" ||\n e.event === \"beforeMCPExecution\" ||\n e.event === \"PreToolUse\",\n )\n .map((e) => {\n const p = getPayload(e);\n return {\n id: e.id,\n timestamp: e.timestamp,\n source: e.source as string,\n command:\n (p.command as string) ||\n (p.tool_name as string) ||\n (p.name as string) ||\n (p.toolName as string) ||\n \"unknown\",\n risk: getRiskLevel(e),\n reason: getReason(e),\n allowed: !isBlocked(e),\n rawEvent: e,\n };\n });\n\n // Top Cursor Hooks\n const cursorHookCounts = new Map<string, number>();\n cursorEvents.forEach((e) => {\n cursorHookCounts.set(e.event, (cursorHookCounts.get(e.event) || 0) + 1);\n });\n const topCursorHooks = Array.from(cursorHookCounts.entries())\n .map(([event, count]) => ({ event, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 5);\n\n // Top Claude Tools\n const claudeToolCounts = new Map<string, number>();\n claudeEvents.forEach((e) => {\n const p = getPayload(e);\n const tool =\n (p.tool_name as string) ||\n (e.event === \"UserPromptSubmit\" ? \"prompt\" : \"unknown\");\n claudeToolCounts.set(tool, (claudeToolCounts.get(tool) || 0) + 1);\n });\n const topClaudeTools = Array.from(claudeToolCounts.entries())\n .map(([tool, count]) => ({ tool, count }))\n .sort((a, b) => b.count - a.count);\n\n // Top GitHub Copilot Hooks\n const githubCopilotHookCounts = new Map<string, number>();\n githubCopilotEvents.forEach((e) => {\n githubCopilotHookCounts.set(e.event, (githubCopilotHookCounts.get(e.event) || 0) + 1);\n });\n const topGitHubCopilotHooks = Array.from(githubCopilotHookCounts.entries())\n .map(([event, count]) => ({ event, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 5);\n\n // Process scans for dashboard display\n const processedScans = scans.map((scan) => {\n const raw = scan.raw as Record<string, unknown> | undefined;\n const results = (raw?.results as Array<Record<string, unknown>>) || [];\n\n const servers = results.map((result) => {\n const serverName = (result.server_name as string) || \"Unknown\";\n const url = result.url as string | undefined;\n const yaraResults =\n (result.yara_results as Array<Record<string, unknown>>) || [];\n\n const issues = yaraResults\n .filter((yr) => yr.status === \"warning\")\n .map((yr) => {\n const metadata = yr.rule_metadata as\n | Record<string, unknown>\n | undefined;\n return {\n severity: ((metadata?.severity as string) || \"low\").toUpperCase(),\n rule_name: yr.rule_name as string | undefined,\n description: metadata?.description as string | undefined,\n target_type: metadata?.target_type as string | undefined,\n status: yr.status as string | undefined,\n };\n });\n\n return {\n server_name: serverName,\n url,\n issues,\n };\n });\n\n return {\n id: scan.id,\n timestamp: scan.timestamp,\n source: scan.source,\n total_servers: scan.total_servers,\n total_issues: scan.total_issues,\n max_severity: scan.max_severity,\n servers,\n };\n });\n\n return {\n stats: {\n totalEvents,\n blockedCalls,\n totalThreats,\n serversScanned,\n activeSessions: sessionsMap.size,\n },\n installation,\n activityTimeline,\n sessions,\n threats,\n commands,\n topCursorHooks,\n topClaudeTools,\n topGitHubCopilotHooks,\n events: sortedEvents,\n scans: processedScans,\n };\n}\n", "import * as http from \"http\";\nimport { logger } from \"../utils\";\nimport {\n createOAuthState,\n generateCodeChallenge,\n buildAuthorizationUrl,\n exchangeCodeForTokens,\n saveTokens,\n OAuthState,\n} from \"../auth\";\nimport { generateSuccessHtml, generateErrorHtml } from \"../auth/html-utils\";\n\nexport class OAuthHandler {\n constructor(\n private port: number,\n private pendingOAuthStates: Map<string, OAuthState>,\n private oauthStateTimeout: number,\n ) {}\n\n async handleStart(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): Promise<void> {\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n\n const oauthState = createOAuthState(this.port);\n const codeChallenge = generateCodeChallenge(oauthState.codeVerifier);\n const authUrl = buildAuthorizationUrl(\n oauthState.state,\n codeChallenge,\n oauthState.redirectUri,\n );\n\n this.pendingOAuthStates.set(oauthState.state, oauthState);\n\n setTimeout(() => {\n const state = this.pendingOAuthStates.get(oauthState.state);\n if (state && state.status === \"pending\") {\n state.status = \"expired\";\n }\n }, this.oauthStateTimeout);\n\n logger.info(\"Started new auth flow\", { state: oauthState.state });\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n state: oauthState.state,\n auth_url: authUrl,\n }),\n );\n }\n\n async handleCallback(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): Promise<void> {\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n const errorDescription = url.searchParams.get(\"error_description\");\n\n if (error) {\n logger.error(\"Auth error:\", { error, errorDescription });\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(errorDescription || error));\n return;\n }\n\n if (!state || !code) {\n logger.error(\"Missing state or code parameter\");\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(\"Missing required parameters\"));\n return;\n }\n\n const oauthState = this.pendingOAuthStates.get(state);\n if (!oauthState) {\n logger.error(\"Unknown or expired state:\", { state });\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(\"Invalid or expired login session\"));\n return;\n }\n\n if (oauthState.status !== \"pending\") {\n logger.error(\"State not pending:\", { state, status: oauthState.status });\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(\"Login session already processed\"));\n return;\n }\n\n try {\n const { tokens, userInfo } = await exchangeCodeForTokens(\n code,\n oauthState.codeVerifier,\n oauthState.redirectUri,\n );\n\n saveTokens(tokens, userInfo);\n\n oauthState.status = \"completed\";\n oauthState.tokens = tokens;\n oauthState.userInfo = userInfo;\n\n logger.info(\"Login successful\", { email: userInfo?.email });\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(\n generateSuccessHtml(\n \"You can close this window and return to the terminal.\",\n userInfo?.email,\n ),\n );\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n logger.error(\"Token exchange failed:\", { error: errorMsg });\n oauthState.status = \"failed\";\n oauthState.error = errorMsg;\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(generateErrorHtml(errorMsg));\n }\n }\n\n async handleStatus(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): Promise<void> {\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n const state = url.searchParams.get(\"state\");\n\n if (!state) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing state parameter\" }));\n return;\n }\n\n const oauthState = this.pendingOAuthStates.get(state);\n if (!oauthState) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Unknown state\", status: \"unknown\" }));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n status: oauthState.status,\n user: oauthState.userInfo,\n error: oauthState.error,\n }),\n );\n\n if (oauthState.status !== \"pending\") {\n this.pendingOAuthStates.delete(state);\n }\n }\n}\n", "/**\n * Cursor IDE Extractor\n * \n * Converts Cursor hook payloads into canonical OverwatchEvent format.\n * Handles all Cursor hook events: prompt, shell, MCP, file operations.\n */\n\nimport { randomUUID } from 'crypto';\nimport { IExtractor } from './index';\nimport { OverwatchEvent, IDESource, SemanticAction } from '../../types/events';\nimport { IDE_SOURCES } from '../../types/config';\n\nexport class CursorExtractor implements IExtractor {\n /**\n * Check if the extractor can handle given event from Cursor\n */\n canHandle(event: string, source: IDESource): boolean {\n if (source !== IDE_SOURCES.CURSOR) {\n return false;\n }\n\n // Cursor events supported\n const supportedEvents = [\n 'beforeSubmitPrompt',\n 'beforeShellExecution',\n 'beforeMCPExecution',\n 'beforeReadFile',\n 'beforeTabFileRead',\n 'afterFileEdit',\n 'afterTabFileEdit',\n 'afterShellExecution',\n 'afterMCPExecution',\n 'afterAgentResponse',\n 'afterAgentThought',\n 'stop',\n ];\n\n return supportedEvents.includes(event);\n }\n\n /**\n * Convert Cursor hook payload to canonical OverwatchEvent\n * canHandle(event, source) is called before andmust return true before calling this method\n */\n async toCanonical(\n event: string,\n input: Record<string, any>,\n _source: IDESource\n ): Promise<OverwatchEvent | null> {\n const id = randomUUID();\n const cwd = this.resolveWorkspaceRoot(input);\n\n // Map Cursor events to semantic actions\n // Valid types: 'prompt', 'tool', 'mcp', 'session'\n const eventMap: Record<string, SemanticAction> = {\n // Before hooks (blocking)\n 'beforeSubmitPrompt': 'prompt',\n 'beforeShellExecution': 'tool',\n 'beforeMCPExecution': 'mcp',\n 'beforeReadFile': 'tool',\n 'beforeTabFileRead': 'tool',\n // After hooks (observational - pass-through, skip security eval)\n 'afterShellExecution': 'tool',\n 'afterMCPExecution': 'mcp',\n 'afterFileEdit': 'tool',\n 'afterTabFileEdit': 'tool',\n 'afterAgentResponse': 'prompt', // AI response to prompt\n 'afterAgentThought': 'prompt', // AI reasoning\n // Stop hook\n 'stop': 'session',\n };\n\n const type = eventMap[event];\n if (!type) {\n return null; // Unknown or unsupported event\n }\n\n // Extract content based on event type\n const content = this.extractContent(input, type, event);\n\n // Extract tool name and MCP info\n const { toolName, mcpServer, mcpTool } = this.extractToolInfo(input, type, event);\n\n return {\n id,\n type,\n content,\n source: IDE_SOURCES.CURSOR,\n context: {\n cwd,\n tool_name: toolName,\n mcp_server: mcpServer,\n mcp_tool: mcpTool,\n user_email: input.user_email as string | undefined,\n workspace_root: this.resolveWorkspaceRoot(input),\n file_path: this.extractFilePath(input, event),\n command: type === 'tool' && toolName === 'shell' ? (input.command as string) : undefined,\n arguments: this.extractArguments(input, event),\n },\n metadata: {\n original_event: event,\n original_input: input,\n ide_version: input.cursor_version as string | undefined,\n },\n };\n }\n\n /**\n * Extract content to be scanned by security engines\n */\n private extractContent(\n input: Record<string, any>,\n type: SemanticAction,\n event: string\n ): string {\n switch (type) {\n case 'prompt':\n // Handle prompt and response events\n if (event === 'afterAgentResponse') {\n return (input.response as string) || \n (input.content as string) || \n (input.text as string) || \n JSON.stringify(input);\n }\n if (event === 'afterAgentThought') {\n return (input.thought as string) || \n (input.content as string) || \n (input.text as string) || \n JSON.stringify(input);\n }\n return (input.prompt as string) || '';\n\n case 'mcp':\n // MCP call: serialize tool name and arguments\n const toolName = input.name || input.toolName || input.tool_name;\n if (event === 'afterMCPExecution') {\n // After MCP: include result\n return JSON.stringify({\n tool_name: toolName,\n server_name: input.command,\n result: input.result || input.output || input.response,\n });\n }\n return JSON.stringify({\n tool_name: toolName,\n server_name: input.command, // Cursor uses 'command' for MCP server name\n arguments: input.arguments || input.params || {},\n });\n\n case 'tool':\n // Handle different tool types\n if (event === 'beforeShellExecution') {\n return (input.command as string) || '';\n }\n\n if (event === 'afterShellExecution') {\n // Shell output\n return (input.output as string) || \n (input.result as string) || \n (input.stdout as string) || \n JSON.stringify(input);\n }\n\n if (event === 'beforeReadFile' || event === 'beforeTabFileRead') {\n // File read: use content if available, otherwise path\n return (input.content as string) ||\n (input.text as string) ||\n (input.path as string) ||\n '';\n }\n\n if (event === 'afterFileEdit' || event === 'afterTabFileEdit') {\n // File edit: use content or diff\n return (input.content as string) ||\n (input.diff as string) ||\n (input.path as string) ||\n '';\n }\n\n // Fallback: serialize input\n return JSON.stringify(input);\n\n case 'session':\n // Stop event - minimal content\n return event === 'stop' ? 'session_stop' : JSON.stringify(input);\n\n default:\n return JSON.stringify(input);\n }\n }\n\n /**\n * Extract tool name and MCP information\n */\n private extractToolInfo(\n input: Record<string, any>,\n type: SemanticAction,\n event: string\n ): { toolName?: string; mcpServer?: string; mcpTool?: string } {\n if (type !== 'tool' && type !== 'mcp') {\n return {};\n }\n\n // Shell execution\n if (event === 'beforeShellExecution') {\n return { toolName: 'shell' };\n }\n\n // MCP execution\n if (event === 'beforeMCPExecution') {\n // Cursor: server name is in 'command' field, tool name in 'name'/'toolName'/'tool_name'\n const serverName = input.command as string;\n const toolName = input.name || input.toolName || input.tool_name;\n\n return {\n toolName: toolName, // Just the tool name, not the full MCP path\n mcpServer: serverName,\n mcpTool: toolName as string | undefined,\n };\n }\n\n // File read\n if (event === 'beforeReadFile' || event === 'beforeTabFileRead') {\n return { toolName: 'read_file' };\n }\n\n // File edit\n if (event === 'afterFileEdit' || event === 'afterTabFileEdit') {\n return { toolName: 'edit_file' };\n }\n\n return {};\n }\n\n /**\n * Extract file path from input\n */\n private extractFilePath(input: Record<string, any>, event: string): string | undefined {\n if (event === 'beforeReadFile' ||\n event === 'beforeTabFileRead' ||\n event === 'afterFileEdit' ||\n event === 'afterTabFileEdit') {\n return (input.path as string) || undefined;\n }\n return undefined;\n }\n\n /**\n * Extract tool arguments\n */\n private extractArguments(input: Record<string, any>, event: string): Record<string, any> | undefined {\n if (event === 'beforeMCPExecution') {\n return (input.arguments || input.params || {}) as Record<string, any>;\n }\n return undefined;\n }\n\n /**\n * Resolve workspace root from various Cursor formats\n */\n private resolveWorkspaceRoot(input: Record<string, any>): string | undefined {\n // Cursor uses workspace_roots array\n if (Array.isArray(input.workspace_roots) && input.workspace_roots.length > 0) {\n return input.workspace_roots[0] as string;\n }\n // Fallback to other common fields\n if (input.workspace_root) {\n return input.workspace_root as string;\n }\n if (input.workspace) {\n return input.workspace as string;\n }\n if (input.cwd) {\n return input.cwd as string;\n }\n return undefined;\n }\n\n /**\n * Generate default response format for Cursor\n */\n getDefaultResponse(\n event: string,\n allowed: boolean,\n reason?: string\n ): Record<string, any> {\n const userMsg = reason\n ? `\uD83D\uDEAB Blocked by Overwatch: ${reason}`\n : '\uD83D\uDEAB Blocked by Overwatch';\n\n // Prompt submission\n if (event === 'beforeSubmitPrompt') {\n return {\n continue: allowed,\n ...(allowed ? {} : { user_message: userMsg }),\n };\n }\n\n // Before hooks (blocking)\n if (event.startsWith('before')) {\n return {\n permission: allowed ? 'allow' : 'deny',\n ...(allowed\n ? {}\n : {\n user_message: userMsg,\n agent_message: 'Action blocked by security policy',\n }),\n };\n }\n\n // After hooks (non-blocking, informational)\n if (event.startsWith('after')) {\n return { permission: 'allow' };\n }\n\n // Stop hook\n if (event === 'stop') {\n return {};\n }\n\n // Default: allow\n return { permission: 'allow' };\n }\n}\n", "/**\n * Claude Code Extractor\n * \n * Converts Claude Code hook payloads into canonical OverwatchEvent format.\n * Claude Code events: UserPromptSubmit, PreToolUse, PostToolUse.\n */\n\nimport { randomUUID } from 'crypto';\nimport { IExtractor } from './index';\nimport { OverwatchEvent, IDESource, SemanticAction } from '../../types/events';\nimport { IDE_SOURCES } from '../../types/config';\n\nexport class ClaudeExtractor implements IExtractor {\n /**\n * Check if this extractor can handle the given event from Claude Code\n */\n canHandle(event: string, source: IDESource): boolean {\n if (source !== IDE_SOURCES.CLAUDE_CODE) {\n return false;\n }\n\n // Claude Code events we support\n const supportedEvents = [\n 'UserPromptSubmit',\n 'PreToolUse',\n 'PostToolUse',\n ];\n\n return supportedEvents.includes(event);\n }\n\n /**\n * Convert Claude Code hook payload to canonical OverwatchEvent\n * canHandle(event, source) is called before and must return true before calling this method\n */\n async toCanonical(\n event: string,\n input: Record<string, any>,\n _source: IDESource\n ): Promise<OverwatchEvent | null> {\n const id = randomUUID();\n const cwd = this.resolveWorkspaceRoot(input);\n\n // Handle prompt submission\n if (event === 'UserPromptSubmit') {\n let content = (input.prompt as string) || '';\n\n return {\n id,\n type: 'prompt',\n content,\n source: IDE_SOURCES.CLAUDE_CODE,\n context: {\n cwd,\n user_email: input.user_email as string | undefined,\n workspace_root: this.resolveWorkspaceRoot(input),\n },\n metadata: {\n original_event: event,\n original_input: input,\n ide_version: input.ide_version as string | undefined,\n transcript_path: input.transcript_path as string | undefined,\n },\n };\n }\n\n // Handle tool usage (PreToolUse / PostToolUse)\n if (event === 'PreToolUse' || event === 'PostToolUse') {\n const toolName = input.tool_name as string;\n if (!toolName) {\n return null; // Invalid tool call\n }\n\n // Determine semantic action type: MCP vs tool\n const isMCP = toolName.startsWith('mcp__');\n const semanticType: SemanticAction = isMCP ? 'mcp' : 'tool';\n const content = await this.extractContent(input, toolName, event, isMCP);\n\n // Extract MCP server/tool from tool_name pattern: \"mcp__<server>__<tool>\"\n let mcpServer: string | undefined;\n let mcpTool: string | undefined;\n let normalizedToolName = toolName;\n\n if (isMCP) {\n const parts = toolName.split('__');\n if (parts.length >= 3) {\n mcpServer = parts[1];\n mcpTool = parts.slice(2).join('__'); // Handle tools with __ in name\n normalizedToolName = mcpTool; // Just the tool name, not the full MCP path\n }\n } else {\n // Map Claude native tools to normalized names\n normalizedToolName = this.normalizeToolName(toolName);\n }\n\n return {\n id,\n type: semanticType,\n content,\n source: IDE_SOURCES.CLAUDE_CODE,\n context: {\n cwd,\n tool_name: normalizedToolName,\n mcp_server: mcpServer,\n mcp_tool: mcpTool,\n user_email: input.user_email as string | undefined,\n workspace_root: this.resolveWorkspaceRoot(input),\n file_path: isMCP ? undefined : this.extractFilePath(input),\n command: isMCP ? undefined : this.extractCommand(input, toolName),\n arguments: this.extractArguments(input, toolName),\n },\n metadata: {\n original_event: event,\n original_input: input,\n ide_version: input.ide_version as string | undefined,\n },\n };\n }\n\n return null;\n }\n\n /**\n * Normalize Claude tool names to standard names\n */\n private normalizeToolName(toolName: string): string {\n const toolMap: Record<string, string> = {\n 'Bash': 'shell',\n 'Read': 'read_file',\n 'Write': 'write_file',\n 'Edit': 'edit_file',\n 'MultiEdit': 'edit_file',\n // Other Claude tools keep their names\n };\n\n return toolMap[toolName] || toolName;\n }\n\n /**\n * Extract content to be scanned by security engines\n */\n private async extractContent(\n input: Record<string, any>,\n toolName: string,\n event: string,\n isMCP: boolean\n ): Promise<string> {\n const toolInput = (input.tool_input as Record<string, any>) || {};\n\n // MCP tools: extract arguments\n if (isMCP) {\n return JSON.stringify(toolInput.arguments || toolInput || {});\n }\n\n // PostToolUse: validate tool output\n if (event === 'PostToolUse') {\n return input.tool_result\n ? JSON.stringify(input.tool_result)\n : JSON.stringify(input);\n }\n\n // PreToolUse: extract based on tool type\n switch (toolName) {\n case 'Bash':\n // Bash tool: tool_input.command\n return (toolInput.command as string) || '';\n\n case 'Read':\n // Read tool: tool_input.file_path\n return (toolInput.file_path as string) || (toolInput.path as string) || '';\n\n case 'Write':\n // Write tool: tool_input.file_path + tool_input.contents\n const writePath = (toolInput.file_path as string) || (toolInput.path as string) || '';\n const writeContent = (toolInput.contents as string) || (toolInput.content as string) || '';\n return `${writePath}\\n${writeContent}`.trim();\n\n case 'Edit':\n case 'MultiEdit':\n // Edit/MultiEdit tool: tool_input.file_path + old_string/new_string\n const editPath = (toolInput.file_path as string) || (toolInput.path as string) || '';\n const oldStr = (toolInput.old_string as string) || '';\n const newStr = (toolInput.new_string as string) || '';\n return `${editPath}\\n${oldStr}\\n\u2192\\n${newStr}`.trim();\n\n default:\n // Generic tools: serialize tool_input\n return JSON.stringify(toolInput);\n }\n }\n\n /**\n * Extract file path from tool input\n */\n private extractFilePath(input: Record<string, any>): string | undefined {\n const toolInput = (input.tool_input as Record<string, any>) || {};\n return (toolInput.file_path as string) || (toolInput.path as string) || undefined;\n }\n\n /**\n * Extract command from tool input (for Bash tools)\n */\n private extractCommand(input: Record<string, any>, toolName: string): string | undefined {\n if (toolName === 'Bash') {\n const toolInput = (input.tool_input as Record<string, any>) || {};\n return (toolInput.command as string) || undefined;\n }\n return undefined;\n }\n\n /**\n * Extract tool arguments\n */\n private extractArguments(input: Record<string, any>, toolName: string): Record<string, any> | undefined {\n const toolInput = (input.tool_input as Record<string, any>) || {};\n\n if (toolName.startsWith('mcp__')) {\n return (toolInput.arguments || toolInput) as Record<string, any>;\n }\n\n // For native tools, return tool_input as arguments\n return Object.keys(toolInput).length > 0 ? toolInput : undefined;\n }\n\n /**\n * Resolve workspace root from Claude Code formats\n */\n private resolveWorkspaceRoot(input: Record<string, any>): string | undefined {\n // Claude Code uses cwd\n if (input.cwd) {\n return input.cwd as string;\n }\n // Fallback to other common fields\n if (input.workspace_root) {\n return input.workspace_root as string;\n }\n if (input.workspace) {\n return input.workspace as string;\n }\n return undefined;\n }\n\n /**\n * Generate default response format for Claude Code\n */\n getDefaultResponse(\n event: string,\n allowed: boolean,\n reason?: string\n ): Record<string, any> {\n const blockReason = reason\n ? `\uD83D\uDEE1\uFE0F Blocked: ${reason}`\n : '\uD83D\uDEE1\uFE0F Blocked by Overwatch';\n\n switch (event) {\n case 'UserPromptSubmit':\n return allowed ? {} : { decision: 'block', reason: blockReason };\n\n case 'PreToolUse':\n return allowed\n ? {}\n : { permissionDecision: 'deny', permissionDecisionReason: blockReason };\n\n case 'PostToolUse':\n // PostToolUse is usually non-blocking, but we can send context\n return allowed ? {} : { additionalContext: `Security alert: ${reason}` };\n\n default:\n return {};\n }\n }\n}\n", "/**\n * GitHub Copilot Extractor\n * \n * Converts GitHub Copilot Agent hook payloads into canonical OverwatchEvent format.\n * Handles GitHub Copilot hook events as defined in .github/hooks/hooks.json\n * \n * GitHub Copilot uses repository-based hooks (.github/hooks/hooks.json) rather than\n * global IDE hooks. See: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/use-hooks\n */\n\nimport { randomUUID } from 'crypto';\nimport { IExtractor } from './index';\nimport { OverwatchEvent, IDESource, SemanticAction } from '../../types/events';\nimport { IDE_SOURCES } from '../../types/config';\n\nexport class GitHubCopilotExtractor implements IExtractor {\n /**\n * Check if the extractor can handle given event from GitHub Copilot\n */\n canHandle(event: string, source: IDESource): boolean {\n if (source !== IDE_SOURCES.GITHUB_COPILOT) {\n return false;\n }\n\n // GitHub Copilot Agent hook events (camelCase)\n // See: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/use-hooks\n const supportedEvents = [\n 'sessionStart',\n 'sessionEnd',\n 'userPromptSubmitted',\n 'preToolUse',\n 'postToolUse',\n 'errorOccurred',\n ];\n\n return supportedEvents.includes(event);\n }\n\n /**\n * Convert GitHub Copilot hook payload to canonical OverwatchEvent\n */\n async toCanonical(\n event: string,\n input: Record<string, any>,\n source: IDESource\n ): Promise<OverwatchEvent | null> {\n if (source !== IDE_SOURCES.GITHUB_COPILOT) {\n return null;\n }\n\n const id = randomUUID();\n const cwd = this.resolveWorkspaceRoot(input) || process.cwd();\n\n // Map GitHub Copilot events to semantic actions\n const eventMap: Record<string, SemanticAction> = {\n 'sessionStart': 'session',\n 'sessionEnd': 'session',\n 'userPromptSubmitted': 'prompt',\n 'preToolUse': 'tool', // May be tool or MCP, determined below\n 'postToolUse': 'tool',\n 'errorOccurred': 'session',\n };\n\n // Determine semantic type\n let type = eventMap[event];\n\n // For preToolUse, check if it's MCP based on tool_name pattern\n if (event === 'preToolUse' || event === 'postToolUse') {\n const toolName = input.tool_name as string;\n if (toolName && toolName.startsWith('mcp__')) {\n type = 'mcp';\n } else {\n type = 'tool';\n }\n }\n\n if (!type) {\n return null; // Unknown or unsupported event\n }\n\n // Extract content based on event type\n const content = this.extractContent(input, type, event);\n\n // Extract tool name and MCP info\n const { toolName, mcpServer, mcpTool } = this.extractToolInfo(input, type, event);\n\n return {\n id,\n type,\n content,\n source: IDE_SOURCES.GITHUB_COPILOT,\n context: {\n cwd,\n tool_name: toolName,\n mcp_server: mcpServer,\n mcp_tool: mcpTool,\n user_email: input.user_email as string | undefined,\n workspace_root: this.resolveWorkspaceRoot(input),\n file_path: this.extractFilePath(input, event),\n command: type === 'tool' && toolName === 'shell' ? (input.command as string) : undefined,\n arguments: this.extractArguments(input, event),\n },\n metadata: {\n original_event: event,\n original_input: input,\n ide_version: input.copilot_version || input.ide_version as string | undefined,\n },\n };\n }\n\n /**\n * Extract content to be scanned by security engines\n */\n private extractContent(\n input: Record<string, any>,\n type: SemanticAction,\n event: string\n ): string {\n switch (type) {\n case 'prompt':\n return (input.prompt as string) || (input.message as string) || '';\n\n case 'session':\n // Session events: return session info or empty\n return JSON.stringify({\n event,\n session_id: input.session_id,\n error: input.error,\n });\n\n case 'mcp':\n // MCP call: serialize tool name and arguments\n const mcpToolName = input.name || input.toolName || input.tool_name;\n const serverName = input.server_name || input.serverName || input.command;\n return JSON.stringify({\n tool_name: mcpToolName,\n server_name: serverName,\n arguments: input.arguments || input.params || input.tool_input || {},\n });\n\n case 'tool':\n // Handle different tool types\n if (input.command) {\n return input.command as string;\n }\n\n if (input.tool_name) {\n // Tool call with input\n const toolInput = input.tool_input || input.arguments || {};\n return JSON.stringify({\n tool_name: input.tool_name,\n tool_input: toolInput,\n });\n }\n\n if (input.path || input.file_path) {\n // File operation\n return (input.content as string) ||\n (input.text as string) ||\n (input.path as string) ||\n (input.file_path as string) ||\n '';\n }\n\n // Fallback: serialize input\n return JSON.stringify(input);\n\n default:\n return JSON.stringify(input);\n }\n }\n\n /**\n * Extract tool name and MCP information\n */\n private extractToolInfo(\n input: Record<string, any>,\n type: SemanticAction,\n _event: string\n ): { toolName?: string; mcpServer?: string; mcpTool?: string } {\n if (type !== 'tool' && type !== 'mcp') {\n return {};\n }\n\n const rawToolName = input.tool_name || input.name || input.toolName;\n\n // Check for MCP pattern: mcp__<server>__<tool>\n if (typeof rawToolName === 'string' && rawToolName.startsWith('mcp__')) {\n const parts = rawToolName.split('__');\n if (parts.length >= 3) {\n return {\n toolName: rawToolName,\n mcpServer: parts[1],\n mcpTool: parts.slice(2).join('__'),\n };\n }\n }\n\n // Shell execution\n if (input.command) {\n return { toolName: 'shell' };\n }\n\n // Regular tool\n if (rawToolName) {\n return { toolName: rawToolName as string };\n }\n\n return { toolName: 'unknown_tool' };\n }\n\n /**\n * Extract file path from input\n */\n private extractFilePath(input: Record<string, any>, _event: string): string | undefined {\n return (input.path as string) ||\n (input.file_path as string) ||\n (input.filePath as string) ||\n undefined;\n }\n\n /**\n * Extract tool arguments\n */\n private extractArguments(input: Record<string, any>, event: string): Record<string, any> | undefined {\n if (event === 'preToolUse' || event === 'postToolUse') {\n return (input.arguments || input.params || input.tool_input || undefined) as Record<string, any> | undefined;\n }\n return undefined;\n }\n\n /**\n * Resolve workspace root from various GitHub Copilot formats\n */\n private resolveWorkspaceRoot(input: Record<string, any>): string | undefined {\n // GitHub Copilot runs in repo context\n if (input.repository_path) {\n return input.repository_path as string;\n }\n if (input.repo_path) {\n return input.repo_path as string;\n }\n // Common alternatives\n if (input.workspaceRoot) {\n return input.workspaceRoot as string;\n }\n if (Array.isArray(input.workspace_roots) && input.workspace_roots.length > 0) {\n return input.workspace_roots[0] as string;\n }\n if (input.workspace_root) {\n return input.workspace_root as string;\n }\n if (input.cwd) {\n return input.cwd as string;\n }\n return undefined;\n }\n\n /**\n * Generate default response format for GitHub Copilot\n * \n * GitHub Copilot hooks expect: { continue: boolean } for blocking hooks\n * See: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/use-hooks\n */\n getDefaultResponse(\n event: string,\n allowed: boolean,\n reason?: string\n ): Record<string, any> {\n const errorMsg = reason\n ? `Blocked by Overwatch: ${reason}`\n : 'Blocked by Overwatch security policy';\n\n // Blocking hooks (preToolUse, userPromptSubmitted)\n if (event === 'preToolUse' || event === 'userPromptSubmitted') {\n return {\n continue: allowed,\n ...(allowed ? {} : { message: errorMsg }),\n };\n }\n\n // Non-blocking hooks (postToolUse, session events, errors)\n if (event === 'postToolUse' || event === 'sessionStart' ||\n event === 'sessionEnd' || event === 'errorOccurred') {\n return { continue: true };\n }\n\n // Default: allow\n return { continue: true };\n }\n}\n", "/**\n * Extractor Registry\n * \n * Factory pattern for managing and retrieving extractors for different IDE/framework sources.\n * Provides a centralized way to register and access extractors.\n */\n\nimport { IDESource } from '../../types/events';\nimport { IDE_SOURCES } from '../../types/config';\nimport { IExtractor } from './index';\nimport { CursorExtractor } from './cursor-extractor';\nimport { ClaudeExtractor } from './claude-extractor';\nimport { GitHubCopilotExtractor } from './github-copilot-extractor';\n\nexport class ExtractorRegistry {\n private extractors: Map<IDESource, IExtractor> = new Map();\n\n /**\n * Register an extractor for a source\n */\n register(source: IDESource, extractor: IExtractor): void {\n this.extractors.set(source, extractor);\n }\n\n /**\n * Get extractor for source\n * Returns null if no extractor is registered for the source\n */\n get(source: IDESource): IExtractor | null {\n return this.extractors.get(source) || null;\n }\n\n /**\n * Find extractor that can handle the given event from the given source\n * Checks both source match and canHandle() method\n */\n findExtractor(event: string, source: IDESource): IExtractor | null {\n const extractor = this.get(source);\n if (extractor && extractor.canHandle(event, source)) {\n return extractor;\n }\n return null;\n }\n\n /**\n * Check if an extractor is registered for the source\n */\n has(source: IDESource): boolean {\n return this.extractors.has(source);\n }\n\n /**\n * Get all registered sources\n */\n getRegisteredSources(): IDESource[] {\n return Array.from(this.extractors.keys());\n }\n\n /**\n * Create a registry with default extractors (Cursor, Claude Code, GitHub Copilot)\n */\n static createDefault(): ExtractorRegistry {\n const registry = new ExtractorRegistry();\n\n // Register extractors\n registry.register(IDE_SOURCES.CURSOR, new CursorExtractor());\n registry.register(IDE_SOURCES.CLAUDE_CODE, new ClaudeExtractor());\n registry.register(IDE_SOURCES.GITHUB_COPILOT, new GitHubCopilotExtractor());\n\n return registry;\n }\n}\n", "/**\n * Skills Scanner\n * Stateless scanner for personal skills from:\n * - ~/.claude/skills/ (Claude Code)\n * - ~/.cursor/skills/ (Cursor)\n * Backend handles change detection via contentHash\n */\n\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport * as crypto from \"crypto\";\nimport { SkillRecord, SkillScanResult } from \"./types\";\nimport { logger } from \"../utils\";\n\nconst CLAUDE_SKILLS_DIR = path.join(os.homedir(), \".claude\", \"skills\");\nconst CURSOR_SKILLS_DIR = path.join(os.homedir(), \".cursor\", \"skills\");\n\nexport class SkillsScanner {\n /**\n * Scan personal skills from both directories:\n * - ~/.claude/skills/\n * - ~/.cursor/skills/\n * Returns current state\n */\n async scan(): Promise<SkillScanResult> {\n const startTime = Date.now();\n\n logger.info(\"Starting skills scan\", {\n directories: [CLAUDE_SKILLS_DIR, CURSOR_SKILLS_DIR],\n });\n\n // Scan both directories in parallel\n const [claudeSkills, cursorSkills] = await Promise.all([\n this.scanDirectory(CLAUDE_SKILLS_DIR),\n this.scanDirectory(CURSOR_SKILLS_DIR),\n ]);\n\n const skills = [...claudeSkills, ...cursorSkills];\n const scanDurationMs = Date.now() - startTime;\n\n const result: SkillScanResult = {\n timestamp: new Date().toISOString(),\n totalSkills: skills.length,\n skills,\n scanDurationMs,\n };\n\n logger.info(\"Skills scan completed\", {\n totalSkills: skills.length,\n durationMs: scanDurationMs,\n });\n\n return result;\n }\n\n /**\n * Scan skills directory\n */\n private async scanDirectory(dir: string): Promise<SkillRecord[]> {\n const skills: SkillRecord[] = [];\n\n if (!(await this.exists(dir))) {\n logger.debug(\"Skills directory does not exist\", { dir });\n return skills;\n }\n\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillDir = path.join(dir, entry.name);\n const content = await this.readSkillContent(skillDir);\n\n if (content === null) {\n // No SKILL.md in this directory\n continue;\n }\n\n const files = await this.listSkillFiles(skillDir);\n const contentHash = this.hashContent(content);\n\n skills.push({\n name: entry.name,\n path: skillDir,\n content,\n contentHash,\n files,\n });\n }\n } catch (error) {\n logger.error(\"Failed to scan skills directory\", {\n dir,\n error: String(error),\n });\n }\n\n return skills;\n }\n\n /**\n * Check if a path exists\n */\n private async exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Read full SKILL.md content\n */\n private async readSkillContent(skillDir: string): Promise<string | null> {\n const skillFile = path.join(skillDir, \"SKILL.md\");\n\n if (!(await this.exists(skillFile))) {\n return null;\n }\n\n try {\n return await fs.readFile(skillFile, \"utf-8\");\n } catch (error) {\n logger.error(\"Failed to read skill file\", {\n skillFile,\n error: String(error),\n });\n return null;\n }\n }\n\n /**\n * List files in skill directory (recursive)\n */\n private async listSkillFiles(skillDir: string): Promise<string[]> {\n const files: string[] = [];\n\n try {\n const listFiles = async (\n dir: string,\n prefix: string = \"\"\n ): Promise<void> => {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n await listFiles(path.join(dir, entry.name), relativePath);\n } else {\n files.push(relativePath);\n }\n }\n };\n\n await listFiles(skillDir);\n } catch (error) {\n logger.error(\"Failed to list skill files\", {\n skillDir,\n error: String(error),\n });\n }\n\n return files;\n }\n\n /**\n * Hash content for backend deduplication\n */\n private hashContent(content: string): string {\n const hash = crypto.createHash(\"sha256\");\n hash.update(content);\n return `sha256:${hash.digest(\"hex\")}`;\n }\n\n /**\n * Scan project-level skills from:\n * - {workspace}/.claude/skills/\n * - {workspace}/.cursor/skills/\n */\n async scanProjectSkills(workspace: string): Promise<SkillScanResult> {\n const startTime = Date.now();\n const claudeSkillsDir = path.join(workspace, \".claude\", \"skills\");\n const cursorSkillsDir = path.join(workspace, \".cursor\", \"skills\");\n\n logger.info(\"Starting project skills scan\", {\n workspace,\n directories: [claudeSkillsDir, cursorSkillsDir],\n });\n\n // Scan both directories in parallel\n const [claudeSkills, cursorSkills] = await Promise.all([\n this.scanDirectory(claudeSkillsDir),\n this.scanDirectory(cursorSkillsDir),\n ]);\n\n const skills = [...claudeSkills, ...cursorSkills];\n const scanDurationMs = Date.now() - startTime;\n\n const result: SkillScanResult = {\n timestamp: new Date().toISOString(),\n totalSkills: skills.length,\n skills,\n scanDurationMs,\n workspace,\n };\n\n logger.info(\"Project skills scan completed\", {\n workspace,\n totalSkills: skills.length,\n durationMs: scanDurationMs,\n });\n\n return result;\n }\n}\n", "import * as net from \"net\";\n\nexport const GUARDIAN_PORTS = [17580, 17581, 17582, 17583, 17584];\n\nexport class PortManager {\n static async isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once(\"error\", () => resolve(false));\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n server.listen(port, \"127.0.0.1\");\n });\n }\n\n static async findAvailablePort(): Promise<number | null> {\n for (const port of GUARDIAN_PORTS) {\n if (await this.isPortAvailable(port)) {\n return port;\n }\n }\n return null;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["exports", "module", "path", "fs", "os", "exports", "exports", "module", "exports", "fs", "path", "dirname", "extname", "compile", "basename", "fs", "path", "os", "fs", "path", "os", "path", "fs", "path", "os", "fs", "path", "os", "fs", "path", "os", "CONFIG_DIR", "fs", "path", "os", "fs", "module", "fs", "fs", "path", "fs", "path", "os", "path", "os", "fs", "fs", "path", "os", "crypto", "fs", "path", "fs", "path", "os", "EVENTS_FILE", "SCANS_FILE", "import_crypto", "import_crypto", "import_crypto", "toolName", "fs", "path", "os", "crypto"]
7
+ }