og-arin commited on
Commit
aa75886
·
verified ·
1 Parent(s): 5fd4180

Update models.py

Browse files
Files changed (1) hide show
  1. models.py +52 -14
models.py CHANGED
@@ -1,7 +1,21 @@
1
  """
2
  models.py – Pydantic Schemas for PhishGuard-Env
3
  ================================================
4
- No changes from the live repo — included here for completeness.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  """
6
 
7
  from pydantic import BaseModel, Field
@@ -11,29 +25,53 @@ from typing import List, Optional
11
  class EmailObservation(BaseModel):
12
  """
13
  Structured email observation returned by /reset and each /step call.
 
14
  """
15
- sender: str = Field(description="Full sender email address")
16
- subject: str = Field(description="Email subject line")
17
- body: str = Field(description="Plain-text email body")
18
- links: List[str] = Field(default_factory=list, description="URLs in the email")
19
- has_attachments: bool = Field(description="True if attachments present")
20
- spf_record: str = Field(description="SPF result: pass|fail|softfail|none")
21
- dmarc_record: str = Field(description="DMARC result: pass|fail|none")
22
- urgency_level: str = Field(description="low|medium|high|critical")
23
- confidence_hint: Optional[str] = Field(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  default=None,
25
- description="Noisy SIEM/gateway signal — treat as one data-point, not ground truth.",
 
 
 
26
  )
27
 
28
 
29
  class PhishAction(BaseModel):
30
  """
31
- Action payload submitted by the agent to POST /step.
32
  """
33
  action: str = Field(
34
- description="MARK_SAFE | MOVE_TO_SPAM | QUARANTINE | BLOCK_DOMAIN"
 
 
 
35
  )
36
  reasoning: Optional[str] = Field(
37
  default=None,
38
- description="One-sentence technical justification (optional).",
39
  )
 
1
  """
2
  models.py – Pydantic Schemas for PhishGuard-Env
3
  ================================================
4
+
5
+ CHANGES vs. original
6
+ ---------------------
7
+ 1. EmailObservation is now the authoritative observation contract.
8
+ All scenario dicts in env.py have been updated to include every field
9
+ declared here — the schema is no longer a dead letter.
10
+
11
+ 2. Added Optional[str] confidence_hint:
12
+ Surfaces noisy SIEM / gateway / threat-intel signals to make the LLM's
13
+ task genuinely adversarial. Optional so old API clients are not broken.
14
+
15
+ 3. PhishAction.reasoning is Optional[str]:
16
+ Some LLM providers omit reasoning even when prompted. Making it Optional
17
+ prevents the /step endpoint from returning HTTP 422 Unprocessable Entity
18
+ when reasoning is absent from the agent's JSON response.
19
  """
20
 
21
  from pydantic import BaseModel, Field
 
25
  class EmailObservation(BaseModel):
26
  """
27
  Structured email observation returned by /reset and each /step call.
28
+ This is exactly what the LLM agent receives as input for each decision.
29
  """
30
+ sender: str = Field(
31
+ description="Full sender email address"
32
+ )
33
+ subject: str = Field(
34
+ description="Email subject line"
35
+ )
36
+ body: str = Field(
37
+ description="Plain-text email body"
38
+ )
39
+ links: List[str] = Field(
40
+ default_factory=list,
41
+ description="List of URLs found in the email body or headers",
42
+ )
43
+ has_attachments: bool = Field(
44
+ description="True if the email carries one or more attachments"
45
+ )
46
+ spf_record: str = Field(
47
+ description="SPF validation result: 'pass' | 'fail' | 'softfail' | 'none'"
48
+ )
49
+ dmarc_record: str = Field(
50
+ description="DMARC policy result: 'pass' | 'fail' | 'none'"
51
+ )
52
+ urgency_level: str = Field(
53
+ description="Perceived urgency of the email: 'low' | 'medium' | 'high' | 'critical'"
54
+ )
55
+ confidence_hint: Optional[str] = Field(
56
  default=None,
57
+ description=(
58
+ "Noisy contextual signal from SIEM, mail gateway, or threat-intel "
59
+ "feed. Treat as one data-point — it may be misleading by design."
60
+ ),
61
  )
62
 
63
 
64
  class PhishAction(BaseModel):
65
  """
66
+ Action payload submitted by the agent to the POST /step endpoint.
67
  """
68
  action: str = Field(
69
+ description=(
70
+ "Triage decision. Must be exactly one of: "
71
+ "MARK_SAFE | MOVE_TO_SPAM | QUARANTINE | BLOCK_DOMAIN"
72
+ )
73
  )
74
  reasoning: Optional[str] = Field(
75
  default=None,
76
+ description="One-sentence technical justification for the triage decision",
77
  )