Metadata-Version: 2.5
Name: neuctra-authix
Version: 2.0.0
Summary: Python SDK for Neuctra Authix — authentication, identity, and user data as a service.
Project-URL: Homepage, https://authix.neuctra.com
Project-URL: Documentation, https://authix.neuctra.com/docs
Project-URL: Source, https://github.com/neuctra/neuctra-authix
Author: Neuctra
License: MIT
License-File: LICENSE
Keywords: auth,authentication,authix,identity,neuctra,sdk,user-management
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: requests>=2.25.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: responses>=0.23; extra == 'dev'
Description-Content-Type: text/markdown

# Neuctra Authix — Python SDK

Authentication, identity, and user data as a service.

```bash
pip install neuctra-authix
```

## Quick start

```python
import os
from neuctra_authix import Authix

authix = Authix(
    secret_key=os.environ["AUTHIX_SECRET_KEY"],
    app_id=os.environ["AUTHIX_APP_ID"],
)

user = authix.signup_user(
    name="Ada Lovelace",
    email="ada@example.com",
    password="a-strong-password",
)

authix.add_user_data(
    user_id=user["user"]["id"],
    data_category="notes",
    data={"title": "First note", "body": "Hello world"},
)
```

## The two key types

Authix issues two credentials and the difference is the whole security model.

| | Publishable | Secret |
|---|---|---|
| Prefix | `pk_live_…` | `sk_live_…` |
| Safe to expose | Yes | **No** |
| Can do | Sign users up and in, verify email, reset passwords, and read/write **the signed-in user's own** records | Everything, on every user and app |

```python
# Server-side — full authority
authix = Authix(secret_key=os.environ["AUTHIX_SECRET_KEY"], app_id=APP_ID)

# Acting on behalf of an end user, with a browser-safe credential
authix = Authix(publishable_key=os.environ["AUTHIX_PUBLISHABLE_KEY"], app_id=APP_ID)
```

Passing the wrong kind raises `ConfigurationError` before any request is sent:

```python
Authix(publishable_key="sk_live_...", app_id=APP_ID)
# ConfigurationError: A secret key (sk_…) was passed as publishable_key.
```

Most Python code runs on a server, so `secret_key` is usually right. Reach for a
publishable key when your service acts on behalf of a signed-in end user.

## Pagination

Every list and search returns a bounded `Page` — 20 records by default, 100
maximum. There is no "fetch everything" mode, because one such request against a
large app would have to load the whole dataset into memory.

```python
page = authix.get_user_data(user_id="u_1", limit=50)

for record in page:          # a Page iterates its records
    print(record["title"])

page.has_more                # bool
page.next_cursor             # pass back as cursor=... for the next page
```

To walk everything, use the `iter_*` helpers — they follow the cursor for you:

```python
for record in authix.iter_user_data(user_id="u_1"):
    process(record)

for user in authix.iter_all_users():
    print(user["email"])

# Bound the traversal when the dataset size is unknown
for record in authix.iter_all_users_data(q="invoice", max_pages=10):
    process(record)
```

## Searching

`keys` is an exact-match containment query; `q` is a substring match. Both are
index-backed in the database, not filtered in Python.

```python
authix.search_in_user_data(user_id="u_1", keys={"status": "paid"})
authix.search_in_user_data(user_id="u_1", q="invoice")
authix.search_in_all_app_users_data(keys={"status": "paid"}, limit=100)
```

User search is restricted to a fixed field list — `id`, `username`, `name`,
`email`, `phone`, `address`, `role`, `isVerified`, `isActive`. Filtering on
anything else raises `ValidationError`; credential columns are never searchable.

## Concurrency

Pass the `version` you last read to avoid clobbering someone else's write:

```python
from neuctra_authix import VersionConflictError

record = authix.get_single_user_data(user_id="u_1", data_id="d_1")

try:
    authix.update_user_data(
        user_id="u_1",
        data_id="d_1",
        data={"status": "shipped"},
        version=record["data"]["version"],
    )
except VersionConflictError as exc:
    print("changed since read; now at version", exc.current_version)
```

## Atomic batches

When records must change together, use `batch()` — every operation commits or
none do:

```python
authix.batch(user_id="u_1", operations=[
    {"type": "create", "dataCategory": "orders", "total": 40},
    {"type": "update", "id": stock_id, "version": 3, "remaining": 9},
    {"type": "delete", "id": draft_id},
])
```

A version mismatch or missing record aborts the whole batch and nothing is
written. Maximum 50 operations.

## Errors

Every failure raises a typed exception, so you can catch what you care about:

```python
from neuctra_authix import (
    AuthixError,             # base — catches everything below
    ConfigurationError,      # bad client setup; raised before any request
    AuthenticationError,     # 401 — bad, expired, or revoked credential
    NoUserSessionError,      # 401 — endpoint needs a signed-in end user
    InsufficientScopeError,  # 403 — publishable key on a secret-key endpoint
    PermissionDeniedError,   # 403 — e.g. account not verified
    NotFoundError,           # 404
    ValidationError,         # 400 — includes non-searchable field rejections
    VersionConflictError,    # 409 — optimistic concurrency
    RateLimitError,          # 429 — rate limited or monthly quota exhausted
    ServerError,             # 5xx
    NetworkError,            # connection failed or timed out
)
```

`InsufficientScopeError` is nearly always a publishable key on an endpoint that
needs a secret key; it carries a `.hint` explaining the fix.

## Sessions

The client holds a `requests.Session`, so a cookie from `login_user()` persists
and later calls act as that user:

```python
authix.login_user(email="ada@example.com", password="…")
authix.check_user_session()   # {"authenticated": True, "user": {...}}
authix.logout_user()
```

Use it as a context manager to close the connection pool deterministically:

```python
with Authix(secret_key=..., app_id=...) as authix:
    authix.get_user(id="u_1")
```

## Configuration

```python
Authix(
    app_id="app_...",              # required
    secret_key="sk_live_...",      # one of secret_key / publishable_key
    publishable_key=None,
    base_url="https://server.authix.neuctra.com/api",
    app_name=None,                 # optional label
    timeout=30.0,                  # seconds
    session=None,                  # bring your own requests.Session
)
```

## API reference

**End-user auth** — `signup_user`, `login_user`, `logout_user`,
`check_user_session`, `change_password`, `request_email_verification_otp`,
`verify_email`, `request_reset_user_password_otp`, `reset_user_password`

**Users** — `get_user`, `get_user_profile`, `update_user`, `delete_user`,
`check_if_user_exists`

**User records** — `add_user_data`, `get_user_data`, `iter_user_data`,
`get_single_user_data`, `search_in_user_data`, `update_user_data`,
`delete_user_data`, `delete_many_user_data`, `batch`

**App-wide records** — `add_app_data`, `get_app_data`, `iter_app_data`,
`get_single_app_data`, `search_in_app_data`, `update_app_data`, `delete_app_data`

**Across all users** *(secret key)* — `get_all_users_from_app`,
`iter_all_users`, `search_in_all_app_users`, `get_all_users_data_from_app`,
`search_in_all_app_users_data`, `iter_all_users_data`

## Development

```bash
pip install -e ".[dev]"
pytest
```

## Links

- [Documentation](https://authix.neuctra.com/docs)
- [Dashboard](https://authix.neuctra.com/dashboard)

MIT licensed.
