privaro 0.1.0__tar.gz

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.
privaro-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,232 @@
1
+ Metadata-Version: 2.4
2
+ Name: privaro
3
+ Version: 0.1.0
4
+ Summary: Privacy Infrastructure for Enterprise AI — Official Python SDK
5
+ Author-email: iCommunity Labs <hello@icommunity.io>
6
+ License: MIT
7
+ Project-URL: Homepage, https://privaro.io
8
+ Project-URL: Documentation, https://privaro.io/docs
9
+ Project-URL: Repository, https://github.com/icommunity-labs/privaro-python-sdk
10
+ Project-URL: Bug Tracker, https://github.com/icommunity-labs/privaro-python-sdk/issues
11
+ Keywords: privacy,pii,gdpr,ai,llm,compliance,blockchain
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Security
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ Provides-Extra: async
25
+ Requires-Dist: aiohttp>=3.9; extra == "async"
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: pytest-asyncio; extra == "dev"
29
+ Requires-Dist: aiohttp>=3.9; extra == "dev"
30
+ Requires-Dist: black; extra == "dev"
31
+ Requires-Dist: ruff; extra == "dev"
32
+
33
+ # Privaro Python SDK
34
+
35
+ **Privacy Infrastructure for Enterprise AI** — Official Python SDK by [iCommunity Labs](https://privaro.io)
36
+
37
+ Protect PII in AI prompts with one line of code. Every interaction is tokenized, audited, and blockchain-certified.
38
+
39
+ ---
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install privaro
45
+ ```
46
+
47
+ No required dependencies — uses Python stdlib only.
48
+
49
+ ```bash
50
+ # Optional: async support
51
+ pip install privaro[async]
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ import privaro
60
+
61
+ # Initialize once (e.g., at app startup)
62
+ privaro.init(
63
+ api_key="prvr_your_api_key",
64
+ pipeline_id="your-pipeline-uuid",
65
+ )
66
+
67
+ # Protect a prompt before sending to any LLM
68
+ result = privaro.protect("Patient: María García, DNI 34521789X, IBAN ES91 2100...")
69
+
70
+ print(result.protected) # "Patient: [NM-0001], DNI [ID-0001], IBAN [BK-0001]..."
71
+ print(result.risk_score) # 0.847
72
+ print(result.risk_level) # "high"
73
+ print(result.gdpr_compliant) # True
74
+
75
+ # Send protected prompt to your LLM — no PII ever reaches the model
76
+ response = openai.chat.completions.create(
77
+ model="gpt-4o",
78
+ messages=[{"role": "user", "content": result.protected}]
79
+ )
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Usage Patterns
85
+
86
+ ### Protect + LLM (full pipeline)
87
+
88
+ ```python
89
+ import privaro
90
+ import openai
91
+
92
+ privaro.init(api_key="prvr_xxx", pipeline_id="uuid")
93
+
94
+ def ask_ai(user_input: str) -> str:
95
+ # 1. Protect PII
96
+ protected = privaro.protect(user_input)
97
+
98
+ if not protected.is_safe:
99
+ raise ValueError(f"PII leak detected: {protected.leaked} entities exposed")
100
+
101
+ # 2. Call LLM with protected prompt
102
+ response = openai.chat.completions.create(
103
+ model="gpt-4o",
104
+ messages=[{"role": "user", "content": protected.protected}]
105
+ )
106
+
107
+ return response.choices[0].message.content
108
+ ```
109
+
110
+ ### Detect only (analysis mode)
111
+
112
+ ```python
113
+ result = privaro.detect("Call me at 612 345 678, email: user@company.es")
114
+
115
+ for detection in result.detections:
116
+ print(f"{detection.type}: {detection.severity} ({detection.detector})")
117
+ # phone: high (regex)
118
+ # email: high (regex)
119
+ ```
120
+
121
+ ### Agent mode (stricter policies)
122
+
123
+ ```python
124
+ result = privaro.protect(
125
+ prompt=agent_input,
126
+ agent_mode=True, # Applies stricter policy preset
127
+ )
128
+ ```
129
+
130
+ ### Multiple clients (multiple pipelines)
131
+
132
+ ```python
133
+ from privaro import PrivaroClient
134
+
135
+ legal_client = PrivaroClient(api_key="prvr_xxx", pipeline_id="legal-pipeline-uuid")
136
+ hr_client = PrivaroClient(api_key="prvr_xxx", pipeline_id="hr-pipeline-uuid")
137
+
138
+ legal_result = legal_client.protect(contract_text)
139
+ hr_result = hr_client.protect(employee_record)
140
+ ```
141
+
142
+ ### Async support
143
+
144
+ ```python
145
+ from privaro.async_client import AsyncPrivaroClient
146
+
147
+ client = AsyncPrivaroClient(api_key="prvr_xxx", pipeline_id="uuid")
148
+
149
+ async def process(prompt: str):
150
+ result = await client.protect(prompt)
151
+ return result.protected
152
+ ```
153
+
154
+ ### Error handling
155
+
156
+ ```python
157
+ from privaro.exceptions import AuthError, PolicyBlockError, ProxyUnavailableError
158
+
159
+ try:
160
+ result = privaro.protect(prompt)
161
+ except PolicyBlockError as e:
162
+ # Request blocked by policy (e.g., health data on non-approved provider)
163
+ logger.warning(f"Request blocked: {e}")
164
+ return "Request cannot be processed — sensitive data detected."
165
+ except ProxyUnavailableError:
166
+ # Fallback: log and fail safely
167
+ logger.error("Privaro proxy unavailable")
168
+ raise
169
+ except AuthError:
170
+ logger.error("Invalid Privaro API key")
171
+ raise
172
+ ```
173
+
174
+ ---
175
+
176
+ ## ProtectResult Reference
177
+
178
+ | Property | Type | Description |
179
+ |---|---|---|
180
+ | `result.protected` | str | Prompt with PII replaced by tokens |
181
+ | `result.original` | str | Original prompt (local only) |
182
+ | `result.risk_score` | float | 0.0–1.0 composite risk score |
183
+ | `result.risk_level` | str | "high" / "medium" / "low" |
184
+ | `result.gdpr_compliant` | bool | True if no PII leaked |
185
+ | `result.is_safe` | bool | True if all PII masked |
186
+ | `result.has_pii` | bool | True if any entities detected |
187
+ | `result.total_detected` | int | Total PII entities found |
188
+ | `result.total_masked` | int | Entities successfully masked |
189
+ | `result.leaked` | int | Entities that passed through |
190
+ | `result.detections` | list[Detection] | Per-entity details |
191
+ | `result.audit_log_id` | str | Supabase audit log UUID |
192
+ | `result.processing_ms` | int | Proxy latency in ms |
193
+ | `result.summary()` | str | One-line log summary |
194
+
195
+ ---
196
+
197
+ ## Detection Reference
198
+
199
+ | Property | Values |
200
+ |---|---|
201
+ | `detection.type` | `dni` `iban` `email` `full_name` `phone` `health_record` `credit_card` `ip_address` `date_of_birth` |
202
+ | `detection.severity` | `critical` `high` `medium` `low` |
203
+ | `detection.action` | `tokenised` `anonymised` `blocked` |
204
+ | `detection.detector` | `regex` `presidio` |
205
+ | `detection.confidence` | 0.0–1.0 |
206
+ | `detection.is_high_risk` | bool |
207
+
208
+ ---
209
+
210
+ ## Blockchain Verification
211
+
212
+ Every `protect()` call creates an immutable audit entry certified on **Fantom Opera Mainnet** via iBS. Verify any event at:
213
+
214
+ ```
215
+ https://checker.icommunitylabs.com/check/fantom_opera_mainnet/{tx_hash}
216
+ ```
217
+
218
+ Access the TX hash from your Privaro dashboard → Audit Logs → ⛓️ badge.
219
+
220
+ ---
221
+
222
+ ## Requirements
223
+
224
+ - Python 3.9+
225
+ - Zero required dependencies (uses `urllib` from stdlib)
226
+ - Optional: `aiohttp>=3.9` for async support
227
+
228
+ ---
229
+
230
+ ## License
231
+
232
+ MIT — © 2026 iCommunity Labs · [privaro.io](https://privaro.io)
@@ -0,0 +1,200 @@
1
+ # Privaro Python SDK
2
+
3
+ **Privacy Infrastructure for Enterprise AI** — Official Python SDK by [iCommunity Labs](https://privaro.io)
4
+
5
+ Protect PII in AI prompts with one line of code. Every interaction is tokenized, audited, and blockchain-certified.
6
+
7
+ ---
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install privaro
13
+ ```
14
+
15
+ No required dependencies — uses Python stdlib only.
16
+
17
+ ```bash
18
+ # Optional: async support
19
+ pip install privaro[async]
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Quick Start
25
+
26
+ ```python
27
+ import privaro
28
+
29
+ # Initialize once (e.g., at app startup)
30
+ privaro.init(
31
+ api_key="prvr_your_api_key",
32
+ pipeline_id="your-pipeline-uuid",
33
+ )
34
+
35
+ # Protect a prompt before sending to any LLM
36
+ result = privaro.protect("Patient: María García, DNI 34521789X, IBAN ES91 2100...")
37
+
38
+ print(result.protected) # "Patient: [NM-0001], DNI [ID-0001], IBAN [BK-0001]..."
39
+ print(result.risk_score) # 0.847
40
+ print(result.risk_level) # "high"
41
+ print(result.gdpr_compliant) # True
42
+
43
+ # Send protected prompt to your LLM — no PII ever reaches the model
44
+ response = openai.chat.completions.create(
45
+ model="gpt-4o",
46
+ messages=[{"role": "user", "content": result.protected}]
47
+ )
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Usage Patterns
53
+
54
+ ### Protect + LLM (full pipeline)
55
+
56
+ ```python
57
+ import privaro
58
+ import openai
59
+
60
+ privaro.init(api_key="prvr_xxx", pipeline_id="uuid")
61
+
62
+ def ask_ai(user_input: str) -> str:
63
+ # 1. Protect PII
64
+ protected = privaro.protect(user_input)
65
+
66
+ if not protected.is_safe:
67
+ raise ValueError(f"PII leak detected: {protected.leaked} entities exposed")
68
+
69
+ # 2. Call LLM with protected prompt
70
+ response = openai.chat.completions.create(
71
+ model="gpt-4o",
72
+ messages=[{"role": "user", "content": protected.protected}]
73
+ )
74
+
75
+ return response.choices[0].message.content
76
+ ```
77
+
78
+ ### Detect only (analysis mode)
79
+
80
+ ```python
81
+ result = privaro.detect("Call me at 612 345 678, email: user@company.es")
82
+
83
+ for detection in result.detections:
84
+ print(f"{detection.type}: {detection.severity} ({detection.detector})")
85
+ # phone: high (regex)
86
+ # email: high (regex)
87
+ ```
88
+
89
+ ### Agent mode (stricter policies)
90
+
91
+ ```python
92
+ result = privaro.protect(
93
+ prompt=agent_input,
94
+ agent_mode=True, # Applies stricter policy preset
95
+ )
96
+ ```
97
+
98
+ ### Multiple clients (multiple pipelines)
99
+
100
+ ```python
101
+ from privaro import PrivaroClient
102
+
103
+ legal_client = PrivaroClient(api_key="prvr_xxx", pipeline_id="legal-pipeline-uuid")
104
+ hr_client = PrivaroClient(api_key="prvr_xxx", pipeline_id="hr-pipeline-uuid")
105
+
106
+ legal_result = legal_client.protect(contract_text)
107
+ hr_result = hr_client.protect(employee_record)
108
+ ```
109
+
110
+ ### Async support
111
+
112
+ ```python
113
+ from privaro.async_client import AsyncPrivaroClient
114
+
115
+ client = AsyncPrivaroClient(api_key="prvr_xxx", pipeline_id="uuid")
116
+
117
+ async def process(prompt: str):
118
+ result = await client.protect(prompt)
119
+ return result.protected
120
+ ```
121
+
122
+ ### Error handling
123
+
124
+ ```python
125
+ from privaro.exceptions import AuthError, PolicyBlockError, ProxyUnavailableError
126
+
127
+ try:
128
+ result = privaro.protect(prompt)
129
+ except PolicyBlockError as e:
130
+ # Request blocked by policy (e.g., health data on non-approved provider)
131
+ logger.warning(f"Request blocked: {e}")
132
+ return "Request cannot be processed — sensitive data detected."
133
+ except ProxyUnavailableError:
134
+ # Fallback: log and fail safely
135
+ logger.error("Privaro proxy unavailable")
136
+ raise
137
+ except AuthError:
138
+ logger.error("Invalid Privaro API key")
139
+ raise
140
+ ```
141
+
142
+ ---
143
+
144
+ ## ProtectResult Reference
145
+
146
+ | Property | Type | Description |
147
+ |---|---|---|
148
+ | `result.protected` | str | Prompt with PII replaced by tokens |
149
+ | `result.original` | str | Original prompt (local only) |
150
+ | `result.risk_score` | float | 0.0–1.0 composite risk score |
151
+ | `result.risk_level` | str | "high" / "medium" / "low" |
152
+ | `result.gdpr_compliant` | bool | True if no PII leaked |
153
+ | `result.is_safe` | bool | True if all PII masked |
154
+ | `result.has_pii` | bool | True if any entities detected |
155
+ | `result.total_detected` | int | Total PII entities found |
156
+ | `result.total_masked` | int | Entities successfully masked |
157
+ | `result.leaked` | int | Entities that passed through |
158
+ | `result.detections` | list[Detection] | Per-entity details |
159
+ | `result.audit_log_id` | str | Supabase audit log UUID |
160
+ | `result.processing_ms` | int | Proxy latency in ms |
161
+ | `result.summary()` | str | One-line log summary |
162
+
163
+ ---
164
+
165
+ ## Detection Reference
166
+
167
+ | Property | Values |
168
+ |---|---|
169
+ | `detection.type` | `dni` `iban` `email` `full_name` `phone` `health_record` `credit_card` `ip_address` `date_of_birth` |
170
+ | `detection.severity` | `critical` `high` `medium` `low` |
171
+ | `detection.action` | `tokenised` `anonymised` `blocked` |
172
+ | `detection.detector` | `regex` `presidio` |
173
+ | `detection.confidence` | 0.0–1.0 |
174
+ | `detection.is_high_risk` | bool |
175
+
176
+ ---
177
+
178
+ ## Blockchain Verification
179
+
180
+ Every `protect()` call creates an immutable audit entry certified on **Fantom Opera Mainnet** via iBS. Verify any event at:
181
+
182
+ ```
183
+ https://checker.icommunitylabs.com/check/fantom_opera_mainnet/{tx_hash}
184
+ ```
185
+
186
+ Access the TX hash from your Privaro dashboard → Audit Logs → ⛓️ badge.
187
+
188
+ ---
189
+
190
+ ## Requirements
191
+
192
+ - Python 3.9+
193
+ - Zero required dependencies (uses `urllib` from stdlib)
194
+ - Optional: `aiohttp>=3.9` for async support
195
+
196
+ ---
197
+
198
+ ## License
199
+
200
+ MIT — © 2026 iCommunity Labs · [privaro.io](https://privaro.io)
@@ -0,0 +1,122 @@
1
+ """
2
+ Privaro Python SDK
3
+ Privacy Infrastructure for Enterprise AI — iCommunity Labs
4
+
5
+ Usage:
6
+ import privaro
7
+
8
+ privaro.init(api_key="prvr_xxx", pipeline_id="uuid")
9
+ result = privaro.protect("Patient: María García, DNI 34521789X")
10
+
11
+ print(result.protected) # "Patient: [NM-0001], DNI [ID-0001]"
12
+ print(result.risk_score) # 0.847
13
+ print(result.gdpr_compliant) # True
14
+ """
15
+
16
+ from .client import PrivaroClient
17
+ from .models import ProtectResult, Detection
18
+ from .exceptions import PrivaroError, AuthError, PipelineNotFoundError
19
+
20
+ __version__ = "0.1.0"
21
+ __all__ = [
22
+ "PrivaroClient",
23
+ "ProtectResult",
24
+ "Detection",
25
+ "PrivaroError",
26
+ "AuthError",
27
+ "PipelineNotFoundError",
28
+ "init",
29
+ "protect",
30
+ "detect",
31
+ ]
32
+
33
+ # ── Module-level default client ───────────────────────────────────────────────
34
+ _default_client: "PrivaroClient | None" = None
35
+
36
+
37
+ def init(
38
+ api_key: str,
39
+ pipeline_id: str,
40
+ base_url: str = "https://privaro-proxy-production.up.railway.app/v1",
41
+ timeout: float = 10.0,
42
+ ) -> PrivaroClient:
43
+ """
44
+ Initialize the default Privaro client.
45
+
46
+ Args:
47
+ api_key: Your Privaro API key (starts with prvr_)
48
+ pipeline_id: UUID of your active pipeline
49
+ base_url: Proxy URL (default: production)
50
+ timeout: Request timeout in seconds
51
+
52
+ Returns:
53
+ PrivaroClient instance (also set as module default)
54
+
55
+ Example:
56
+ privaro.init(
57
+ api_key="prvr_abc123",
58
+ pipeline_id="c93aed87-b440-4de0-bb21-54a938e475f2"
59
+ )
60
+ """
61
+ global _default_client
62
+ _default_client = PrivaroClient(
63
+ api_key=api_key,
64
+ pipeline_id=pipeline_id,
65
+ base_url=base_url,
66
+ timeout=timeout,
67
+ )
68
+ return _default_client
69
+
70
+
71
+ def _require_client() -> "PrivaroClient":
72
+ if _default_client is None:
73
+ raise PrivaroError(
74
+ "Privaro not initialized. Call privaro.init(api_key=..., pipeline_id=...) first."
75
+ )
76
+ return _default_client
77
+
78
+
79
+ def protect(
80
+ prompt: str,
81
+ mode: str = "tokenise",
82
+ reversible: bool = True,
83
+ agent_mode: bool = False,
84
+ include_detections: bool = True,
85
+ ) -> "ProtectResult":
86
+ """
87
+ Detect and tokenize PII in a prompt.
88
+
89
+ Args:
90
+ prompt: Text to protect
91
+ mode: tokenise | anonymise | block
92
+ reversible: Store reversible tokens in vault
93
+ agent_mode: Apply stricter policies for agent pipelines
94
+ include_detections: Include detection details in response
95
+
96
+ Returns:
97
+ ProtectResult with .protected, .risk_score, .detections, etc.
98
+
99
+ Example:
100
+ result = privaro.protect("Patient: María García, DNI 34521789X")
101
+ llm_response = your_llm.complete(result.protected)
102
+ """
103
+ return _require_client().protect(
104
+ prompt=prompt,
105
+ mode=mode,
106
+ reversible=reversible,
107
+ agent_mode=agent_mode,
108
+ include_detections=include_detections,
109
+ )
110
+
111
+
112
+ def detect(prompt: str) -> "ProtectResult":
113
+ """
114
+ Detect PII without masking (analysis mode).
115
+ Does not store audit logs or tokens.
116
+
117
+ Example:
118
+ result = privaro.detect("Call me at 612 345 678")
119
+ for d in result.detections:
120
+ print(d.type, d.confidence)
121
+ """
122
+ return _require_client().detect(prompt=prompt)
@@ -0,0 +1,110 @@
1
+ """
2
+ Privaro SDK — Async Client (optional, requires Python 3.11+)
3
+
4
+ Usage:
5
+ from privaro.async_client import AsyncPrivaroClient
6
+
7
+ client = AsyncPrivaroClient(api_key="prvr_xxx", pipeline_id="uuid")
8
+
9
+ async with client:
10
+ result = await client.protect("María García, DNI 34521789X")
11
+ """
12
+ import json
13
+ from typing import Optional
14
+ from .client import PrivaroClient
15
+ from .models import ProtectResult
16
+ from .exceptions import (
17
+ AuthError, PipelineNotFoundError, PolicyBlockError,
18
+ RateLimitError, ProxyUnavailableError, PrivaroError,
19
+ )
20
+
21
+
22
+ class AsyncPrivaroClient(PrivaroClient):
23
+ """
24
+ Async version of PrivaroClient using aiohttp (optional dependency).
25
+
26
+ Install with: pip install privaro[async]
27
+ """
28
+
29
+ async def _request_async(self, method: str, path: str, payload: dict) -> dict:
30
+ try:
31
+ import aiohttp
32
+ except ImportError:
33
+ raise PrivaroError(
34
+ "aiohttp is required for async support. "
35
+ "Install with: pip install privaro[async]"
36
+ )
37
+
38
+ url = f"{self.base_url}{path}"
39
+
40
+ async with aiohttp.ClientSession() as session:
41
+ try:
42
+ async with session.request(
43
+ method, url,
44
+ json=payload,
45
+ headers=self._headers(),
46
+ timeout=aiohttp.ClientTimeout(total=self.timeout),
47
+ ) as resp:
48
+ body = await resp.json()
49
+
50
+ if resp.status == 401:
51
+ raise AuthError("Invalid API key.")
52
+ if resp.status == 404:
53
+ raise PipelineNotFoundError(f"Pipeline '{self.pipeline_id}' not found.")
54
+ if resp.status == 429:
55
+ raise RateLimitError("Rate limit exceeded.")
56
+ if resp.status >= 400:
57
+ raise PrivaroError(f"HTTP {resp.status}: {body}")
58
+
59
+ return body
60
+
61
+ except aiohttp.ClientConnectorError as e:
62
+ raise ProxyUnavailableError(f"Cannot reach proxy: {e}")
63
+
64
+ async def protect(
65
+ self,
66
+ prompt: str,
67
+ mode: str = "tokenise",
68
+ reversible: bool = True,
69
+ agent_mode: bool = False,
70
+ include_detections: bool = True,
71
+ ) -> ProtectResult:
72
+ """Async version of protect()."""
73
+ if not prompt or not prompt.strip():
74
+ return ProtectResult(protected="", original="", request_id="",
75
+ audit_log_id=None, gdpr_compliant=True)
76
+
77
+ raw = await self._request_async("POST", "/proxy/protect", {
78
+ "pipeline_id": self.pipeline_id,
79
+ "prompt": prompt,
80
+ "options": {
81
+ "mode": mode,
82
+ "reversible": reversible,
83
+ "agent_mode": agent_mode,
84
+ "include_detections": include_detections,
85
+ },
86
+ })
87
+ return self._parse_result(raw, original=prompt)
88
+
89
+ async def detect(self, prompt: str) -> ProtectResult:
90
+ """Async version of detect()."""
91
+ if not prompt or not prompt.strip():
92
+ return ProtectResult(protected=prompt, original=prompt, request_id="",
93
+ audit_log_id=None, gdpr_compliant=True)
94
+
95
+ raw = await self._request_async("POST", "/proxy/detect", {
96
+ "pipeline_id": self.pipeline_id,
97
+ "prompt": prompt,
98
+ })
99
+ result = self._parse_result(
100
+ {**raw, "protected_prompt": prompt, "gdpr_compliant": True},
101
+ original=prompt,
102
+ )
103
+ result.protected = prompt
104
+ return result
105
+
106
+ async def __aenter__(self):
107
+ return self
108
+
109
+ async def __aexit__(self, *args):
110
+ pass