sentinelsup 0.2.2__tar.gz → 0.2.4__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.
@@ -0,0 +1,31 @@
1
+ name: Python SDK
2
+ on: [push, pull_request]
3
+
4
+ permissions:
5
+ contents: read
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ timeout-minutes: 10
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
15
+ steps:
16
+ - uses: actions/checkout@v7
17
+ with:
18
+ persist-credentials: false
19
+ - uses: actions/setup-python@v7
20
+ with:
21
+ python-version: ${{ matrix.python }}
22
+ - run: python -m unittest discover -s tests -v
23
+ - name: Build and check distributions
24
+ if: matrix.python == '3.14'
25
+ run: |
26
+ python -m pip install build twine
27
+ python -m build
28
+ python -m twine check dist/*
29
+ python -m pip install --no-deps dist/*.whl
30
+ cd "$RUNNER_TEMP"
31
+ python -c "from sentinel import Sentinel, SentinelError; assert Sentinel('sk_test_fixture').api_key == 'sk_test_fixture'"
@@ -1,7 +1,7 @@
1
- __pycache__/
2
- *.py[cod]
3
- *.egg-info/
4
- build/
5
- dist/
6
- .venv/
7
- .pytest_cache/
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .venv/
7
+ .pytest_cache/
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Sentinel Edge Networks LTD
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sentinel Edge Networks LTD
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentinelsup
3
- Version: 0.2.2
4
- Summary: Sentinel — real-time fraud, VPN, proxy, and bot detection API. Free tier, sub-40ms response.
5
- Project-URL: Homepage, https://sntlhq.com
6
- Project-URL: Documentation, https://sntlhq.com/api
7
- Project-URL: Repository, https://github.com/sentinelsup/sentinel-python
8
- Project-URL: Issues, https://github.com/sentinelsup/sentinel-python/issues
9
- Author-email: Sentinel Edge Networks LTD <support@sntlhq.com>
3
+ Version: 0.2.4
4
+ Summary: Official Maskbreak SDK for browser-backed fraud checks and cloud/Tor IP lookups.
5
+ Project-URL: Homepage, https://maskbreak.com
6
+ Project-URL: Documentation, https://maskbreak.com/api
7
+ Project-URL: Repository, https://github.com/sentinelsup/maskbreak-python
8
+ Project-URL: Issues, https://github.com/sentinelsup/maskbreak-python/issues
9
+ Author-email: Sentinel Edge Networks LTD <support@maskbreak.com>
10
10
  License: MIT
11
11
  License-File: LICENSE
12
12
  Keywords: antidetect-browser,api,bot-detection,device-fingerprinting,fraud-detection,proxy-detection,sentinel,vpn-detection
@@ -27,9 +27,13 @@ Classifier: Typing :: Typed
27
27
  Requires-Python: >=3.8
28
28
  Description-Content-Type: text/markdown
29
29
 
30
- # sentinelsup — Sentinel Python SDK
30
+ # sentinelsup — Maskbreak Python SDK
31
31
 
32
- Official Python SDK for [Sentinel](https://sntlhq.com) — a real-time fraud detection API that flags VPNs, residential proxies, antidetect browsers (Kameleo, GoLogin, Multilogin), Tor exit nodes, and AI bots in under 40 ms.
32
+ Official Python SDK for [Maskbreak](https://maskbreak.com). Evaluate SDK-backed
33
+ visits for network and browser risk signals, or look up a public IP for cloud
34
+ range and Tor signals. These are different evidence sources, not interchangeable
35
+ checks. VPN/proxy service names are returned when known; a VPN alone routes to
36
+ review under the default policy, not automatic blocking.
33
37
 
34
38
  [![PyPI](https://img.shields.io/pypi/v/sentinelsup.svg)](https://pypi.org/project/sentinelsup/)
35
39
  [![Python versions](https://img.shields.io/pypi/pyversions/sentinelsup.svg)](https://pypi.org/project/sentinelsup/)
@@ -37,18 +41,18 @@ Official Python SDK for [Sentinel](https://sntlhq.com) — a real-time fraud det
37
41
 
38
42
  Zero dependencies — just the standard library. Works with Flask, Django, FastAPI, or bare `urllib`.
39
43
 
40
- ## Set up with AI (fastest)
44
+ ## Set up with an AI assistant
41
45
 
42
46
  Using Claude Code, Cursor, Copilot, or any AI coding assistant? Paste this one
43
47
  prompt and it wires the whole integration — frontend script, backend check,
44
48
  env var, and a test:
45
49
 
46
- > Fetch https://sntlhq.com/integrate.md and follow it to add Sentinel fraud
47
- > protection to this app — protect signup, login, and checkout. My API key
48
- > is sk_live_YOUR_KEY; put it in a SENTINEL_KEY env var, never in
49
- > client-side code. Then show me how to test it.
50
+ > Fetch https://maskbreak.com/integrate.md and follow it to add Maskbreak fraud
51
+ > protection to this app — protect signup, login, and checkout. Read the API key
52
+ > from the server-only SENTINEL_KEY environment variable; I will configure the
53
+ > secret separately. Never put it in client-side code. Show me how to test it.
50
54
 
51
- [`integrate.md`](https://sntlhq.com/integrate.md) is the canonical
55
+ [`integrate.md`](https://maskbreak.com/integrate.md) is the canonical
52
56
  machine-readable integration guide, kept in sync with the live API.
53
57
 
54
58
  ## Install
@@ -57,7 +61,7 @@ machine-readable integration guide, kept in sync with the live API.
57
61
  pip install sentinelsup
58
62
  ```
59
63
 
60
- Python 3.8+. Get a free API key (no credit card) at [sntlhq.com/signup](https://sntlhq.com/signup).
64
+ Python 3.8+. Get a free API key (no credit card) at [maskbreak.com/signup](https://maskbreak.com/signup).
61
65
 
62
66
  ## Quick start
63
67
 
@@ -67,7 +71,10 @@ from sentinel import Sentinel
67
71
 
68
72
  s = Sentinel(api_key=os.environ["SENTINEL_KEY"]) # or omit — reads the env var itself
69
73
 
70
- result = s.evaluate(token=request.json["sentinelToken"]) # token from the frontend SDK
74
+ result = s.evaluate(
75
+ token=request.json["sentinelToken"],
76
+ fingerprint_event_id=request.json.get("fingerprintEventId"),
77
+ )
71
78
 
72
79
  if result.is_blocked: # decision == 'block'
73
80
  abort(403)
@@ -78,6 +85,11 @@ print(result.network) # {'vpn': True, 'proxy': False, 'datacenter': True
78
85
  print(result.reasons) # ['vpn_detected', 'datacenter_asn', ...]
79
86
  ```
80
87
 
88
+ This is a handler fragment, not a complete signup implementation. Route `review`
89
+ to your verification/review flow; only `allow` is an approval. Keep API keys on
90
+ the server. An unavailable device layer or `raw["degraded"]` is not proof of a
91
+ clean visit; `degraded` describes the network layer only.
92
+
81
93
  Check the signup email against the disposable-domain feed (checked
82
94
  transiently, never stored), or look up an arbitrary IP with no browser
83
95
  token at all:
@@ -94,7 +106,8 @@ print(info["signals"]) # {'vpn': ..., 'proxied': ..., 'tor': ..., '
94
106
 
95
107
  ## What you get back
96
108
 
97
- `evaluate()` returns an `EvaluateResult` dataclass:
109
+ `evaluate()` returns an `EvaluateResult` dataclass. The type sketch below uses
110
+ Python 3.10+ annotation syntax for readability; the package minimum stays 3.8:
98
111
 
99
112
  ```python
100
113
  @dataclass
@@ -112,25 +125,25 @@ class EvaluateResult:
112
125
  test: bool # True for test-token / test-key calls
113
126
  raw: dict # full upstream response
114
127
 
115
- is_suspicious: bool # True if decision != 'allow'
128
+ is_suspicious: bool # True for a non-null decision other than 'allow'
116
129
  is_blocked: bool # True if decision == 'block'
117
130
  ```
118
131
 
119
132
  Try the live sample (same shape, no key needed):
120
133
 
121
134
  ```bash
122
- curl "https://sntlhq.com/v1/evaluate/sample?scenario=vpn"
135
+ curl "https://maskbreak.com/v1/evaluate/sample?scenario=vpn"
123
136
  ```
124
137
 
125
- Or use the [interactive playground](https://sntlhq.com/api#playground).
138
+ Or use the [interactive playground](https://maskbreak.com/api#playground).
126
139
 
127
140
  ## Frontend setup
128
141
 
129
- Add the Sentinel SDK to your frontend. One script loads **both** layers —
142
+ Add the Maskbreak SDK to your frontend. One script loads **both** layers —
130
143
  network (VPN/proxy/datacenter) and device (antidetect/bot/tampering):
131
144
 
132
145
  ```html
133
- <script async src="https://sntlhq.com/assets/sentinel.js"></script>
146
+ <script async src="https://maskbreak.com/assets/sentinel.js"></script>
134
147
 
135
148
  <!-- Add class="monocle-enriched" to any form you want evaluated -->
136
149
  <form class="monocle-enriched" id="signup-form">
@@ -142,7 +155,7 @@ network (VPN/proxy/datacenter) and device (antidetect/bot/tampering):
142
155
 
143
156
  Forward both fields to your backend with the form submission and pass them to
144
157
  `evaluate()` as `token` and `fingerprint_event_id` — without the second one,
145
- the device-layer signals (antidetect, automation, emulator) never fire. For
158
+ the device-layer signals (antidetect, automation, emulator) are unavailable. For
146
159
  fetch/XHR submissions, collect them explicitly:
147
160
 
148
161
  ```js
@@ -151,7 +164,7 @@ const { token, fingerprintEventId } = await window.Sentinel.collect();
151
164
 
152
165
  ## Examples
153
166
 
154
- ### Flask — block VPN/proxy signups
167
+ ### Flask — route signup decisions
155
168
 
156
169
  ```python
157
170
  from flask import Flask, request, abort, jsonify
@@ -164,7 +177,8 @@ sentinel = Sentinel() # reads SENTINEL_KEY (or SENTINEL_API_KEY) from env
164
177
  def signup():
165
178
  data = request.get_json()
166
179
  try:
167
- result = sentinel.evaluate(token=data["sentinelToken"])
180
+ result = sentinel.evaluate(token=data["sentinelToken"],
181
+ fingerprint_event_id=data.get("fingerprintEventId"))
168
182
  except SentinelError as e:
169
183
  # Fail open OR fail closed — your call. Logged either way.
170
184
  app.logger.warning("Sentinel error: %s", e)
@@ -173,6 +187,11 @@ def signup():
173
187
  if result and result.is_blocked:
174
188
  abort(403, "Signup blocked")
175
189
 
190
+ if result and result.decision == "review":
191
+ return jsonify({"needs_verification": True}), 202
192
+
193
+ # This example explicitly fails open on SDK errors. Choose an endpoint-
194
+ # specific fallback; do not reuse this policy for transfers or withdrawals.
176
195
  # ... your normal signup flow
177
196
  return jsonify({"ok": True})
178
197
  ```
@@ -181,7 +200,7 @@ def signup():
181
200
 
182
201
  ```python
183
202
  from django.http import JsonResponse
184
- from sentinel import Sentinel
203
+ from sentinel import Sentinel, SentinelError
185
204
 
186
205
  sentinel = Sentinel() # reads SENTINEL_KEY (or SENTINEL_API_KEY) from env
187
206
 
@@ -192,13 +211,17 @@ class FraudCheckMiddleware:
192
211
  def __call__(self, request):
193
212
  if request.path.startswith("/api/checkout"):
194
213
  token = request.META.get("HTTP_X_SENTINEL_TOKEN")
195
- if token:
196
- try:
197
- result = sentinel.evaluate(token=token)
198
- if result.is_blocked:
199
- return JsonResponse({"error": "blocked"}, status=403)
200
- except Exception:
201
- pass # fail open
214
+ if not token:
215
+ return JsonResponse({"error": "verification required"}, status=400)
216
+ try:
217
+ result = sentinel.evaluate(token=token,
218
+ fingerprint_event_id=request.META.get("HTTP_X_SENTINEL_FINGERPRINT_EVENT_ID"))
219
+ except SentinelError:
220
+ return JsonResponse({"error": "verification unavailable"}, status=503)
221
+ if result.is_blocked:
222
+ return JsonResponse({"error": "blocked"}, status=403)
223
+ if result.decision == "review":
224
+ return JsonResponse({"error": "additional verification required"}, status=409)
202
225
  return self.get_response(request)
203
226
  ```
204
227
 
@@ -206,12 +229,12 @@ Runnable versions live in [`examples/`](./examples/).
206
229
 
207
230
  ## API
208
231
 
209
- ### `Sentinel(api_key=None, endpoint="https://sntlhq.com", timeout=5.0)`
232
+ ### `Sentinel(api_key=None, endpoint="https://maskbreak.com", timeout=5.0)`
210
233
 
211
234
  | Option | Default | Description |
212
235
  |--------|---------|-------------|
213
236
  | `api_key` | `$SENTINEL_KEY` (falls back to `$SENTINEL_API_KEY`) | Your key starting with `sk_live_` |
214
- | `endpoint` | `https://sntlhq.com` | Override base URL (for testing) |
237
+ | `endpoint` | `https://maskbreak.com` | Override base URL (for testing) |
215
238
  | `timeout` | `5.0` | Per-request timeout in seconds |
216
239
 
217
240
  ### `sentinel.evaluate(token, fingerprint_event_id=None, account_id=None, email=None)`
@@ -222,31 +245,66 @@ Returns `EvaluateResult`. Raises `SentinelError` on network/API failure.
222
245
  - `account_id` — your own user id for this session; enables multi-accounting detection (`device.linked_accounts` / `device.multi_account`).
223
246
  - `email` — adds `email.disposable` to the raw response; burner domains escalate `allow` to `review`.
224
247
 
248
+ This synchronous SDK forwards only these named inputs. It does not expose a
249
+ timezone input, automatic retries, a circuit breaker, or every REST endpoint.
250
+ Device availability and `degraded` remain accessible through `raw`; missing
251
+ device evidence must not be treated as a clean device result. Account linking
252
+ (`linked_accounts`) is customer-scoped; device `first_seen`/`times_seen` history
253
+ is not customer-scoped.
254
+
225
255
  ### `sentinel.lookup(ip)`
226
256
 
227
257
  Returns the raw response dict for any public IPv4/IPv6 address (wraps `GET /v1/lookup/{ip}`): `verdict` (`allow`/`review`/`block`), `risk_score` (0–100), `known`, `signals` (`{vpn, proxied, tor, dch, anon}` or `None`), `network` (`{asn, org, country, city}`), `latency_ms`. Shares the per-key hourly quota with `evaluate()`. `known: False` means our feeds hold no data — it is **not** a clean guarantee.
228
258
 
259
+ Production bare-IP lookup checks cloud ranges and Tor exits, not live-visit
260
+ VPN/proxy evidence. Legacy `vpn`/`proxied` keys in the shape do not imply those
261
+ checks ran. Use `evaluate()` with browser evidence for VPN/proxy checks. When
262
+ obtaining an IP behind a proxy, trust forwarded headers only from configured
263
+ trusted proxies; never blindly take the first client-supplied value.
264
+
229
265
  ## Testing
230
266
 
231
- Deterministic test tokens exercise your allow / review / block handling end-to-end — no browser needed. Test calls are authenticated and rate-limited like real ones but never billed, stored, or webhooked, and the response carries `test=True`:
267
+ Deterministic `test_*` tokens exercise response handling, not detection quality.
268
+ SDK fixture calls use authentication and quota but do not increment billable
269
+ usage or trigger webhooks; console-originated live-key fixtures can be stored
270
+ as test events. Personal rules and exception pins can change fixture decisions.
232
271
 
233
272
  ```python
234
273
  result = s.evaluate(token="test_vpn") # also: test_clean, test_proxy, test_datacenter, test_tor
235
- assert result.decision == "review"
274
+ assert result.decision == "review" # default policy, no overriding rules/pins
236
275
  assert result.test
237
276
  ```
238
277
 
239
278
  No account yet? The public sandbox key accepts the same test tokens:
240
279
 
241
280
  ```python
242
- s = Sentinel(api_key="sk_test_sandbox") # CI/staging — nothing billed, nothing stored
281
+ s = Sentinel(api_key="sk_test_sandbox") # deterministic fixtures only, no live detection
282
+ ```
283
+
284
+ The public sandbox is separately rate-limited, accepts only supported fixture
285
+ tokens, and does not store events or run live detection. It is not a production
286
+ allowance. A personal `sk_test_...` key runs the live pipeline with real browser
287
+ evidence and your policy; resulting events can be stored with `is_test` set,
288
+ without incrementing usage or firing webhooks. Test keys still have rate limits.
289
+
290
+ Local checks require no API credentials:
291
+
292
+ ```bash
293
+ python -m unittest discover -s tests -v
294
+ python -m pip install build twine
295
+ python -m build
296
+ python -m twine check dist/*
243
297
  ```
244
298
 
245
- Every account also has a personal `sk_test_...` key (Settings → API Key) that runs the *complete* live pipeline — real tokens, your rules and exception pins included — while events stay flagged as test and never count toward usage or webhooks.
299
+ The CI matrix targets Python 3.8–3.14 without raising the 3.8 minimum. A configured
300
+ matrix is not a claim that every interpreter was tested locally; inspect its run.
246
301
 
247
302
  ## Errors
248
303
 
249
- All failures raise `SentinelError`. The exception carries `.status` (HTTP code) and `.body` (parsed error body) when available.
304
+ Transport/API failures and unusable success responses raise `SentinelError`.
305
+ The exception carries `.status` (HTTP code) and `.body` (parsed error body) when
306
+ available. Redirects are rejected to avoid forwarding credentials. Configure the
307
+ final API base URL; the client does not retry automatically.
250
308
 
251
309
  ```python
252
310
  from sentinel import Sentinel, SentinelError
@@ -259,15 +317,15 @@ except SentinelError as e:
259
317
  elif e.status and 400 <= e.status < 500:
260
318
  pass # bad input, won't recover by retrying
261
319
  else:
262
- pass # transient — retry once or fail open
320
+ pass # unknown outcome — use the endpoint's explicit fallback policy
263
321
  ```
264
322
 
265
323
  ## Rate limits
266
324
 
267
325
  Free tier: **1,000 requests/hour** per API key. No monthly cap, no credit
268
- card. Upgrade at [sntlhq.com](https://sntlhq.com) when you need more.
326
+ card.
269
327
 
270
- ## What Sentinel detects
328
+ ## What Maskbreak detects
271
329
 
272
330
  VPNs (commercial + self-hosted) · residential proxies (Bright Data, IPRoyal,
273
331
  and similar networks) · datacenter IPs · Tor exit nodes · antidetect browsers
@@ -277,10 +335,10 @@ virtual machines · browser tampering.
277
335
 
278
336
  ## Related
279
337
 
280
- - **Node.js SDK** — [`@sentinelsup/sdk`](https://github.com/sentinelsup/sentinel-node) on npm
281
- - **API docs** — [sntlhq.com/api](https://sntlhq.com/api)
282
- - **Free IP lookup tool** — [sntlhq.com/ip-lookup](https://sntlhq.com/ip-lookup)
338
+ - **Node.js SDK** — [`@sentinelsup/sdk`](https://github.com/sentinelsup/maskbreak-node) on npm
339
+ - **API docs** — [maskbreak.com/api](https://maskbreak.com/api)
340
+ - **Free IP lookup tool** — [maskbreak.com/ip-lookup](https://maskbreak.com/ip-lookup)
283
341
 
284
342
  ## License
285
343
 
286
- MIT © [Sentinel Edge Networks LTD](https://sntlhq.com). See [LICENSE](LICENSE).
344
+ MIT © [Sentinel Edge Networks LTD](https://maskbreak.com). See [LICENSE](LICENSE).