dominusnode-haystack 1.2.0__tar.gz → 1.2.1__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.

Potentially problematic release.


This version of dominusnode-haystack might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dominusnode-haystack
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: Dominus Node rotating proxy tools for Haystack AI pipelines
5
5
  Author-email: Dominus Node <dev@dominusnode.com>
6
6
  License: MIT
@@ -42,6 +42,7 @@ Requires: httpx (``pip install httpx``), haystack-ai (``pip install haystack-ai`
42
42
 
43
43
  from __future__ import annotations
44
44
 
45
+ import hashlib
45
46
  import ipaddress
46
47
  import json
47
48
  import math
@@ -381,6 +382,46 @@ def _sanitize_error(message: str) -> str:
381
382
  return _CREDENTIAL_RE.sub("***", message)
382
383
 
383
384
 
385
+ def _count_leading_zero_bits(data: bytes) -> int:
386
+ """Count leading zero bits in a byte array."""
387
+ count = 0
388
+ for byte in data:
389
+ if byte == 0:
390
+ count += 8
391
+ else:
392
+ mask = 0x80
393
+ while mask and not (byte & mask):
394
+ count += 1
395
+ mask >>= 1
396
+ break
397
+ return count
398
+
399
+
400
+ def _solve_pow(base_url: str) -> Optional[dict]:
401
+ """Solve a Proof-of-Work challenge for CAPTCHA-free registration."""
402
+ try:
403
+ pow_url = f"{base_url.rstrip('/')}/api/auth/pow/challenge"
404
+ with httpx.Client(timeout=30.0, follow_redirects=False) as client:
405
+ resp = client.post(pow_url, headers={"Content-Type": "application/json"})
406
+ if resp.status_code >= 400:
407
+ return None
408
+ challenge = resp.json()
409
+ prefix = challenge.get("prefix", "")
410
+ difficulty = challenge.get("difficulty", 20)
411
+ challenge_id = challenge.get("challengeId", "")
412
+ if not prefix or not challenge_id:
413
+ return None
414
+ nonce = 0
415
+ while nonce < 100_000_000:
416
+ h = hashlib.sha256((prefix + str(nonce)).encode()).digest()
417
+ if _count_leading_zero_bits(h) >= difficulty:
418
+ return {"challengeId": challenge_id, "nonce": str(nonce)}
419
+ nonce += 1
420
+ return None
421
+ except Exception:
422
+ return None
423
+
424
+
384
425
  # ---------------------------------------------------------------------------
385
426
  # Prototype pollution prevention
386
427
  # ---------------------------------------------------------------------------
@@ -1858,11 +1899,17 @@ class DominusNodeToolkit:
1858
1899
  return {"error": err}
1859
1900
 
1860
1901
  try:
1902
+ body: dict = {"email": email, "password": password}
1903
+ pow_result = _solve_pow(self.base_url)
1904
+ if pow_result:
1905
+ body["pow"] = pow_result
1861
1906
  result = self._api_request_public(
1862
1907
  "POST",
1863
1908
  "/api/auth/register",
1864
- {"email": email, "password": password},
1909
+ body,
1865
1910
  )
1911
+ if pow_result and isinstance(result, dict):
1912
+ result["_pow_verified"] = True
1866
1913
  return result
1867
1914
  except Exception as e:
1868
1915
  return {"error": _sanitize_error(str(e))}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dominusnode-haystack
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: Dominus Node rotating proxy tools for Haystack AI pipelines
5
5
  Author-email: Dominus Node <dev@dominusnode.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dominusnode-haystack"
7
- version = "1.2.0"
7
+ version = "1.2.1"
8
8
  description = "Dominus Node rotating proxy tools for Haystack AI pipelines"
9
9
  requires-python = ">=3.9"
10
10
  license = {text = "MIT"}