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
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: glacis
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: GLACIS SDK for Python - AI Compliance Attestation
|
|
5
|
+
Project-URL: Homepage, https://glacis.io
|
|
6
|
+
Project-URL: Documentation, https://docs.glacis.io/sdk/python
|
|
7
|
+
Project-URL: Repository, https://github.com/Glacis-io/glacis-python
|
|
8
|
+
Project-URL: Issues, https://github.com/Glacis-io/glacis-python/issues
|
|
9
|
+
Author-email: GLACIS <sdk@glacis.io>
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai,attestation,compliance,logging,transparency
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Security :: Cryptography
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Requires-Dist: httpx>=0.25.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Requires-Dist: pynacl>=1.5.0
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: anthropic>=0.18.0; extra == 'all'
|
|
29
|
+
Requires-Dist: mypy>=1.0.0; extra == 'all'
|
|
30
|
+
Requires-Dist: openai>=1.0.0; extra == 'all'
|
|
31
|
+
Requires-Dist: presidio-analyzer>=2.2.0; extra == 'all'
|
|
32
|
+
Requires-Dist: presidio-anonymizer>=2.2.0; extra == 'all'
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'all'
|
|
34
|
+
Requires-Dist: pytest-httpx>=0.22.0; extra == 'all'
|
|
35
|
+
Requires-Dist: pytest>=7.0.0; extra == 'all'
|
|
36
|
+
Requires-Dist: pyyaml>=6.0.0; extra == 'all'
|
|
37
|
+
Requires-Dist: ruff>=0.1.0; extra == 'all'
|
|
38
|
+
Requires-Dist: spacy>=3.5.0; extra == 'all'
|
|
39
|
+
Requires-Dist: torch>=2.0.0; extra == 'all'
|
|
40
|
+
Requires-Dist: transformers>=4.35.0; extra == 'all'
|
|
41
|
+
Provides-Extra: anthropic
|
|
42
|
+
Requires-Dist: anthropic>=0.18.0; extra == 'anthropic'
|
|
43
|
+
Provides-Extra: controls
|
|
44
|
+
Requires-Dist: presidio-analyzer>=2.2.0; extra == 'controls'
|
|
45
|
+
Requires-Dist: presidio-anonymizer>=2.2.0; extra == 'controls'
|
|
46
|
+
Requires-Dist: pyyaml>=6.0.0; extra == 'controls'
|
|
47
|
+
Requires-Dist: spacy>=3.5.0; extra == 'controls'
|
|
48
|
+
Requires-Dist: torch>=2.0.0; extra == 'controls'
|
|
49
|
+
Requires-Dist: transformers>=4.35.0; extra == 'controls'
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
52
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
53
|
+
Requires-Dist: pytest-httpx>=0.22.0; extra == 'dev'
|
|
54
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
55
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
56
|
+
Provides-Extra: jailbreak
|
|
57
|
+
Requires-Dist: pyyaml>=6.0.0; extra == 'jailbreak'
|
|
58
|
+
Requires-Dist: torch>=2.0.0; extra == 'jailbreak'
|
|
59
|
+
Requires-Dist: transformers>=4.35.0; extra == 'jailbreak'
|
|
60
|
+
Provides-Extra: openai
|
|
61
|
+
Requires-Dist: openai>=1.0.0; extra == 'openai'
|
|
62
|
+
Provides-Extra: redaction
|
|
63
|
+
Requires-Dist: presidio-analyzer>=2.2.0; extra == 'redaction'
|
|
64
|
+
Requires-Dist: presidio-anonymizer>=2.2.0; extra == 'redaction'
|
|
65
|
+
Requires-Dist: pyyaml>=6.0.0; extra == 'redaction'
|
|
66
|
+
Requires-Dist: spacy>=3.5.0; extra == 'redaction'
|
|
67
|
+
Description-Content-Type: text/markdown
|
|
68
|
+
|
|
69
|
+
<p align="center">
|
|
70
|
+
<img src="assets/glacis-logo.png" alt="Glacis" width="200">
|
|
71
|
+
</p>
|
|
72
|
+
|
|
73
|
+
# Glacis Python SDK
|
|
74
|
+
|
|
75
|
+
**Tamper-proof audit logs for AI systems - without exposing sensitive data.**
|
|
76
|
+
|
|
77
|
+
## The Problem
|
|
78
|
+
|
|
79
|
+
You need to prove what your AI did for compliance, audits, or legal discovery. But sending prompts and responses to a logging service exposes sensitive data (PII, PHI, trade secrets).
|
|
80
|
+
|
|
81
|
+
## The Solution
|
|
82
|
+
|
|
83
|
+
Glacis creates cryptographic proofs of AI operations. Your data stays local - only a SHA-256 hash is sent for witnessing.
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Your Infrastructure Glacis Log
|
|
87
|
+
┌─────────────────────┐ ┌─────────────────────┐
|
|
88
|
+
│ "Pt. Frodo Baggins │ │ 7a3f8b2c... │
|
|
89
|
+
│ has diabetes" │ ──→ │ (64-char hash) │
|
|
90
|
+
│ │ │ + timestamp │
|
|
91
|
+
│ (data stays here) │ │ + Merkle proof │
|
|
92
|
+
└─────────────────────┘ └─────────────────────┘
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Later, you can prove the hash matches your local records without revealing the data itself.
|
|
96
|
+
|
|
97
|
+
## Installation
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install glacis[openai] # For OpenAI
|
|
101
|
+
pip install glacis[anthropic] # For Anthropic
|
|
102
|
+
pip install glacis[controls] # Add PII redaction + jailbreak detection
|
|
103
|
+
pip install glacis[all] # Everything
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Quick Start
|
|
107
|
+
|
|
108
|
+
### Option 1: Drop-in Wrapper (Recommended)
|
|
109
|
+
|
|
110
|
+
Replace your OpenAI/Anthropic client with a wrapped version. Every API call is automatically attested.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
import os
|
|
114
|
+
from glacis.integrations.openai import attested_openai, get_last_receipt
|
|
115
|
+
|
|
116
|
+
# Create wrapped client (offline mode - no Glacis account needed)
|
|
117
|
+
client = attested_openai(
|
|
118
|
+
openai_api_key="sk-...",
|
|
119
|
+
offline=True,
|
|
120
|
+
signing_seed=os.urandom(32),
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Use exactly like the normal OpenAI client
|
|
124
|
+
response = client.chat.completions.create(
|
|
125
|
+
model="gpt-4",
|
|
126
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Get the attestation receipt
|
|
130
|
+
receipt = get_last_receipt()
|
|
131
|
+
print(f"Attestation ID: {receipt.attestation_id}")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Works the same for Anthropic:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from glacis.integrations.anthropic import attested_anthropic, get_last_receipt
|
|
138
|
+
|
|
139
|
+
client = attested_anthropic(
|
|
140
|
+
anthropic_api_key="sk-ant-...",
|
|
141
|
+
offline=True,
|
|
142
|
+
signing_seed=os.urandom(32),
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Option 2: Direct API
|
|
147
|
+
|
|
148
|
+
For custom attestations (non-OpenAI/Anthropic, or manual control):
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
import os
|
|
152
|
+
from glacis import Glacis
|
|
153
|
+
|
|
154
|
+
glacis = Glacis(mode="offline", signing_seed=os.urandom(32))
|
|
155
|
+
|
|
156
|
+
receipt = glacis.attest(
|
|
157
|
+
service_id="my-ai-app",
|
|
158
|
+
operation_type="inference",
|
|
159
|
+
input={"prompt": "Summarize this..."},
|
|
160
|
+
output={"response": "The document..."},
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Adding PII Redaction
|
|
165
|
+
|
|
166
|
+
Automatically detect and redact sensitive data before it's hashed:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
client = attested_openai(
|
|
170
|
+
openai_api_key="sk-...",
|
|
171
|
+
offline=True,
|
|
172
|
+
signing_seed=os.urandom(32),
|
|
173
|
+
redaction="fast", # Regex-based, or "full" for ML models
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
response = client.chat.completions.create(
|
|
177
|
+
model="gpt-4",
|
|
178
|
+
messages=[{"role": "user", "content": "My SSN is 123-45-6789"}]
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# The attestation hash is computed on: "My SSN is [US_SSN]"
|
|
182
|
+
# Original text still sent to OpenAI, but redacted version is attested
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Configuration File
|
|
186
|
+
|
|
187
|
+
For persistent settings, create `glacis.yaml`:
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
attestation:
|
|
191
|
+
offline: true
|
|
192
|
+
service_id: my-ai-service
|
|
193
|
+
|
|
194
|
+
controls:
|
|
195
|
+
pii_phi:
|
|
196
|
+
enabled: true
|
|
197
|
+
mode: fast # "fast" (regex) or "full" (Presidio NER)
|
|
198
|
+
|
|
199
|
+
jailbreak:
|
|
200
|
+
enabled: true
|
|
201
|
+
threshold: 0.5 # Block prompt injection attempts
|
|
202
|
+
action: block # "warn" or "block"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Then:
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
client = attested_openai(
|
|
209
|
+
openai_api_key="sk-...",
|
|
210
|
+
config_path="glacis.yaml",
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Retrieving Evidence
|
|
215
|
+
|
|
216
|
+
Full payloads are stored locally for audits:
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from glacis.integrations.openai import get_last_receipt, get_evidence
|
|
220
|
+
|
|
221
|
+
receipt = get_last_receipt()
|
|
222
|
+
evidence = get_evidence(receipt.attestation_id)
|
|
223
|
+
|
|
224
|
+
print(evidence["input"]) # Original input
|
|
225
|
+
print(evidence["output"]) # Original output
|
|
226
|
+
print(evidence["control_plane_results"]) # PII/jailbreak results
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Evidence is stored in `~/.glacis/receipts.db` (SQLite).
|
|
230
|
+
|
|
231
|
+
## Online vs Offline Mode
|
|
232
|
+
|
|
233
|
+
| Feature | Offline | Online |
|
|
234
|
+
|---------|---------|--------|
|
|
235
|
+
| Requires Glacis account | No | Yes |
|
|
236
|
+
| Signing | Local Ed25519 | Glacis witness |
|
|
237
|
+
| Third-party verifiable | No | Yes (Merkle proofs) |
|
|
238
|
+
| Use case | Development, air-gapped | Production, audits |
|
|
239
|
+
|
|
240
|
+
To use online mode:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
client = attested_openai(
|
|
244
|
+
openai_api_key="sk-...",
|
|
245
|
+
glacis_api_key="glsk_live_...", # Get at glacis.io
|
|
246
|
+
)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## What Gets Sent to Glacis?
|
|
250
|
+
|
|
251
|
+
| Data | Sent? |
|
|
252
|
+
|------|-------|
|
|
253
|
+
| Your prompts | No (hash only) |
|
|
254
|
+
| Model responses | No (hash only) |
|
|
255
|
+
| API keys | No |
|
|
256
|
+
| service_id, operation_type | Yes |
|
|
257
|
+
| Timestamps | Yes |
|
|
258
|
+
|
|
259
|
+
## CLI
|
|
260
|
+
|
|
261
|
+
Verify a receipt:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
python -m glacis verify receipt.json
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Security
|
|
268
|
+
|
|
269
|
+
- **Hashing**: SHA-256 with RFC 8785 canonical JSON (cross-runtime compatible)
|
|
270
|
+
- **Signing**: Ed25519 via PyNaCl (libsodium)
|
|
271
|
+
- **Online mode**: Merkle tree inclusion proofs (RFC 6962)
|
|
272
|
+
|
|
273
|
+
## License
|
|
274
|
+
|
|
275
|
+
Apache 2.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
glacis/__init__.py,sha256=c56NUPfPCDk2kh9wuSiQvREvnJ3lZGk889zOUNIZt4c,3925
|
|
2
|
+
glacis/__main__.py,sha256=jnL1RezHA3aCK9Vx3JziwEZF5Wxl34fyoGmB9i4_gVs,141
|
|
3
|
+
glacis/client.py,sha256=dpMmaQCQ8u6QYCwY_dEyM69AI1j7xpwS6ljq4xDTOVM,29075
|
|
4
|
+
glacis/config.py,sha256=tjaPgXpIkoURkVPEsRb7ELjrZf53b5IXaqho57bXo_o,4034
|
|
5
|
+
glacis/crypto.py,sha256=Pq6b99DvWGtqaC-rpoDgRAZz87ygZ0lJqKDU9n-sBZg,5924
|
|
6
|
+
glacis/models.py,sha256=jb-vU2r90zxEnMzmN_BgJdnN6kd3cMgbAMOPANUo79I,17265
|
|
7
|
+
glacis/storage.py,sha256=2wPa4zX9ef_yoKRY_qyQm6Fj4lgkIJ4kzbK5ZZQbSNk,21428
|
|
8
|
+
glacis/streaming.py,sha256=hAmR4XHQixLia6awnFfCaA9hZOtCq2b-pOzgaMd3YzQ,11260
|
|
9
|
+
glacis/verify.py,sha256=e2Hr9cYrqt3gdsY7Qx69wYjAL_eoXaxZHJDuft7lNMA,4886
|
|
10
|
+
glacis/controls/__init__.py,sha256=gs4avL8EAKgKwr2ocPzIl2TfEr1PeUpHi44GaCwQtWk,7737
|
|
11
|
+
glacis/controls/base.py,sha256=AiLZQcH5KkXk1yQPOPB-hd0-Q8NCqX0rVoZSdq_NBOo,3321
|
|
12
|
+
glacis/controls/jailbreak.py,sha256=hXPAYcN2-qnmQMZBs5QOtk7IhErNp2oKbDoU361IOss,7740
|
|
13
|
+
glacis/controls/pii.py,sha256=K9_ZY4UMUiN6WTac-BvTaCyO3MhOc1oH9k5BGmq_Vrw,27833
|
|
14
|
+
glacis/integrations/__init__.py,sha256=reRDe-JaxHP3TrskPjdS5mxr1uCcVSKj-Vb5-ussl8o,1965
|
|
15
|
+
glacis/integrations/anthropic.py,sha256=rFf7cQuXq3Bs5ZkaPZcZltjd5EjGVCx2EeKmy287Jsg,10568
|
|
16
|
+
glacis/integrations/base.py,sha256=SAB_cIK_D8hEyClOx53Qe9p0Um0KtP9Ua4gZ23FBD-o,14784
|
|
17
|
+
glacis/integrations/openai.py,sha256=jtfo0RlVbEhDZfsSiGliJLcgFL2hziS2n8JukT-a4e0,8441
|
|
18
|
+
glacis-0.2.0.dist-info/METADATA,sha256=UiHN1EXWrzgUxriHL9U5F7A6XmlUbMq_6u8dQuSQ5KU,8290
|
|
19
|
+
glacis-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
20
|
+
glacis-0.2.0.dist-info/licenses/LICENSE,sha256=B7g2sM9vz4NF1poTFNMil2cnkwMFel1qUnimyvYW1sw,10766
|
|
21
|
+
glacis-0.2.0.dist-info/RECORD,,
|
glacis/wasm/s3p_core_wasi.wasm
DELETED
|
Binary file
|