glacis 0.1.3__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
glacis/models.py CHANGED
@@ -69,21 +69,86 @@ class AttestInput(BaseModel):
69
69
  populate_by_name = True
70
70
 
71
71
 
72
+ class InclusionProof(BaseModel):
73
+ """Merkle inclusion proof from transparency log."""
74
+
75
+ leaf_index: int = Field(alias="leaf_index", description="Leaf index in tree")
76
+ tree_size: int = Field(alias="tree_size", description="Tree size when proof generated")
77
+ hashes: list[str] = Field(description="Sibling hashes")
78
+ root_hash: str = Field(alias="root_hash", description="Root hash")
79
+
80
+ class Config:
81
+ populate_by_name = True
82
+
83
+
84
+ class STH(BaseModel):
85
+ """Signed Tree Head."""
86
+
87
+ tree_size: int = Field(alias="tree_size")
88
+ timestamp: str
89
+ root_hash: str = Field(alias="root_hash")
90
+ signature: str
91
+
92
+ class Config:
93
+ populate_by_name = True
94
+
95
+
96
+ class TransparencyProofs(BaseModel):
97
+ """Transparency proofs from receipt-service."""
98
+
99
+ inclusion_proof: InclusionProof
100
+ sth_curr: STH
101
+ sth_prev: STH
102
+ consistency_path: list[str] = Field(default_factory=list)
103
+
104
+ class Config:
105
+ populate_by_name = True
106
+
107
+
108
+ class FullReceipt(BaseModel):
109
+ """Full receipt from receipt-service."""
110
+
111
+ schema_version: str = Field(default="1.0")
112
+ attestation_hash: str
113
+ heartbeat_epoch: int
114
+ binary_hash: str
115
+ network_state_hash: str
116
+ mono_counter: int
117
+ wall_time_ns: str
118
+ witness_signature: str
119
+ transparency_proofs: TransparencyProofs
120
+
121
+ class Config:
122
+ populate_by_name = True
123
+
124
+
72
125
  class AttestReceipt(BaseModel):
73
126
  """Receipt returned from attestation."""
74
127
 
75
128
  attestation_id: str = Field(alias="attestationId", description="Unique attestation ID")
129
+ attestation_hash: str = Field(alias="attestation_hash", description="Content hash")
76
130
  timestamp: str = Field(description="ISO 8601 timestamp")
77
131
  leaf_index: int = Field(alias="leafIndex", description="Merkle tree leaf index")
78
- leaf_hash: str = Field(alias="leafHash", description="Leaf node hash")
79
- merkle_proof: MerkleInclusionProof = Field(
80
- alias="merkleProof", description="Inclusion proof"
81
- )
82
- signed_tree_head: SignedTreeHead = Field(
83
- alias="signedTreeHead", description="Tree head at attestation time"
84
- )
85
- badge_url: str = Field(alias="badgeUrl", description="Verification badge URL")
132
+ tree_size: int = Field(alias="treeSize", description="Tree size")
133
+ epoch_id: Optional[str] = Field(alias="epochId", default=None)
134
+ receipt: Optional[FullReceipt] = Field(default=None, description="Full receipt with proofs")
86
135
  verify_url: str = Field(alias="verifyUrl", description="Verification endpoint URL")
136
+ control_plane_results: Optional["ControlPlaneAttestation"] = Field(
137
+ alias="controlPlaneResults",
138
+ default=None,
139
+ description="Control plane results from executed controls",
140
+ )
141
+
142
+ # Computed properties for convenience
143
+ @property
144
+ def witness_status(self) -> str:
145
+ """Return witness status based on receipt presence."""
146
+ return "WITNESSED" if self.receipt else "PENDING"
147
+
148
+ @property
149
+ def badge_url(self) -> str:
150
+ """Return badge/verify URL."""
151
+ return self.verify_url
87
152
 
88
153
  class Config:
89
154
  populate_by_name = True
@@ -122,9 +187,9 @@ class OrgInfo(BaseModel):
122
187
  class Verification(BaseModel):
123
188
  """Verification details."""
124
189
 
125
- signature_valid: bool = Field(alias="signatureValid")
126
- proof_valid: bool = Field(alias="proofValid")
127
- verified_at: str = Field(alias="verifiedAt")
190
+ signature_valid: bool = Field(alias="signatureValid", default=False)
191
+ proof_valid: bool = Field(alias="proofValid", default=False)
192
+ verified_at: Optional[str] = Field(alias="verifiedAt", default=None)
128
193
 
129
194
  class Config:
130
195
  populate_by_name = True
@@ -138,9 +203,11 @@ class VerifyResult(BaseModel):
138
203
  default=None, description="The attestation entry (if valid)"
139
204
  )
140
205
  org: Optional[OrgInfo] = Field(default=None, description="Organization info")
141
- verification: Verification = Field(description="Verification details")
142
- proof: MerkleInclusionProof = Field(description="Merkle proof")
143
- tree_head: SignedTreeHead = Field(alias="treeHead", description="Current tree head")
206
+ verification: Optional[Verification] = Field(default=None, description="Verification details")
207
+ proof: Optional[MerkleInclusionProof] = Field(default=None, description="Merkle proof")
208
+ tree_head: Optional[SignedTreeHead] = Field(
209
+ alias="treeHead", default=None, description="Current tree head"
210
+ )
144
211
  error: Optional[str] = Field(
145
212
  default=None, description="Error message if validation failed"
146
213
  )
@@ -166,16 +233,18 @@ class LogQueryParams(BaseModel):
166
233
  class LogEntry(BaseModel):
167
234
  """Log entry in query results."""
168
235
 
169
- entry_id: str = Field(alias="entryId")
170
- timestamp: str
171
- org_id: str = Field(alias="orgId")
236
+ # Server returns attestationId as the primary identifier
237
+ attestation_id: str = Field(alias="attestationId")
238
+ entry_id: Optional[str] = Field(alias="entryId", default=None)
239
+ timestamp: Optional[str] = None
240
+ org_id: Optional[str] = Field(alias="orgId", default=None)
172
241
  org_name: Optional[str] = Field(alias="orgName", default=None)
173
- service_id: str = Field(alias="serviceId")
174
- operation_type: str = Field(alias="operationType")
175
- payload_hash: str = Field(alias="payloadHash")
176
- signature: str
177
- leaf_index: int = Field(alias="leafIndex")
178
- leaf_hash: str = Field(alias="leafHash")
242
+ service_id: Optional[str] = Field(alias="serviceId", default=None)
243
+ operation_type: Optional[str] = Field(alias="operationType", default=None)
244
+ payload_hash: Optional[str] = Field(alias="payloadHash", default=None)
245
+ signature: Optional[str] = None
246
+ leaf_index: Optional[int] = Field(alias="leafIndex", default=None)
247
+ leaf_hash: Optional[str] = Field(alias="leafHash", default=None)
179
248
 
180
249
  class Config:
181
250
  populate_by_name = True
@@ -190,7 +259,9 @@ class LogQueryResult(BaseModel):
190
259
  alias="nextCursor", default=None, description="Cursor for next page"
191
260
  )
192
261
  count: int = Field(description="Number of entries returned")
193
- tree_head: SignedTreeHead = Field(alias="treeHead", description="Current tree head")
262
+ tree_head: Optional[SignedTreeHead] = Field(
263
+ alias="treeHead", default=None, description="Current tree head"
264
+ )
194
265
 
195
266
  class Config:
196
267
  populate_by_name = True
@@ -232,6 +303,183 @@ class GlacisRateLimitError(GlacisApiError):
232
303
  self.retry_after_ms = retry_after_ms
233
304
 
234
305
 
306
+ # ==============================================================================
307
+ # Control Plane Attestation Models
308
+ # ==============================================================================
309
+
310
+ ControlType = Literal[
311
+ "content_safety",
312
+ "pii",
313
+ "jailbreak",
314
+ "topic",
315
+ "prompt_security",
316
+ "grounding",
317
+ "word_filter",
318
+ "custom",
319
+ ]
320
+
321
+ ControlStatus = Literal["pass", "flag", "block", "error"]
322
+
323
+
324
+ class ModelInfo(BaseModel):
325
+ """Model information for policy context."""
326
+
327
+ model_id: str = Field(alias="modelId")
328
+ provider: str
329
+ system_prompt_hash: Optional[str] = Field(alias="systemPromptHash", default=None)
330
+
331
+ class Config:
332
+ populate_by_name = True
333
+
334
+
335
+ class PolicyScope(BaseModel):
336
+ """Scope for policy application."""
337
+
338
+ tenant_id: str = Field(alias="tenantId")
339
+ endpoint: str
340
+ user_class: Optional[str] = Field(alias="userClass", default=None)
341
+
342
+ class Config:
343
+ populate_by_name = True
344
+
345
+
346
+ class PolicyContext(BaseModel):
347
+ """Policy context for attestation."""
348
+
349
+ id: str
350
+ version: str
351
+ model: Optional[ModelInfo] = None
352
+ scope: PolicyScope
353
+
354
+ class Config:
355
+ populate_by_name = True
356
+
357
+
358
+ class Determination(BaseModel):
359
+ """Final determination for the request."""
360
+
361
+ action: Literal["forwarded", "redacted", "blocked"]
362
+ trigger: Optional[str] = None
363
+ confidence: float = Field(ge=0.0, le=1.0)
364
+
365
+ class Config:
366
+ populate_by_name = True
367
+
368
+
369
+ class ControlExecution(BaseModel):
370
+ """Record of a control execution."""
371
+
372
+ id: str
373
+ type: ControlType
374
+ version: str
375
+ provider: str # "aws", "azure", "glacis", "custom", etc.
376
+ latency_ms: int = Field(alias="latencyMs")
377
+ status: ControlStatus
378
+ result_hash: Optional[str] = Field(alias="resultHash", default=None)
379
+
380
+ class Config:
381
+ populate_by_name = True
382
+
383
+
384
+ class SafetyScores(BaseModel):
385
+ """Aggregated safety scores."""
386
+
387
+ overall_risk: float = Field(alias="overallRisk", ge=0.0, le=1.0)
388
+ scores: dict[str, float] = Field(default_factory=dict)
389
+
390
+ class Config:
391
+ populate_by_name = True
392
+
393
+
394
+ class PiiPhiSummary(BaseModel):
395
+ """Summary of PII/PHI detection and handling.
396
+
397
+ This model captures metadata about PII/PHI detection for attestation.
398
+ The actual redacted text is stored in evidence, not in the attestation schema.
399
+ """
400
+
401
+ detected: bool = False
402
+ action: Literal["none", "redacted", "blocked"] = "none"
403
+ categories: list[str] = Field(default_factory=list)
404
+ count: int = 0
405
+
406
+ class Config:
407
+ populate_by_name = True
408
+
409
+
410
+ class JailbreakSummary(BaseModel):
411
+ """Summary of jailbreak/prompt injection detection for attestation.
412
+
413
+ This model captures metadata about jailbreak detection results.
414
+ The raw model outputs and detailed scores are stored in evidence.
415
+ """
416
+
417
+ detected: bool = False
418
+ score: float = Field(default=0.0, ge=0.0, le=1.0, description="Model confidence score")
419
+ action: Literal["pass", "flag", "block", "log"] = "pass"
420
+ categories: list[str] = Field(
421
+ default_factory=list, description="Detection categories (e.g., ['jailbreak'])"
422
+ )
423
+ backend: str = Field(default="", description="Backend model used for detection")
424
+
425
+ class Config:
426
+ populate_by_name = True
427
+
428
+
429
+ class DeepInspection(BaseModel):
430
+ """Deep inspection results from L2 verification."""
431
+
432
+ judge_ids: list[str] = Field(alias="judgeIds", default_factory=list)
433
+ nonconformity_score: float = Field(alias="nonconformityScore", ge=0.0, le=1.0)
434
+ recommendation: Literal["uphold", "borderline", "escalate"]
435
+ evaluation_rationale: str = Field(alias="evaluationRationale")
436
+
437
+ class Config:
438
+ populate_by_name = True
439
+
440
+
441
+ class SamplingDecision(BaseModel):
442
+ """Sampling decision details."""
443
+
444
+ sampled: bool
445
+ reason: Literal["prf", "policy_trigger", "forced"]
446
+ prf_tag: Optional[str] = Field(alias="prfTag", default=None)
447
+ rate: float = Field(ge=0.0, le=1.0)
448
+
449
+ class Config:
450
+ populate_by_name = True
451
+
452
+
453
+ class SamplingMetadata(BaseModel):
454
+ """Sampling metadata for attestation level."""
455
+
456
+ level: Literal["L0", "L2"]
457
+ decision: SamplingDecision
458
+
459
+ class Config:
460
+ populate_by_name = True
461
+
462
+
463
+ class ControlPlaneAttestation(BaseModel):
464
+ """Control plane attestation capturing policy, controls, and safety metadata."""
465
+
466
+ schema_version: Literal["1.0"] = "1.0"
467
+ policy: PolicyContext
468
+ determination: Determination
469
+ controls: list[ControlExecution] = Field(default_factory=list)
470
+ safety: SafetyScores
471
+ pii_phi: Optional[PiiPhiSummary] = Field(alias="piiPhi", default=None)
472
+ jailbreak: Optional[JailbreakSummary] = Field(
473
+ default=None, description="Jailbreak detection results"
474
+ )
475
+ evidence_commitment: Optional[str] = Field(alias="evidenceCommitment", default=None)
476
+ deep_inspection: Optional[DeepInspection] = Field(alias="deepInspection", default=None)
477
+ sampling: SamplingMetadata
478
+
479
+ class Config:
480
+ populate_by_name = True
481
+
482
+
235
483
  # Offline Mode Models
236
484
 
237
485
 
@@ -264,6 +512,11 @@ class OfflineAttestReceipt(BaseModel):
264
512
  alias="witnessStatus",
265
513
  description="Always UNVERIFIED for offline receipts",
266
514
  )
515
+ control_plane_results: Optional[ControlPlaneAttestation] = Field(
516
+ alias="controlPlaneResults",
517
+ default=None,
518
+ description="Control plane results from executed controls",
519
+ )
267
520
 
268
521
  class Config:
269
522
  populate_by_name = True