"use strict";
/**
 * Shared base classifiers for the compliance pack ecosystem.
 *
 * RATIONALE: No copy-paste. Every pack that needs PII or PHI detection
 * composes around these shared patterns rather than duplicating them.
 * Before this module existed, 52+ packs each inlined the same email +
 * SSN regex, and 8+ packs copied the HIPAA 18-identifier PHI pattern
 * verbatim. The result: an SSN anywhere in input fired 23+ packs
 * simultaneously, producing noisy audit reports that obscured which
 * regulation actually applied.
 *
 * COMPOSITION PATTERN:
 *   - Framework packs (DORA, ISO27001, NIST-AI-RMF, etc.) should NOT
 *     use PII or PHI classifiers at all. Their value is in validators,
 *     modules, and retentionPolicy -- not in classifying generic personal
 *     data. Remove PII/PHI from their scanCategories.
 *   - Data-regulation packs (GLBA, CCPA, FERPA, etc.) have a legitimate
 *     need to scan for PII. They should import sharedPiiClassifier and,
 *     where their regulation is jurisdiction-specific, wrap it with
 *     requireMarker to add a regulation-specific qualifier so the pack
 *     only fires when BOTH the broad PII pattern AND the regulation's
 *     own marker are present.
 *   - Health-data packs that intersect with HIPAA (HITECH, PART11,
 *     PART2, FDA-SAMD) should use sharedPhiClassifier from this module
 *     rather than reimplementing the 18-identifier set.
 *
 * @connexum/ai-governance
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.sharedPiiClassifier = sharedPiiClassifier;
exports.sharedPhiClassifier = sharedPhiClassifier;
exports.requireMarker = requireMarker;
// ---------------------------------------------------------------------------
// Shared PII classifier
//
// Matches the two patterns that were duplicated across 52+ packs:
//   1. Email address (RFC 5322 simplified)
//   2. US Social Security Number (###-##-####)
//
// This is the BROAD pattern. Regulation-specific packs should wrap it
// with requireMarker() to add a jurisdiction or context qualifier.
// ---------------------------------------------------------------------------
/**
 * Broad PII classifier shared across all packs.
 *
 * Matches:
 *   - Email addresses  (RFC 5322 simplified pattern)
 *   - US SSN           (\b\d{3}-\d{2}-\d{4}\b)
 *
 * For regulation-specific PII (e.g. GLBA NPI, CCPA California PI,
 * FERPA student PII), compose with requireMarker() so the pack only
 * fires when its own jurisdiction marker is also present.
 */
function sharedPiiClassifier(input) {
    if (/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/.test(input))
        return true;
    if (/\b\d{3}-\d{2}-\d{4}\b/.test(input))
        return true;
    return false;
}
// ---------------------------------------------------------------------------
// Shared PHI classifier (HIPAA 18 Safe Harbor identifiers)
//
// Canonical implementation lives in hipaa.ts (HIPAA_CATEGORY_CLASSIFIERS.PHI).
// This shared export makes the same pattern available to packs that
// explicitly reference HIPAA PHI (e.g. HITECH which extends HIPAA BA chain,
// FDA-SAMD which cross-references 45 CFR 164.312).
//
// Packs that have their own health-data category (e.g. GDPR SPECIAL_CATEGORY,
// Colorado AI PHI for impact assessments) should define their own health
// keyword classifiers rather than using this function, because their scope
// differs from the HIPAA 18-identifier definition.
// ---------------------------------------------------------------------------
/**
 * Shared PHI classifier implementing the HIPAA 18 Safe Harbor identifiers
 * (45 CFR 164.514(b)(2)).
 *
 * Use this in packs that explicitly reference HIPAA PHI:
 *   - HITECH (extends HIPAA BA chain; §13402 breach notification)
 *   - FDA-SAMD (cross-references 45 CFR 164.312 when PHI is processed)
 *   - PART11 (clinical electronic records subject to 45 CFR 164.312)
 *   - PART2 (2024 Final Rule aligns Part 2 breach notification with HIPAA)
 *
 * Do NOT use for:
 *   - GDPR -- EU health data is "special category" under Art. 9, not PHI
 *   - Colorado AI -- state law PHI uses a broader consequential-decision scope
 *   - ISO/NIST framework packs -- they should not classify PHI at all
 */
function sharedPhiClassifier(input) {
    // SSN (also appears in HIPAA PHI scope as a government identifier)
    if (/\b\d{3}-\d{2}-\d{4}\b/.test(input))
        return true;
    // Medical Record Number (MRN)
    if (/\bMRN[:\s#]*\d{6,12}\b/i.test(input))
        return true;
    // Date of Birth
    if (/\b(?:DOB|Date\s+of\s+Birth|Birth\s*date)[:\s]*\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}\b/i.test(input))
        return true;
    // Phone numbers
    if (/\b(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/.test(input)) {
        const digits = input.replace(/\D/g, '');
        if (digits.length >= 10)
            return true;
    }
    // Email
    if (/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/.test(input))
        return true;
    // Health plan beneficiary number
    if (/\b(?:member|subscriber|beneficiary|policy)\s*(?:id|#|number)[:\s]*[A-Z0-9]{6,20}\b/i.test(input))
        return true;
    // Vehicle / VIN
    if (/\b(?:VIN|vehicle\s+id)[:\s]*[A-HJ-NPR-Z0-9]{17}\b/i.test(input))
        return true;
    // Device identifiers
    if (/\b(?:device\s*(?:id|serial)|serial\s*(?:number|#))[:\s]*[A-Z0-9\-]{8,30}\b/i.test(input))
        return true;
    // Biometric identifiers
    if (/\b(?:fingerprint|retinal|biometric|voiceprint|faceprint)\s*(?:id|hash|template|data)[:\s]*\S+/i.test(input))
        return true;
    // ZIP code (geographic subdivision)
    if (/\b(?:zip\s*(?:code)?|postal)[:\s]*\d{5}(?:-\d{4})?\b/i.test(input))
        return true;
    // Driver license / state ID
    if (/\b(?:DL|Driver['']?s?\s*License|state\s*ID)[:\s#]*[A-Z0-9]{6,15}\b/i.test(input))
        return true;
    return false;
}
// ---------------------------------------------------------------------------
// requireMarker: composition helper
//
// Creates a classifier that only fires when BOTH:
//   1. broadFn matches (the shared base pattern)
//   2. markerFn matches (the regulation-specific qualifier)
//
// This prevents a pack's PII or PHI category from firing on bare SSN/email
// alone; the regulation's own contextual marker must also be present.
//
// Example usage (GLBA NPI):
//
//   classifier: requireMarker(
//     sharedPiiClassifier,
//     (input) => /\b(?:nonpublic personal information|NPI|financial institution customer)\b/i.test(input)
//   )
//
// The GLBA PII category will then fire only when the input contains BOTH
// a recognized PII signal AND a GLBA-specific NPI context marker.
// ---------------------------------------------------------------------------
/**
 * Composes two classifier functions into a single classifier that returns
 * true only when BOTH functions return true.
 *
 * Use this to add a regulation-specific qualifier on top of a broad shared
 * pattern. The broad pattern (e.g. sharedPiiClassifier) gates on recognizable
 * PII signals; the marker pattern gates on the jurisdiction or context that
 * makes this regulation applicable.
 *
 * @param broadFn  - Broad base classifier (e.g. sharedPiiClassifier)
 * @param markerFn - Regulation-specific qualifier
 * @returns A composed classifier function
 */
function requireMarker(broadFn, markerFn) {
    return (input) => broadFn(input) && markerFn(input);
}
//# sourceMappingURL=_base-classifiers.js.map