Metadata-Version: 2.4
Name: sonnet-storage
Version: 0.1.3
Summary: Virtual file storage backed by PostgreSQL for sonnet-server applications
Author-email: Wolfgang Miller <wolfgang.miller@petrarca-labs.com>
License-Expression: Apache-2.0
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Requires-Python: <4.0,>=3.14
Description-Content-Type: text/markdown
Requires-Dist: sonnet-server>=0.3.0
Requires-Dist: universal-pathlib>=0.3.10
Requires-Dist: loguru>=0.7.3
Requires-Dist: typer>=0.12.0
Requires-Dist: rich>=13.0.0
Provides-Extra: dev
Requires-Dist: ruff>=0.3.0; extra == "dev"
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"

# sonnet-storage

Virtual file storage backed by a single PostgreSQL table, presented as a
filesystem. Consumers use ordinary `pathlib` operations -- `read_text()`,
`write_text()`, `iterdir()`, `glob()` -- and the backend is transparent.

Version 0.1.2. The public API is a
[UPath](https://github.com/fsspec/universal_pathlib) subclass plus two factory
functions; there is no service class and no repository to learn. Resources that
would otherwise be baked into a Python package -- SQL fragments, rule files,
templates, prompts, config -- become rows you can change without a redeploy.

## What it provides

- **`DBPath`** -- the `UPath` implementation over the `file_storage` table,
  with virtual directories, soft delete and recovery.
- **Content types** -- text, JSON stored as native JSONB, and binary.
- **Versioning** -- a monotonic write counter per file.
- **Seeding** -- loading local directories or bundled package data into
  storage.
- **Configurable protocol** -- `db://` by default, renameable for applications
  that already use another scheme.
- **`StorageExtension`** -- registers the protocol and mounts the router in a
  sonnet-server application.
- **Adapters** -- a REST router factory and `ls` / `cat` / `rm` / `tree` /
  `purge` CLI commands, both thin layers over `DBPath`.

The shipped router is unauthenticated: `DBPath` has no notion of a caller, so
authorization belongs in front of it.

## Install

```bash
uv add sonnet-storage
```

Depends on [`sonnet-server`](../sonnet-server/README.md),
`universal-pathlib`, loguru, typer and rich. PostgreSQL only -- `json_content`
and `tags` use PostgreSQL types and there is no portability layer. The only
extra is `dev`.

## Usage

`register_protocol()` must be called **once at startup**, before any `db://`
URL is resolved. `StorageExtension` does it in `on_startup`; a CLI, a worker,
an Alembic hook or a test must call it itself.

```python
from sonnet_core.database import borrow_db_session
from sonnet_storage import get_storage_root_db, register_protocol

register_protocol()

root = get_storage_root_db()

for path in (root / "rules").iterdir():
    print(path.read_text())

with borrow_db_session():
    (root / "config.yaml").write_text("debug: true")
```

Nothing in this package commits. Writes need a transaction boundary around
them, or they are lost. See the usage guides for the full filesystem surface,
seeding, and the REST and CLI adapters.

## Database

The package ships the `FileStorage` model and the schema reference, but no
migration -- the consumer owns its Alembic chain, per
[ADR-0002](../../docs/adr/0002-no-shipped-migrations.md). The authoritative
schema is [`docs/design/data-model.md`](docs/design/data-model.md).

## Documentation

- **Usage** -- [`docs/usage/index.md`](docs/usage/index.md)
- **Design** -- [`docs/design/index.md`](docs/design/index.md)
- **Workspace** -- [`../../docs/README.md`](../../docs/README.md)

## License

Apache 2.0 -- see [LICENSE.md](../../LICENSE.md).
