// SPDX-License-Identifier: Apache-2.0
// Copyright 2024-2026 Vorion LLC
/**
 * FedRAMP System Boundary Documentation
 *
 * Manages system boundary documentation including:
 * - Component inventory
 * - Data flow diagrams (metadata)
 * - Network diagrams (metadata)
 * - Interconnections tracking
 * - External services documentation
 *
 * @packageDocumentation
 */
import { randomUUID } from 'crypto';
import { z } from 'zod';
import { createLogger } from '../../common/logger.js';
const logger = createLogger({ component: 'fedramp-boundary' });
// =============================================================================
// TYPES
// =============================================================================
/**
 * Component types within the boundary
 */
export const COMPONENT_TYPES = [
    'server',
    'database',
    'load-balancer',
    'firewall',
    'storage',
    'container',
    'serverless',
    'api-gateway',
    'message-queue',
    'cache',
    'monitoring',
    'logging',
    'identity-provider',
    'dns',
    'cdn',
    'waf',
    'vpn',
    'hsm',
    'secrets-manager',
    'workstation',
    'mobile-device',
    'network-device',
    'other',
];
/**
 * Component status
 */
export const COMPONENT_STATUSES = [
    'production',
    'development',
    'staging',
    'decommissioned',
    'planned',
];
/**
 * Data classification levels
 */
export const DATA_CLASSIFICATIONS = [
    'public',
    'internal',
    'confidential',
    'restricted',
    'cui', // Controlled Unclassified Information
    'pii', // Personally Identifiable Information
    'phi', // Protected Health Information
];
/**
 * Connection type
 */
export const CONNECTION_TYPES = [
    'https',
    'tls',
    'ssh',
    'vpn',
    'direct-connect',
    'ipsec',
    'mtls',
    'api',
    'database',
    'internal',
];
/**
 * Interconnection type
 */
export const INTERCONNECTION_TYPES = [
    'federal-agency',
    'commercial-csp',
    'third-party-service',
    'partner-organization',
    'customer-system',
];
/**
 * External service type
 */
export const EXTERNAL_SERVICE_TYPES = [
    'saas',
    'paas',
    'iaas',
    'api-service',
    'identity-provider',
    'payment-processor',
    'email-service',
    'monitoring-service',
    'cdn',
    'dns',
    'security-service',
    'other',
];
export const systemComponentSchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1),
    type: z.enum(COMPONENT_TYPES),
    description: z.string().min(1),
    status: z.enum(COMPONENT_STATUSES),
    withinBoundary: z.boolean(),
    ipAddresses: z.array(z.string()).optional(),
    hostname: z.string().optional(),
    operatingSystem: z.string().optional(),
    software: z
        .array(z.object({
        name: z.string(),
        version: z.string(),
        vendor: z.string(),
        patchLevel: z.string().optional(),
    }))
        .optional(),
    location: z.string().min(1),
    cloudProvider: z.string().optional(),
    cloudRegion: z.string().optional(),
    availabilityZone: z.string().optional(),
    owner: z.string().min(1),
    dataClassifications: z.array(z.enum(DATA_CLASSIFICATIONS)),
    securityControls: z.array(z.string()),
    lastScanDate: z.coerce.date().optional(),
    assetTag: z.string().optional(),
    serialNumber: z.string().optional(),
    purchaseDate: z.coerce.date().optional(),
    endOfLifeDate: z.coerce.date().optional(),
    isVirtual: z.boolean(),
    parentComponentId: z.string().optional(),
    tags: z.array(z.string()),
    metadata: z.record(z.unknown()).optional(),
});
export const dataFlowSchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1),
    description: z.string().min(1),
    sourceComponentId: z.string().min(1),
    destinationComponentId: z.string().min(1),
    dataTypes: z.array(z.string()),
    dataClassifications: z.array(z.enum(DATA_CLASSIFICATIONS)),
    connectionType: z.enum(CONNECTION_TYPES),
    protocol: z.string().min(1),
    ports: z.array(z.number().int().positive()),
    isEncrypted: z.boolean(),
    encryptionMethod: z.string().optional(),
    direction: z.enum(['unidirectional', 'bidirectional']),
    isRequired: z.boolean(),
    associatedControls: z.array(z.string()),
    diagramReference: z.string().optional(),
});
export const networkZoneSchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1),
    description: z.string().min(1),
    cidrRanges: z.array(z.string()),
    securityLevel: z.enum(['dmz', 'internal', 'restricted', 'management']),
    componentIds: z.array(z.string()),
    allowedInbound: z.array(z.object({
        fromZone: z.string(),
        ports: z.array(z.number()),
        protocol: z.string(),
    })),
    allowedOutbound: z.array(z.object({
        toZone: z.string(),
        ports: z.array(z.number()),
        protocol: z.string(),
    })),
    firewallRulesRef: z.string().optional(),
});
export const systemInterconnectionSchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1),
    description: z.string().min(1),
    type: z.enum(INTERCONNECTION_TYPES),
    remoteSystemName: z.string().min(1),
    remoteOrganization: z.string().min(1),
    remotePoc: z.object({
        name: z.string().min(1),
        email: z.string().email(),
        phone: z.string().optional(),
    }),
    localPoc: z.object({
        name: z.string().min(1),
        email: z.string().email(),
        phone: z.string().optional(),
    }),
    connectionType: z.enum(CONNECTION_TYPES),
    dataShared: z.array(z.enum(DATA_CLASSIFICATIONS)),
    direction: z.enum(['inbound', 'outbound', 'bidirectional']),
    securityRequirements: z.array(z.string()),
    agreementDocRef: z.string().optional(),
    agreementEffectiveDate: z.coerce.date().optional(),
    agreementExpirationDate: z.coerce.date().optional(),
    status: z.enum(['proposed', 'pending-approval', 'active', 'suspended', 'terminated']),
    associatedControls: z.array(z.string()),
    atcReference: z.string().optional(),
    lastReviewDate: z.coerce.date().optional(),
    reviewFrequency: z.enum(['annual', 'biannual', 'quarterly']),
});
export const externalServiceSchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1),
    type: z.enum(EXTERNAL_SERVICE_TYPES),
    provider: z.string().min(1),
    description: z.string().min(1),
    purpose: z.string().min(1),
    dataClassifications: z.array(z.enum(DATA_CLASSIFICATIONS)),
    isFedRAMPAuthorized: z.boolean(),
    fedrampPackageId: z.string().optional(),
    fedrampLevel: z.enum(['low', 'moderate', 'high', 'li-saas']).optional(),
    authorizationDate: z.coerce.date().optional(),
    contractReference: z.string().optional(),
    connectionType: z.enum(CONNECTION_TYPES),
    apiEndpoints: z.array(z.string()).optional(),
    status: z.enum(['active', 'pending', 'deprecated', 'terminated']),
    responsibleParty: z.string().min(1),
    securityReviewDate: z.coerce.date().optional(),
    riskAssessmentRef: z.string().optional(),
    associatedControls: z.array(z.string()),
    slaReference: z.string().optional(),
    dpaReference: z.string().optional(),
});
export const diagramMetadataSchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1),
    type: z.enum(['network', 'data-flow', 'system-architecture', 'boundary', 'deployment']),
    description: z.string().min(1),
    version: z.string().min(1),
    lastUpdated: z.coerce.date(),
    author: z.string().min(1),
    fileReference: z.string().min(1),
    fileFormat: z.enum(['pdf', 'png', 'visio', 'drawio', 'lucidchart']),
    componentsDepicted: z.array(z.string()),
    dataFlowsDepicted: z.array(z.string()).optional(),
    reviewStatus: z.enum(['draft', 'reviewed', 'approved']),
    reviewedBy: z.string().optional(),
    reviewDate: z.coerce.date().optional(),
});
// =============================================================================
// BOUNDARY SERVICE
// =============================================================================
/**
 * System Boundary Management Service
 */
export class BoundaryService {
    config;
    components;
    dataFlows;
    networkZones;
    interconnections;
    externalServices;
    diagrams;
    constructor(config) {
        this.config = config;
        this.components = new Map();
        this.dataFlows = new Map();
        this.networkZones = new Map();
        this.interconnections = new Map();
        this.externalServices = new Map();
        this.diagrams = new Map();
        logger.info({ systemName: config.systemName }, 'Boundary service initialized');
    }
    // ===========================================================================
    // COMPONENT MANAGEMENT
    // ===========================================================================
    /**
     * Add a system component
     */
    addComponent(component) {
        const id = `COMP-${randomUUID().slice(0, 8).toUpperCase()}`;
        const newComponent = { ...component, id };
        systemComponentSchema.parse(newComponent);
        this.components.set(id, newComponent);
        logger.info({ componentId: id, name: component.name, type: component.type }, 'Component added to inventory');
        return newComponent;
    }
    /**
     * Update a component
     */
    updateComponent(id, updates) {
        const existing = this.components.get(id);
        if (!existing) {
            throw new Error(`Component not found: ${id}`);
        }
        const updated = { ...existing, ...updates, id };
        systemComponentSchema.parse(updated);
        this.components.set(id, updated);
        logger.info({ componentId: id }, 'Component updated');
        return updated;
    }
    /**
     * Remove a component
     */
    removeComponent(id) {
        if (!this.components.has(id)) {
            throw new Error(`Component not found: ${id}`);
        }
        this.components.delete(id);
        // Remove from network zones
        for (const zone of Array.from(this.networkZones.values())) {
            zone.componentIds = zone.componentIds.filter((cid) => cid !== id);
        }
        // Remove associated data flows
        for (const [flowId, flow] of Array.from(this.dataFlows.entries())) {
            if (flow.sourceComponentId === id || flow.destinationComponentId === id) {
                this.dataFlows.delete(flowId);
            }
        }
        logger.info({ componentId: id }, 'Component removed');
    }
    /**
     * Get component by ID
     */
    getComponent(id) {
        return this.components.get(id);
    }
    /**
     * Get all components
     */
    getAllComponents(filter) {
        let components = Array.from(this.components.values());
        if (filter?.type) {
            components = components.filter((c) => c.type === filter.type);
        }
        if (filter?.status) {
            components = components.filter((c) => c.status === filter.status);
        }
        if (filter?.withinBoundary !== undefined) {
            components = components.filter((c) => c.withinBoundary === filter.withinBoundary);
        }
        if (filter?.dataClassification) {
            components = components.filter((c) => c.dataClassifications.includes(filter.dataClassification));
        }
        return components;
    }
    /**
     * Get components within authorization boundary
     */
    getBoundaryComponents() {
        return this.getAllComponents({ withinBoundary: true });
    }
    // ===========================================================================
    // DATA FLOW MANAGEMENT
    // ===========================================================================
    /**
     * Add a data flow
     */
    addDataFlow(flow) {
        // Validate source and destination exist
        if (!this.components.has(flow.sourceComponentId)) {
            throw new Error(`Source component not found: ${flow.sourceComponentId}`);
        }
        if (!this.components.has(flow.destinationComponentId)) {
            throw new Error(`Destination component not found: ${flow.destinationComponentId}`);
        }
        const id = `FLOW-${randomUUID().slice(0, 8).toUpperCase()}`;
        const newFlow = { ...flow, id };
        dataFlowSchema.parse(newFlow);
        this.dataFlows.set(id, newFlow);
        logger.info({
            flowId: id,
            name: flow.name,
            source: flow.sourceComponentId,
            destination: flow.destinationComponentId,
        }, 'Data flow added');
        return newFlow;
    }
    /**
     * Get all data flows
     */
    getAllDataFlows(filter) {
        let flows = Array.from(this.dataFlows.values());
        if (filter?.sourceComponentId) {
            flows = flows.filter((f) => f.sourceComponentId === filter.sourceComponentId);
        }
        if (filter?.destinationComponentId) {
            flows = flows.filter((f) => f.destinationComponentId === filter.destinationComponentId);
        }
        if (filter?.dataClassification) {
            flows = flows.filter((f) => f.dataClassifications.includes(filter.dataClassification));
        }
        return flows;
    }
    /**
     * Get data flows for a component
     */
    getComponentDataFlows(componentId) {
        return Array.from(this.dataFlows.values()).filter((f) => f.sourceComponentId === componentId || f.destinationComponentId === componentId);
    }
    // ===========================================================================
    // NETWORK ZONE MANAGEMENT
    // ===========================================================================
    /**
     * Add a network zone
     */
    addNetworkZone(zone) {
        const id = `ZONE-${randomUUID().slice(0, 8).toUpperCase()}`;
        const newZone = { ...zone, id };
        networkZoneSchema.parse(newZone);
        this.networkZones.set(id, newZone);
        logger.info({ zoneId: id, name: zone.name }, 'Network zone added');
        return newZone;
    }
    /**
     * Get all network zones
     */
    getAllNetworkZones() {
        return Array.from(this.networkZones.values());
    }
    /**
     * Add component to zone
     */
    addComponentToZone(zoneId, componentId) {
        const zone = this.networkZones.get(zoneId);
        if (!zone) {
            throw new Error(`Network zone not found: ${zoneId}`);
        }
        if (!this.components.has(componentId)) {
            throw new Error(`Component not found: ${componentId}`);
        }
        if (!zone.componentIds.includes(componentId)) {
            zone.componentIds.push(componentId);
            this.networkZones.set(zoneId, zone);
        }
    }
    // ===========================================================================
    // INTERCONNECTION MANAGEMENT
    // ===========================================================================
    /**
     * Add a system interconnection
     */
    addInterconnection(interconnection) {
        const id = `ISA-${randomUUID().slice(0, 8).toUpperCase()}`;
        const newInterconnection = { ...interconnection, id };
        systemInterconnectionSchema.parse(newInterconnection);
        this.interconnections.set(id, newInterconnection);
        logger.info({
            interconnectionId: id,
            name: interconnection.name,
            remoteSystem: interconnection.remoteSystemName,
        }, 'System interconnection added');
        return newInterconnection;
    }
    /**
     * Update interconnection status
     */
    updateInterconnectionStatus(id, status) {
        const interconnection = this.interconnections.get(id);
        if (!interconnection) {
            throw new Error(`Interconnection not found: ${id}`);
        }
        interconnection.status = status;
        this.interconnections.set(id, interconnection);
        logger.info({ interconnectionId: id, status }, 'Interconnection status updated');
        return interconnection;
    }
    /**
     * Get all interconnections
     */
    getAllInterconnections(filter) {
        let interconnections = Array.from(this.interconnections.values());
        if (filter?.type) {
            interconnections = interconnections.filter((i) => i.type === filter.type);
        }
        if (filter?.status) {
            interconnections = interconnections.filter((i) => i.status === filter.status);
        }
        return interconnections;
    }
    /**
     * Get interconnections needing review
     */
    getInterconnectionsNeedingReview() {
        const now = new Date();
        return Array.from(this.interconnections.values()).filter((i) => {
            if (!i.lastReviewDate)
                return true;
            const monthsSinceReview = Math.floor((now.getTime() - i.lastReviewDate.getTime()) / (1000 * 60 * 60 * 24 * 30));
            const reviewPeriods = {
                quarterly: 3,
                biannual: 6,
                annual: 12,
            };
            return monthsSinceReview >= reviewPeriods[i.reviewFrequency];
        });
    }
    /**
     * Get expiring agreements
     */
    getExpiringAgreements(daysThreshold = 90) {
        const threshold = new Date();
        threshold.setDate(threshold.getDate() + daysThreshold);
        return Array.from(this.interconnections.values()).filter((i) => i.status === 'active' &&
            i.agreementExpirationDate &&
            i.agreementExpirationDate <= threshold);
    }
    // ===========================================================================
    // EXTERNAL SERVICE MANAGEMENT
    // ===========================================================================
    /**
     * Add an external service
     */
    addExternalService(service) {
        const id = `EXT-${randomUUID().slice(0, 8).toUpperCase()}`;
        const newService = { ...service, id };
        externalServiceSchema.parse(newService);
        this.externalServices.set(id, newService);
        logger.info({
            serviceId: id,
            name: service.name,
            provider: service.provider,
            isFedRAMPAuthorized: service.isFedRAMPAuthorized,
        }, 'External service added');
        return newService;
    }
    /**
     * Get all external services
     */
    getAllExternalServices(filter) {
        let services = Array.from(this.externalServices.values());
        if (filter?.type) {
            services = services.filter((s) => s.type === filter.type);
        }
        if (filter?.status) {
            services = services.filter((s) => s.status === filter.status);
        }
        if (filter?.isFedRAMPAuthorized !== undefined) {
            services = services.filter((s) => s.isFedRAMPAuthorized === filter.isFedRAMPAuthorized);
        }
        return services;
    }
    /**
     * Get non-FedRAMP authorized services (requires risk assessment)
     */
    getNonFedRAMPServices() {
        return this.getAllExternalServices({ isFedRAMPAuthorized: false, status: 'active' });
    }
    // ===========================================================================
    // DIAGRAM MANAGEMENT
    // ===========================================================================
    /**
     * Add diagram metadata
     */
    addDiagram(diagram) {
        const id = `DGM-${randomUUID().slice(0, 8).toUpperCase()}`;
        const newDiagram = { ...diagram, id };
        diagramMetadataSchema.parse(newDiagram);
        this.diagrams.set(id, newDiagram);
        logger.info({ diagramId: id, name: diagram.name, type: diagram.type }, 'Diagram added');
        return newDiagram;
    }
    /**
     * Get all diagrams
     */
    getAllDiagrams(filter) {
        let diagrams = Array.from(this.diagrams.values());
        if (filter?.type) {
            diagrams = diagrams.filter((d) => d.type === filter.type);
        }
        if (filter?.reviewStatus) {
            diagrams = diagrams.filter((d) => d.reviewStatus === filter.reviewStatus);
        }
        return diagrams;
    }
    // ===========================================================================
    // REPORTING
    // ===========================================================================
    /**
     * Generate boundary inventory summary
     */
    generateInventorySummary() {
        const components = Array.from(this.components.values());
        const boundaryComponents = components.filter((c) => c.withinBoundary);
        const componentsByType = {};
        for (const comp of boundaryComponents) {
            componentsByType[comp.type] = (componentsByType[comp.type] || 0) + 1;
        }
        const componentsByStatus = {};
        for (const comp of boundaryComponents) {
            componentsByStatus[comp.status] = (componentsByStatus[comp.status] || 0) + 1;
        }
        const dataClassificationsHandled = new Set();
        for (const comp of boundaryComponents) {
            for (const dc of comp.dataClassifications) {
                dataClassificationsHandled.add(dc);
            }
        }
        return {
            generatedDate: new Date(),
            systemName: this.config.systemName,
            authorizationLevel: this.config.authorizationLevel,
            totalComponents: components.length,
            boundaryComponents: boundaryComponents.length,
            componentsByType,
            componentsByStatus,
            dataFlowCount: this.dataFlows.size,
            networkZoneCount: this.networkZones.size,
            activeInterconnections: this.getAllInterconnections({ status: 'active' }).length,
            activeExternalServices: this.getAllExternalServices({ status: 'active' }).length,
            nonFedRAMPServices: this.getNonFedRAMPServices().length,
            dataClassificationsHandled: Array.from(dataClassificationsHandled),
            diagramsApproved: this.getAllDiagrams({ reviewStatus: 'approved' }).length,
            interconnectionsNeedingReview: this.getInterconnectionsNeedingReview().length,
            expiringAgreements: this.getExpiringAgreements().length,
        };
    }
    /**
     * Export boundary documentation for SSP
     */
    exportForSSP() {
        return {
            systemDescription: {
                systemName: this.config.systemName,
                organizationName: this.config.organizationName,
                boundaryDescription: this.config.boundaryDescription,
                authorizationLevel: this.config.authorizationLevel,
            },
            componentInventory: this.getBoundaryComponents(),
            dataFlows: Array.from(this.dataFlows.values()),
            networkZones: Array.from(this.networkZones.values()),
            interconnections: this.getAllInterconnections({ status: 'active' }),
            externalServices: this.getAllExternalServices({ status: 'active' }),
            diagrams: this.getAllDiagrams({ reviewStatus: 'approved' }),
        };
    }
}
// =============================================================================
// EXPORTS
// =============================================================================
export default BoundaryService;
//# sourceMappingURL=boundary.js.map