{"version":3,"sources":["../src/utils/checksum.ts","../src/core/research-suite.ts","../src/core/privacy.ts","../src/core/deep-verify.ts"],"names":[],"mappings":"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","file":"chunk-GYQ26ETL.mjs","sourcesContent":["/**\r\n * Validates a number string using the Luhn algorithm (Mod 10).\r\n * Used for credit cards, IMEI, etc.\r\n * @param numStr The number string to validate.\r\n * @returns True if valid, false otherwise.\r\n */\r\nexport const validateLuhn = (numStr: any): boolean => {\r\n    // Defensive: Handle null/undefined/non-string\r\n    if (numStr == null || typeof numStr !== 'string') return false;\r\n    if (!/^\\d+$/.test(numStr)) return false;\r\n\r\n    let sum = 0;\r\n    let shouldDouble = false;\r\n\r\n    // Loop through values starting from the rightmost digit\r\n    for (let i = numStr.length - 1; i >= 0; i--) {\r\n        let digit = parseInt(numStr.charAt(i));\r\n\r\n        if (shouldDouble) {\r\n            if ((digit *= 2) > 9) digit -= 9;\r\n        }\r\n\r\n        sum += digit;\r\n        shouldDouble = !shouldDouble;\r\n    }\r\n\r\n    return sum % 10 === 0;\r\n};\r\n\r\n/**\r\n * Validates using Mod 11 algorithm with specified weights.\r\n * @param numStr The number string to validate.\r\n * @param weights The weights array (aligned from right to left).\r\n * @returns True if remainder is 0 (or matches specific check digit logic).\r\n * Note: This is a base implementation, specific IDs often have variations.\r\n */\r\n// export const validateMod11 = ... // Saving for specific implementation needs (PAN/TAN have alpha-numeric logic)\r\n","import { GST_STATE_CODES } from '../data/gstStates';\n\r\n// --------------------------------------------------------------------------\r\n// 0. GRAPHEME-SAFE UTILITIES\r\n// --------------------------------------------------------------------------\r\n\r\n/**\r\n * Safely slices text respecting grapheme cluster boundaries.\r\n * Prevents breaking combined characters (e.g., consonant + matra in Devanagari).\r\n * Uses Intl.Segmenter (Node 16+, modern browsers).\r\n * \r\n * @param text The input string.\r\n * @param start Start index (grapheme-based, 0-indexed).\r\n * @param end End index (grapheme-based, exclusive).\r\n * @returns Sliced string without breaking graphemes.\r\n * \r\n * @complexity O(n) where n is the number of graphemes.\r\n */\r\nexport const safeSlice = (text: string, start: number, end?: number): string => {\r\n    if (!text) return '';\r\n\r\n    // Fallback for environments without Intl.Segmenter\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    const IntlAny = Intl as any;\r\n    if (typeof IntlAny.Segmenter !== 'function') {\r\n        return text.slice(start, end);\r\n    }\r\n\r\n    const segmenter = new IntlAny.Segmenter(undefined, { granularity: 'grapheme' });\r\n    const graphemes = Array.from(segmenter.segment(text), (s: any) => s.segment);\r\n\r\n    return graphemes.slice(start, end).join('');\r\n};\r\n\r\n/**\r\n * Returns the number of grapheme clusters in a string.\r\n * Useful for accurate length measurement of Indic text.\r\n * \r\n * @param text The input string.\r\n * @returns Number of grapheme clusters.\r\n */\r\nexport const graphemeLength = (text: string): number => {\r\n    if (!text) return 0;\r\n\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    const IntlAny = Intl as any;\r\n    if (typeof IntlAny.Segmenter !== 'function') {\r\n        return text.length;\r\n    }\r\n\r\n    const segmenter = new IntlAny.Segmenter(undefined, { granularity: 'grapheme' });\r\n    return Array.from(segmenter.segment(text)).length;\r\n};\r\n\r\n// --------------------------------------------------------------------------\r\n// 1. INDIC TEXT NORMALIZATION\r\n// --------------------------------------------------------------------------\r\n\r\n/**\r\n * Normalizes Indic text for NLP and LLM preprocessing.\r\n * - Converts to NFC Normalization Form.\r\n * - Removes Zero Width Joiners (ZWJ) and Non-Joiners (ZWNJ).\r\n * - Standardizes whitespace.\r\n * \r\n * @param text The input string (e.g., Devanagari text).\r\n * @returns Cleaned and normalized string.\r\n * \r\n * @complexity O(n) where n is string length.\r\n */\r\nexport const normalizeIndic = (text: string): string => {\r\n    if (!text) return '';\r\n\r\n    // 1. Unicode NFC Normalization (Canonical Composition)\r\n    let normalized = text.normalize('NFC');\r\n\r\n    // 2. Remove ZWNJ (\\u200C) and ZWJ (\\u200D)\r\n    normalized = normalized.replace(/[\\u200C\\u200D]/g, '');\r\n\r\n    // 3. Normalize whitespace (tabs, zero-width spaces, multiple spaces -> single space)\r\n    normalized = normalized.replace(/[\\s\\u200b]+/g, ' ').trim();\r\n\r\n    return normalized;\r\n};\r\n\r\n// --------------------------------------------------------------------------\r\n// 2. PHONETIC MATCHING (INDIAN SOUNDEX)\r\n// --------------------------------------------------------------------------\r\n\r\n/**\r\n * Generates phonetic code tailored for Indian names.\r\n * Handles common variations: PH→F, BH→B, V→B, SH→S, etc.\r\n * \r\n * @complexity O(n) where n is word length.\r\n */\r\nconst getIndicPhoneticCode = (word: string): string => {\r\n    if (!word) return '';\r\n\r\n    // 1. Uppercase and remove non-alpha\r\n    let code = word.toUpperCase().replace(/[^A-Z]/g, '');\r\n\r\n    if (code.length === 0) return '';\r\n\r\n    // 2. Common Indian Phonetic Replacements (order matters)\r\n    code = code.replace(/PH/g, 'F');\r\n    code = code.replace(/BH/g, 'B');\r\n    code = code.replace(/TH/g, 'T');\r\n    code = code.replace(/SH/g, 'S');\r\n    code = code.replace(/X/g, 'K');\r\n    code = code.replace(/KS/g, 'K');\r\n    code = code.replace(/[VW]/g, 'B');\r\n    code = code.replace(/Z/g, 'J');\r\n    code = code.replace(/EE/g, 'I');\r\n    code = code.replace(/OO/g, 'U');\r\n    code = code.replace(/AU|OU/g, 'O');\r\n\r\n    // 3. Dedup adjacent characters\r\n    code = code.replace(/(.)\\1+/g, '$1');\r\n\r\n    // 4. Remove vowels except first character\r\n    const firstChar = code.charAt(0);\r\n    const rest = code.slice(1).replace(/[AEIOUY]/g, '');\r\n\r\n    return firstChar + rest;\r\n};\r\n\r\n/**\r\n * Calculates phonetic similarity score (0-1) between two Indian names.\r\n * Uses modified Soundex + Levenshtein distance.\r\n * \r\n * @param str1 First string.\r\n * @param str2 Second string.\r\n * @returns Similarity score between 0 and 1.\r\n * \r\n * @complexity O(m*n) time, O(min(m,n)) space where m,n are phonetic code lengths.\r\n */\r\nexport const phoneticMatch = (str1: string, str2: string): number => {\r\n    const code1 = getIndicPhoneticCode(str1);\r\n    const code2 = getIndicPhoneticCode(str2);\r\n\r\n    if (!code1 || !code2) return 0;\r\n    if (code1 === code2) return 1;\r\n\r\n    const distance = levenshteinOptimized(code1, code2);\r\n    const maxLength = Math.max(code1.length, code2.length);\r\n\r\n    return 1 - (distance / maxLength);\r\n};\r\n\r\n/**\r\n * Memory-optimized Levenshtein distance using two-row technique.\r\n * \r\n * @complexity O(m*n) time, O(min(m,n)) space.\r\n */\r\nconst levenshteinOptimized = (a: string, b: string): number => {\r\n    // Ensure 'a' is the shorter string for space optimization\r\n    if (a.length > b.length) [a, b] = [b, a];\r\n\r\n    const m = a.length;\r\n    const n = b.length;\r\n\r\n    // Use only two rows instead of full matrix\r\n    let prevRow = new Array(m + 1);\r\n    let currRow = new Array(m + 1);\r\n\r\n    // Initialize first row\r\n    for (let j = 0; j <= m; j++) prevRow[j] = j;\r\n\r\n    for (let i = 1; i <= n; i++) {\r\n        currRow[0] = i;\r\n\r\n        for (let j = 1; j <= m; j++) {\r\n            if (b.charAt(i - 1) === a.charAt(j - 1)) {\r\n                currRow[j] = prevRow[j - 1];\r\n            } else {\r\n                currRow[j] = 1 + Math.min(\r\n                    prevRow[j - 1], // substitution\r\n                    prevRow[j],     // deletion\r\n                    currRow[j - 1]  // insertion\r\n                );\r\n            }\r\n        }\r\n\r\n        // Swap rows\r\n        [prevRow, currRow] = [currRow, prevRow];\r\n    }\r\n\r\n    return prevRow[m];\r\n};\r\n\r\n\r\n// --------------------------------------------------------------------------\r\n// 3. ADDRESS PARSING (NER-LITE)\r\n// --------------------------------------------------------------------------\r\n\r\nexport interface AddressObject {\r\n    pincode: string | null;\r\n    city: string | null;\r\n    state: string | null;\r\n    landmarks: string[];\r\n}\r\n\r\n// Inverted state map: Name -> Code\r\nconst STATE_NAMES = Object.values(GST_STATE_CODES).map(s => s.toLowerCase());\r\n\r\n/**\r\n * Heuristically parses an Indian address string.\r\n * @param address The raw address string.\r\n */\r\nexport const parseAddress = (address: string): AddressObject => {\r\n    const result: AddressObject = {\r\n        pincode: null,\r\n        city: null,\r\n        state: null,\r\n        landmarks: []\r\n    };\r\n\r\n    if (!address) return result;\r\n\r\n    // 1. Extract Pincode (6 digits, word boundary)\n    // Look for pattern like \"110001\"\r\n    const pinMatch = address.match(/\\b\\d{6}\\b/);\r\n    if (pinMatch) {\r\n        result.pincode = pinMatch[0];\r\n    }\r\n\r\n    // 2. Extract State (Simple keyword matching)\r\n    // We iterate known states.\r\n    // Optimization: This is O(N) on states.\r\n    for (const stateName of STATE_NAMES) {\r\n        // Check valid boundaries to avoid partial matches inside words\r\n        if (new RegExp(`\\\\b${stateName}\\\\b`, 'i').test(address)) {\r\n            result.state = stateName.replace(/\\w\\S*/g, (w) => (w.replace(/^\\w/, (c) => c.toUpperCase()))); // Title Case\r\n            break; // Assume one state\r\n        }\r\n    }\r\n\r\n    // 3. Extract Landmarks (Near, Opp, Behind)\r\n    const landmarkKeywords = ['near', 'opposite', 'opp', 'behind', 'adj', 'adjacent', 'next to'];\r\n    // Split by comma or newline, but NOT by dot (which breaks 'Opp.')\r\n    const parts = address.split(/[,|\\n]+/);\r\n\r\n    for (const part of parts) {\r\n        const trimmed = part.trim();\r\n        const lowerPart = trimmed.toLowerCase();\r\n\r\n        for (const kw of landmarkKeywords) {\r\n            // Check if it STARTS with keyword followed by non-alpha (space, dot, etc)\r\n            // Or contains keyword surrounded by spaces\r\n            // Regex for keyword at start: ^kw(\\W|$)\r\n            const kwRegex = new RegExp(`^${kw}(\\\\W|$)`, 'i');\r\n\r\n            if (kwRegex.test(lowerPart) || lowerPart.includes(' ' + kw + ' ')) {\r\n                // Clean trailing punctuation (dots, commas are already gone from split, but dots remain)\r\n                const cleanLandmark = trimmed.replace(/[.]+$/, '');\r\n                result.landmarks.push(cleanLandmark);\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    // 4. City Extraction (Very hard without a DB)\r\n    // Heuristic: If we found a Pincode, sometimes we can look near it?\r\n    // Or assume the word before state?\r\n    // Currently leaving City as null unless we match explicit known cities (out of scope for \"Lite\").\r\n    // We will leave it as null for now or implement a basic \"last word before pincode\" heuristic if requested,\r\n    // but the prompt asked for \"Identify Indian-specific keywords... extract PIN, State, City, Landmark\".\r\n    // I'll try to guess standard metros if present.\r\n    const COMMON_CITIES = ['mumbai', 'delhi', 'bangalore', 'bengaluru', 'chennai', 'kolkata', 'hyderabad', 'pune', 'ahmedabad', 'jaipur', 'lucknow'];\r\n    for (const city of COMMON_CITIES) {\r\n        if (new RegExp(`\\\\b${city}\\\\b`, 'i').test(address)) {\r\n            result.city = city.charAt(0).toUpperCase() + city.slice(1);\r\n            break;\r\n        }\r\n    }\r\n\r\n    return result;\r\n};\r\n","import { isValidAadhaar } from '../validators/aadhaar';\r\nimport { isValidPAN } from '../validators/pan';\r\nimport { isValidGSTIN } from '../validators/gstin';\r\n\r\nexport interface ScrubOptions {\r\n    maskChar?: string;\r\n    scrubAadhaar?: boolean;\r\n    scrubPAN?: boolean;\r\n    scrubGSTIN?: boolean;\r\n}\r\n\r\nconst DEFAULT_OPTIONS: ScrubOptions = {\r\n    maskChar: 'X',\r\n    scrubAadhaar: true,\r\n    scrubPAN: true,\r\n    scrubGSTIN: true\r\n};\r\n\r\n/**\r\n * Invisible/control characters that attackers might inject between digits.\r\n * Includes: ZWNJ, ZWJ, Zero-Width Space, Soft Hyphen, etc.\r\n */\r\nconst INVISIBLE_CHARS_REGEX = /[\\u200B-\\u200D\\u00AD\\uFEFF\\u2060\\u180E]/g;\r\n\r\n/**\r\n * Strips invisible Unicode characters from a string.\r\n * Critical for preventing obfuscation attacks on PII detection.\r\n * \r\n * @param text Input text.\r\n * @returns Text with invisible characters removed.\r\n */\r\nconst stripInvisibleChars = (text: string): string => {\r\n    return text.replace(INVISIBLE_CHARS_REGEX, '');\r\n};\r\n\r\n/**\r\n * Scans text for sensitive Indian PII (Aadhaar, PAN, GSTIN) and redacts them.\r\n * \r\n * **Security Features**:\r\n * - Strips invisible Unicode characters before detection (prevents obfuscation).\r\n * - Uses strict checksum verification (Verhoeff for Aadhaar, Mod-36 for GSTIN).\r\n * - Prevents false positives on random numbers.\r\n * \r\n * @param text Input text.\r\n * @param options Configuration for scrubbing.\r\n * @returns Sanitized text with PII replaced by mask tokens.\r\n * \r\n * @complexity O(n) where n is text length.\r\n */\r\nexport const scrubPII = (text: string, options: ScrubOptions = {}): string => {\r\n    if (!text) return '';\r\n\r\n    const opts = { ...DEFAULT_OPTIONS, ...options };\r\n\r\n    // SECURITY: Strip invisible characters before processing\r\n    let processed = stripInvisibleChars(text);\r\n\r\n    // 1. Scrub Aadhaar (12 digits, optional spaces/dashes)\r\n    if (opts.scrubAadhaar) {\r\n        // Regex to find candidate 12-digit numbers with common separators\r\n        const aadhaarRegex = /\\b\\d{4}[ -]?\\d{4}[ -]?\\d{4}\\b/g;\r\n\r\n        processed = processed.replace(aadhaarRegex, (match) => {\r\n            const clean = match.replace(/[- ]/g, '');\r\n            if (isValidAadhaar(clean)) {\r\n                return `[AADHAAR_MASKED]`;\r\n            }\r\n            return match;\r\n        });\r\n    }\r\n\r\n    // 2. Scrub PAN\r\n    if (opts.scrubPAN) {\r\n        const panRegex = /\\b[A-Z]{5}[0-9]{4}[A-Z]{1}\\b/g;\r\n\r\n        processed = processed.replace(panRegex, (match) => {\r\n            if (isValidPAN(match)) {\r\n                return `[PAN_MASKED]`;\r\n            }\r\n            return match;\r\n        });\r\n    }\r\n\r\n    // 3. Scrub GSTIN\r\n    if (opts.scrubGSTIN) {\r\n        const gstinRegex = /\\b\\d{2}[A-Z]{5}\\d{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}\\b/g;\r\n\r\n        processed = processed.replace(gstinRegex, (match) => {\r\n            if (isValidGSTIN(match)) {\r\n                return `[GSTIN_MASKED]`;\r\n            }\r\n            return match;\r\n        });\r\n    }\r\n\r\n    return processed;\r\n};\r\n","export type VerificationType = 'VOTER_ID' | 'RC' | 'UDID';\n\n// State abbreviations used by Voter ID / vehicle registration formats.\nconst VALID_STATE_CODES = new Set([\n    'AP', 'AR', 'AS', 'BR', 'CG', 'GA', 'GJ', 'HR', 'HP', 'JK', 'JH', 'KA', 'KL', 'MP', 'MH', 'MN', 'ML', 'MZ', 'NL', 'OR', 'PB', 'RJ', 'SK', 'TN', 'TS', 'TR', 'UP', 'UK', 'WB', 'AN', 'CH', 'DN', 'DD', 'DL', 'LD', 'PY', 'LA'\r\n]);\r\n\r\n/**\r\n * Deep Verification for government IDs.\r\n * Goes beyond simple Regex by validating component logic (State codes, Structure).\r\n * @param id The ID string.\r\n * @param type The ID type.\r\n */\r\nexport const deepVerify = (id: string, type: VerificationType): boolean => {\r\n    if (!id || typeof id !== 'string') return false;\r\n    const cleanId = id.toUpperCase().trim();\r\n\r\n    switch (type) {\r\n        case 'VOTER_ID':\r\n            return verifyVoterID(cleanId);\r\n        case 'RC':\r\n            return verifyRC(cleanId);\r\n        case 'UDID':\r\n            return verifyUDID(cleanId);\r\n        default:\r\n            return false;\r\n    }\r\n};\r\n\r\nconst verifyVoterID = (id: string): boolean => {\r\n    // Standard EPIC Format: 3 Alpha (Series) + 7 Numeric\r\n    // Example: ABC1234567\r\n    const standardRegex = /^[A-Z]{3}[0-9]{7}$/;\r\n\r\n    // Old Format support could be added, but standardizing on modern EPIC for \"Deep Verify\".\r\n    // Old: DL/01/023/123456 (State/Const/Part/Serial)\r\n    const oldRegex = /^[A-Z]{2}\\/\\d{2}\\/\\d{3}\\/\\d{6}$/;\r\n\r\n    if (standardRegex.test(id)) {\r\n        return true;\r\n    }\r\n    if (oldRegex.test(id)) {\r\n        // Validate State Code in old format\r\n        const state = id.split('/')[0];\r\n        if (VALID_STATE_CODES.has(state)) return true;\r\n    }\r\n\r\n    return false;\r\n};\r\n\r\nconst verifyRC = (id: string): boolean => {\r\n    // Format: SS-RR-AA-NNNN\r\n    // SS: State Code (2 char)\r\n    // RR: RTO Code (2 digits)\r\n    // AA: Series (optional, 1-3 chars)\r\n    // NNNN: Number (4 digits)\r\n    // Clean spaces/hyphens first?\r\n    const clean = id.replace(/[- ]/g, '');\r\n\r\n    // Regex: ^[A-Z]{2}[0-9]{2}[A-Z]{0,3}[0-9]{4}$\r\n    // Minimum length check? e.g. DL1C1234 -> DL 1 C 1234\r\n\r\n    if (!/^[A-Z]{2}[0-9]{1,2}[A-Z]{0,3}[0-9]{4}$/.test(clean)) return false;\r\n\r\n    // Check State Code\r\n    const state = clean.substring(0, 2);\r\n    if (!VALID_STATE_CODES.has(state)) return false;\r\n\r\n    return true;\r\n};\r\n\r\nconst verifyUDID = (id: string): boolean => {\r\n    // Format: SS DD YYYY NNNNNNN\r\n    // SS: State Code\r\n    // DD: District Code\r\n    // YYYY: Year of Birth? or Issuance?\r\n    // NNNNNNN: Serial\r\n    // Total 18 chars usually. \"UDID Card Number is an 18 digit numeric string\"?\r\n    // Actually, usually it looks like: MH 01 101 1990 0000001 (example)\r\n    // Often starts with State Code.\r\n\r\n    // Pattern: ^[A-Z]{2}[0-9A-Z]{16}$ (Generic)\r\n\r\n    if (id.length !== 18) return false;\r\n\r\n    // Check State Code\r\n    const state = id.substring(0, 2);\r\n    if (!VALID_STATE_CODES.has(state)) return false;\r\n\r\n    // Basic structure check\r\n    // Expecting alphanumerics after state\r\n    return /^[A-Z]{2}[0-9A-Z]{16}$/.test(id);\r\n};\r\n"]}