aethex 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.
aethex-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: aethex
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for Aethex — multi-domain AI threat verification (cyber, finance, LLM safety) with explainable reasoning chains.
5
+ Author-email: Aethex <lizsanchez@aethexai.net>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/aethexa1/aethexai
8
+ Project-URL: Documentation, https://github.com/aethexa1/aethexai/tree/main/docs
9
+ Project-URL: Repository, https://github.com/aethexa1/aethexai
10
+ Project-URL: Issues, https://github.com/aethexa1/aethexai/issues
11
+ Keywords: ai-safety,threat-detection,llm-safety,cybersecurity,fraud-detection,aml,fatf,mitre-attack,explainable-ai
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Information Technology
15
+ Classifier: Intended Audience :: Financial and Insurance Industry
16
+ Classifier: Topic :: Security
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Operating System :: OS Independent
26
+ Requires-Python: >=3.8
27
+ Description-Content-Type: text/markdown
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7.0; extra == "dev"
30
+ Requires-Dist: build>=1.0; extra == "dev"
31
+ Requires-Dist: twine>=4.0; extra == "dev"
32
+
33
+ # Aethex Python SDK
34
+
35
+ Official Python client for [Aethex](https://github.com/aethexa1/aethexai) —
36
+ a multi-domain AI threat verification API with explainable reasoning chains.
37
+
38
+ Aethex runs threat events through 10 deterministic reasoning engines and
39
+ returns a verdict with severity, confidence, and a traceable reasoning
40
+ chain. Same engines work across three product domains:
41
+
42
+ - **Cyber** — SOC alerts, intrusion patterns, insider threats
43
+ - **Finance** — AML, sanctions screening, FATF typologies
44
+ - **LLM safety** — agent failure modes, prompt injection, tool-use exfiltration
45
+
46
+ Verdicts are deterministic. Same input produces the same output every
47
+ time, with the same audit trail. This is the core differentiator vs
48
+ LLM-only detection systems.
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install aethex
54
+ ```
55
+
56
+ No external dependencies. Pure stdlib (urllib, json).
57
+
58
+ ## Quick start
59
+
60
+ ```python
61
+ from aethex import AethexClient
62
+
63
+ client = AethexClient(api_key="aex_live_...")
64
+
65
+ # Cyber threat analysis
66
+ verdict = client.cyber.analyze(events=[
67
+ {"type": "failed_login"},
68
+ {"type": "failed_login"},
69
+ {"type": "successful_login", "suspicious": True},
70
+ {"type": "privilege_escalation", "suspicious": True},
71
+ {"type": "lateral_movement", "suspicious": True},
72
+ ])
73
+
74
+ print(verdict["final_severity"]) # CRITICAL
75
+ print(verdict["final_confidence"]) # 0.92
76
+ print(verdict["verdict"]) # human-readable summary
77
+ ```
78
+
79
+ ## Three product domains
80
+
81
+ ```python
82
+ # Cyber
83
+ client.cyber.analyze(events=[...])
84
+
85
+ # Finance (AML / sanctions / fraud)
86
+ client.finance.analyze(events=[
87
+ {"type": "ofac_full_match", "suspicious": True},
88
+ {"type": "sanctioned_geography_routing", "suspicious": True},
89
+ ])
90
+
91
+ # LLM safety
92
+ client.llm.analyze(events=[
93
+ {"type": "external_document_retrieval"},
94
+ {"type": "instruction_override_detected", "suspicious": True},
95
+ {"type": "tool_use_data_exfiltration", "suspicious": True},
96
+ ])
97
+
98
+ # Discover the canonical LLM event vocabulary
99
+ mapping = client.llm.vocabulary()
100
+ ```
101
+
102
+ ## Account operations
103
+
104
+ ```python
105
+ # Audit log export (compliance)
106
+ audit = client.account.export_audit(format="json", from_="2026-01-01")
107
+
108
+ # Customer-tunable severity weighting
109
+ client.account.replace_loss_matrix({
110
+ "failed_login": 0.5, # downweight noisy events
111
+ "external_transfer": 5.0, # upweight critical events
112
+ })
113
+
114
+ # Webhooks for real-time alerts
115
+ webhook = client.account.create_webhook(
116
+ url="https://your-app.com/aethex-webhook",
117
+ threshold="CRITICAL",
118
+ )
119
+ # Save webhook["secret"] now -- it's shown only once.
120
+
121
+ deliveries = client.account.list_deliveries(webhook["id"])
122
+ ```
123
+
124
+ ## Error handling
125
+
126
+ ```python
127
+ from aethex import (
128
+ AethexAuthError,
129
+ AethexRateLimitError,
130
+ AethexValidationError,
131
+ AethexConnectionError,
132
+ AethexError,
133
+ )
134
+
135
+ try:
136
+ verdict = client.cyber.analyze(events=[...])
137
+ except AethexAuthError:
138
+ # 401 — bad / missing / revoked API key
139
+ ...
140
+ except AethexRateLimitError:
141
+ # 429 — back off and retry
142
+ ...
143
+ except AethexValidationError as e:
144
+ # 400 — request body malformed
145
+ print(e.response)
146
+ except AethexConnectionError:
147
+ # network / timeout / DNS / SSL
148
+ ...
149
+ except AethexError:
150
+ # catch-all for anything Aethex-related
151
+ ...
152
+ ```
153
+
154
+ ## What you get back
155
+
156
+ Every `analyze` call returns a verdict dict with:
157
+
158
+ - `final_severity` — `LOW` / `MEDIUM` / `HIGH` / `CRITICAL`
159
+ - `final_confidence` — 0.0 to 1.0
160
+ - `verdict` — human-readable summary
161
+ - `action` — recommended operational response
162
+ - `engines` — per-engine outputs from all 10 reasoning engines
163
+ - `nyaya` — the formal reasoning chain that produced the verdict
164
+ - `chakravyuha` — defense-in-depth layers breached
165
+ - `disagreement` — when engines disagree, the system surfaces uncertainty
166
+ rather than producing false confidence
167
+
168
+ See the [API documentation](https://github.com/aethexa1/aethexai)
169
+ for the full verdict shape.
170
+
171
+ ## Configuration
172
+
173
+ ```python
174
+ client = AethexClient(
175
+ api_key="aex_live_...",
176
+ base_url="https://aethex-api-1yqe.onrender.com", # default
177
+ timeout=30, # seconds
178
+ )
179
+ ```
180
+
181
+ ## Status
182
+
183
+ Alpha. APIs are stabilizing. Breaking changes possible until 1.0.
184
+
185
+ ## License
186
+
187
+ MIT. See LICENSE for details.
188
+
189
+ ---
190
+
191
+ Built by Aethex. Questions: open an issue at the
192
+ [GitHub repo](https://github.com/aethexa1/aethexai/issues).
aethex-0.1.0/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # Aethex Python SDK
2
+
3
+ Official Python client for [Aethex](https://github.com/aethexa1/aethexai) —
4
+ a multi-domain AI threat verification API with explainable reasoning chains.
5
+
6
+ Aethex runs threat events through 10 deterministic reasoning engines and
7
+ returns a verdict with severity, confidence, and a traceable reasoning
8
+ chain. Same engines work across three product domains:
9
+
10
+ - **Cyber** — SOC alerts, intrusion patterns, insider threats
11
+ - **Finance** — AML, sanctions screening, FATF typologies
12
+ - **LLM safety** — agent failure modes, prompt injection, tool-use exfiltration
13
+
14
+ Verdicts are deterministic. Same input produces the same output every
15
+ time, with the same audit trail. This is the core differentiator vs
16
+ LLM-only detection systems.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pip install aethex
22
+ ```
23
+
24
+ No external dependencies. Pure stdlib (urllib, json).
25
+
26
+ ## Quick start
27
+
28
+ ```python
29
+ from aethex import AethexClient
30
+
31
+ client = AethexClient(api_key="aex_live_...")
32
+
33
+ # Cyber threat analysis
34
+ verdict = client.cyber.analyze(events=[
35
+ {"type": "failed_login"},
36
+ {"type": "failed_login"},
37
+ {"type": "successful_login", "suspicious": True},
38
+ {"type": "privilege_escalation", "suspicious": True},
39
+ {"type": "lateral_movement", "suspicious": True},
40
+ ])
41
+
42
+ print(verdict["final_severity"]) # CRITICAL
43
+ print(verdict["final_confidence"]) # 0.92
44
+ print(verdict["verdict"]) # human-readable summary
45
+ ```
46
+
47
+ ## Three product domains
48
+
49
+ ```python
50
+ # Cyber
51
+ client.cyber.analyze(events=[...])
52
+
53
+ # Finance (AML / sanctions / fraud)
54
+ client.finance.analyze(events=[
55
+ {"type": "ofac_full_match", "suspicious": True},
56
+ {"type": "sanctioned_geography_routing", "suspicious": True},
57
+ ])
58
+
59
+ # LLM safety
60
+ client.llm.analyze(events=[
61
+ {"type": "external_document_retrieval"},
62
+ {"type": "instruction_override_detected", "suspicious": True},
63
+ {"type": "tool_use_data_exfiltration", "suspicious": True},
64
+ ])
65
+
66
+ # Discover the canonical LLM event vocabulary
67
+ mapping = client.llm.vocabulary()
68
+ ```
69
+
70
+ ## Account operations
71
+
72
+ ```python
73
+ # Audit log export (compliance)
74
+ audit = client.account.export_audit(format="json", from_="2026-01-01")
75
+
76
+ # Customer-tunable severity weighting
77
+ client.account.replace_loss_matrix({
78
+ "failed_login": 0.5, # downweight noisy events
79
+ "external_transfer": 5.0, # upweight critical events
80
+ })
81
+
82
+ # Webhooks for real-time alerts
83
+ webhook = client.account.create_webhook(
84
+ url="https://your-app.com/aethex-webhook",
85
+ threshold="CRITICAL",
86
+ )
87
+ # Save webhook["secret"] now -- it's shown only once.
88
+
89
+ deliveries = client.account.list_deliveries(webhook["id"])
90
+ ```
91
+
92
+ ## Error handling
93
+
94
+ ```python
95
+ from aethex import (
96
+ AethexAuthError,
97
+ AethexRateLimitError,
98
+ AethexValidationError,
99
+ AethexConnectionError,
100
+ AethexError,
101
+ )
102
+
103
+ try:
104
+ verdict = client.cyber.analyze(events=[...])
105
+ except AethexAuthError:
106
+ # 401 — bad / missing / revoked API key
107
+ ...
108
+ except AethexRateLimitError:
109
+ # 429 — back off and retry
110
+ ...
111
+ except AethexValidationError as e:
112
+ # 400 — request body malformed
113
+ print(e.response)
114
+ except AethexConnectionError:
115
+ # network / timeout / DNS / SSL
116
+ ...
117
+ except AethexError:
118
+ # catch-all for anything Aethex-related
119
+ ...
120
+ ```
121
+
122
+ ## What you get back
123
+
124
+ Every `analyze` call returns a verdict dict with:
125
+
126
+ - `final_severity` — `LOW` / `MEDIUM` / `HIGH` / `CRITICAL`
127
+ - `final_confidence` — 0.0 to 1.0
128
+ - `verdict` — human-readable summary
129
+ - `action` — recommended operational response
130
+ - `engines` — per-engine outputs from all 10 reasoning engines
131
+ - `nyaya` — the formal reasoning chain that produced the verdict
132
+ - `chakravyuha` — defense-in-depth layers breached
133
+ - `disagreement` — when engines disagree, the system surfaces uncertainty
134
+ rather than producing false confidence
135
+
136
+ See the [API documentation](https://github.com/aethexa1/aethexai)
137
+ for the full verdict shape.
138
+
139
+ ## Configuration
140
+
141
+ ```python
142
+ client = AethexClient(
143
+ api_key="aex_live_...",
144
+ base_url="https://aethex-api-1yqe.onrender.com", # default
145
+ timeout=30, # seconds
146
+ )
147
+ ```
148
+
149
+ ## Status
150
+
151
+ Alpha. APIs are stabilizing. Breaking changes possible until 1.0.
152
+
153
+ ## License
154
+
155
+ MIT. See LICENSE for details.
156
+
157
+ ---
158
+
159
+ Built by Aethex. Questions: open an issue at the
160
+ [GitHub repo](https://github.com/aethexa1/aethexai/issues).
@@ -0,0 +1,51 @@
1
+ """
2
+ Aethex Python SDK.
3
+
4
+ Quick start:
5
+
6
+ from aethex import AethexClient
7
+
8
+ client = AethexClient(api_key="aex_live_...")
9
+
10
+ verdict = client.cyber.analyze(events=[
11
+ {"type": "failed_login"},
12
+ {"type": "successful_login", "suspicious": True},
13
+ {"type": "privilege_escalation", "suspicious": True},
14
+ ])
15
+
16
+ print(verdict["final_severity"])
17
+
18
+ Three product domains: cyber, finance, llm.
19
+ Account operations on client.account.
20
+
21
+ Full docs: https://github.com/aethexa1/aethexai
22
+ """
23
+
24
+ from ._version import __version__
25
+
26
+ from .client import AethexClient
27
+
28
+ from .exceptions import (
29
+ AethexError,
30
+ AethexAuthError,
31
+ AethexConnectionError,
32
+ AethexNotFoundError,
33
+ AethexPermissionError,
34
+ AethexRateLimitError,
35
+ AethexServerError,
36
+ AethexValidationError,
37
+ )
38
+
39
+
40
+ __all__ = [
41
+ "__version__",
42
+ "AethexClient",
43
+ "AethexError",
44
+ "AethexAuthError",
45
+ "AethexConnectionError",
46
+ "AethexNotFoundError",
47
+ "AethexPermissionError",
48
+ "AethexRateLimitError",
49
+ "AethexServerError",
50
+ "AethexValidationError",
51
+ ]
@@ -0,0 +1,15 @@
1
+ """
2
+ Aethex Python SDK — single source of truth for version number.
3
+
4
+ Imported by setup.py / pyproject.toml at build time, and by
5
+ aethex/__init__.py at runtime so customers can introspect the
6
+ SDK version they have installed (`aethex.__version__`).
7
+
8
+ Bump on every PyPI release. Pre-1.0 follows 0.x.y where:
9
+ - x bumps for breaking changes (rare pre-1.0)
10
+ - y bumps for new features and bug fixes
11
+
12
+ Post-1.0 we'll switch to strict semver.
13
+ """
14
+
15
+ __version__ = "0.1.0"
@@ -0,0 +1,348 @@
1
+ """
2
+ Aethex Python SDK — main client.
3
+
4
+ Provides AethexClient: a unified interface to all three product
5
+ domains (cyber, finance, llm) plus account-level operations
6
+ (audit export, loss matrix, webhooks).
7
+
8
+ Usage:
9
+ from aethex import AethexClient
10
+
11
+ client = AethexClient(api_key="aex_live_...")
12
+
13
+ # Cyber analysis
14
+ verdict = client.cyber.analyze(events=[
15
+ {"type": "failed_login"},
16
+ {"type": "successful_login", "suspicious": True},
17
+ {"type": "privilege_escalation", "suspicious": True},
18
+ ])
19
+ print(verdict["final_severity"]) # e.g. "CRITICAL"
20
+
21
+ # Finance analysis
22
+ verdict = client.finance.analyze(events=[
23
+ {"type": "ofac_full_match", "suspicious": True},
24
+ {"type": "sanctioned_geography_routing", "suspicious": True},
25
+ ])
26
+
27
+ # LLM safety analysis
28
+ verdict = client.llm.analyze(events=[
29
+ {"type": "external_document_retrieval"},
30
+ {"type": "instruction_override_detected", "suspicious": True},
31
+ {"type": "tool_use_data_exfiltration", "suspicious": True},
32
+ ])
33
+
34
+ Implementation notes:
35
+ - Pure stdlib HTTP (urllib). No external dependencies. Customers
36
+ don't need to pip install requests just to use Aethex.
37
+ - One client instance is thread-safe for read-only attribute access
38
+ but should be created once and reused, not constructed per call.
39
+ - Default timeout: 30 seconds. Configurable per client or per call.
40
+ - All API errors map to typed exceptions in aethex.exceptions.
41
+ """
42
+
43
+ import json
44
+ from typing import Any, Dict, List, Optional
45
+ from urllib.error import HTTPError, URLError
46
+ from urllib.request import Request, urlopen
47
+
48
+ from ._version import __version__
49
+ from .exceptions import (
50
+ AethexAuthError,
51
+ AethexConnectionError,
52
+ AethexError,
53
+ AethexNotFoundError,
54
+ AethexPermissionError,
55
+ AethexRateLimitError,
56
+ AethexServerError,
57
+ AethexValidationError,
58
+ )
59
+
60
+
61
+ # ─── defaults ──────────────────────────────────────────────
62
+
63
+ DEFAULT_BASE_URL = "https://aethex-api-1yqe.onrender.com"
64
+ DEFAULT_TIMEOUT = 30
65
+ USER_AGENT = f"aethex-python/{__version__}"
66
+
67
+
68
+ # ─── http core ─────────────────────────────────────────────
69
+
70
+ def _raise_for_status(status: int, body: str) -> None:
71
+ """Map an HTTP status code to a typed AethexError."""
72
+ if status == 401:
73
+ raise AethexAuthError(
74
+ "API key invalid, missing, or revoked.",
75
+ status_code=status, response=body,
76
+ )
77
+ if status == 403:
78
+ raise AethexPermissionError(
79
+ "API key not scoped for this product domain.",
80
+ status_code=status, response=body,
81
+ )
82
+ if status == 404:
83
+ raise AethexNotFoundError(
84
+ "Resource not found.",
85
+ status_code=status, response=body,
86
+ )
87
+ if status == 429:
88
+ raise AethexRateLimitError(
89
+ "Rate limit exceeded.",
90
+ status_code=status, response=body,
91
+ )
92
+ if status == 400 or 405 <= status < 500:
93
+ raise AethexValidationError(
94
+ f"Request rejected ({status}): {body[:200]}",
95
+ status_code=status, response=body,
96
+ )
97
+ if 500 <= status < 600:
98
+ raise AethexServerError(
99
+ f"Aethex server error ({status}).",
100
+ status_code=status, response=body,
101
+ )
102
+ # Other unexpected status -- still surface it.
103
+ raise AethexError(
104
+ f"Unexpected HTTP {status}: {body[:200]}",
105
+ status_code=status, response=body,
106
+ )
107
+
108
+
109
+ # ─── client ────────────────────────────────────────────────
110
+
111
+ class AethexClient:
112
+ """
113
+ Main entry point for the Aethex SDK.
114
+
115
+ Args:
116
+ api_key: your aex_live_... key (required)
117
+ base_url: override the API endpoint (defaults to production)
118
+ timeout: per-request timeout in seconds (default 30)
119
+ """
120
+
121
+ def __init__(
122
+ self,
123
+ api_key: str,
124
+ base_url: str = DEFAULT_BASE_URL,
125
+ timeout: int = DEFAULT_TIMEOUT,
126
+ ):
127
+ if not api_key or not isinstance(api_key, str):
128
+ raise ValueError("api_key must be a non-empty string")
129
+ if not api_key.startswith("aex_"):
130
+ raise ValueError(
131
+ "api_key has invalid format (expected to start with 'aex_')"
132
+ )
133
+
134
+ self._api_key = api_key
135
+ self._base_url = base_url.rstrip("/")
136
+ self._timeout = timeout
137
+
138
+ # Sub-clients for each product domain
139
+ self.cyber = _CyberAPI(self)
140
+ self.finance = _FinanceAPI(self)
141
+ self.llm = _LLMAPI(self)
142
+
143
+ # Account-level operations
144
+ self.account = _AccountAPI(self)
145
+
146
+ # ─── internal HTTP ────────────────────────────────────
147
+
148
+ def _request(
149
+ self,
150
+ method: str,
151
+ path: str,
152
+ body: Optional[Dict[str, Any]] = None,
153
+ timeout: Optional[int] = None,
154
+ ) -> Dict[str, Any]:
155
+ """
156
+ Internal HTTP helper. Customers should not call this directly --
157
+ use the typed methods on cyber/finance/llm/account instead.
158
+ """
159
+ url = self._base_url + path
160
+ timeout = timeout or self._timeout
161
+ headers = {
162
+ "Authorization": f"Bearer {self._api_key}",
163
+ "User-Agent": USER_AGENT,
164
+ "Accept": "application/json",
165
+ }
166
+ data = None
167
+ if body is not None:
168
+ data = json.dumps(body).encode("utf-8")
169
+ headers["Content-Type"] = "application/json"
170
+
171
+ req = Request(url, data=data, method=method, headers=headers)
172
+
173
+ try:
174
+ with urlopen(req, timeout=timeout) as resp:
175
+ response_body = resp.read().decode("utf-8")
176
+ if resp.status >= 400:
177
+ _raise_for_status(resp.status, response_body)
178
+ return json.loads(response_body) if response_body else {}
179
+ except HTTPError as e:
180
+ response_body = ""
181
+ try:
182
+ response_body = e.read().decode("utf-8", errors="replace")
183
+ except Exception:
184
+ pass
185
+ _raise_for_status(e.code, response_body)
186
+ raise # _raise_for_status always raises, but keep type checker happy
187
+ except URLError as e:
188
+ raise AethexConnectionError(
189
+ f"Network error reaching Aethex: {e.reason}"
190
+ ) from e
191
+ except Exception as e:
192
+ if isinstance(e, AethexError):
193
+ raise
194
+ raise AethexConnectionError(
195
+ f"Unexpected SDK error: {type(e).__name__}: {e}"
196
+ ) from e
197
+
198
+ # ─── repr ─────────────────────────────────────────────
199
+
200
+ def __repr__(self) -> str:
201
+ # Don't leak the API key in repr.
202
+ suffix = self._api_key[-4:] if self._api_key else "????"
203
+ return f"AethexClient(api_key=aex_live_***{suffix}, base_url={self._base_url!r})"
204
+
205
+
206
+ # ─── sub-clients ───────────────────────────────────────────
207
+
208
+ class _DomainAPI:
209
+ """Shared base for cyber/finance/llm domain sub-clients."""
210
+
211
+ _path = "" # subclass override
212
+
213
+ def __init__(self, client: AethexClient):
214
+ self._client = client
215
+
216
+ def analyze(
217
+ self,
218
+ events: List[Dict[str, Any]],
219
+ session_id: Optional[str] = None,
220
+ timestamp: Optional[str] = None,
221
+ frames: Optional[List[str]] = None,
222
+ ) -> Dict[str, Any]:
223
+ """
224
+ Run a sequence of events through Aethex's 10 ancient engines.
225
+
226
+ Args:
227
+ events: list of {"type": "...", "suspicious": bool} dicts
228
+ session_id: optional client-supplied session identifier
229
+ timestamp: optional ISO 8601 timestamp (defaults to now)
230
+ frames: optional list of perspective frames
231
+
232
+ Returns:
233
+ verdict dict containing final_severity, final_confidence,
234
+ engines (per-engine outputs), nyaya reasoning chain,
235
+ chakravyuha layers, and recommended action.
236
+ """
237
+ body: Dict[str, Any] = {"events": events}
238
+ if session_id is not None: body["session_id"] = session_id
239
+ if timestamp is not None: body["timestamp"] = timestamp
240
+ if frames is not None: body["frames"] = frames
241
+
242
+ return self._client._request("POST", f"{self._path}/analyze", body=body)
243
+
244
+
245
+ class _CyberAPI(_DomainAPI):
246
+ """Cyber threat analysis. Use for SOC alerts, intrusion patterns, insider threats."""
247
+ _path = "/api/cyber"
248
+
249
+
250
+ class _FinanceAPI(_DomainAPI):
251
+ """Financial fraud / AML / sanctions analysis."""
252
+ _path = "/api/finance"
253
+
254
+
255
+ class _LLMAPI(_DomainAPI):
256
+ """LLM agent safety analysis. Translates LLM event types to engine vocabulary."""
257
+ _path = "/api/llm"
258
+
259
+ def vocabulary(self) -> Dict[str, Any]:
260
+ """
261
+ Return the canonical LLM event-type -> cyber-vocabulary
262
+ mapping. Useful for understanding which LLM events Aethex
263
+ recognizes and what their engine-level equivalents are.
264
+ """
265
+ return self._client._request("GET", "/api/llm/vocabulary")
266
+
267
+
268
+ class _AccountAPI:
269
+ """Account-level operations: audit export, loss matrix, webhooks."""
270
+
271
+ def __init__(self, client: AethexClient):
272
+ self._client = client
273
+
274
+ # --- audit ---
275
+
276
+ def export_audit(
277
+ self,
278
+ format: str = "json",
279
+ from_: Optional[str] = None,
280
+ to: Optional[str] = None,
281
+ ) -> Dict[str, Any]:
282
+ """
283
+ Export the calling key's audit log.
284
+
285
+ Args:
286
+ format: "json" (default) or "csv"
287
+ from_: ISO 8601 start (e.g. "2026-01-01")
288
+ to: ISO 8601 end
289
+ """
290
+ params = []
291
+ if format: params.append(f"format={format}")
292
+ if from_: params.append(f"from={from_}")
293
+ if to: params.append(f"to={to}")
294
+ path = "/api/audit/export" + ("?" + "&".join(params) if params else "")
295
+ return self._client._request("GET", path)
296
+
297
+ # --- loss matrix ---
298
+
299
+ def get_loss_matrix(self) -> Dict[str, Any]:
300
+ """Return the calling key's current loss matrix."""
301
+ return self._client._request("GET", "/api/keys/me/loss-matrix")
302
+
303
+ def replace_loss_matrix(self, matrix: Dict[str, float]) -> Dict[str, Any]:
304
+ """Replace the entire loss matrix with the supplied dict."""
305
+ return self._client._request(
306
+ "PUT", "/api/keys/me/loss-matrix", body={"matrix": matrix},
307
+ )
308
+
309
+ def patch_loss_matrix(self, matrix: Dict[str, float]) -> Dict[str, Any]:
310
+ """Merge the supplied entries into the existing loss matrix."""
311
+ return self._client._request(
312
+ "PATCH", "/api/keys/me/loss-matrix", body={"matrix": matrix},
313
+ )
314
+
315
+ # --- webhooks ---
316
+
317
+ def list_webhooks(self) -> List[Dict[str, Any]]:
318
+ """List webhooks registered to the calling key."""
319
+ return self._client._request("GET", "/api/keys/me/webhooks")
320
+
321
+ def create_webhook(
322
+ self,
323
+ url: str,
324
+ threshold: str = "CRITICAL",
325
+ name: str = "default",
326
+ ) -> Dict[str, Any]:
327
+ """
328
+ Register a new webhook. The plaintext secret is returned ONCE
329
+ in the response. Save it immediately -- it is not retrievable
330
+ afterwards.
331
+ """
332
+ return self._client._request(
333
+ "POST", "/api/keys/me/webhooks",
334
+ body={"url": url, "threshold": threshold, "name": name},
335
+ )
336
+
337
+ def delete_webhook(self, webhook_id: int) -> Dict[str, Any]:
338
+ """Delete a webhook by id."""
339
+ return self._client._request(
340
+ "DELETE", f"/api/keys/me/webhooks/{webhook_id}",
341
+ )
342
+
343
+ def list_deliveries(self, webhook_id: int, limit: int = 50) -> List[Dict[str, Any]]:
344
+ """List recent delivery attempts for a webhook."""
345
+ return self._client._request(
346
+ "GET",
347
+ f"/api/keys/me/webhooks/{webhook_id}/deliveries?limit={limit}",
348
+ )
@@ -0,0 +1,71 @@
1
+ """
2
+ Aethex SDK — exception hierarchy.
3
+
4
+ Customers catch these in their integration code. The hierarchy
5
+ lets them either catch broadly (every Aethex error) or narrowly
6
+ (only auth, only rate-limit, etc).
7
+
8
+ AethexError -- root; catch this for any SDK error
9
+ AethexAuthError -- 401: bad / missing / revoked API key
10
+ AethexPermissionError -- 403: key not scoped for this product
11
+ AethexNotFoundError -- 404: resource doesn't exist
12
+ AethexRateLimitError -- 429: over rate limit
13
+ AethexValidationError -- 400: malformed request
14
+ AethexServerError -- 5xx: Aethex side broke
15
+ AethexConnectionError -- network failure, timeout, DNS, SSL
16
+ """
17
+
18
+ from typing import Optional
19
+
20
+
21
+ class AethexError(Exception):
22
+ """
23
+ Base class for every error this SDK raises.
24
+ Carries the HTTP status code (if applicable) and the response
25
+ body returned by the Aethex API for debugging.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ message: str,
31
+ status_code: Optional[int] = None,
32
+ response: Optional[str] = None,
33
+ ):
34
+ super().__init__(message)
35
+ self.status_code = status_code
36
+ self.response = response
37
+
38
+ def __repr__(self) -> str:
39
+ return (
40
+ f"{type(self).__name__}("
41
+ f"message={str(self)!r}, "
42
+ f"status_code={self.status_code!r})"
43
+ )
44
+
45
+
46
+ class AethexAuthError(AethexError):
47
+ """401 — API key missing, malformed, or revoked."""
48
+
49
+
50
+ class AethexPermissionError(AethexError):
51
+ """403 — API key valid but not scoped for the requested product."""
52
+
53
+
54
+ class AethexNotFoundError(AethexError):
55
+ """404 — resource (webhook, audit entry, etc) does not exist."""
56
+
57
+
58
+ class AethexRateLimitError(AethexError):
59
+ """429 — over the per-key rate limit. Customer should back off."""
60
+
61
+
62
+ class AethexValidationError(AethexError):
63
+ """400 — request body malformed (bad event types, missing fields)."""
64
+
65
+
66
+ class AethexServerError(AethexError):
67
+ """5xx — Aethex side broke. Retry may help."""
68
+
69
+
70
+ class AethexConnectionError(AethexError):
71
+ """Network-layer failure: timeout, DNS error, SSL error, connection refused."""
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: aethex
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for Aethex — multi-domain AI threat verification (cyber, finance, LLM safety) with explainable reasoning chains.
5
+ Author-email: Aethex <lizsanchez@aethexai.net>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/aethexa1/aethexai
8
+ Project-URL: Documentation, https://github.com/aethexa1/aethexai/tree/main/docs
9
+ Project-URL: Repository, https://github.com/aethexa1/aethexai
10
+ Project-URL: Issues, https://github.com/aethexa1/aethexai/issues
11
+ Keywords: ai-safety,threat-detection,llm-safety,cybersecurity,fraud-detection,aml,fatf,mitre-attack,explainable-ai
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Information Technology
15
+ Classifier: Intended Audience :: Financial and Insurance Industry
16
+ Classifier: Topic :: Security
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Operating System :: OS Independent
26
+ Requires-Python: >=3.8
27
+ Description-Content-Type: text/markdown
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7.0; extra == "dev"
30
+ Requires-Dist: build>=1.0; extra == "dev"
31
+ Requires-Dist: twine>=4.0; extra == "dev"
32
+
33
+ # Aethex Python SDK
34
+
35
+ Official Python client for [Aethex](https://github.com/aethexa1/aethexai) —
36
+ a multi-domain AI threat verification API with explainable reasoning chains.
37
+
38
+ Aethex runs threat events through 10 deterministic reasoning engines and
39
+ returns a verdict with severity, confidence, and a traceable reasoning
40
+ chain. Same engines work across three product domains:
41
+
42
+ - **Cyber** — SOC alerts, intrusion patterns, insider threats
43
+ - **Finance** — AML, sanctions screening, FATF typologies
44
+ - **LLM safety** — agent failure modes, prompt injection, tool-use exfiltration
45
+
46
+ Verdicts are deterministic. Same input produces the same output every
47
+ time, with the same audit trail. This is the core differentiator vs
48
+ LLM-only detection systems.
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install aethex
54
+ ```
55
+
56
+ No external dependencies. Pure stdlib (urllib, json).
57
+
58
+ ## Quick start
59
+
60
+ ```python
61
+ from aethex import AethexClient
62
+
63
+ client = AethexClient(api_key="aex_live_...")
64
+
65
+ # Cyber threat analysis
66
+ verdict = client.cyber.analyze(events=[
67
+ {"type": "failed_login"},
68
+ {"type": "failed_login"},
69
+ {"type": "successful_login", "suspicious": True},
70
+ {"type": "privilege_escalation", "suspicious": True},
71
+ {"type": "lateral_movement", "suspicious": True},
72
+ ])
73
+
74
+ print(verdict["final_severity"]) # CRITICAL
75
+ print(verdict["final_confidence"]) # 0.92
76
+ print(verdict["verdict"]) # human-readable summary
77
+ ```
78
+
79
+ ## Three product domains
80
+
81
+ ```python
82
+ # Cyber
83
+ client.cyber.analyze(events=[...])
84
+
85
+ # Finance (AML / sanctions / fraud)
86
+ client.finance.analyze(events=[
87
+ {"type": "ofac_full_match", "suspicious": True},
88
+ {"type": "sanctioned_geography_routing", "suspicious": True},
89
+ ])
90
+
91
+ # LLM safety
92
+ client.llm.analyze(events=[
93
+ {"type": "external_document_retrieval"},
94
+ {"type": "instruction_override_detected", "suspicious": True},
95
+ {"type": "tool_use_data_exfiltration", "suspicious": True},
96
+ ])
97
+
98
+ # Discover the canonical LLM event vocabulary
99
+ mapping = client.llm.vocabulary()
100
+ ```
101
+
102
+ ## Account operations
103
+
104
+ ```python
105
+ # Audit log export (compliance)
106
+ audit = client.account.export_audit(format="json", from_="2026-01-01")
107
+
108
+ # Customer-tunable severity weighting
109
+ client.account.replace_loss_matrix({
110
+ "failed_login": 0.5, # downweight noisy events
111
+ "external_transfer": 5.0, # upweight critical events
112
+ })
113
+
114
+ # Webhooks for real-time alerts
115
+ webhook = client.account.create_webhook(
116
+ url="https://your-app.com/aethex-webhook",
117
+ threshold="CRITICAL",
118
+ )
119
+ # Save webhook["secret"] now -- it's shown only once.
120
+
121
+ deliveries = client.account.list_deliveries(webhook["id"])
122
+ ```
123
+
124
+ ## Error handling
125
+
126
+ ```python
127
+ from aethex import (
128
+ AethexAuthError,
129
+ AethexRateLimitError,
130
+ AethexValidationError,
131
+ AethexConnectionError,
132
+ AethexError,
133
+ )
134
+
135
+ try:
136
+ verdict = client.cyber.analyze(events=[...])
137
+ except AethexAuthError:
138
+ # 401 — bad / missing / revoked API key
139
+ ...
140
+ except AethexRateLimitError:
141
+ # 429 — back off and retry
142
+ ...
143
+ except AethexValidationError as e:
144
+ # 400 — request body malformed
145
+ print(e.response)
146
+ except AethexConnectionError:
147
+ # network / timeout / DNS / SSL
148
+ ...
149
+ except AethexError:
150
+ # catch-all for anything Aethex-related
151
+ ...
152
+ ```
153
+
154
+ ## What you get back
155
+
156
+ Every `analyze` call returns a verdict dict with:
157
+
158
+ - `final_severity` — `LOW` / `MEDIUM` / `HIGH` / `CRITICAL`
159
+ - `final_confidence` — 0.0 to 1.0
160
+ - `verdict` — human-readable summary
161
+ - `action` — recommended operational response
162
+ - `engines` — per-engine outputs from all 10 reasoning engines
163
+ - `nyaya` — the formal reasoning chain that produced the verdict
164
+ - `chakravyuha` — defense-in-depth layers breached
165
+ - `disagreement` — when engines disagree, the system surfaces uncertainty
166
+ rather than producing false confidence
167
+
168
+ See the [API documentation](https://github.com/aethexa1/aethexai)
169
+ for the full verdict shape.
170
+
171
+ ## Configuration
172
+
173
+ ```python
174
+ client = AethexClient(
175
+ api_key="aex_live_...",
176
+ base_url="https://aethex-api-1yqe.onrender.com", # default
177
+ timeout=30, # seconds
178
+ )
179
+ ```
180
+
181
+ ## Status
182
+
183
+ Alpha. APIs are stabilizing. Breaking changes possible until 1.0.
184
+
185
+ ## License
186
+
187
+ MIT. See LICENSE for details.
188
+
189
+ ---
190
+
191
+ Built by Aethex. Questions: open an issue at the
192
+ [GitHub repo](https://github.com/aethexa1/aethexai/issues).
@@ -0,0 +1,13 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ aethex/__init__.py
5
+ aethex/_version.py
6
+ aethex/client.py
7
+ aethex/exceptions.py
8
+ aethex.egg-info/PKG-INFO
9
+ aethex.egg-info/SOURCES.txt
10
+ aethex.egg-info/dependency_links.txt
11
+ aethex.egg-info/requires.txt
12
+ aethex.egg-info/top_level.txt
13
+ tests/test_client.py
@@ -0,0 +1,5 @@
1
+
2
+ [dev]
3
+ pytest>=7.0
4
+ build>=1.0
5
+ twine>=4.0
@@ -0,0 +1 @@
1
+ aethex
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "aethex"
7
+ dynamic = ["version"]
8
+ description = "Official Python SDK for Aethex — multi-domain AI threat verification (cyber, finance, LLM safety) with explainable reasoning chains."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Aethex", email = "lizsanchez@aethexai.net" }
14
+ ]
15
+ keywords = [
16
+ "ai-safety",
17
+ "threat-detection",
18
+ "llm-safety",
19
+ "cybersecurity",
20
+ "fraud-detection",
21
+ "aml",
22
+ "fatf",
23
+ "mitre-attack",
24
+ "explainable-ai",
25
+ ]
26
+ classifiers = [
27
+ "Development Status :: 3 - Alpha",
28
+ "Intended Audience :: Developers",
29
+ "Intended Audience :: Information Technology",
30
+ "Intended Audience :: Financial and Insurance Industry",
31
+ "Topic :: Security",
32
+ "Topic :: Software Development :: Libraries :: Python Modules",
33
+ "License :: OSI Approved :: MIT License",
34
+ "Programming Language :: Python :: 3",
35
+ "Programming Language :: Python :: 3.8",
36
+ "Programming Language :: Python :: 3.9",
37
+ "Programming Language :: Python :: 3.10",
38
+ "Programming Language :: Python :: 3.11",
39
+ "Programming Language :: Python :: 3.12",
40
+ "Operating System :: OS Independent",
41
+ ]
42
+
43
+ # No runtime dependencies. Pure stdlib (urllib, json).
44
+ # Customers shouldn't need to install requests or httpx just to use Aethex.
45
+ dependencies = []
46
+
47
+ [project.optional-dependencies]
48
+ dev = [
49
+ "pytest>=7.0",
50
+ "build>=1.0",
51
+ "twine>=4.0",
52
+ ]
53
+
54
+ [project.urls]
55
+ Homepage = "https://github.com/aethexa1/aethexai"
56
+ Documentation = "https://github.com/aethexa1/aethexai/tree/main/docs"
57
+ Repository = "https://github.com/aethexa1/aethexai"
58
+ Issues = "https://github.com/aethexa1/aethexai/issues"
59
+
60
+ [tool.setuptools.packages.find]
61
+ where = ["."]
62
+ include = ["aethex*"]
63
+
64
+ [tool.setuptools.dynamic]
65
+ version = { attr = "aethex._version.__version__" }
aethex-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
aethex-0.1.0/setup.py ADDED
@@ -0,0 +1,12 @@
1
+ """
2
+ Aethex Python SDK — setup.py
3
+
4
+ Modern packaging metadata lives in pyproject.toml. This file exists
5
+ for legacy compatibility with build tools that still expect a
6
+ setup.py to be present in the package root. setuptools will read
7
+ the pyproject.toml automatically.
8
+ """
9
+
10
+ from setuptools import setup
11
+
12
+ setup()
@@ -0,0 +1,171 @@
1
+ """
2
+ Aethex SDK — basic tests.
3
+
4
+ Run with:
5
+ cd sdk && pip install -e .[dev] && pytest tests/
6
+
7
+ These are unit tests that don't hit the live API. They verify:
8
+ - Client construction validates inputs
9
+ - Exception mapping is correct for each HTTP status code
10
+ - The repr doesn't leak the API key
11
+
12
+ Integration tests (which actually call the live API) live separately
13
+ and require AETHEX_API_KEY to be set. See test_integration.py if it
14
+ exists.
15
+ """
16
+
17
+ import pytest
18
+
19
+ from aethex import (
20
+ AethexClient,
21
+ AethexAuthError,
22
+ AethexConnectionError,
23
+ AethexError,
24
+ AethexNotFoundError,
25
+ AethexPermissionError,
26
+ AethexRateLimitError,
27
+ AethexServerError,
28
+ AethexValidationError,
29
+ )
30
+ from aethex.client import _raise_for_status
31
+
32
+
33
+ # ─── client construction ──────────────────────────────────
34
+
35
+ class TestClientConstruction:
36
+
37
+ def test_valid_key(self):
38
+ client = AethexClient(api_key="aex_live_test123")
39
+ assert client._api_key == "aex_live_test123"
40
+
41
+ def test_default_base_url(self):
42
+ client = AethexClient(api_key="aex_live_test123")
43
+ assert client._base_url == "https://aethex-api-1yqe.onrender.com"
44
+
45
+ def test_custom_base_url(self):
46
+ client = AethexClient(
47
+ api_key="aex_live_test123",
48
+ base_url="http://localhost:8000",
49
+ )
50
+ assert client._base_url == "http://localhost:8000"
51
+
52
+ def test_base_url_trailing_slash_stripped(self):
53
+ client = AethexClient(
54
+ api_key="aex_live_test123",
55
+ base_url="http://localhost:8000/",
56
+ )
57
+ assert client._base_url == "http://localhost:8000"
58
+
59
+ def test_empty_key_rejected(self):
60
+ with pytest.raises(ValueError, match="non-empty string"):
61
+ AethexClient(api_key="")
62
+
63
+ def test_none_key_rejected(self):
64
+ with pytest.raises(ValueError, match="non-empty string"):
65
+ AethexClient(api_key=None)
66
+
67
+ def test_non_string_key_rejected(self):
68
+ with pytest.raises(ValueError, match="non-empty string"):
69
+ AethexClient(api_key=12345)
70
+
71
+ def test_bad_format_key_rejected(self):
72
+ with pytest.raises(ValueError, match="invalid format"):
73
+ AethexClient(api_key="not_aethex_key")
74
+
75
+ def test_subclients_present(self):
76
+ client = AethexClient(api_key="aex_live_test123")
77
+ assert client.cyber is not None
78
+ assert client.finance is not None
79
+ assert client.llm is not None
80
+ assert client.account is not None
81
+
82
+
83
+ class TestClientRepr:
84
+
85
+ def test_repr_does_not_leak_key(self):
86
+ """The repr must never include the full API key."""
87
+ client = AethexClient(api_key="aex_live_supersecret_dontleakme_abcdef")
88
+ r = repr(client)
89
+ assert "supersecret" not in r
90
+ assert "dontleakme" not in r
91
+ # But the suffix is fine for debugging
92
+ assert "cdef" in r
93
+
94
+ def test_repr_includes_base_url(self):
95
+ client = AethexClient(
96
+ api_key="aex_live_test123",
97
+ base_url="http://localhost:8000",
98
+ )
99
+ assert "localhost:8000" in repr(client)
100
+
101
+
102
+ # ─── exception mapping ────────────────────────────────────
103
+
104
+ class TestExceptionMapping:
105
+
106
+ def test_401_raises_auth(self):
107
+ with pytest.raises(AethexAuthError) as exc:
108
+ _raise_for_status(401, '{"detail":"Invalid key"}')
109
+ assert exc.value.status_code == 401
110
+
111
+ def test_403_raises_permission(self):
112
+ with pytest.raises(AethexPermissionError):
113
+ _raise_for_status(403, '{"detail":"Wrong product"}')
114
+
115
+ def test_404_raises_not_found(self):
116
+ with pytest.raises(AethexNotFoundError):
117
+ _raise_for_status(404, '{"detail":"Webhook not found"}')
118
+
119
+ def test_429_raises_rate_limit(self):
120
+ with pytest.raises(AethexRateLimitError):
121
+ _raise_for_status(429, '{"detail":"Slow down"}')
122
+
123
+ def test_400_raises_validation(self):
124
+ with pytest.raises(AethexValidationError):
125
+ _raise_for_status(400, '{"detail":"Bad event"}')
126
+
127
+ def test_422_raises_validation(self):
128
+ """FastAPI returns 422 for Pydantic validation errors."""
129
+ with pytest.raises(AethexValidationError):
130
+ _raise_for_status(422, '{"detail":[{"msg":"field required"}]}')
131
+
132
+ def test_500_raises_server(self):
133
+ with pytest.raises(AethexServerError):
134
+ _raise_for_status(500, "Internal Server Error")
135
+
136
+ def test_502_raises_server(self):
137
+ with pytest.raises(AethexServerError):
138
+ _raise_for_status(502, "Bad Gateway")
139
+
140
+ def test_503_raises_server(self):
141
+ with pytest.raises(AethexServerError):
142
+ _raise_for_status(503, "Service Unavailable")
143
+
144
+
145
+ # ─── exception class behavior ─────────────────────────────
146
+
147
+ class TestExceptionClasses:
148
+
149
+ def test_all_inherit_from_aethex_error(self):
150
+ """Customers should be able to catch AethexError to catch any SDK error."""
151
+ for exc_cls in (
152
+ AethexAuthError,
153
+ AethexPermissionError,
154
+ AethexNotFoundError,
155
+ AethexRateLimitError,
156
+ AethexValidationError,
157
+ AethexServerError,
158
+ AethexConnectionError,
159
+ ):
160
+ assert issubclass(exc_cls, AethexError)
161
+
162
+ def test_carries_status_code(self):
163
+ e = AethexAuthError("test", status_code=401, response="body")
164
+ assert e.status_code == 401
165
+ assert e.response == "body"
166
+
167
+ def test_repr_includes_class_name_and_status(self):
168
+ e = AethexAuthError("auth failed", status_code=401)
169
+ r = repr(e)
170
+ assert "AethexAuthError" in r
171
+ assert "401" in r