"use strict";
/**
 * GeminiCodeAssistIdeAdapter -- Google Gemini Code Assist adapter.
 *
 * Gemini Code Assist (formerly Duet AI for Developers) is the natural
 * governance pair with the Google ADK orchestrator adapter
 * (P3-SUB-ADAPT-02, src/orchestrator-adapters/google-adk.ts). The same
 * Google Cloud / Vertex AI data-residency region list applies to both.
 *
 * Hook surfaces:
 *   Standard six (shared contract across all IDE adapters):
 *   completionRequested(file, cursor, context) -- pre-completion gate.
 *     Classifier checks surrounding code context for secrets, PHI
 *     indicators, and trade-secret markers before the request leaves the
 *     IDE. Under HIPAA/HITECH binding, PHI-bearing completions require
 *     reviewer approval.
 *   completionReceived(completion, context) -- post-completion ingress.
 *     Scans the returned completion for leaked secret patterns.
 *   chatRequested(prompt, context) -- pre-chat gate. Secret scan + PHI
 *     check on the prompt body and any attached file context.
 *   chatReceived(response) -- post-chat ingress classification.
 *   suggestionAccepted(suggestion, targetFile) -- audit on acceptance,
 *     links accepted code to its originating completion.
 *   suggestionRejected(suggestion, reason) -- optional audit event.
 *
 *   Gemini Code Assist-specific surfaces:
 *   cloudWorkspaceOperationRequested(workspace, operation) -- Gemini
 *     Code Assist can interact with Google Cloud Workspaces (Cloud Code,
 *     Cloud Shell, Cloud Run). Cloud-destructive operations (delete, stop,
 *     undeploy) require explicit approval. (PT-ADAPT-GEMINI-3)
 *   dataSovereigntyCheckRequested(region, dataClass) -- Vertex AI has
 *     data-residency commitments tied to Google Cloud regions. Under
 *     HIPAA binding, only HIPAA-eligible Vertex AI regions are permitted.
 *     (PT-ADAPT-GEMINI-1)
 *   duetCodeCitationReceived(citation) -- Gemini Code Assist surfaces
 *     license citations for generated code. Adapter enforces pack-binding
 *     license policy (GPL gate, attribution requirement).
 *     (PT-ADAPT-GEMINI-2)
 *
 * Google Cloud-specific considerations:
 *   - Vertex AI region compliance: HIPAA-eligible Vertex AI regions are
 *     listed in GEMINI_HIPAA_ELIGIBLE_REGIONS. Non-eligible regions are
 *     blocked under HIPAA/HITECH pack binding.
 *   - GDPR/DPA: European Vertex AI regions map to EU data-processing
 *     agreements. GDPR binding enforces EU-only or explicitly-adequate
 *     regions.
 *   - Code citation: Gemini Code Assist surfaces license attributions
 *     for generated code. Copyleft (GPL, AGPL, LGPL) licenses are blocked
 *     under SOC 2 / enterprise pack bindings.
 *   - Cloud Workspace operations: Cloud Code can create, deploy, and
 *     delete Cloud Run services and Cloud Functions. Destructive operations
 *     require explicit approval (G4 Destructive Command Guard equivalent).
 *
 * Spec: P3-SUB-IDE-05
 *
 * @connexum/ai-governance
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeminiCodeAssistIdeAdapter = exports.GEMINI_GDPR_ADEQUATE_REGIONS = exports.GEMINI_HIPAA_ELIGIBLE_REGIONS = void 0;
const base_1 = require("./base");
const index_1 = require("./index");
const shared_1 = require("./shared");
// ---------------------------------------------------------------------------
// Vertex AI / Gemini HIPAA-eligible regions
//
// Google Cloud regions that carry HIPAA-eligible data-processing commitments
// under an executed Google Cloud HIPAA Business Associate Agreement.
//
// Reference: https://cloud.google.com/security/compliance/hipaa
// (Vertex AI is listed as HIPAA eligible in the following regions)
// ---------------------------------------------------------------------------
exports.GEMINI_HIPAA_ELIGIBLE_REGIONS = [
    'us-central1',
    'us-east1',
    'us-east4',
    'us-west1',
    'us-west4',
    'northamerica-northeast1',
    'northamerica-northeast2',
    'europe-west1',
    'europe-west2',
    'europe-west3',
    'europe-west4',
    'australia-southeast1',
];
// ---------------------------------------------------------------------------
// Vertex AI / Gemini GDPR-adequate regions
//
// European Economic Area (EEA) and adequacy-decision regions for GDPR
// data-residency requirements. Under GDPR binding, data must remain in
// EEA or an adequacy-decision country.
// ---------------------------------------------------------------------------
exports.GEMINI_GDPR_ADEQUATE_REGIONS = [
    'europe-west1',
    'europe-west2',
    'europe-west3',
    'europe-west4',
    'europe-west6',
    'europe-north1',
    'europe-central2',
    'northamerica-northeast1', // Canada (adequacy decision)
    'northamerica-northeast2', // Canada
    'australia-southeast1', // Australia (adequacy decision)
];
// ---------------------------------------------------------------------------
// Cloud Workspace destructive operation set
// ---------------------------------------------------------------------------
const DESTRUCTIVE_CLOUD_OPERATIONS = new Set([
    'delete-service',
    'delete-function',
    'delete-cluster',
    'delete-bucket',
    'delete-database',
    'delete-instance',
    'undeploy-service',
    'stop-service',
    'revoke-iam-binding',
    'delete-secret',
    'delete-workstation',
    'destroy-environment',
]);
// ---------------------------------------------------------------------------
// Copyleft license patterns (blocked under enterprise / SOC 2 bindings)
// ---------------------------------------------------------------------------
const COPYLEFT_LICENSE_PATTERNS = [
    // AGPL and LGPL must appear before GPL to prevent the shorter GPL pattern
    // from matching inside AGPL/LGPL strings.
    { spdx: 'AGPL-3.0', re: /\bAGPL[- ]?v?3(?:[\. ]|$)/i },
    { spdx: 'LGPL-2.1', re: /\bLGPL[- ]?v?2\.1/i },
    { spdx: 'LGPL-3.0', re: /\bLGPL[- ]?v?3(?:[\. ]|$)/i },
    { spdx: 'GPL-2.0', re: /\bGPL[- ]?v?2(?:[\. ]|$)/i },
    { spdx: 'GPL-3.0', re: /\bGPL[- ]?v?3(?:[\. ]|$)/i },
    { spdx: 'EUPL-1.2', re: /EUPL[- ]?v?1\.2/i },
    { spdx: 'CCDL-1.0', re: /Common Development and Distribution License/i },
];
// ---------------------------------------------------------------------------
// Secret patterns (same subset as other IDE adapters)
// ---------------------------------------------------------------------------
const GCA_SECRET_PATTERNS = [
    { name: 'GCP service account key', re: /"type"\s*:\s*"service_account"/ },
    { name: 'GCP API key', re: /AIza[0-9A-Za-z\-_]{35}/ },
    { name: 'AWS access key', re: /AKIA[0-9A-Z]{16}/ },
    { name: 'GitHub PAT', re: /ghp_[0-9A-Za-z]{36}|github_pat_[0-9A-Za-z_]{82}/ },
    { name: 'Anthropic API key', re: /sk-ant-[0-9A-Za-z\-_]{20,}/ },
    { name: 'OpenAI API key', re: /sk-[0-9A-Za-z]{20,}/ },
    { name: 'Private key header', re: /-----BEGIN (RSA|EC|OPENSSH) PRIVATE KEY-----/ },
    { name: 'Generic secret env var', re: /(SECRET|PASSWORD|PASSWD|API_KEY|PRIVATE_KEY)\s*=\s*["']?\S{8,}["']?/i },
    { name: 'Bearer token', re: /Authorization:\s*Bearer\s+[0-9A-Za-z\-._~+/]{20,}/i },
    { name: 'Database URL with creds', re: /(postgres|mysql|mongodb|redis):\/\/[^:]+:[^@]+@/ },
];
// ---------------------------------------------------------------------------
// PHI indicators (same subset as other IDE adapters)
// ---------------------------------------------------------------------------
const GCA_PHI_INDICATORS = [
    /\bpatient[_\s]?(id|name|dob|ssn|mrn|record)\b/i,
    /\bdiagnos(is|es)\b/i,
    /\bprescription\b/i,
    /\bmedical[_\s]?record\b/i,
    /\bhealth[_\s]?plan\b/i,
    /\bssn\b/,
    /\bdate[_\s]?of[_\s]?birth\b/i,
    /\btreatment[_\s]?plan\b/i,
    /\bhipaa\b/i,
    /\bphi\b/,
];
// ---------------------------------------------------------------------------
// GeminiCodeAssistIdeAdapter
// ---------------------------------------------------------------------------
class GeminiCodeAssistIdeAdapter extends base_1.BaseIdeAdapter {
    adapterId = 'gemini-code-assist';
    ideId = 'gemini-code-assist';
    gcaConfig = null;
    // ---------------------------------------------------------------------------
    // Lifecycle
    // ---------------------------------------------------------------------------
    initialize(config) {
        super.initialize(config);
        this.gcaConfig = config;
        const region = this.gcaConfig.gcpRegion ?? 'us-central1';
        this.emit((0, shared_1.buildIdeAuditEvent)('ide:session-open', {
            ideId: this.ideId,
            adapterId: this.adapterId,
            detail: `GeminiCodeAssistIdeAdapter initialized. ` +
                `GCP region: ${region}. ` +
                `HIPAA eligible: ${exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.includes(region)}. ` +
                `GDPR adequate: ${exports.GEMINI_GDPR_ADEQUATE_REGIONS.includes(region)}.`,
            data: {
                region,
                hipaaEligible: exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.includes(region),
                gdprAdequate: exports.GEMINI_GDPR_ADEQUATE_REGIONS.includes(region),
            },
        }));
    }
    // ---------------------------------------------------------------------------
    // IdeAdapter: resolveUserIdentity
    // ---------------------------------------------------------------------------
    async resolveUserIdentity(session) {
        this.ensureInitialized();
        // Gemini Code Assist identity comes from the Google Cloud identity
        // tied to the developer's gcloud credentials (email address).
        const fromSession = session.identity?.userId?.trim() ?? session.identity?.email?.trim();
        if (fromSession) {
            const identity = {
                userId: fromSession,
                email: session.identity?.email,
                orgId: session.identity?.orgId,
                attributionMethod: 'cursor-composer',
            };
            this.emitIdentityResolved(identity.userId, session.clientSessionId);
            return identity;
        }
        const allowAnon = this.config?.allowAnonymousIdeSessions === true;
        if (allowAnon) {
            const anon = { userId: 'anonymous', attributionMethod: 'cursor-composer' };
            this.emitIdentityResolved(anon.userId, session.clientSessionId);
            return anon;
        }
        this.emitIdentityUnresolved(session.clientSessionId, 'GeminiCodeAssistIdeAdapter: no user identity in session context.');
        throw new index_1.IdeAttributionError({
            message: 'GeminiCodeAssistIdeAdapter: cannot resolve user identity. Provide a userId or ' +
                'email (Google Cloud identity) in session.identity, or set ' +
                'allowAnonymousIdeSessions: true in adapter config.',
            ideId: this.ideId,
            adapterId: this.adapterId,
        });
    }
    // ---------------------------------------------------------------------------
    // IdeAdapter: interceptToolInvocation
    //
    // Normalised tool invocations:
    //   Standard six:
    //   'gca:completion-requested'               -> completionRequested gate
    //   'gca:completion-received'                -> completionReceived ingress
    //   'gca:chat-requested'                     -> chatRequested gate
    //   'gca:chat-received'                      -> chatReceived ingress
    //   'gca:suggestion-accepted'                -> audit
    //   'gca:suggestion-rejected'                -> audit
    //
    //   Gemini Code Assist-specific:
    //   'gca:cloud-workspace-operation'          -> cloudWorkspaceOperationRequested
    //   'gca:data-sovereignty-check'             -> dataSovereigntyCheckRequested
    //   'gca:code-citation-received'             -> duetCodeCitationReceived
    // ---------------------------------------------------------------------------
    async interceptToolInvocation(ctx) {
        this.ensureInitialized();
        switch (ctx.tool) {
            case 'gca:completion-requested':
                return this._gateCompletionRequest(ctx);
            case 'gca:completion-received':
                return this._scanCompletionResponse(ctx);
            case 'gca:chat-requested':
                return this._gateChatRequest(ctx);
            case 'gca:chat-received':
                return this._scanChatResponse(ctx);
            case 'gca:suggestion-accepted':
                return this._auditSuggestionAccepted(ctx);
            case 'gca:suggestion-rejected':
                return this._auditSuggestionRejected(ctx);
            case 'gca:cloud-workspace-operation':
                return this._gateCloudWorkspaceOperation(ctx);
            case 'gca:data-sovereignty-check':
                return this._gateDataSovereignty(ctx);
            case 'gca:code-citation-received':
                return this._gateCitationReceived(ctx);
            default:
                this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-approved', {
                    ideId: this.ideId,
                    adapterId: this.adapterId,
                    sessionId: ctx.sessionHandle.sessionId,
                    initiatingUserId: ctx.initiatingUser.userId,
                    tool: ctx.tool,
                    detail: `GeminiCodeAssistIdeAdapter: unknown surface '${ctx.tool}' -- allowed with audit.`,
                }));
                return this.routeToolInvocation(ctx, {
                    decision: 'ALLOW',
                    reason: `Unknown Gemini Code Assist surface '${ctx.tool}' permitted with audit.`,
                });
        }
    }
    // ---------------------------------------------------------------------------
    // Hook: completionRequested
    // ---------------------------------------------------------------------------
    async _gateCompletionRequest(ctx) {
        const surroundingContext = String(ctx.input['surroundingContext'] ?? ctx.input['context'] ?? '');
        const filePath = String(ctx.input['filePath'] ?? ctx.input['file_path'] ?? '');
        // Data-residency gate under HIPAA (PT-ADAPT-GEMINI-1)
        const regionDecision = this._checkRegionCompliance(ctx);
        if (regionDecision)
            return regionDecision;
        const secretMatch = this._scanForSecrets(surroundingContext);
        if (secretMatch) {
            return this.routeToolInvocation(ctx, {
                decision: 'DENY',
                reason: `Completion blocked: secret pattern '${secretMatch}' in surrounding context (${filePath}).`,
                metadata: { filePath, secretPattern: secretMatch },
            });
        }
        if (this._isHipaaBinding()) {
            const phiMatch = this._scanForPhiIndicators(surroundingContext);
            if (phiMatch) {
                const tier = this.gcaConfig?.hipaaReviewerTier ?? 'T2_LEAD';
                return this.routeToolInvocation(ctx, {
                    decision: 'REQUIRE_APPROVAL',
                    reason: `Completion routed for review: PHI indicator '${phiMatch}' in context. Tier: ${tier}.`,
                    metadata: { filePath, phiIndicator: phiMatch, tier },
                });
            }
        }
        return this.routeToolInvocation(ctx, {
            decision: 'ALLOW',
            reason: `Completion request permitted by GeminiCodeAssistIdeAdapter.`,
            metadata: { filePath },
        });
    }
    // ---------------------------------------------------------------------------
    // Hook: completionReceived
    // ---------------------------------------------------------------------------
    async _scanCompletionResponse(ctx) {
        const completionText = String(ctx.input['completionText'] ?? ctx.input['completion'] ?? '');
        const secretMatch = this._scanForSecrets(completionText);
        if (secretMatch) {
            return this.routeToolInvocation(ctx, {
                decision: 'DENY',
                reason: `Completion response blocked: secret pattern '${secretMatch}' in returned code.`,
                metadata: { secretPattern: secretMatch },
            });
        }
        return this.routeToolInvocation(ctx, {
            decision: 'ALLOW',
            reason: 'Completion response passed Gemini Code Assist secret-scan ingress.',
        });
    }
    // ---------------------------------------------------------------------------
    // Hook: chatRequested
    // ---------------------------------------------------------------------------
    async _gateChatRequest(ctx) {
        const promptText = String(ctx.input['promptText'] ?? ctx.input['prompt'] ?? '');
        const regionDecision = this._checkRegionCompliance(ctx);
        if (regionDecision)
            return regionDecision;
        const secretMatch = this._scanForSecrets(promptText);
        if (secretMatch) {
            return this.routeToolInvocation(ctx, {
                decision: 'DENY',
                reason: `Chat request blocked: secret pattern '${secretMatch}' in prompt.`,
                metadata: { secretPattern: secretMatch },
            });
        }
        return this.routeToolInvocation(ctx, {
            decision: 'ALLOW',
            reason: 'Chat request permitted by GeminiCodeAssistIdeAdapter.',
        });
    }
    // ---------------------------------------------------------------------------
    // Hook: chatReceived
    // ---------------------------------------------------------------------------
    async _scanChatResponse(ctx) {
        const responseText = String(ctx.input['responseText'] ?? ctx.input['response'] ?? '');
        const secretMatch = this._scanForSecrets(responseText);
        if (secretMatch) {
            return this.routeToolInvocation(ctx, {
                decision: 'DENY',
                reason: `Chat response blocked: secret pattern '${secretMatch}' in response.`,
                metadata: { secretPattern: secretMatch },
            });
        }
        return this.routeToolInvocation(ctx, {
            decision: 'ALLOW',
            reason: 'Chat response passed Gemini Code Assist ingress scan.',
        });
    }
    // ---------------------------------------------------------------------------
    // Hook: suggestionAccepted
    // ---------------------------------------------------------------------------
    async _auditSuggestionAccepted(ctx) {
        const targetFilePath = String(ctx.input['targetFilePath'] ?? '');
        const completionId = String(ctx.input['completionId'] ?? '');
        this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-approved', {
            ideId: this.ideId,
            adapterId: this.adapterId,
            sessionId: ctx.sessionHandle.sessionId,
            initiatingUserId: ctx.initiatingUser.userId,
            tool: ctx.tool,
            detail: `Developer accepted Gemini Code Assist suggestion. Target: ${targetFilePath}. CompletionId: ${completionId || 'n/a'}.`,
            data: { targetFilePath, completionId },
        }));
        return this.routeToolInvocation(ctx, {
            decision: 'ALLOW',
            reason: `Suggestion acceptance audited for '${targetFilePath}'.`,
        });
    }
    // ---------------------------------------------------------------------------
    // Hook: suggestionRejected
    // ---------------------------------------------------------------------------
    async _auditSuggestionRejected(ctx) {
        const reason = String(ctx.input['reason'] ?? 'not-specified');
        const completionId = String(ctx.input['completionId'] ?? '');
        this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-approved', {
            ideId: this.ideId,
            adapterId: this.adapterId,
            sessionId: ctx.sessionHandle.sessionId,
            initiatingUserId: ctx.initiatingUser.userId,
            tool: ctx.tool,
            detail: `Developer rejected Gemini Code Assist suggestion. Reason: ${reason}. CompletionId: ${completionId || 'n/a'}.`,
        }));
        return this.routeToolInvocation(ctx, {
            decision: 'ALLOW',
            reason: `Suggestion rejection audited. Reason: ${reason}.`,
        });
    }
    // ---------------------------------------------------------------------------
    // Gemini-specific Hook: cloudWorkspaceOperationRequested (PT-ADAPT-GEMINI-3)
    //
    // Gemini Code Assist via Cloud Code can create, deploy, and delete Cloud
    // Run services, Cloud Functions, and Cloud Workstations. Destructive
    // operations require explicit approval (G4 Destructive Command Guard
    // equivalent).
    // ---------------------------------------------------------------------------
    async cloudWorkspaceOperationRequested(ctx) {
        this.ensureInitialized();
        const { workspaceName, operation, resourceType, gcpProject } = ctx;
        const effectiveRegion = ctx.region ?? this.gcaConfig?.gcpRegion ?? 'us-central1';
        // 1. Data-residency gate under HIPAA
        if (this._isHipaaBinding() && !exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.includes(effectiveRegion)) {
            const decision = {
                decision: 'DENY',
                reason: `Cloud Workspace operation blocked: GCP region '${effectiveRegion}' is not HIPAA-eligible ` +
                    `under pack binding '${this.config?.packId}'. ` +
                    `HIPAA-eligible Vertex AI regions: ${exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.join(', ')}.`,
                metadata: { region: effectiveRegion, operation, workspaceName },
            };
            this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-denied', {
                ideId: this.ideId,
                adapterId: this.adapterId,
                tool: 'gca:cloud-workspace-operation',
                detail: decision.reason,
                data: { region: effectiveRegion, workspaceName, operation },
            }));
            return decision;
        }
        // 2. Destructive operation gate -- requires explicit approval
        const normalizedOp = operation.toLowerCase().replace(/[_ ]/g, '-');
        if (DESTRUCTIVE_CLOUD_OPERATIONS.has(normalizedOp)) {
            const tier = this.gcaConfig?.cloudDestructiveReviewerTier ?? 'T3_SECURITY';
            const decision = {
                decision: 'REQUIRE_APPROVAL',
                reason: `Cloud Workspace destructive operation '${operation}' on '${workspaceName}' ` +
                    `(type: ${resourceType ?? 'unknown'}, project: ${gcpProject ?? 'unknown'}) ` +
                    `requires explicit approval. This operation cannot be reversed without a recovery procedure. ` +
                    `Reviewer tier: ${tier}.`,
                metadata: {
                    workspaceName,
                    operation,
                    resourceType,
                    gcpProject,
                    region: effectiveRegion,
                    destructive: true,
                    tier,
                },
            };
            this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-require-approval', {
                ideId: this.ideId,
                adapterId: this.adapterId,
                tool: 'gca:cloud-workspace-operation',
                detail: decision.reason,
                data: { workspaceName, operation, resourceType, region: effectiveRegion },
            }));
            return decision;
        }
        // 3. Non-destructive operation -- audit and allow
        this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-approved', {
            ideId: this.ideId,
            adapterId: this.adapterId,
            tool: 'gca:cloud-workspace-operation',
            detail: `Cloud Workspace operation '${operation}' on '${workspaceName}' in ${effectiveRegion} permitted.`,
            data: { workspaceName, operation, resourceType, region: effectiveRegion, gcpProject },
        }));
        return {
            decision: 'ALLOW',
            reason: `Cloud Workspace operation '${operation}' on '${workspaceName}' permitted.`,
            metadata: { workspaceName, operation, resourceType, region: effectiveRegion },
        };
    }
    // ---------------------------------------------------------------------------
    // Gemini-specific Hook: dataSovereigntyCheckRequested (PT-ADAPT-GEMINI-1)
    //
    // Vertex AI data-residency enforcement. Called when the Gemini Code Assist
    // extension negotiates a Cloud region for completions. Blocks non-eligible
    // regions under HIPAA and GDPR pack bindings.
    // ---------------------------------------------------------------------------
    async dataSovereigntyCheckRequested(ctx) {
        this.ensureInitialized();
        const { gcpRegion, dataClass } = ctx;
        // HIPAA check
        if (this._isHipaaBinding() && !exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.includes(gcpRegion)) {
            const decision = {
                decision: 'DENY',
                reason: `Data sovereignty check failed: GCP region '${gcpRegion}' is not HIPAA-eligible ` +
                    `under pack binding '${this.config?.packId}'. ` +
                    `Data class: '${dataClass}'. ` +
                    `HIPAA-eligible regions: ${exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.join(', ')}.`,
                metadata: { gcpRegion, dataClass, binding: this.config?.packId },
            };
            this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-denied', {
                ideId: this.ideId,
                adapterId: this.adapterId,
                tool: 'gca:data-sovereignty-check',
                detail: decision.reason,
                data: { gcpRegion, dataClass },
            }));
            return decision;
        }
        // GDPR check
        if (this._isGdprBinding() && !exports.GEMINI_GDPR_ADEQUATE_REGIONS.includes(gcpRegion)) {
            const decision = {
                decision: 'DENY',
                reason: `Data sovereignty check failed: GCP region '${gcpRegion}' is not in a GDPR-adequate ` +
                    `jurisdiction under pack binding '${this.config?.packId}'. ` +
                    `Data class: '${dataClass}'. ` +
                    `GDPR-adequate regions: ${exports.GEMINI_GDPR_ADEQUATE_REGIONS.join(', ')}.`,
                metadata: { gcpRegion, dataClass, binding: this.config?.packId },
            };
            this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-denied', {
                ideId: this.ideId,
                adapterId: this.adapterId,
                tool: 'gca:data-sovereignty-check',
                detail: decision.reason,
                data: { gcpRegion, dataClass },
            }));
            return decision;
        }
        this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-approved', {
            ideId: this.ideId,
            adapterId: this.adapterId,
            tool: 'gca:data-sovereignty-check',
            detail: `Data sovereignty check passed for region '${gcpRegion}', data class '${dataClass}'.`,
            data: { gcpRegion, dataClass },
        }));
        return {
            decision: 'ALLOW',
            reason: `Data sovereignty check passed. Region '${gcpRegion}' is compliant for data class '${dataClass}'.`,
            metadata: { gcpRegion, dataClass },
        };
    }
    // ---------------------------------------------------------------------------
    // Gemini-specific Hook: duetCodeCitationReceived (PT-ADAPT-GEMINI-2)
    //
    // Gemini Code Assist surfaces license citations for generated code. This
    // gate enforces copyleft license policy. GPL/AGPL/LGPL citations are
    // blocked under enterprise / SOC 2 pack bindings when blockCopyleftCitations
    // is configured, or whenever a HIPAA/regulated pack is active.
    // ---------------------------------------------------------------------------
    async duetCodeCitationReceived(ctx) {
        this.ensureInitialized();
        const { spdxLicense, licenseText, sourceUrl, codeSnippet } = ctx;
        // Check copyleft patterns in SPDX identifier or license text
        const combinedText = [spdxLicense ?? '', licenseText ?? ''].join(' ');
        const copyleftMatch = this._detectCopyleftLicense(combinedText);
        if (copyleftMatch) {
            const shouldBlock = this.gcaConfig?.blockCopyleftCitations === true ||
                this._isRegulatedBinding();
            if (shouldBlock) {
                const decision = {
                    decision: 'DENY',
                    reason: `Code citation blocked: copyleft license '${copyleftMatch}' detected in generated code. ` +
                        `Copyleft code cannot be incorporated into proprietary or regulated software without ` +
                        `satisfying license terms. Source: ${sourceUrl ?? 'unknown'}.`,
                    metadata: {
                        spdxLicense: copyleftMatch,
                        sourceUrl,
                        blocked: true,
                    },
                };
                this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-denied', {
                    ideId: this.ideId,
                    adapterId: this.adapterId,
                    tool: 'gca:code-citation-received',
                    detail: decision.reason,
                    data: { spdxLicense: copyleftMatch, sourceUrl },
                }));
                return decision;
            }
            // Not configured to block -- allow with WARN audit
            this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-approved', {
                ideId: this.ideId,
                adapterId: this.adapterId,
                tool: 'gca:code-citation-received',
                detail: `Code citation with copyleft license '${copyleftMatch}' allowed (no block policy active). Source: ${sourceUrl ?? 'unknown'}. Review required.`,
                data: { spdxLicense: copyleftMatch, sourceUrl, warnOnly: true },
            }));
            return {
                decision: 'ALLOW',
                reason: `Copyleft license '${copyleftMatch}' detected but no block policy configured. ` +
                    `Enable blockCopyleftCitations: true or bind a regulated pack to enforce blocking.`,
                metadata: { spdxLicense: copyleftMatch, sourceUrl, warnOnly: true },
            };
        }
        // No copyleft match -- permit with audit
        this.emit((0, shared_1.buildIdeAuditEvent)('ide:tool-invocation-approved', {
            ideId: this.ideId,
            adapterId: this.adapterId,
            tool: 'gca:code-citation-received',
            detail: `Code citation permitted. License: ${spdxLicense ?? 'unknown'}. Source: ${sourceUrl ?? 'unknown'}.`,
            data: { spdxLicense, sourceUrl },
        }));
        return {
            decision: 'ALLOW',
            reason: `Code citation passed license check. License: ${spdxLicense ?? 'unknown'}.`,
            metadata: { spdxLicense, sourceUrl, codeSnippet },
        };
    }
    // ---------------------------------------------------------------------------
    // interceptToolInvocation dispatch helpers for Gemini-specific surfaces
    // ---------------------------------------------------------------------------
    async _gateCloudWorkspaceOperation(ctx) {
        return this.cloudWorkspaceOperationRequested({
            workspaceName: String(ctx.input['workspaceName'] ?? ctx.input['workspace'] ?? 'unknown'),
            operation: String(ctx.input['operation'] ?? ''),
            resourceType: ctx.input['resourceType'],
            gcpProject: ctx.input['gcpProject'],
            region: ctx.input['region'],
            sessionId: ctx.sessionHandle.sessionId,
        });
    }
    async _gateDataSovereignty(ctx) {
        return this.dataSovereigntyCheckRequested({
            gcpRegion: String(ctx.input['gcpRegion'] ?? ctx.input['region'] ?? this.gcaConfig?.gcpRegion ?? 'us-central1'),
            dataClass: String(ctx.input['dataClass'] ?? 'unknown'),
            sessionId: ctx.sessionHandle.sessionId,
        });
    }
    async _gateCitationReceived(ctx) {
        return this.duetCodeCitationReceived({
            spdxLicense: ctx.input['spdxLicense'],
            licenseText: ctx.input['licenseText'],
            sourceUrl: ctx.input['sourceUrl'],
            codeSnippet: ctx.input['codeSnippet'],
            sessionId: ctx.sessionHandle.sessionId,
        });
    }
    // ---------------------------------------------------------------------------
    // IdeAdapter: getIdeCapabilities
    // ---------------------------------------------------------------------------
    getIdeCapabilities() {
        return {
            runtimeHooks: true,
            prBoundary: false,
            userIdentity: true,
            reviewerRouting: true,
            integrationMode: 'gemini-code-assist-normalised-event-shim',
        };
    }
    // ---------------------------------------------------------------------------
    // Error translation
    // ---------------------------------------------------------------------------
    translateError(raw) {
        if (raw instanceof index_1.IdeAttributionError)
            return raw;
        if (raw instanceof index_1.IdeUnsupportedError)
            return raw;
        return super.translateError(raw);
    }
    // ---------------------------------------------------------------------------
    // Helpers
    // ---------------------------------------------------------------------------
    _scanForSecrets(text) {
        if (!text)
            return null;
        for (const { name, re } of GCA_SECRET_PATTERNS) {
            if (re.test(text))
                return name;
        }
        return null;
    }
    _scanForPhiIndicators(text) {
        if (!text)
            return null;
        for (const re of GCA_PHI_INDICATORS) {
            if (re.test(text))
                return re.source;
        }
        return null;
    }
    _detectCopyleftLicense(text) {
        if (!text)
            return null;
        for (const { spdx, re } of COPYLEFT_LICENSE_PATTERNS) {
            if (re.test(text))
                return spdx;
        }
        return null;
    }
    _isHipaaBinding() {
        const packId = this.config?.packId ?? '';
        return packId === 'hipaa' || packId.startsWith('hipaa') || packId === 'hitech' || packId.startsWith('hitech');
    }
    _isGdprBinding() {
        const packId = this.config?.packId ?? '';
        return packId === 'gdpr' || packId.startsWith('gdpr');
    }
    _isRegulatedBinding() {
        const packId = this.config?.packId ?? '';
        return (packId === 'hipaa' || packId.startsWith('hipaa') ||
            packId === 'hitech' || packId.startsWith('hitech') ||
            packId === 'pci-dss' || packId.startsWith('pci') ||
            packId === 'gdpr' || packId.startsWith('gdpr') ||
            packId === 'soc2' || packId.startsWith('soc2'));
    }
    /**
     * Check region compliance for a tool invocation context.
     * Returns a DENY decision if non-compliant, or null if compliant.
     * Used by completion and chat gates (PT-ADAPT-GEMINI-1).
     */
    _checkRegionCompliance(ctx) {
        const region = this.gcaConfig?.gcpRegion ?? 'us-central1';
        if (this._isHipaaBinding() && !exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.includes(region)) {
            return {
                decision: 'DENY',
                reason: `Gemini Code Assist request blocked: GCP region '${region}' is not HIPAA-eligible ` +
                    `under pack binding '${this.config?.packId}'. ` +
                    `HIPAA-eligible regions: ${exports.GEMINI_HIPAA_ELIGIBLE_REGIONS.join(', ')}.`,
                metadata: {
                    region,
                    packId: this.config?.packId,
                    hipaaEligibleRegions: exports.GEMINI_HIPAA_ELIGIBLE_REGIONS,
                },
            };
        }
        if (this._isGdprBinding() && !exports.GEMINI_GDPR_ADEQUATE_REGIONS.includes(region)) {
            return {
                decision: 'DENY',
                reason: `Gemini Code Assist request blocked: GCP region '${region}' is not in a GDPR-adequate ` +
                    `jurisdiction under pack binding '${this.config?.packId}'. ` +
                    `GDPR-adequate regions: ${exports.GEMINI_GDPR_ADEQUATE_REGIONS.join(', ')}.`,
                metadata: {
                    region,
                    packId: this.config?.packId,
                    gdprAdequateRegions: exports.GEMINI_GDPR_ADEQUATE_REGIONS,
                },
            };
        }
        return null;
    }
    /** Expose the configured GCP region for diagnostics / tests. */
    getGcpRegion() {
        return this.gcaConfig?.gcpRegion ?? 'us-central1';
    }
}
exports.GeminiCodeAssistIdeAdapter = GeminiCodeAssistIdeAdapter;
//# sourceMappingURL=gemini-code-assist.js.map