# For shoppers — evaluating mgf-common

> **Who you are.** You're trying to decide whether to adopt
> `mgf-common` (or pick something else). You want a fast,
> honest read on scope, fit, alternatives, and risks — not a
> 300-page tutorial.

## In 60 seconds

`mgf-common` is the cornerstone Python library for the Magogi
ecosystem. It bundles cross-project infrastructure that every
real Python application re-derives: typed exceptions, layered
configuration (kwargs > env > .env > YAML > defaults),
structured logging + OpenTelemetry, crash reporting, vault
abstraction, process management, FastAPI/Django/alembic
adapters, and a small CLI toolkit.

Stable on PyPI as `mgf-common` since v0.13.0; current major
release `v0.24.0`. Three real consumers in production:
**vm-vmanager-app** (Qt desktop, libvirt VM toolkit), **inthewords**
(Django web), **PlasmaMapper** (FastAPI scientific platform).

## Scope statement (the canonical short form)

> `mgf-fed standards SCOPE` is the authoritative scope document.
> The two-paragraph short form:

`mgf-common` covers cross-project **infrastructure** —
behaviours every Python service-or-app writes once and
copy-pastes thereafter. It does NOT cover domain logic,
framework-specific glue beyond the shipped adapters, or
production daemon supervision.

Out of scope (deliberately):

- Restart-on-crash supervision (use systemd / supervisord).
- Multi-service declarative orchestration (use docker-compose).
- Domain-specific framework adapters beyond fastapi / django /
  alembic / db (consumers add their own).
- Anything requiring a hard dep on a third-party SaaS.

## Decision tree — is mgf-common a fit?

```
  ↓ Are you writing Python ≥ 3.11?
  └─ No → not a fit (we don't support older Pythons)

  ↓ Will you have ≥1 of: typed exceptions, structured logs,
    OpenTelemetry, crash reports, vault, process orchestration,
    FastAPI/Django integration?
  └─ No → standard library is enough

  ↓ Are you OK depending on pydantic v2 + pydantic-settings?
  └─ No → not a fit (pydantic-settings is the load-bearing config
          primitive; rewriting it is out-of-scope)

  ↓ Do you need shell-string subprocess (run("foo | bar"))?
  └─ Yes → mgf.common.process is list-only by construction;
          either use raw subprocess for that case OR pass
          ["/bin/sh", "-c", "foo | bar"] explicitly

  ↓ Do you need restart-on-crash supervision?
  └─ Yes → mgf-common is out-of-scope; use systemd / supervisord

  ↓ Otherwise → adopt; start with the tutorial.
```

## Conformance levels (L1/L2/L3)

A project declares a conformance level — how strictly it follows the
standards — per [`FEDERATION.md` §4](../../FEDERATION.md) (summary in
`mgf-fed standards README`):

- **L1 Lite** — conform to the spirit, best-effort. Greenfield / spikes.
- **L2 Standard** — every MUST rule, with a per-rule audit. The default
  for production consumers + federation siblings.
- **L3 Strict** — every MUST + SHOULD rule, with run-time enforcement
  (audit-logs, redaction) wired. Cornerstone + high-stakes services.

`mgf-common` itself holds to L3.

## Comparing alternatives

| Need | mgf-common | The alternatives |
|---|---|---|
| Subprocess + timeout + redaction + logging | [`mgf.common.process.run`](../recipes/process-management.md) | `subprocess.run` (no redaction, no log streaming); `plumbum` (heavier; different ergonomics); `sh` (Pythonic shell wrapper, different security model) |
| Long-lived service orchestration (test fixtures, demo runners) | [`mgf.common.process.Service`](../recipes/process-management.md) | bash + traps; `pytest-services`; `testcontainers` (heavier; container-only) |
| Layered config (kwargs > env > .env > YAML > defaults) | [`BaseAppSettings`](../reference/config.md) | `pydantic-settings` directly (mgf wraps it with conventions); `dynaconf` (different design philosophy) |
| Typed exception hierarchy + translation seams | [`mgf.common.exceptions`](../reference/exceptions.md) | hand-rolled; `result` libraries (different shape) |
| Cross-project standards corpus | `mgf-fed standards` | none — most projects re-derive |

## Consumers using it today

| Consumer | Shape | Adoption depth | Notes |
|---|---|---|---|
| **vm-vmanager-app** | Qt desktop, libvirt | L2 (full) | Reference consumer; co-designed |
| **inthewords** | Django web | L2 (full) | The canonical web consumer; drove BOOTSTRAP-01, LOG-01, CONFIG-01 |
| **PlasmaMapper** | FastAPI scientific | L1 (small-consumer scope discipline) | Selectively adopted per `mgf-fed standards principles/non-adoption-is-valid` |

## When to NOT adopt

The principle `mgf-fed standards principles/non-adoption-is-valid`
codifies this. Concretely, you should NOT adopt if:

- Your project is < 200 LOC (the standards' overhead exceeds
  the value).
- You're stuck on Python < 3.11.
- You're allergic to pydantic v2.
- Your deployment couples you to a JSON wire shape that
  diverges from `mgf.common.observability.JsonFormatter` AND
  you don't want to opt into LG-06's cloud-native carve-out.

These are real, honest reasons. **Documented non-adoption
preserves L1/L2 conformance** when the rationale is recorded
(per the named principle).

## What ships in the wheel

| Surface | Names | Stability |
|---|---|---|
| `mgf.common.*` (top-level) | 193 names across 20 modules | All experimental per AP-11 (0.x window — see `mgf-fed standards API_DESIGN`) |
| Standards corpus | 11 topic docs + per-kind subtrees | Versioned with the wheel; `mgf-fed standards <topic>` reads them |
| 17 recipes | One per integration shape | Stable when listed in [`recipes/`](../recipes/) |
| Tutorials | Zero → working app | [`docs/tutorial.md`](../tutorial.md) |

## Read next

If this looks like a fit:

1. [`docs/tutorial.md`](../tutorial.md) — zero → working app in ~30 minutes.
2. [`docs/audience/users.md`](users.md) — the post-adoption reading list.
3. `mgf-fed standards README` — the bar your project commits to at L1/L2.

If it doesn't:

- `mgf-fed standards SCOPE` reads honestly about what we don't try to be.
- `mgf-fed standards principles/non-adoption-is-valid` is the principled exit.
