Metadata-Version: 2.4
Name: parad
Version: 2.2.4
Summary: Drop-in encrypted database with cloud sync — connect() and go
Author-email: nexuss0781 <nexuss0781@gmail.com>
Project-URL: Homepage, https://github.com/nexuss0781/Paradox-DB
Project-URL: Repository, https://github.com/nexuss0781/Paradox-DB
Project-URL: Issues, https://github.com/nexuss0781/Paradox-DB/issues
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Database
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: click>=8.0
Requires-Dist: httpx>=0.25
Requires-Dist: cryptography>=41.0
Requires-Dist: pydantic>=2.0
Requires-Dist: python-dotenv>=1.0
Provides-Extra: sqlalchemy
Requires-Dist: SQLAlchemy>=2.0; extra == "sqlalchemy"

# parad

Encrypted local-first SQLite with Telegram cloud sync — a git-like, zero-cost
workflow database. Telegram is the disk: every change you commit becomes a
version-stored snapshot you can revert to anytime.

## Install

```bash
pip install parad
```

## Quick Start

### Python SDK (developer workflow — auto-sync on by default)

Connect with a postgres-like connection string, write SQL offline, and the
sync daemon version-stores your changes automatically. No manual push needed.

```python
from parad import connect

# Auto-login (email:password), auto-provision project + database on the
# gateway, open/create the local encrypted SQLite file.
db = connect(url="parad://alice@example.com:secretpw@local/myproj/mydb?passphrase=secret")

# Build SQL offline like any SQLite database ...
db.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")
db.execute("INSERT INTO users (name) VALUES (?)", ("alice",))
db.commit()

# ... and it's already pushed to the cloud as a new snapshot version (~2s).
# Revert anytime (from the CLI):
# !parad rollback 1

db.close()
```

Offline? Keep writing — changes are flagged `dirty` and batch-pushed as new
versions the moment you reconnect. On conflicts your local data always wins
(never silently dropped).

Local-only is just as easy:

```python
db = connect("mydb", passphrase="secret", auto_sync=False)
```

### CLI

```bash
# Create a new encrypted database and print the canonical URL deliberately
parad auth login
parad init mydb --project myproject --print-database-url
# Retrieve the existing canonical URL without remote mutation
parad url
parad url --print-database-url
# Push to cloud

parad push

# Pull latest
parad pull

# Check status
parad status

# Interactive SQL
parad shell
```

## Commands

| Command | Description |
|---|---|
| `parad init <name>` | Create encrypted DB + register with gateway; emit canonical DATABASE_URL |
| `parad push` | Push database to Telegram cloud |
| `parad pull [version]` | Pull latest or specific version |
| `parad sync` | Push then pull |
| `parad status` | Local vs remote version |
| `parad versions` | List all remote versions |
| `parad rollback <ver>` | Rollback to previous version |
| `parad exec <sql>` | Run raw SQL |
| `parad insert <table> <json>` | Insert a row |
| `parad select <table> [where]` | Query rows |
| `parad update <table> <set> <where>` | Update rows |
| `parad delete <table> <where>` | Delete rows |
| `parad shell` | Interactive SQL REPL |
| `parad config show/set` | Manage config; secret-bearing fields are redacted |
| `parad url [name]` | Retrieve the canonical database_url |
| `parad database-url [name]` | Alias for `parad url` |
## Canonical DATABASE_URL first
Use one canonical connection value for new applications and deployments. After `parad init` provisions the project/database, it persists `database_url` in `~/.paradox/config.json` and prints a redacted URL by default:
```bash
parad auth login
parad init mydb --project myproject
```
Print the complete secret-bearing value only when intentionally copying it into a secret manager:
```bash
parad init mydb --project myproject --print-database-url
```
For an existing database, retrieve the saved canonical value without opening, syncing, or mutating the remote database:
```bash
parad url
parad url --print-database-url
```
Retrieval checks `DATABASE_URL`, then persisted `database_url`, then reconstructs and persists a canonical URL from legacy split fields when a passphrase is available. If the passphrase is missing, it stops instead of inventing a replacement. New projects should use only `DATABASE_URL`; split fields remain supported for legacy applications.
Applications can use the same single value:
```python
import os
from parad import connect
db = connect(url=os.environ["DATABASE_URL"])
```
An explicit `url` argument is strongest. Explicit `name` or `db_path` options remain available for legacy target selection.


## SQLAlchemy

Install the optional integration with `pip install "parad[sqlalchemy]"`, then use the same canonical URL with `create_engine("parad://...")`. The ORM, Core, DB-API, and encrypted lifecycle examples are documented in [`docs/SQLALCHEMY.md`](docs/SQLALCHEMY.md).

## Configuration

Config lives at `~/.paradox/config.json`:

```json
{
  "database_url": "parad://<api-key>@local/project/mydb?gateway=https%3A%2F%2F...&passphrase=...",
  "database_path": "~/.paradox/data.db",
  "sync": {
    "gateway_url": "https://paradox-db.onrender.com/v1",
    "api_key": "pk_..."
  }
}
```

## Security

- AES-256-CBC encryption at rest
- PBKDF2-HMAC-SHA512 key derivation (256k iterations)
- Your passphrase never leaves your machine
