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/__init__.py +62 -1
- glacis/__main__.py +1 -80
- glacis/client.py +60 -31
- glacis/config.py +141 -0
- glacis/controls/__init__.py +232 -0
- glacis/controls/base.py +104 -0
- glacis/controls/jailbreak.py +224 -0
- glacis/controls/pii.py +855 -0
- glacis/crypto.py +70 -1
- glacis/integrations/__init__.py +53 -3
- glacis/integrations/anthropic.py +207 -142
- glacis/integrations/base.py +476 -0
- glacis/integrations/openai.py +156 -121
- glacis/models.py +277 -24
- glacis/storage.py +324 -8
- glacis/verify.py +154 -0
- glacis-0.2.0.dist-info/METADATA +275 -0
- glacis-0.2.0.dist-info/RECORD +21 -0
- glacis/wasm/s3p_core_wasi.wasm +0 -0
- glacis/wasm_runtime.py +0 -533
- glacis-0.1.3.dist-info/METADATA +0 -324
- glacis-0.1.3.dist-info/RECORD +0 -16
- {glacis-0.1.3.dist-info → glacis-0.2.0.dist-info}/WHEEL +0 -0
- {glacis-0.1.3.dist-info → glacis-0.2.0.dist-info}/licenses/LICENSE +0 -0
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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(
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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(
|
|
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
|