# `mgf-sqlalchemy` — scope policy

> This is `mgf-sqlalchemy`'s **scope policy** (federation rule family **SP**). It
> governs what belongs in this async-SQLAlchemy adapter. A proposed addition is in
> scope only if it passes the §3 gate.

## §1 In scope (SP-01)

Thin, typed **async-SQLAlchemy adapters** for mgf-common consumers:

- a typed async engine factory (`create_engine`) + URL password-masking (`make_safe_url`)
- a sessionmaker factory + session dependency (`create_sessionmaker`)
- Postgres RLS tenant-scoping (`tenant_session`, `SET LOCAL` GUC)
- keyset/offset pagination (`paginate_cursor`)
- declarative mixins: UUID7 primary keys, audit-trail columns (`AuditTrailMixin`, `uuid7`)

The boundary: **wiring async SQLAlchemy + mgf-common together with typed, safe
defaults.** Consumers own their ORM models, their DB driver, and their migrations.

## §2 Out of scope (SP-02) — with reasons

| Not here | Why | Where instead |
|---|---|---|
| ORM model definitions | those are the consumer's domain | the consumer app (declarative `Base`) |
| Schema migrations | a separate concern with its own sibling | `mgf-alembic` / `alembic` |
| The async DB driver | consumers pick their own | `asyncpg` / `aiosqlite` / … |
| Sync SQLAlchemy support | this library is async-only by charter | `sqlalchemy` directly |
| A query builder / repository layer | beyond adapter scope; opinionated | SQLAlchemy core/ORM |
| Connection-pool tuning policy | consumer-owned via `**extra` passthrough | SQLAlchemy engine options |

## §3 Scope-creep gate (SP-03)

A PR adding a module/helper MUST answer in its description:
1. Does it need async SQLAlchemy types? (If no → it likely belongs in `mgf-common`.)
2. Is it an adapter (wiring + safe defaults), not a consumer domain model / migration?
3. Is there a consumer demand signal (a `FEEDBACK.md` paper / a sibling's need), or speculative?

Any "no/unclear" blocks the addition until resolved.

## §4 Adjacent scope (SP-04)

Adjacent (plausible, not yet in): read-replica/primary routing, connection-pool
metrics emission, a typed `Repository` base, soft-delete mixins. These move
adjacent → in only on a **documented consumer-demand signal** (a real sibling need
or `FEEDBACK.md` paper), never speculatively.

## §5 Alternatives for out-of-scope needs (SP-05)

Need something §2 excludes? ORM models → SQLAlchemy declarative directly;
migrations → `mgf-alembic` / `alembic`; a driver → `asyncpg`/`aiosqlite`; sync
SQLAlchemy → `sqlalchemy` directly; query building → SQLAlchemy core/ORM.

## §6 Revisiting scope (SP-06)

Revisited at every **MAJOR** boundary (0.x → 1.0, and each later major). Pre-1.0,
scope may tighten/loosen per the §3 gate; a major bump is the checkpoint to
re-justify the whole surface against §1/§2 and re-affirm the async-only,
adapter-not-domain invariant.
