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",