Metadata-Version: 2.5
Name: sovaria-cli
Version: 0.2.8
Summary: Sovaria BaaS command-line interface (sov)
Project-URL: Homepage, https://sovaria.in
Project-URL: Documentation, https://docs.sovaria.in/cli
Project-URL: Repository, https://github.com/sovaria/sovaria-cli
Author: Sovaria Team
License: MIT
Requires-Python: >=3.11
Requires-Dist: httpx>=0.28.1
Requires-Dist: keyring>=25.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.7.0
Requires-Dist: sovaria-sdk==0.4.0
Requires-Dist: tomli-w>=1.2.0
Requires-Dist: typer>=0.17.4
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.13; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.9; extra == 'dev'
Requires-Dist: twine>=6.0; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: sovaria-sdk[mcp]==0.4.0; extra == 'mcp'
Description-Content-Type: text/markdown

# Sovaria CLI

Operator CLI for gateway-backed Sovaria project and platform workflows.

## Run

Examples below use `sov ...` command syntax.

If `sov` is installed on your PATH:

```bash
sov --help
```

From repo root without installation:

```bash
python -m apps.cli.src.main --help
```

## Cross-SDK Happy Path Smoke

Use the repository smoke script to validate one shared happy path across:

- CLI auth + scoped SQL call
- TypeScript SDK SQL + engine health
- Python SDK SQL + engine health

```bash
SOVARIA_URL=http://localhost:8000 \
SOVARIA_ORG_ID=<org_uuid> \
SOVARIA_PROJECT_ID=<project_uuid> \
SOVARIA_EMAIL=<owner_email> \
SOVARIA_PASSWORD='<owner_password>' \
scripts/cli_sdk_happy_path.sh
```

If you already have valid CLI tokens, omit `SOVARIA_EMAIL` and `SOVARIA_PASSWORD`.

## Authentication

```bash
sov login
sov login --email you@example.com
sov login --file-storage          # headless: tokens in ~/.sovaria/credentials.toml
sov logout
sov logout --force                # clear local tokens if server revoke fails
```

- **Browser (PKCE):** authorize opens the console origin (`get_console_url`); the token exchange POSTs to the gateway `api_url` `/oauth/token` proxy. That split is intentional.
- **Password:** never pass `--password`. Operator login prompts with `getpass`, or reads `SOVARIA_PASSWORD`.
- **Product user create:** `sov auth-product create --email ...` prompts for the new user's password, or reads `SOVARIA_USER_PASSWORD`. Do not reuse `SOVARIA_PASSWORD` (that is the operator login secret).
- **Magic link:** `sov auth magic-link verify` reads the token from stdin or `SOVARIA_MAGIC_TOKEN`.
- **GitHub deploy PAT:** set `SOVARIA_GITHUB_TOKEN` or use `gh auth token`. There is no `--token` flag.
- **OAuth callback:** binds `127.0.0.1` by default. Non-loopback `SOVARIA_CLI_CALLBACK_HOST` requires `--insecure-callback`.

### Token refresh contract

Axis supports two refresh modes. Do not mix them:

| Client | How refresh is sent |
|---|---|
| **CLI / Python SDK** | JSON body: `POST /api/v1/auth/refresh` with `{"refresh_token": "<stored>"}`. The CLI keeps the refresh token in OS keyring (or `credentials.toml` with `--file-storage`). |
| **Console / browser** | Empty JSON body `{}` plus the HttpOnly refresh cookie. The browser never puts the refresh token in the request body. |

Copying the console cookie pattern into a CLI or SDK client will fail silently (no cookie jar). Copying the CLI JSON-body pattern into a browser app bypasses HttpOnly cookie storage.

### Pulse WebSocket URLs

`sov realtime ws-url` issues an opaque `ticket=` query parameter. Never put a JWT in `?token=` — production gateways disable `GATEWAY_WS_ALLOW_QUERY_TOKEN`. Local `.env.local` may still enable the legacy query-token path; do not copy that into clients.

```bash
sov realtime ws-url my-channel --org <org_id> --project <project_id>
# wss://api.sovaria.in/api/v1/rt/ws/my-channel?ticket=...&org_id=...&project_id=...
```

## Core Command Groups

- `sov auth ...` auth login/logout
- `sov scope ...` default org/project/env scope
- `sov data ...` Atlas-Doc and Atlas-Rel
- `sov realtime ...` Pulse realtime and e2ee
- `sov policy ...` Guard policy management
- `sov audit ...` Echo audit and simulation
- `sov chrono ...` Chrono timeline/snapshot operations
- `sov fn ...` Forge function deploy/status/invoke
- `sov project ...` project config template + scaffold creation
- `sov api call ...` raw gateway API request

## Project Bootstrap (Config JSON)

Create a template config file:

```bash
sov project init-config my-app --output sovaria.config.json
```

Then scaffold a project from that config:

```bash
sov project create --config sovaria.config.json --dir .
```

## Function Sandbox Flow

Deploy a function bundle (zipped from local folder):

```bash
sov fn deploy ./my-function --name hello --project <project_id> --note "add audit logging"
```

Poll deployment status:

```bash
sov fn status <deploy_id> --project <project_id>
```

Invoke the deployed function in its project sandbox:

```bash
sov fn invoke hello --project <project_id> --data '{"message":"hi"}'
```

Run a simulation invocation (tracked separately from normal invoke):

```bash
sov fn invoke hello --project <project_id> --simulate --data '{"message":"dry-run"}'
```

Queue heavy async invocation and wait for completion:

```bash
sov fn invoke hello --project <project_id> --execution-profile heavy --async --wait --data-file payload.json
```

List function versions:

```bash
sov fn versions hello --project <project_id>
```

List functions with active versions + queue depth:

```bash
sov fn functions --project <project_id>
```

List invocation history:

```bash
sov fn history hello --project <project_id> --mode invoke
```

List durable async jobs:

```bash
sov fn jobs hello --project <project_id> --status QUEUED
```

Promote a specific function version:

```bash
sov fn promote hello --project <project_id> --version 3 --reason "promote stable release"
```

Rollback to previous active version:

```bash
sov fn rollback hello --project <project_id> --reason "rollback regression"
```

Diff two simulation invocations:

```bash
sov fn sim-diff hello <left_invocation_id> <right_invocation_id> --project <project_id>
```

## Scope Requirement

Realtime and relational routes require org/project scope. You can pass scope per command (`--org --project --env`) or set defaults:

```bash
sov scope set <org_id> <project_id> --env <env_id>
```
