"""Code generated by scripts/generate_sdk_models.py. DO NOT EDIT."""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum

class MergeStrategy(str, Enum):
    REPLACE = 'replace'
    MERGE = 'merge'
    DEEP_MERGE = 'deep_merge'

class Severity(str, Enum):
    CRITICAL = 'critical'
    ERROR = 'error'
    WARN = 'warn'

class DefaultAction(str, Enum):
    ALLOW = 'allow'
    BLOCK = 'block'

class ComputerUseMode(str, Enum):
    OBSERVE = 'observe'
    GUARDRAIL = 'guardrail'
    FAIL_CLOSED = 'fail_closed'

class TransitionTrigger(str, Enum):
    USER_APPROVAL = 'user_approval'
    USER_DENIAL = 'user_denial'
    CRITICAL_VIOLATION = 'critical_violation'
    ANY_VIOLATION = 'any_violation'
    TIMEOUT = 'timeout'
    BUDGET_EXHAUSTED = 'budget_exhausted'
    PATTERN_MATCH = 'pattern_match'

class OriginDefaultBehavior(str, Enum):
    DENY = 'deny'
    MINIMAL_PROFILE = 'minimal_profile'

class DetectionLevel(str, Enum):
    SAFE = 'safe'
    SUSPICIOUS = 'suspicious'
    HIGH = 'high'
    CRITICAL = 'critical'

class Classification(str, Enum):
    PUBLIC = 'public'
    INTERNAL = 'internal'
    CONFIDENTIAL = 'confidential'
    RESTRICTED = 'restricted'

class LifecycleState(str, Enum):
    DRAFT = 'draft'
    REVIEW = 'review'
    APPROVED = 'approved'
    DEPLOYED = 'deployed'
    DEPRECATED = 'deprecated'
    ARCHIVED = 'archived'

@dataclass
class HushSpec:
    hushspec: str
    name: str | None = None
    description: str | None = None
    extends: str | None = None
    merge_strategy: MergeStrategy | None = None
    rules: Rules | None = None
    extensions: Extensions | None = None
    metadata: GovernanceMetadata | None = None

    @classmethod
    def from_dict(cls, data: dict) -> HushSpec:
        return cls(
            hushspec=data['hushspec'],
            name=(data.get('name') if data.get('name') is not None else None),
            description=(data.get('description') if data.get('description') is not None else None),
            extends=(data.get('extends') if data.get('extends') is not None else None),
            merge_strategy=(MergeStrategy(data.get('merge_strategy')) if data.get('merge_strategy') is not None else None),
            rules=(Rules.from_dict(data.get('rules')) if data.get('rules') is not None else None),
            extensions=(Extensions.from_dict(data.get('extensions')) if data.get('extensions') is not None else None),
            metadata=(GovernanceMetadata.from_dict(data.get('metadata')) if data.get('metadata') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['hushspec'] = self.hushspec
        if self.name is not None:
            data['name'] = self.name
        if self.description is not None:
            data['description'] = self.description
        if self.extends is not None:
            data['extends'] = self.extends
        if self.merge_strategy is not None:
            data['merge_strategy'] = self.merge_strategy.value
        if self.rules is not None:
            data['rules'] = self.rules.to_dict()
        if self.extensions is not None:
            data['extensions'] = self.extensions.to_dict()
        if self.metadata is not None:
            data['metadata'] = self.metadata.to_dict()
        return data

@dataclass
class Rules:
    forbidden_paths: ForbiddenPathsRule | None = None
    path_allowlist: PathAllowlistRule | None = None
    egress: EgressRule | None = None
    secret_patterns: SecretPatternsRule | None = None
    patch_integrity: PatchIntegrityRule | None = None
    shell_commands: ShellCommandsRule | None = None
    tool_access: ToolAccessRule | None = None
    computer_use: ComputerUseRule | None = None
    remote_desktop_channels: RemoteDesktopChannelsRule | None = None
    input_injection: InputInjectionRule | None = None

    @classmethod
    def from_dict(cls, data: dict) -> Rules:
        return cls(
            forbidden_paths=(ForbiddenPathsRule.from_dict(data.get('forbidden_paths')) if data.get('forbidden_paths') is not None else None),
            path_allowlist=(PathAllowlistRule.from_dict(data.get('path_allowlist')) if data.get('path_allowlist') is not None else None),
            egress=(EgressRule.from_dict(data.get('egress')) if data.get('egress') is not None else None),
            secret_patterns=(SecretPatternsRule.from_dict(data.get('secret_patterns')) if data.get('secret_patterns') is not None else None),
            patch_integrity=(PatchIntegrityRule.from_dict(data.get('patch_integrity')) if data.get('patch_integrity') is not None else None),
            shell_commands=(ShellCommandsRule.from_dict(data.get('shell_commands')) if data.get('shell_commands') is not None else None),
            tool_access=(ToolAccessRule.from_dict(data.get('tool_access')) if data.get('tool_access') is not None else None),
            computer_use=(ComputerUseRule.from_dict(data.get('computer_use')) if data.get('computer_use') is not None else None),
            remote_desktop_channels=(RemoteDesktopChannelsRule.from_dict(data.get('remote_desktop_channels')) if data.get('remote_desktop_channels') is not None else None),
            input_injection=(InputInjectionRule.from_dict(data.get('input_injection')) if data.get('input_injection') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.forbidden_paths is not None:
            data['forbidden_paths'] = self.forbidden_paths.to_dict()
        if self.path_allowlist is not None:
            data['path_allowlist'] = self.path_allowlist.to_dict()
        if self.egress is not None:
            data['egress'] = self.egress.to_dict()
        if self.secret_patterns is not None:
            data['secret_patterns'] = self.secret_patterns.to_dict()
        if self.patch_integrity is not None:
            data['patch_integrity'] = self.patch_integrity.to_dict()
        if self.shell_commands is not None:
            data['shell_commands'] = self.shell_commands.to_dict()
        if self.tool_access is not None:
            data['tool_access'] = self.tool_access.to_dict()
        if self.computer_use is not None:
            data['computer_use'] = self.computer_use.to_dict()
        if self.remote_desktop_channels is not None:
            data['remote_desktop_channels'] = self.remote_desktop_channels.to_dict()
        if self.input_injection is not None:
            data['input_injection'] = self.input_injection.to_dict()
        return data

@dataclass
class ForbiddenPathsRule:
    enabled: bool = True
    patterns: list[str] = field(default_factory=list)
    exceptions: list[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> ForbiddenPathsRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else True),
            patterns=[item for item in data.get('patterns') or []],
            exceptions=[item for item in data.get('exceptions') or []],
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        if self.patterns:
            data['patterns'] = [item for item in self.patterns]
        if self.exceptions:
            data['exceptions'] = [item for item in self.exceptions]
        return data

@dataclass
class PathAllowlistRule:
    enabled: bool = False
    read: list[str] = field(default_factory=list)
    write: list[str] = field(default_factory=list)
    patch: list[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> PathAllowlistRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else False),
            read=[item for item in data.get('read') or []],
            write=[item for item in data.get('write') or []],
            patch=[item for item in data.get('patch') or []],
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        if self.read:
            data['read'] = [item for item in self.read]
        if self.write:
            data['write'] = [item for item in self.write]
        if self.patch:
            data['patch'] = [item for item in self.patch]
        return data

@dataclass
class EgressRule:
    enabled: bool = True
    allow: list[str] = field(default_factory=list)
    block: list[str] = field(default_factory=list)
    default: DefaultAction = DefaultAction.BLOCK

    @classmethod
    def from_dict(cls, data: dict) -> EgressRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else True),
            allow=[item for item in data.get('allow') or []],
            block=[item for item in data.get('block') or []],
            default=DefaultAction((data.get('default') if data.get('default') is not None else DefaultAction.BLOCK.value)),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        if self.allow:
            data['allow'] = [item for item in self.allow]
        if self.block:
            data['block'] = [item for item in self.block]
        data['default'] = self.default.value
        return data

@dataclass
class SecretPattern:
    name: str
    pattern: str
    severity: Severity
    description: str | None = None

    @classmethod
    def from_dict(cls, data: dict) -> SecretPattern:
        return cls(
            name=data['name'],
            pattern=data['pattern'],
            severity=Severity(data['severity']),
            description=(data.get('description') if data.get('description') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['name'] = self.name
        data['pattern'] = self.pattern
        data['severity'] = self.severity.value
        if self.description is not None:
            data['description'] = self.description
        return data

@dataclass
class SecretPatternsRule:
    enabled: bool = True
    patterns: list[SecretPattern] = field(default_factory=list)
    skip_paths: list[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> SecretPatternsRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else True),
            patterns=[SecretPattern.from_dict(item) for item in data.get('patterns') or []],
            skip_paths=[item for item in data.get('skip_paths') or []],
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        if self.patterns:
            data['patterns'] = [item.to_dict() for item in self.patterns]
        if self.skip_paths:
            data['skip_paths'] = [item for item in self.skip_paths]
        return data

@dataclass
class PatchIntegrityRule:
    enabled: bool = True
    max_additions: int = 1000
    max_deletions: int = 500
    forbidden_patterns: list[str] = field(default_factory=list)
    require_balance: bool = False
    max_imbalance_ratio: float = 10.0

    @classmethod
    def from_dict(cls, data: dict) -> PatchIntegrityRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else True),
            max_additions=(data.get('max_additions') if data.get('max_additions') is not None else 1000),
            max_deletions=(data.get('max_deletions') if data.get('max_deletions') is not None else 500),
            forbidden_patterns=[item for item in data.get('forbidden_patterns') or []],
            require_balance=(data.get('require_balance') if data.get('require_balance') is not None else False),
            max_imbalance_ratio=(data.get('max_imbalance_ratio') if data.get('max_imbalance_ratio') is not None else 10.0),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        data['max_additions'] = self.max_additions
        data['max_deletions'] = self.max_deletions
        if self.forbidden_patterns:
            data['forbidden_patterns'] = [item for item in self.forbidden_patterns]
        data['require_balance'] = self.require_balance
        data['max_imbalance_ratio'] = self.max_imbalance_ratio
        return data

@dataclass
class ShellCommandsRule:
    enabled: bool = True
    forbidden_patterns: list[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> ShellCommandsRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else True),
            forbidden_patterns=[item for item in data.get('forbidden_patterns') or []],
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        if self.forbidden_patterns:
            data['forbidden_patterns'] = [item for item in self.forbidden_patterns]
        return data

@dataclass
class ToolAccessRule:
    enabled: bool = True
    allow: list[str] = field(default_factory=list)
    block: list[str] = field(default_factory=list)
    require_confirmation: list[str] = field(default_factory=list)
    default: DefaultAction = DefaultAction.ALLOW
    max_args_size: int | None = None

    @classmethod
    def from_dict(cls, data: dict) -> ToolAccessRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else True),
            allow=[item for item in data.get('allow') or []],
            block=[item for item in data.get('block') or []],
            require_confirmation=[item for item in data.get('require_confirmation') or []],
            default=DefaultAction((data.get('default') if data.get('default') is not None else DefaultAction.ALLOW.value)),
            max_args_size=(data.get('max_args_size') if data.get('max_args_size') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        if self.allow:
            data['allow'] = [item for item in self.allow]
        if self.block:
            data['block'] = [item for item in self.block]
        if self.require_confirmation:
            data['require_confirmation'] = [item for item in self.require_confirmation]
        data['default'] = self.default.value
        if self.max_args_size is not None:
            data['max_args_size'] = self.max_args_size
        return data

@dataclass
class ComputerUseRule:
    enabled: bool = False
    mode: ComputerUseMode = ComputerUseMode.GUARDRAIL
    allowed_actions: list[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> ComputerUseRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else False),
            mode=ComputerUseMode((data.get('mode') if data.get('mode') is not None else ComputerUseMode.GUARDRAIL.value)),
            allowed_actions=[item for item in data.get('allowed_actions') or []],
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        data['mode'] = self.mode.value
        if self.allowed_actions:
            data['allowed_actions'] = [item for item in self.allowed_actions]
        return data

@dataclass
class RemoteDesktopChannelsRule:
    enabled: bool = False
    clipboard: bool = False
    file_transfer: bool = False
    audio: bool = True
    drive_mapping: bool = False

    @classmethod
    def from_dict(cls, data: dict) -> RemoteDesktopChannelsRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else False),
            clipboard=(data.get('clipboard') if data.get('clipboard') is not None else False),
            file_transfer=(data.get('file_transfer') if data.get('file_transfer') is not None else False),
            audio=(data.get('audio') if data.get('audio') is not None else True),
            drive_mapping=(data.get('drive_mapping') if data.get('drive_mapping') is not None else False),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        data['clipboard'] = self.clipboard
        data['file_transfer'] = self.file_transfer
        data['audio'] = self.audio
        data['drive_mapping'] = self.drive_mapping
        return data

@dataclass
class InputInjectionRule:
    enabled: bool = False
    allowed_types: list[str] = field(default_factory=list)
    require_postcondition_probe: bool = False

    @classmethod
    def from_dict(cls, data: dict) -> InputInjectionRule:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else False),
            allowed_types=[item for item in data.get('allowed_types') or []],
            require_postcondition_probe=(data.get('require_postcondition_probe') if data.get('require_postcondition_probe') is not None else False),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['enabled'] = self.enabled
        if self.allowed_types:
            data['allowed_types'] = [item for item in self.allowed_types]
        data['require_postcondition_probe'] = self.require_postcondition_probe
        return data

@dataclass
class Extensions:
    posture: PostureExtension | None = None
    origins: OriginsExtension | None = None
    detection: DetectionExtension | None = None

    @classmethod
    def from_dict(cls, data: dict) -> Extensions:
        return cls(
            posture=(PostureExtension.from_dict(data.get('posture')) if data.get('posture') is not None else None),
            origins=(OriginsExtension.from_dict(data.get('origins')) if data.get('origins') is not None else None),
            detection=(DetectionExtension.from_dict(data.get('detection')) if data.get('detection') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.posture is not None:
            data['posture'] = self.posture.to_dict()
        if self.origins is not None:
            data['origins'] = self.origins.to_dict()
        if self.detection is not None:
            data['detection'] = self.detection.to_dict()
        return data

@dataclass
class PostureExtension:
    initial: str
    states: dict[str, PostureState]
    transitions: list[PostureTransition]

    @classmethod
    def from_dict(cls, data: dict) -> PostureExtension:
        return cls(
            initial=data['initial'],
            states={key: PostureState.from_dict(item) for key, item in (data.get('states', {})).items()},
            transitions=[PostureTransition.from_dict(item) for item in data.get('transitions', [])],
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['initial'] = self.initial
        data['states'] = {key: item.to_dict() for key, item in self.states.items()}
        data['transitions'] = [item.to_dict() for item in self.transitions]
        return data

@dataclass
class PostureState:
    description: str | None = None
    capabilities: list[str] = field(default_factory=list)
    budgets: dict[str, int] = field(default_factory=dict)

    @classmethod
    def from_dict(cls, data: dict) -> PostureState:
        return cls(
            description=(data.get('description') if data.get('description') is not None else None),
            capabilities=[item for item in data.get('capabilities') or []],
            budgets={key: item for key, item in (data.get('budgets') or {}).items()},
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.description is not None:
            data['description'] = self.description
        if self.capabilities:
            data['capabilities'] = [item for item in self.capabilities]
        if self.budgets:
            data['budgets'] = {key: item for key, item in self.budgets.items()}
        return data

@dataclass
class PostureTransition:
    from_state: str
    to: str
    on: TransitionTrigger
    after: str | None = None

    @classmethod
    def from_dict(cls, data: dict) -> PostureTransition:
        return cls(
            from_state=data['from'],
            to=data['to'],
            on=TransitionTrigger(data['on']),
            after=(data.get('after') if data.get('after') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['from'] = self.from_state
        data['to'] = self.to
        data['on'] = self.on.value
        if self.after is not None:
            data['after'] = self.after
        return data

@dataclass
class OriginsExtension:
    default_behavior: OriginDefaultBehavior | None = None
    profiles: list[OriginProfile] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> OriginsExtension:
        return cls(
            default_behavior=(OriginDefaultBehavior(data.get('default_behavior')) if data.get('default_behavior') is not None else None),
            profiles=[OriginProfile.from_dict(item) for item in data.get('profiles') or []],
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.default_behavior is not None:
            data['default_behavior'] = self.default_behavior.value
        if self.profiles:
            data['profiles'] = [item.to_dict() for item in self.profiles]
        return data

@dataclass
class OriginProfile:
    id: str
    match_rules: OriginMatch | None = None
    posture: str | None = None
    tool_access: ToolAccessRule | None = None
    egress: EgressRule | None = None
    data: OriginDataPolicy | None = None
    budgets: OriginBudgets | None = None
    bridge: BridgePolicy | None = None
    explanation: str | None = None

    @classmethod
    def from_dict(cls, data: dict) -> OriginProfile:
        return cls(
            id=data['id'],
            match_rules=(OriginMatch.from_dict(data.get('match')) if data.get('match') is not None else None),
            posture=(data.get('posture') if data.get('posture') is not None else None),
            tool_access=(ToolAccessRule.from_dict(data.get('tool_access')) if data.get('tool_access') is not None else None),
            egress=(EgressRule.from_dict(data.get('egress')) if data.get('egress') is not None else None),
            data=(OriginDataPolicy.from_dict(data.get('data')) if data.get('data') is not None else None),
            budgets=(OriginBudgets.from_dict(data.get('budgets')) if data.get('budgets') is not None else None),
            bridge=(BridgePolicy.from_dict(data.get('bridge')) if data.get('bridge') is not None else None),
            explanation=(data.get('explanation') if data.get('explanation') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['id'] = self.id
        if self.match_rules is not None:
            data['match'] = self.match_rules.to_dict()
        if self.posture is not None:
            data['posture'] = self.posture
        if self.tool_access is not None:
            data['tool_access'] = self.tool_access.to_dict()
        if self.egress is not None:
            data['egress'] = self.egress.to_dict()
        if self.data is not None:
            data['data'] = self.data.to_dict()
        if self.budgets is not None:
            data['budgets'] = self.budgets.to_dict()
        if self.bridge is not None:
            data['bridge'] = self.bridge.to_dict()
        if self.explanation is not None:
            data['explanation'] = self.explanation
        return data

@dataclass
class OriginMatch:
    provider: str | None = None
    tenant_id: str | None = None
    space_id: str | None = None
    space_type: str | None = None
    visibility: str | None = None
    external_participants: bool | None = None
    tags: list[str] = field(default_factory=list)
    sensitivity: str | None = None
    actor_role: str | None = None

    @classmethod
    def from_dict(cls, data: dict) -> OriginMatch:
        return cls(
            provider=(data.get('provider') if data.get('provider') is not None else None),
            tenant_id=(data.get('tenant_id') if data.get('tenant_id') is not None else None),
            space_id=(data.get('space_id') if data.get('space_id') is not None else None),
            space_type=(data.get('space_type') if data.get('space_type') is not None else None),
            visibility=(data.get('visibility') if data.get('visibility') is not None else None),
            external_participants=(data.get('external_participants') if data.get('external_participants') is not None else None),
            tags=[item for item in data.get('tags') or []],
            sensitivity=(data.get('sensitivity') if data.get('sensitivity') is not None else None),
            actor_role=(data.get('actor_role') if data.get('actor_role') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.provider is not None:
            data['provider'] = self.provider
        if self.tenant_id is not None:
            data['tenant_id'] = self.tenant_id
        if self.space_id is not None:
            data['space_id'] = self.space_id
        if self.space_type is not None:
            data['space_type'] = self.space_type
        if self.visibility is not None:
            data['visibility'] = self.visibility
        if self.external_participants is not None:
            data['external_participants'] = self.external_participants
        if self.tags:
            data['tags'] = [item for item in self.tags]
        if self.sensitivity is not None:
            data['sensitivity'] = self.sensitivity
        if self.actor_role is not None:
            data['actor_role'] = self.actor_role
        return data

@dataclass
class OriginDataPolicy:
    allow_external_sharing: bool = False
    redact_before_send: bool = False
    block_sensitive_outputs: bool = False

    @classmethod
    def from_dict(cls, data: dict) -> OriginDataPolicy:
        return cls(
            allow_external_sharing=(data.get('allow_external_sharing') if data.get('allow_external_sharing') is not None else False),
            redact_before_send=(data.get('redact_before_send') if data.get('redact_before_send') is not None else False),
            block_sensitive_outputs=(data.get('block_sensitive_outputs') if data.get('block_sensitive_outputs') is not None else False),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['allow_external_sharing'] = self.allow_external_sharing
        data['redact_before_send'] = self.redact_before_send
        data['block_sensitive_outputs'] = self.block_sensitive_outputs
        return data

@dataclass
class OriginBudgets:
    tool_calls: int | None = None
    egress_calls: int | None = None
    shell_commands: int | None = None

    @classmethod
    def from_dict(cls, data: dict) -> OriginBudgets:
        return cls(
            tool_calls=(data.get('tool_calls') if data.get('tool_calls') is not None else None),
            egress_calls=(data.get('egress_calls') if data.get('egress_calls') is not None else None),
            shell_commands=(data.get('shell_commands') if data.get('shell_commands') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.tool_calls is not None:
            data['tool_calls'] = self.tool_calls
        if self.egress_calls is not None:
            data['egress_calls'] = self.egress_calls
        if self.shell_commands is not None:
            data['shell_commands'] = self.shell_commands
        return data

@dataclass
class BridgePolicy:
    allow_cross_origin: bool = False
    allowed_targets: list[BridgeTarget] = field(default_factory=list)
    require_approval: bool = False

    @classmethod
    def from_dict(cls, data: dict) -> BridgePolicy:
        return cls(
            allow_cross_origin=(data.get('allow_cross_origin') if data.get('allow_cross_origin') is not None else False),
            allowed_targets=[BridgeTarget.from_dict(item) for item in data.get('allowed_targets') or []],
            require_approval=(data.get('require_approval') if data.get('require_approval') is not None else False),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        data['allow_cross_origin'] = self.allow_cross_origin
        if self.allowed_targets:
            data['allowed_targets'] = [item.to_dict() for item in self.allowed_targets]
        data['require_approval'] = self.require_approval
        return data

@dataclass
class BridgeTarget:
    provider: str | None = None
    space_type: str | None = None
    tags: list[str] = field(default_factory=list)
    visibility: str | None = None

    @classmethod
    def from_dict(cls, data: dict) -> BridgeTarget:
        return cls(
            provider=(data.get('provider') if data.get('provider') is not None else None),
            space_type=(data.get('space_type') if data.get('space_type') is not None else None),
            tags=[item for item in data.get('tags') or []],
            visibility=(data.get('visibility') if data.get('visibility') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.provider is not None:
            data['provider'] = self.provider
        if self.space_type is not None:
            data['space_type'] = self.space_type
        if self.tags:
            data['tags'] = [item for item in self.tags]
        if self.visibility is not None:
            data['visibility'] = self.visibility
        return data

@dataclass
class DetectionExtension:
    prompt_injection: PromptInjectionDetection | None = None
    jailbreak: JailbreakDetection | None = None
    threat_intel: ThreatIntelDetection | None = None

    @classmethod
    def from_dict(cls, data: dict) -> DetectionExtension:
        return cls(
            prompt_injection=(PromptInjectionDetection.from_dict(data.get('prompt_injection')) if data.get('prompt_injection') is not None else None),
            jailbreak=(JailbreakDetection.from_dict(data.get('jailbreak')) if data.get('jailbreak') is not None else None),
            threat_intel=(ThreatIntelDetection.from_dict(data.get('threat_intel')) if data.get('threat_intel') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.prompt_injection is not None:
            data['prompt_injection'] = self.prompt_injection.to_dict()
        if self.jailbreak is not None:
            data['jailbreak'] = self.jailbreak.to_dict()
        if self.threat_intel is not None:
            data['threat_intel'] = self.threat_intel.to_dict()
        return data

@dataclass
class PromptInjectionDetection:
    enabled: bool | None = None
    warn_at_or_above: DetectionLevel | None = None
    block_at_or_above: DetectionLevel | None = None
    max_scan_bytes: int | None = None

    @classmethod
    def from_dict(cls, data: dict) -> PromptInjectionDetection:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else None),
            warn_at_or_above=(DetectionLevel(data.get('warn_at_or_above')) if data.get('warn_at_or_above') is not None else None),
            block_at_or_above=(DetectionLevel(data.get('block_at_or_above')) if data.get('block_at_or_above') is not None else None),
            max_scan_bytes=(data.get('max_scan_bytes') if data.get('max_scan_bytes') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.enabled is not None:
            data['enabled'] = self.enabled
        if self.warn_at_or_above is not None:
            data['warn_at_or_above'] = self.warn_at_or_above.value
        if self.block_at_or_above is not None:
            data['block_at_or_above'] = self.block_at_or_above.value
        if self.max_scan_bytes is not None:
            data['max_scan_bytes'] = self.max_scan_bytes
        return data

@dataclass
class JailbreakDetection:
    enabled: bool | None = None
    block_threshold: int | None = None
    warn_threshold: int | None = None
    max_input_bytes: int | None = None

    @classmethod
    def from_dict(cls, data: dict) -> JailbreakDetection:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else None),
            block_threshold=(data.get('block_threshold') if data.get('block_threshold') is not None else None),
            warn_threshold=(data.get('warn_threshold') if data.get('warn_threshold') is not None else None),
            max_input_bytes=(data.get('max_input_bytes') if data.get('max_input_bytes') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.enabled is not None:
            data['enabled'] = self.enabled
        if self.block_threshold is not None:
            data['block_threshold'] = self.block_threshold
        if self.warn_threshold is not None:
            data['warn_threshold'] = self.warn_threshold
        if self.max_input_bytes is not None:
            data['max_input_bytes'] = self.max_input_bytes
        return data

@dataclass
class ThreatIntelDetection:
    enabled: bool | None = None
    pattern_db: str | None = None
    similarity_threshold: float | None = None
    top_k: int | None = None

    @classmethod
    def from_dict(cls, data: dict) -> ThreatIntelDetection:
        return cls(
            enabled=(data.get('enabled') if data.get('enabled') is not None else None),
            pattern_db=(data.get('pattern_db') if data.get('pattern_db') is not None else None),
            similarity_threshold=(data.get('similarity_threshold') if data.get('similarity_threshold') is not None else None),
            top_k=(data.get('top_k') if data.get('top_k') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.enabled is not None:
            data['enabled'] = self.enabled
        if self.pattern_db is not None:
            data['pattern_db'] = self.pattern_db
        if self.similarity_threshold is not None:
            data['similarity_threshold'] = self.similarity_threshold
        if self.top_k is not None:
            data['top_k'] = self.top_k
        return data

@dataclass
class GovernanceMetadata:
    author: str | None = None
    approved_by: str | None = None
    approval_date: str | None = None
    classification: Classification | None = None
    change_ticket: str | None = None
    lifecycle_state: LifecycleState | None = None
    policy_version: int | None = None
    effective_date: str | None = None
    expiry_date: str | None = None

    @classmethod
    def from_dict(cls, data: dict) -> GovernanceMetadata:
        return cls(
            author=(data.get('author') if data.get('author') is not None else None),
            approved_by=(data.get('approved_by') if data.get('approved_by') is not None else None),
            approval_date=(data.get('approval_date') if data.get('approval_date') is not None else None),
            classification=(Classification(data.get('classification')) if data.get('classification') is not None else None),
            change_ticket=(data.get('change_ticket') if data.get('change_ticket') is not None else None),
            lifecycle_state=(LifecycleState(data.get('lifecycle_state')) if data.get('lifecycle_state') is not None else None),
            policy_version=(data.get('policy_version') if data.get('policy_version') is not None else None),
            effective_date=(data.get('effective_date') if data.get('effective_date') is not None else None),
            expiry_date=(data.get('expiry_date') if data.get('expiry_date') is not None else None),
        )

    def to_dict(self) -> dict:
        data: dict = {}
        if self.author is not None:
            data['author'] = self.author
        if self.approved_by is not None:
            data['approved_by'] = self.approved_by
        if self.approval_date is not None:
            data['approval_date'] = self.approval_date
        if self.classification is not None:
            data['classification'] = self.classification.value
        if self.change_ticket is not None:
            data['change_ticket'] = self.change_ticket
        if self.lifecycle_state is not None:
            data['lifecycle_state'] = self.lifecycle_state.value
        if self.policy_version is not None:
            data['policy_version'] = self.policy_version
        if self.effective_date is not None:
            data['effective_date'] = self.effective_date
        if self.expiry_date is not None:
            data['expiry_date'] = self.expiry_date
        return data
