From f16f6d14aa84f39f1c3e1e0cfde31998b0fdd624 Mon Sep 17 00:00:00 2001 From: Andre Ambrosio Date: Mon, 20 Apr 2026 15:51:50 -0300 Subject: [PATCH 1/2] chore(exports): include __version__ in __all__ for explicit public API __version__ = '2.1.0' was defined at module level but omitted from __all__, meaning `from bsp_sdk import *` would not expose it and tools like `bsp_sdk.__version__` checks via __all__ introspection would miss it. Add it as the first entry under a 'Package metadata' comment. Co-Authored-By: Claude Sonnet 4.6 --- bsp_sdk/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bsp_sdk/__init__.py b/bsp_sdk/__init__.py index 48a72eb..25e63f0 100644 --- a/bsp_sdk/__init__.py +++ b/bsp_sdk/__init__.py @@ -45,6 +45,8 @@ __version__ = "2.1.0" __all__ = [ + # Package metadata + "__version__", # Clients "BSPClient", "BEOClient", "IEOBuilder", "BioRecordBuilder", "TaxonomyResolver", From 2fceb208b29fcee8abb099f1693edd05cadca0ca Mon Sep 17 00:00:00 2001 From: Andre Ambrosio Date: Mon, 20 Apr 2026 16:01:47 -0300 Subject: [PATCH 2/2] feat(beo): add list_beos(), destroy() docs, and Beta classifier - BEOClient.list_beos(limit, offset): GET /api/beo with pagination - README: added list_beos and destroy() usage examples; updated method table - pyproject.toml: added "Development Status :: 4 - Beta" classifier Co-Authored-By: Claude Sonnet 4.6 --- README.md | 18 ++++++++++++++++++ bsp_sdk/beo.py | 28 ++++++++++++++++++++++++++++ pyproject.toml | 1 + 3 files changed, 47 insertions(+) diff --git a/README.md b/README.md index f8136ec..575e190 100644 --- a/README.md +++ b/README.md @@ -89,8 +89,26 @@ beo = BEOClient(config) | `is_available` | `(domain: str) -> bool` | Check if a domain is unclaimed | | `lock` | `(reason?) -> dict` | Lock a BEO against new writes | | `unlock` | `() -> dict` | Unlock a previously locked BEO | +| `list_beos` | `(limit=20, offset=0) -> list` | List BEOs accessible to the configured IEO | +| `destroy` | `(beo_id: str \| int, reason?) -> dict` | Permanently destroy a BEO (LGPD/GDPR erasure) | | `update_recovery` | `(config: RecoveryConfig) -> dict` | Update guardian recovery settings | +```python +# List BEOs accessible to the configured IEO +beos = beo_client.list_beos(limit=50, offset=0) +for b in beos: + print(b["beo_id"], b["domain"]) + +# Permanently destroy a BEO (LGPD Art. 18 / GDPR Art. 17 — right to erasure) +# WARNING: irreversible. Nullifies key, revokes all ConsentTokens, releases domain. +result = beo_client.destroy( + beo_id=42, # accepts int or decimal string + reason="user_requested_deletion", +) +print(result["destroyed_at"]) +print(result["aptos_tx"]) +``` + ```python # Create with guardians from bsp_sdk import Guardian, RecoveryConfig diff --git a/bsp_sdk/beo.py b/bsp_sdk/beo.py index 1c547a6..833da1e 100644 --- a/bsp_sdk/beo.py +++ b/bsp_sdk/beo.py @@ -120,6 +120,34 @@ def update_recovery(self, config: RecoveryConfig) -> dict: raise ValueError(f"threshold must be between 1 and {len(config.guardians)}") raise NotImplementedError("Registry connection required") + def list_beos(self, limit: int = 20, offset: int = 0) -> list: + """List BEOs accessible to the configured IEO. + + Makes a GET request to ``/api/beo?limit=N&offset=N`` and returns the + list of BEO objects from the response. + + :param limit: Maximum number of BEOs to return (default: 20). + :param offset: Number of records to skip for pagination (default: 0). + :returns: List of BEO dicts as returned by the registry API. + :raises BSPApiError: Non-2xx response from the registry API. + + Example:: + + client = BSPClient(ieo_domain="lab.bsp", private_key="...", environment="mainnet") + beos = client.beo.list_beos(limit=50, offset=0) + for beo in beos: + print(beo["beo_id"], beo["domain"]) + """ + data = self.http.get(f"/api/beo?limit={limit}&offset={offset}") + if isinstance(data, list): + return data + # Some registry responses wrap the list in a 'beos' or 'items' key + if isinstance(data, dict): + for key in ("beos", "items", "results", "data"): + if isinstance(data.get(key), list): + return data[key] + return [] + def destroy( self, beo_id: BeoId, diff --git a/pyproject.toml b/pyproject.toml index 42742e0..45f24ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ license = { text = "Apache-2.0" } authors = [{ name = "Ambrósio Institute", email = "dev@ambrosioinstitute.org" }] keywords = ["bsp", "biological-sovereignty", "longevity", "health-data", "biomarker", "aptos", "blockchain"] classifiers = [ + "Development Status :: 4 - Beta", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11",