Metadata-Version: 2.5
Name: sovaria-sdk
Version: 0.2.0
Summary: Python SDK for Sovaria Gateway and Engines
Project-URL: Homepage, https://sovaria.in
Project-URL: Documentation, https://docs.sovaria.in/sdk
Project-URL: Repository, https://github.com/sovaria/sovaria-sdk
Author: Sovaria Team
Requires-Python: >=3.11
Requires-Dist: argon2-cffi>=23.1.0
Requires-Dist: cryptography>=46.0.0
Requires-Dist: email-validator>=2.2.0
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.12.0
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: twine>=6.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.29.0; extra == 'docs'
Description-Content-Type: text/markdown

# Sovaria Python SDK

Async Python SDK for the Sovaria gateway.

## Install

```bash
pip install sovaria-sdk
```

Local workspace development:

```bash
pip install -e apps/sdk/python
```

## Supabase-Style Bootstrap (Portal Config)

```python
from sovaria import create_client

client = create_client(
    {
        "url": "https://gateway.sovaria.in",
        "org_id": "11111111-1111-1111-1111-111111111111",
        "project_id": "22222222-2222-2222-2222-222222222222",
        "env_id": "33333333-3333-3333-3333-333333333333",
        # optional: portal-issued publishable/anon key
        "publishable_key": "<token>",
    }
)
```

Or initialize directly from environment variables:

```python
from sovaria import SovariaClient

client = SovariaClient.from_env()
```

Supported environment variables:
- `SOVARIA_URL`
- `SOVARIA_ORG_ID`
- `SOVARIA_PROJECT_ID`
- `SOVARIA_ENV_ID`
- `SOVARIA_ACCESS_TOKEN` or `SOVARIA_PUBLISHABLE_KEY` or `SOVARIA_ANON_KEY`

## Quick Start

```python
import asyncio
from sovaria import SovariaClient


async def main() -> None:
    async with SovariaClient.from_env() as sov:
        await sov.login("you@example.com", "password")
        me = await sov.get_me()

        # If your token includes scope claims, get_me() auto-hydrates scope.
        # Otherwise, set scope explicitly for SQL/realtime routes:
        # sov.set_scope(org_id="...", project_id="...", env_id="...")

        health = await sov.get_engines_health()
        print(me)
        print(health)

        # Realtime usage
        await sov.stream_subscribe("db.table.users", "py-client-1")
        presence = await sov.stream_presence("db.table.users")
        print(presence)


asyncio.run(main())
```

## Sync Quick Start

```python
from sovaria import SovariaSyncClient

with SovariaSyncClient.from_env() as sov:
    sov.login("you@example.com", "password")
    me = sov.get_me()
    print(me)
```

Use `SovariaSyncClient` for WSGI workers, cron jobs, and scripts where an
explicit async event loop would add unnecessary complexity.

## Coverage

- Axis: auth, context, graph
- Atlas-Doc: put/get/delete/scan plain docs
- Atlas-Rel: SQL, table lifecycle, migrations
- Pulse: stream, e2ee key lifecycle, websocket URL helper
- Guard: templates, CRUD, evaluate, rollback, history
- Echo: audit + simulation
- Chrono: commit/timelines/snapshots/converge/variance
- Gateway: engine health

## Project Scaffold from `sovaria.config.json`

You can scaffold a new client project directly from the SDK package.

```python
from sovaria import (
    DEFAULT_CONFIG_FILENAME,
    create_project_from_config_file,
    write_project_config_template,
)

# 1) Write template config JSON
write_project_config_template(DEFAULT_CONFIG_FILENAME, name="my-app")

# 2) Generate project folder structure from config
result = create_project_from_config_file(DEFAULT_CONFIG_FILENAME, target_dir=".")
print(result.project_root)
```

Generated files include:

- `<project>/sovaria.config.json`
- `<project>/.env.example`
- `<project>/sovaria/functions/`
- `<project>/sovaria/migrations/`
- `<project>/sovaria/tests/`

## Raw API Escape Hatch

You can call any gateway endpoint directly:

```python
await sov.request("GET", "/api/v1/system/engines/health", requires_auth=False)
```

## Functions + Storage Pass-Through

```python
# Forge deployment status
status = await sov.fn_status("deploy-123")

# Generic Vault path operations
await sov.store_put_json("kv/app/settings", {"theme": "light"})
settings = await sov.store_get("kv/app/settings")
await sov.store_delete("kv/app/settings")
```
