# Public API — `mgf-alembic`

> ⚠️ **This file documents `master` HEAD.** Names listed here may
> be unreleased. To learn what your installed wheel actually
> ships, run `pip show mgf-alembic` and compare against the git tag
> matching the published version.

This document is the **contract list** for `mgf-alembic`. Every name
listed below is a public name that consumers MAY depend on.

The contract terms are defined in
[`mgf-standard/docs/standards/API_DESIGN.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/API_DESIGN.md). In
short:

- **Stability tiers:**
  - `experimental` — MAY change shape in any MINOR release
    (the 0.x window keeps everything experimental in practice).
  - `stable` — follows the deprecation cycle; removal only in MAJOR.
  - `deprecated` — slated for removal; emits `DeprecationWarning`.
- **Names not listed below are private.** Anything starting with
  `_` (underscore-prefixed module names like `_env.py`) is internal
  and MAY change without notice.
- **The 0.x window applies.** Per [SemVer](https://semver.org/) 0.x
  semantics, MINOR releases MAY break the public API. Pin tightly:
  `mgf-alembic = ">=0.X.0,<0.Y"`.

---

## `mgf.alembic`

Top-level alembic env.py helper. Closed-box: depends on
`mgf-common` + `mgf-sqlalchemy` + `alembic` only.

| Name | Tier | Description |
|---|---|---|
| `configure_env` | experimental | One-call replacement for the ~40-line async-alembic env.py boilerplate. Keyword-only parameters: `database_url` (str), `target_metadata` (sqlalchemy `MetaData`), `compare_type` (default True), `compare_server_default` (default True), `naming_convention` (dict, default None), `include_object` (callable, default None), `include_schemas` (default False). Auto-detects sync vs async drivers from URL prefix; offline mode (`alembic upgrade --sql`) detected from `context.is_offline_mode()`. |
| `run_async_migrations` | experimental | The public async primitive: `await run_async_migrations(database_url=..., target_metadata=..., ...)` — use directly when calling from inside a running event loop (configure_env raises there). |
| `detect_drift` | experimental | Compare live DB schema against `target_metadata`; returns a `DriftReport`. Read-only (no migration). |
| `DriftReport` | experimental | Frozen dataclass result of `detect_drift` — `is_clean`, `all_differences`, `summary()`, and per-category tuples (added/removed tables, columns, indexes, ...). |

### Behaviours guaranteed at the public surface

- Async URL prefixes detected: `postgresql+asyncpg://`,
  `postgresql+psycopg://` (psycopg 3 async), `mysql+aiomysql://`,
  `mysql+asyncmy://`, `sqlite+aiosqlite://`. Other URLs take the
  sync path.
- `include_object=None` and `include_schemas=False` (the defaults)
  match alembic's own defaults — no behaviour change for consumers
  that don't supply them.
- `naming_convention` is applied to `target_metadata.naming_convention`
  before `context.configure` runs, so auto-generated constraints
  pick up the convention.
- All keyword arguments are pass-through to `alembic.context.configure`
  — adding/removing options requires a `mgf-alembic` minor bump per
  AP-03.

---


## Exceptions (AP-07)

Public functions raise typed exceptions from `mgf.common.exceptions`:

- `configure_env` / `run_async_migrations` raise **`OperationError`** when invoked from a running event loop on an async URL (use `run_async_migrations` directly instead). Engine/DB errors propagate with credentials masked.

## What stays in `mgf-common`, NOT here

- **`AppError`, `OperationError`** and the rest of the typed
  exception hierarchy — `mgf.common.exceptions`.
- **`bootstrap`, `app_name`, `app_version`, `current_context`** —
  `mgf.common`.

`mgf-alembic` reaches into none of mgf-common's private modules. The
runtime dep is `mgf-common>=0.30,<0.31`.

## Companion sibling: `mgf-sqlalchemy`

`mgf.sqlalchemy.create_engine`, `create_sessionmaker`,
`tenant_session` — the async-SQLAlchemy helpers paired with this
alembic helper. Install both for the full DB+migrations story:

```toml
dependencies = [
    "mgf-common>=0.30,<0.31",
    "mgf-sqlalchemy>=0.1,<0.2",
    "mgf-alembic>=0.1,<0.2",
]
```
