nihalaninihal's picture
Implement Phase 1: models, enterprise systems, attacks, rewards
a4e6593
from enum import Enum
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
from openenv.core.env_server.types import Action, Observation, State
# ---------------------------------------------------------------------------
# Enums
# ---------------------------------------------------------------------------
class AgentRole(str, Enum):
ATTACKER = "attacker"
WORKER = "worker"
OVERSIGHT = "oversight"
class AttackType(str, Enum):
SCHEMA_DRIFT = "schema_drift"
POLICY_DRIFT = "policy_drift"
SOCIAL_ENGINEERING = "social_engineering"
RATE_LIMIT = "rate_limit"
class TargetSystem(str, Enum):
CRM = "crm"
BILLING = "billing"
TICKETING = "ticketing"
class CustomerTier(str, Enum):
GOLD = "gold"
SILVER = "silver"
BRONZE = "bronze"
class InvoiceStatus(str, Enum):
PAID = "paid"
PENDING = "pending"
OVERDUE = "overdue"
REFUNDED = "refunded"
class TicketStatus(str, Enum):
OPEN = "open"
IN_PROGRESS = "in_progress"
RESOLVED = "resolved"
ESCALATED = "escalated"
class TicketPriority(str, Enum):
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
class TaskType(str, Enum):
REFUND = "refund"
TICKET_CHECK = "ticket_check"
TIER_UPGRADE = "tier_upgrade"
NEW_TICKET = "new_ticket"
BALANCE_INQUIRY = "balance_inquiry"
SLA_ESCALATION = "sla_escalation"
class ViolationType(str, Enum):
POLICY_VIOLATION = "policy_violation"
SOCIAL_ENGINEERING = "social_engineering"
SCHEMA_ERROR_UNHANDLED = "schema_error_unhandled"
SLA_BREACH = "sla_breach"
# ---------------------------------------------------------------------------
# Data Models
# ---------------------------------------------------------------------------
class Customer(BaseModel):
customer_id: str
name: str
tier: CustomerTier
region: str
contact_email: str
lifetime_value: float
notes: List[str] = Field(default_factory=list)
class Invoice(BaseModel):
invoice_id: str
customer_id: str
amount: float
status: InvoiceStatus
date_tick: int
items: List[str]
class Ticket(BaseModel):
ticket_id: str
customer_id: str
subject: str
priority: TicketPriority
status: TicketStatus
created_tick: int
sla_deadline_tick: int
assigned_to: Optional[str] = None
data_region: str = "us-east"
class RefundPolicy(BaseModel):
window_ticks: int = 8
requires_approval: bool = False
max_amount: float = 5000.0
class SLARules(BaseModel):
high: int = 6
medium: int = 12
low: int = 18
class CustomerTask(BaseModel):
task_id: str
customer_id: str
task_type: TaskType
message: str
required_systems: List[TargetSystem]
arrival_tick: int
# ---------------------------------------------------------------------------
# OpenEnv Types
# ---------------------------------------------------------------------------
class SentinelAction(Action):
"""Action for all three agent roles.
Action base has extra='forbid', so every agent-specific field must be
Optional with a default so that agents only populate the subset they use.
"""
agent: AgentRole
action_type: str
target_system: Optional[TargetSystem] = None
parameters: Dict[str, Any] = Field(default_factory=dict)
response_text: Optional[str] = None
flag: Optional[bool] = None
explanation: Optional[str] = None
class SentinelObservation(Observation):
"""Observation returned to each agent on its turn.
Observation base already provides done, reward, and metadata.
"""
current_agent: AgentRole
current_task: Optional[Dict[str, Any]] = None
systems_snapshot: Dict[str, Any] = Field(default_factory=dict)
last_action_result: Optional[Dict[str, Any]] = None
trajectory: List[Dict[str, Any]] = Field(default_factory=list)
tick: int = 0
class SentinelState(State):
"""Internal environment state.
State base has extra='allow', episode_id, and step_count built-in.
"""
tick: int = 0
scores: Dict[str, float] = Field(default_factory=dict)
active_attacks: List[Dict[str, Any]] = Field(default_factory=list)
tasks_completed: int = 0
tasks_total: int = 0
class TickGroundTruth(BaseModel):
"""Per-tick ground truth for oversight scoring."""
violations_present: bool = False
violation_types: List[ViolationType] = Field(default_factory=list)
correct_action: Optional[str] = None
is_social_engineering: bool = False