// SPDX-License-Identifier: Apache-2.0
// Copyright 2024-2026 Vorion LLC
/**
 * Security Policy Engine Types
 *
 * Type definitions for the flexible security policy engine including:
 * - Policy conditions (user, request, time, risk, resource attributes)
 * - Policy rules (MFA, approval, block, rate-limit, encryption, audit)
 * - Policy actions (allow, deny, challenge, notify, log, escalate, quarantine)
 * - Policy DSL schema
 *
 * @packageDocumentation
 */
import { z } from 'zod';
// =============================================================================
// CONDITION OPERATORS
// =============================================================================
export const ConditionOperator = {
    EQUALS: 'equals',
    NOT_EQUALS: 'not_equals',
    GREATER_THAN: 'greater_than',
    LESS_THAN: 'less_than',
    GREATER_THAN_OR_EQUAL: 'greater_than_or_equal',
    LESS_THAN_OR_EQUAL: 'less_than_or_equal',
    IN: 'in',
    NOT_IN: 'not_in',
    CONTAINS: 'contains',
    NOT_CONTAINS: 'not_contains',
    STARTS_WITH: 'starts_with',
    ENDS_WITH: 'ends_with',
    MATCHES: 'matches',
    EXISTS: 'exists',
    NOT_EXISTS: 'not_exists',
    BETWEEN: 'between',
};
export const conditionOperatorSchema = z.nativeEnum(ConditionOperator);
// =============================================================================
// LOGICAL OPERATORS
// =============================================================================
export const LogicalOperator = {
    AND: 'and',
    OR: 'or',
    NOT: 'not',
};
export const logicalOperatorSchema = z.nativeEnum(LogicalOperator);
// =============================================================================
// CONDITION TYPES
// =============================================================================
export const ConditionType = {
    USER_ATTRIBUTE: 'user_attribute',
    REQUEST_ATTRIBUTE: 'request_attribute',
    TIME_BASED: 'time_based',
    RISK_BASED: 'risk_based',
    RESOURCE_ATTRIBUTE: 'resource_attribute',
    COMPOSITE: 'composite',
    CUSTOM: 'custom',
};
export const conditionTypeSchema = z.nativeEnum(ConditionType);
export const userAttributeConditionSchema = z.object({
    type: z.literal('user_attribute'),
    field: z.enum(['role', 'department', 'tenant', 'groups', 'permissions', 'email_domain', 'custom']),
    customField: z.string().optional(),
    operator: conditionOperatorSchema,
    value: z.unknown(),
});
export const requestAttributeConditionSchema = z.object({
    type: z.literal('request_attribute'),
    field: z.enum(['ip', 'user_agent', 'path', 'method', 'header', 'query', 'body', 'origin', 'referer', 'custom']),
    customField: z.string().optional(),
    headerName: z.string().optional(),
    queryParam: z.string().optional(),
    bodyPath: z.string().optional(),
    operator: conditionOperatorSchema,
    value: z.unknown(),
});
export const timeBasedConditionSchema = z.object({
    type: z.literal('time_based'),
    field: z.enum(['hour', 'day_of_week', 'date', 'business_hours', 'weekend', 'holiday', 'custom']),
    timezone: z.string().optional(),
    startHour: z.number().int().min(0).max(23).optional(),
    endHour: z.number().int().min(0).max(23).optional(),
    daysOfWeek: z.array(z.number().int().min(0).max(6)).optional(),
    dates: z.array(z.string()).optional(),
    holidayCalendar: z.string().optional(),
    operator: conditionOperatorSchema,
    value: z.unknown(),
});
export const riskBasedConditionSchema = z.object({
    type: z.literal('risk_based'),
    field: z.enum(['user_risk_score', 'ip_reputation', 'device_trust', 'session_risk', 'anomaly_score', 'threat_level', 'custom']),
    customField: z.string().optional(),
    operator: conditionOperatorSchema,
    value: z.unknown(),
    threshold: z.number().optional(),
});
export const resourceAttributeConditionSchema = z.object({
    type: z.literal('resource_attribute'),
    field: z.enum(['sensitivity_level', 'data_type', 'classification', 'owner', 'department', 'region', 'tags', 'custom']),
    customField: z.string().optional(),
    operator: conditionOperatorSchema,
    value: z.unknown(),
});
export const customConditionSchema = z.object({
    type: z.literal('custom'),
    expression: z.string().min(1),
    language: z.enum(['jsonpath', 'cel', 'jmespath', 'custom']).optional(),
    params: z.record(z.unknown()).optional(),
});
// Base condition schema without composite (to avoid circular reference)
const baseConditionSchema = z.discriminatedUnion('type', [
    userAttributeConditionSchema,
    requestAttributeConditionSchema,
    timeBasedConditionSchema,
    riskBasedConditionSchema,
    resourceAttributeConditionSchema,
    customConditionSchema,
]);
// Use any for recursive schema to avoid TypeScript issues
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const policyConditionSchema = z.lazy(() => z.union([
    baseConditionSchema,
    z.object({
        type: z.literal('composite'),
        operator: logicalOperatorSchema,
        conditions: z.array(policyConditionSchema),
    }),
]));
// Composite condition schema for direct use
export const compositeConditionSchema = z.object({
    type: z.literal('composite'),
    operator: logicalOperatorSchema,
    conditions: z.array(policyConditionSchema),
});
// =============================================================================
// POLICY RULE TYPES
// =============================================================================
export const PolicyRuleType = {
    REQUIRE_MFA: 'require_mfa',
    REQUIRE_APPROVAL: 'require_approval',
    BLOCK_ACCESS: 'block_access',
    RATE_LIMIT: 'rate_limit',
    REQUIRE_ENCRYPTION: 'require_encryption',
    AUDIT_LOG: 'audit_log',
    STEP_UP_AUTH: 'step_up_auth',
    DATA_MASKING: 'data_masking',
    SESSION_TIMEOUT: 'session_timeout',
    GEO_RESTRICTION: 'geo_restriction',
    CUSTOM: 'custom',
};
export const policyRuleTypeSchema = z.nativeEnum(PolicyRuleType);
export const mfaRuleSchema = z.object({
    type: z.literal('require_mfa'),
    enforced: z.boolean(),
    methods: z.array(z.enum(['totp', 'sms', 'email', 'push', 'webauthn', 'hardware_key'])).optional(),
    timeout: z.number().int().positive().optional(),
    rememberDevice: z.boolean().optional(),
    rememberDuration: z.number().int().positive().optional(),
});
export const approvalRuleSchema = z.object({
    type: z.literal('require_approval'),
    enforced: z.boolean(),
    approvers: z.array(z.string()).optional(),
    approverRoles: z.array(z.string()).optional(),
    approvalTimeout: z.number().int().positive().optional(),
    minApprovers: z.number().int().positive().optional(),
    autoRejectOnTimeout: z.boolean().optional(),
    requireJustification: z.boolean().optional(),
});
export const blockAccessRuleSchema = z.object({
    type: z.literal('block_access'),
    enforced: z.boolean(),
    reason: z.string().optional(),
    errorCode: z.string().optional(),
    redirectUrl: z.string().url().optional(),
});
export const rateLimitRuleSchema = z.object({
    type: z.literal('rate_limit'),
    enforced: z.boolean(),
    limit: z.number().int().positive(),
    window: z.number().int().positive(),
    windowUnit: z.enum(['second', 'minute', 'hour', 'day']).optional(),
    keyBy: z.array(z.enum(['user', 'ip', 'tenant', 'api_key', 'custom'])).optional(),
    customKey: z.string().optional(),
    burstLimit: z.number().int().positive().optional(),
    retryAfter: z.number().int().positive().optional(),
});
export const encryptionRuleSchema = z.object({
    type: z.literal('require_encryption'),
    enforced: z.boolean(),
    fields: z.array(z.string()).optional(),
    algorithm: z.enum(['AES-256-GCM', 'RSA-OAEP', 'ChaCha20-Poly1305']).optional(),
    keyId: z.string().optional(),
});
export const auditLogRuleSchema = z.object({
    type: z.literal('audit_log'),
    enforced: z.boolean(),
    level: z.enum(['basic', 'detailed', 'full']).optional(),
    includeRequest: z.boolean().optional(),
    includeResponse: z.boolean().optional(),
    includeHeaders: z.boolean().optional(),
    redactFields: z.array(z.string()).optional(),
    destination: z.string().optional(),
});
export const stepUpAuthRuleSchema = z.object({
    type: z.literal('step_up_auth'),
    enforced: z.boolean(),
    requiredLevel: z.number().int().min(0).max(7),
    method: z.enum(['mfa', 'password', 'biometric']).optional(),
    timeout: z.number().int().positive().optional(),
});
export const dataMaskingRuleSchema = z.object({
    type: z.literal('data_masking'),
    enforced: z.boolean(),
    fields: z.array(z.string()),
    maskType: z.enum(['full', 'partial', 'hash', 'tokenize']).optional(),
    partialMaskPattern: z.string().optional(),
});
export const sessionTimeoutRuleSchema = z.object({
    type: z.literal('session_timeout'),
    enforced: z.boolean(),
    maxDuration: z.number().int().positive().optional(),
    idleTimeout: z.number().int().positive().optional(),
    requireReauth: z.boolean().optional(),
});
export const geoRestrictionRuleSchema = z.object({
    type: z.literal('geo_restriction'),
    enforced: z.boolean(),
    allowedCountries: z.array(z.string()).optional(),
    blockedCountries: z.array(z.string()).optional(),
    allowedRegions: z.array(z.string()).optional(),
    blockedRegions: z.array(z.string()).optional(),
});
export const customRuleSchema = z.object({
    type: z.literal('custom'),
    enforced: z.boolean(),
    handler: z.string().min(1),
    config: z.record(z.unknown()).optional(),
});
export const policyRuleSchema = z.discriminatedUnion('type', [
    mfaRuleSchema,
    approvalRuleSchema,
    blockAccessRuleSchema,
    rateLimitRuleSchema,
    encryptionRuleSchema,
    auditLogRuleSchema,
    stepUpAuthRuleSchema,
    dataMaskingRuleSchema,
    sessionTimeoutRuleSchema,
    geoRestrictionRuleSchema,
    customRuleSchema,
]);
// =============================================================================
// POLICY ACTION TYPES
// =============================================================================
export const PolicyActionType = {
    ALLOW: 'allow',
    DENY: 'deny',
    CHALLENGE: 'challenge',
    NOTIFY: 'notify',
    LOG: 'log',
    ESCALATE: 'escalate',
    QUARANTINE: 'quarantine',
    REDIRECT: 'redirect',
    MODIFY: 'modify',
};
export const policyActionTypeSchema = z.nativeEnum(PolicyActionType);
export const allowActionSchema = z.object({
    type: z.literal('allow'),
    message: z.string().optional(),
    metadata: z.record(z.unknown()).optional(),
});
export const denyActionSchema = z.object({
    type: z.literal('deny'),
    reason: z.string().min(1),
    errorCode: z.string().optional(),
    httpStatus: z.number().int().min(400).max(599).optional(),
    retryable: z.boolean().optional(),
    retryAfter: z.number().int().positive().optional(),
});
export const challengeActionSchema = z.object({
    type: z.literal('challenge'),
    method: z.enum(['mfa', 'password', 'captcha', 'approval', 'custom']),
    timeout: z.number().int().positive().optional(),
    redirectUrl: z.string().url().optional(),
    customChallenge: z.string().optional(),
});
export const notifyActionSchema = z.object({
    type: z.literal('notify'),
    channels: z.array(z.enum(['email', 'slack', 'pagerduty', 'webhook', 'sms'])),
    recipients: z.array(z.string()).optional(),
    severity: z.enum(['low', 'medium', 'high', 'critical']),
    template: z.string().optional(),
    includeContext: z.boolean().optional(),
});
export const logActionSchema = z.object({
    type: z.literal('log'),
    level: z.enum(['debug', 'info', 'warn', 'error']),
    message: z.string().optional(),
    includeContext: z.boolean().optional(),
    includeRequest: z.boolean().optional(),
    includeUser: z.boolean().optional(),
    destination: z.string().optional(),
    tags: z.array(z.string()).optional(),
});
export const escalateActionSchema = z.object({
    type: z.literal('escalate'),
    severity: z.enum(['low', 'medium', 'high', 'critical']),
    assignTo: z.array(z.string()).optional(),
    assignToRoles: z.array(z.string()).optional(),
    createIncident: z.boolean().optional(),
    incidentType: z.string().optional(),
    timeout: z.number().int().positive().optional(),
    autoResolve: z.boolean().optional(),
});
export const quarantineActionSchema = z.object({
    type: z.literal('quarantine'),
    duration: z.number().int().positive(),
    durationUnit: z.enum(['second', 'minute', 'hour', 'day']).optional(),
    reason: z.string().min(1),
    notifyUser: z.boolean().optional(),
    notifyAdmin: z.boolean().optional(),
    allowAppeal: z.boolean().optional(),
});
export const redirectActionSchema = z.object({
    type: z.literal('redirect'),
    url: z.string().url(),
    statusCode: z.union([z.literal(301), z.literal(302), z.literal(303), z.literal(307), z.literal(308)]).optional(),
    preserveQuery: z.boolean().optional(),
});
export const modifyActionSchema = z.object({
    type: z.literal('modify'),
    addHeaders: z.record(z.string()).optional(),
    removeHeaders: z.array(z.string()).optional(),
    modifyBody: z.record(z.unknown()).optional(),
    addClaims: z.record(z.unknown()).optional(),
});
export const policyActionSchema = z.discriminatedUnion('type', [
    allowActionSchema,
    denyActionSchema,
    challengeActionSchema,
    notifyActionSchema,
    logActionSchema,
    escalateActionSchema,
    quarantineActionSchema,
    redirectActionSchema,
    modifyActionSchema,
]);
export const securityPolicySchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1).max(255),
    description: z.string().max(2000),
    priority: z.number().int().min(0).max(10000),
    enabled: z.boolean(),
    conditions: z.array(policyConditionSchema),
    rules: z.array(policyRuleSchema),
    actions: z.array(policyActionSchema),
    version: z.string().regex(/^\d+\.\d+\.\d+$/),
    tags: z.array(z.string()).optional(),
    metadata: z.record(z.unknown()).optional(),
    createdAt: z.string().datetime(),
    updatedAt: z.string().datetime(),
    createdBy: z.string().optional(),
    updatedBy: z.string().optional(),
});
export const policyContextSchema = z.object({
    user: z.object({
        id: z.string().min(1),
        email: z.string().email().optional(),
        role: z.string().optional(),
        roles: z.array(z.string()).optional(),
        department: z.string().optional(),
        tenant: z.string().optional(),
        groups: z.array(z.string()).optional(),
        permissions: z.array(z.string()).optional(),
        attributes: z.record(z.unknown()).optional(),
        riskScore: z.number().min(0).max(100).optional(),
        mfaVerified: z.boolean().optional(),
        lastMfaAt: z.string().datetime().optional(),
        sessionStartedAt: z.string().datetime().optional(),
    }).optional(),
    request: z.object({
        id: z.string().min(1),
        method: z.string().min(1),
        path: z.string().min(1),
        url: z.string().min(1),
        ip: z.string().min(1),
        userAgent: z.string().optional(),
        origin: z.string().optional(),
        referer: z.string().optional(),
        headers: z.record(z.union([z.string(), z.array(z.string()), z.undefined()])).optional(),
        query: z.record(z.union([z.string(), z.array(z.string())])).optional(),
        body: z.unknown().optional(),
        contentType: z.string().optional(),
    }),
    resource: z.object({
        id: z.string().optional(),
        type: z.string().optional(),
        sensitivityLevel: z.enum(['public', 'internal', 'confidential', 'restricted', 'top_secret']).optional(),
        dataType: z.string().optional(),
        classification: z.string().optional(),
        owner: z.string().optional(),
        department: z.string().optional(),
        region: z.string().optional(),
        tags: z.array(z.string()).optional(),
        attributes: z.record(z.unknown()).optional(),
    }).optional(),
    risk: z.object({
        userRiskScore: z.number().min(0).max(100).optional(),
        ipReputation: z.number().min(0).max(100).optional(),
        deviceTrust: z.number().min(0).max(100).optional(),
        sessionRisk: z.number().min(0).max(100).optional(),
        anomalyScore: z.number().min(0).max(100).optional(),
        threatLevel: z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
        riskFactors: z.array(z.string()).optional(),
    }).optional(),
    environment: z.object({
        timestamp: z.string().datetime(),
        timezone: z.string(),
        dayOfWeek: z.number().int().min(0).max(6),
        hour: z.number().int().min(0).max(23),
        isBusinessHours: z.boolean().optional(),
        isWeekend: z.boolean().optional(),
        isHoliday: z.boolean().optional(),
        geoLocation: z.object({
            country: z.string().optional(),
            region: z.string().optional(),
            city: z.string().optional(),
        }).optional(),
    }).optional(),
    custom: z.record(z.unknown()).optional(),
    breakGlassToken: z.string().optional(),
});
// =============================================================================
// POLICY DECISION
// =============================================================================
/**
 * Decision outcome
 */
export const DecisionOutcome = {
    ALLOW: 'allow',
    DENY: 'deny',
    CHALLENGE: 'challenge',
    PENDING: 'pending',
};
//# sourceMappingURL=types.js.map