# Federation roadmap — `mgf-common` v0.28 → v1.0 split plan

> **Audience:** maintainers of `mgf-common` and every Magogi
> sibling package. Engineering managers tracking the v1.0 cut.
> AI agents driving the staged extractions across multiple
> sessions.
> **What this is:** the load-bearing tracking document for the
> federation split. Per-sibling specs, quality gates, decisions
> log, open questions, future improvements. **Owns the truth on
> the split-plan; the FEEDBACK paper (ASPIRE-06) cross-references
> here.**

---

## TL;DR

Between v0.28 and v1.0 (target lock), `mgf-common` extracts every
framework-coupled module into its own sibling package under the
`mgf.*` namespace. The pure-Python core stays in `mgf-common`. The
standards source-of-truth moved to `mgf-standard`; `mgf-common` wheels them as package data.

```
v0.28  →  extract mgf-fastapi
v0.29  →  extract mgf-http
v0.30  →  extract mgf-sqlalchemy + mgf-alembic
v0.31  →  extract mgf-django
v0.32+ →  stabilization, deprecation cleanup
v1.0   →  lock surface, promote experimental → stable
```

Goal at v1.0: `mgf-common` is **clean, focused, and load-bearing**
— pure-Python infrastructure + standards. Framework adapters
ship as siblings with independent versioning.

The user's existing memory ([stay in 0.x](../../FEEDBACK.md))
applies — keep climbing 0.28 / 0.29 / … / 0.32; v1.0 happens only
when the maintainer explicitly green-lights.

---

## Why federation, why now

Three forces converged in the design conversation on 2026-05-08:

1. **Surface size.** v0.26 + v0.27 (shipped same day) added 7
   public names — all `mgf.common.fastapi.*`. The web-stack
   surface grows faster than the core; co-locating creates
   friction.

2. **The 0.x window is the design window.** Once v1.0 ships, the
   public-API contract locks. Reorganizing AFTER v1.0 either
   breaks the contract or requires v2.0 within 6–12 months.
   Doing the split BEFORE v1.0 is the cheap path.

3. **Consumer-protection lifted.** The maintainer explicitly
   authorized: *"don't worry about current consumers below v1.0
   … the goal of the current library consumers is to help shape
   the library."* Consumers (PlasmaMapper, inthewords, vm-vmanager-app)
   are co-designers in the 0.x window, not deployment targets.
   They migrate at each extraction; the rename is part of
   their role.

The federation pattern itself is documented in
[`docs/design/federation.md`](../design/federation.md). This
document is the **execution plan** for it.

---

## v1.0 target architecture

### Pure-Python core (stays in `mgf-common`)

| Submodule | What |
|---|---|
| `mgf.common.exceptions` | `AppError` + 8 categories + generic concretes + HTTP-01 hierarchy roots + status-code leaves (`HttpUnauthorized`, `HttpForbidden`, `HttpNotFound`, `HttpConflict`, `HttpGone`, `HttpUnprocessable`, `HttpInternalServerError`, `HttpServiceUnavailable`). The federation-wide typed-exception contract. |
| `mgf.common.config` + `mgf.common.settings` | `BaseAppSettings`, `MgfSettings`, `settings_config()` — pydantic-settings-based; framework-agnostic. |
| `mgf.common.observability` | Logging, OTel setup, redactor. Stdlib + opentelemetry as optional extra. |
| `mgf.common.bootstrap` (`_lifecycle.py`) | The transactional wiring entry point. Framework-agnostic. |
| `mgf.common.providers` | `ProviderABC` + `translate_at_seam` — DP-02 implementation. |
| `mgf.common.process` | Subprocess + `Service` lifecycle. Stdlib only. |
| `mgf.common.vault` | Optional encrypted file vault. Cryptography as optional extra. |
| `mgf.common.versioned` | Versioned satellite-config files. |
| `mgf.common.cli` | CLI primitives (exit codes, structured handler). |
| `mgf.common.registry` | Tiny registry pattern. |
| `mgf.common.pytest_plugin` | pytest fixtures (entry-point auto-registers). |
| `mgf.common.progress` | Cancellation tokens. |
| `mgf.common.typing` | Type aliases. |
| Standards docs | `mgf-standard/docs/standards/*` — source of truth for the federation; wheeled into mgf-common as package data. |
| `mgf-fed init-project` | Federation orchestrator — scaffolds projects of any kind, including those that pull sibling deps. |

### Framework-adapter siblings (each = one 3rd-party dep)

| Sibling | Owns | Depends on (mgf.*) | Imports (3rd-party) |
|---|---|---|---|
| **`mgf-fastapi`** | `mgf.fastapi.{__init__, webhooks, security, testing}` + `HmacVerificationError`, `IpAllowlist`, `LOOPBACK_CIDRS`, `WebhookHeaderSchema`, `SVIX_SCHEMA`, `HmacWebhookVerifier`, `verify_request`, `run_test_app`, `ExceptionTranslationMiddleware`, `RequestIdMiddleware`, `setup_lifespan`, `get_app_context`, `get_settings`, `get_request_id`, `REQUEST_ID_HEADER`, `DEFAULT_STATUS_MAP`. Plus (v0.2+) `mgf.fastapi.db.{get_session, setup_db}` behind the `[sqlalchemy]` extra. | `mgf.common` (+ `mgf.sqlalchemy` via `[sqlalchemy]` extra) | `fastapi`, `starlette`, `uvicorn` (testing extra) |
| **`mgf-django`** | `mgf.django.*` (`MgfCommonConfig`, `MgfRequestIdMiddleware`, settings bridge) | `mgf.common` | `django` |
| **`mgf-http`** | `mgf.http.*` (`AsyncHttpClient`, `RetryPolicy`, `HttpTransportError`) | `mgf.common` | `httpx` |
| **`mgf-sqlalchemy`** | `mgf.sqlalchemy.*` — pure async-SQLAlchemy helpers (`create_engine`, `create_sessionmaker`, `tenant_session`). Genuinely framework-agnostic — no Starlette / FastAPI in dep graph. The FastAPI-shaped helpers (`get_session`, `setup_db`) ship from `mgf.fastapi.db` instead (v0.30 design refinement). | `mgf.common` | `sqlalchemy` |
| **`mgf-alembic`** | `mgf.alembic.*` (`configure_env`, including PAPER-22 `include_object` / `include_schemas`) | `mgf.common`, `mgf.sqlalchemy` | `alembic` |

### Domain-specific siblings (existing or upcoming)

| Sibling | Owns |
|---|---|
| **`mgf-apiprobe`** | Already a sibling (per [`project_apiprobe_sibling.md`](../../../../.claude/projects/-home-bassam-PycharmProjects-mgf-common/memory/project_apiprobe_sibling.md) memory). API verification primitives. |

### Templates (cookiecutter repos; not Python libraries)

| Repo | Purpose |
|---|---|
| **`mgf-website-template`** | Astro + Infomaniak deploy + CLAUDE.md referencing mgf-common standards. Marketing-site cookiecutter. PAPER-30. |
| (future) `mgf-cli-template` | Standalone CLI project cookiecutter; mgf-common's existing `init-project --kind cli` template gets pulled out as the second consumer arrives. |
| (future) `mgf-fastapi-template` | Same shape for `--kind fastapi`. |

---

## Per-sibling spec (extraction details)

### v0.28 — `mgf-fastapi`

| Field | Value |
|---|---|
| **Distribution** | `mgf-fastapi` on PyPI |
| **Repo** | `codeberg.org/magogi-admin/mgf-fastapi` |
| **Import path** | `mgf.fastapi` |
| **Runtime dep on mgf-common** | `mgf-common>=X.Y,<X.(Y+1)` (pinned per AP-03) |
| **Import deps** | `fastapi>=0.110`; optional `[testing]` extra adds `uvicorn>=0.30`, `httpx>=0.27` |
| **What lands in v0.1.0 of mgf-fastapi** | Everything currently in `mgf.common.fastapi.*` (incl. `webhooks/`, `security.py`, `testing.py`) + `HmacVerificationError` (currently in mgf-common.exceptions). |
| **What stays in mgf-common** | The HTTP-01 hierarchy roots + status-code leaves (`HttpError`, `HttpUnauthorized`, `HttpForbidden`, etc.). `HmacVerificationError` no longer ships from mgf-common. |
| **Migration story for consumers** | `from mgf.common.fastapi import …` → `from mgf.fastapi import …`. `from mgf.common.fastapi.webhooks import …` → `from mgf.fastapi.webhooks import …`. Same for `.security`, `.testing`. `from mgf.common.exceptions import HmacVerificationError` → `from mgf.fastapi.exceptions import HmacVerificationError` (or however the sibling exposes it). |
| **mgf-common v0.28 release** | Removes `mgf.common.fastapi.*` entirely. Removes `HmacVerificationError`. Cutover guide v0.28 documents the rename map. The `[fastapi]` extra in mgf-common removed; consumers install `mgf-fastapi` directly. |
| **Test surface** | Every test in `tests/unit/fastapi/test_*.py` (currently 49 tests as of v0.27.0) moves to `mgf-fastapi/tests/`. Coverage stays ≥ what mgf-common achieved. |
| **Standards / recipe doc moves** | `docs/recipes/{fastapi,webhooks}.md` move to `mgf-fastapi/docs/recipes/`. `docs/standards/web/` moved to mgf-standard (cross-cuts mgf-fastapi + mgf-django). |
| **Risk** | Touches PlasmaMapper most. Just-shipped v0.26/v0.27 surface (PAPER-26/27/28) renames; PlasmaMapper hasn't even consumed those yet, so the migration is clean. |

### v0.29 — `mgf-http`

| Field | Value |
|---|---|
| **Distribution** | `mgf-http` on PyPI |
| **Repo** | `codeberg.org/magogi-admin/mgf-http` |
| **Import path** | `mgf.http` |
| **Runtime dep on mgf-common** | `mgf-common>=X.Y,<X.(Y+1)` |
| **Import deps** | `httpx>=0.27`; optional `[test]` adds `respx>=0.21` |
| **What lands** | `AsyncHttpClient`, `RetryPolicy`, `HttpClientError` (the http-client-specific concrete) |
| **Migration** | `from mgf.common.http import …` → `from mgf.http import …` |
| **Test surface** | `tests/unit/http/test_*.py` moves; coverage parity preserved. |
| **Recipe** | `docs/recipes/http.md` moves to `mgf-http/docs/recipes/`. |
| **Risk** | Used by PlasmaMapper + potential future consumers. Mechanical rename. |

### v0.30 — `mgf-sqlalchemy` + `mgf-alembic` + `mgf-fastapi` v0.2 (paired triple)

✅ **Shipped 2026-05-10.**

| Field | Value |
|---|---|
| **Distributions** | `mgf-sqlalchemy` v0.1.0, `mgf-alembic` v0.1.0, `mgf-fastapi` v0.2.0 (paired triple release) |
| **Repos** | `codeberg.org/magogi-admin/mgf-sqlalchemy`, `…/mgf-alembic`, `…/mgf-fastapi` (existing) |
| **Import paths** | `mgf.sqlalchemy`, `mgf.alembic`, `mgf.fastapi.db` |
| **Dep relationships** | `mgf-alembic` depends on `mgf-sqlalchemy>=0.1,<0.2` AND `mgf-common>=0.30,<0.31`. `mgf-fastapi[sqlalchemy]` extra pulls `mgf-sqlalchemy>=0.1,<0.2`. |
| **What lands** | mgf-sqlalchemy: pure helpers (`create_engine`, `create_sessionmaker`, `tenant_session`) — framework-agnostic, no Starlette in dep graph. mgf-alembic: `configure_env` (with PAPER-22 `include_object` / `include_schemas`). mgf-fastapi v0.2: new `mgf.fastapi.db` submodule with `get_session` + `setup_db` (gated behind `[sqlalchemy]` extra). |
| **Migration** | `from mgf.common.db import {create_engine, create_sessionmaker, tenant_session}` → `from mgf.sqlalchemy import …`; `from mgf.common.db import {get_session, setup_db}` → `from mgf.fastapi.db import …`; `from mgf.common.alembic import configure_env` → `from mgf.alembic import …`. |
| **Test surface** | `tests/unit/db/` + `tests/unit/alembic/` removed from mgf-common (26 tests). Moved: 13 to `mgf-sqlalchemy/tests/unit/`, 16 to `mgf-alembic/tests/unit/`, 6 to `mgf-fastapi/tests/unit/test_db.py`. |
| **Recipes** | `docs/recipes/db.md` → `mgf-sqlalchemy/docs/recipes/sqlalchemy.md`; `docs/recipes/alembic.md` → `mgf-alembic/docs/recipes/alembic.md`. |
| **Design refinement at extraction time** | Roadmap originally stated mgf-sqlalchemy ships engine + session + lifespan + FastAPI-agnostic helpers, but `get_session` + `setup_db` were inherently FastAPI-shaped (Starlette `Request`, `app.state`). Splitting by shape — pure helpers in mgf-sqlalchemy, FastAPI helpers in `mgf.fastapi.db` (mgf-fastapi v0.2) — kept mgf-sqlalchemy genuinely framework-agnostic per the roadmap intent. The trade-off: FastAPI consumers now install both `mgf-sqlalchemy` and `mgf-fastapi[sqlalchemy]`. Pure-SQLAlchemy consumers shed Starlette as a transitive dep. |
| **Risk** | Paired triple — three packages must ship together. mgf-alembic's pin to mgf-sqlalchemy and mgf-fastapi v0.2's `[sqlalchemy]` extra are the load-bearing constraints. |

### v0.31 — `mgf-django` (final framework-adapter extraction)

✅ **Shipped 2026-05-10.**

| Field | Value |
|---|---|
| **Distribution** | `mgf-django` v0.1.0 on PyPI |
| **Repo** | `codeberg.org/magogi-admin/mgf-django` |
| **Import path** | `mgf.django` |
| **Runtime dep on mgf-common** | `mgf-common>=0.31,<0.32` |
| **Import deps** | `django>=4.2` |
| **What lands** | All five public names: `MgfCommonConfig`, `MgfRequestIdMiddleware`, `MgfContextMiddleware`, `JsonFormatter`, `DjangoSettingsBridge`. Plus a top-level `apps.py` for Django's `INSTALLED_APPS` discovery. |
| **Migration** | `from mgf.common.django import …` → `from mgf.django import …`; `INSTALLED_APPS` `"mgf.common.django"` → `"mgf.django"`; app-label `"mgf_common"` → `"mgf_django"` (consumer hardcodes break — sed in cutover guide). |
| **Test surface** | `tests/unit/django/test_*.py` moved (18 tests); coverage parity preserved. |
| **Recipe** | `docs/recipes/django.md` removed from mgf-common; canonical recipe now at `mgf-django/docs/recipes/django.md`. |
| **Consumer impact** | inthewords doesn't actually import from `mgf.common.django` (uses its own middleware/AppConfig); pin bump only. PlasmaMapper / vm-vmanager-app / mgf-apiprobe: no Django surface in use, untouched. |
| **Risk realized** | Trivial. The single Django consumer (inthewords) doesn't actually use the surface; only doc cosmetics needed there. The label rename is theoretically breaking but no consumer hardcoded the old label. |
| **Federation milestone** | This was the FINAL framework-adapter extraction. mgf-common is now the federation leaf with pure-Python infrastructure only. v0.32+ stabilization window opens. |

### v0.32+ — stabilization

The release window between the last extraction (v0.31) and v1.0 is
**stabilization-only** — no new public surface, no new siblings.
Goals:

- Run the whole federation through real consumers (PlasmaMapper +
  inthewords) for at least one minor cycle before v1.0 lock.
- Surface friction via FEEDBACK papers; address blockers.
- Migrate `experimental` → `stable` tier on names that survive.
- Fix any deprecation-shim shape if a v0.x rename was cosmetic.

**Status of each goal (post-v0.32.0):**

- Real-consumer run: ✅ partial — PlasmaMapper drove PAPER-29
  (BearerSession), inthewords drove PAPER-15 (pip-tools audit),
  and both surfaced friction that closed in v0.32 / mgf-fastapi
  v0.3. Both are now on the new federation pins. vm-vmanager-app's
  v0.32 adoption walk happens at its own pace.
- Friction surfaced via papers: ✅ — PAPER-06, PAPER-15, and
  PAPER-29 all closed in this window. ASPIRE-05 still parked
  (mgf-website-template is its live exercise).
- Experimental → stable: ✅ first walk pass landed in v0.32.0
  (12 core foundation names promoted). HTTP-01 hierarchy +
  concrete exception leaves + `MgfSettings` family held for
  later walks once another minor cycle of evidence accumulates.
- Cosmetic-rename deprecation cleanup: 🟡 partial — the
  `EnvironmentError → HostEnvironmentError` deprecated alias is
  still in play (one more minor for the standard deprecation
  cycle, per AP-12).

### v1.0 — lock the federated surface

When the maintainer green-lights v1.0:

- Promote every public name in mgf-common + every sibling from
  `experimental` to `stable` per AP-09.
- Bump every package to v1.0 simultaneously.
- One v1.0 cutover guide spans all siblings.
- The deprecation cycle (AP-12) starts applying.

---

## Quality gates (each release MUST pass)

The 0.x window is the design window, but quality is non-negotiable.
Each extraction release MUST clear:

| Gate | Mechanism | Threshold |
|---|---|---|
| **Tests pass** | `pytest` in both mgf-common AND the new sibling | 100% green |
| **Type checking** | `mypy --strict` on the sibling's `src/` | Zero errors |
| **Lint** | `ruff check` on the sibling | Zero errors |
| **Coverage** | `pytest-cov` per the sibling's threshold (matches mgf-common's standard, typically ≥85%) | Per-package threshold met |
| **Public-API contract** | The sibling's `PUBLIC_API.md` lists every name in `__all__` (AP-10) + `PUBLIC_API.json` matches | Pin tests pass |
| **CLAUDE.md presence** | The sibling has a `docs/CLAUDE.md` with auto-managed BEGIN/END markers | `mgf-fed catch-up` clean |
| **Cutover guide** | mgf-common `docs/cutover/v0.<N>.md` documents the rename map for the extraction | Required before merge |
| **Sibling cutover** | The new sibling has its own `docs/cutover/v0.1.0.md` documenting the maiden voyage | Required before PyPI publish |
| **Inter-package coupling** | The sibling imports `mgf.common` only through public names (`__all__`); no `mgf.common._private` reaches | import-linter contract enforces |
| **PyPI verification** | After publish, `pip install mgf-<sibling>` from a fresh venv → import succeeds → smoke test passes | Required before declaring extraction done |
| **Consumer notification** | A FEEDBACK retrospective in mgf-common notes the affected consumers + their migration steps (REL-09) | Required |

The four-layer test pyramid (per v0.24.0) applies per-sibling:
unit → integration → e2e → smoke.

---

## Decisions log (locked 2026-05-08)

These are the load-bearing decisions made in the federation-shape
conversation. Changes require an updated FEEDBACK paper.

| # | Decision | Rationale |
|---|---|---|
| **D1** | mgf-common stays the federation leaf | Per `docs/design/federation.md`. Every sibling depends ON it; nothing depends BACK on a sibling. |
| **D2** | HTTP-01 hierarchy roots + status-code leaves stay in mgf-common.exceptions | They're THE typed-exception contract for the federation; every sibling raises through them. |
| **D3** | Sibling-domain concrete leaves move with their sibling | E.g. `HmacVerificationError` moves to `mgf-fastapi`. This generalises: future `CsrfVerificationError` (mgf-django), `HttpRetryExhaustedError` (mgf-http), etc. |
| **D4** | Standards docs moved to `mgf-standard`; wheeled into mgf-common | Source of truth for the federation; cross-cuts every sibling. |
| **D5** | Framework-specific recipes split with their package | `fastapi.md`, `webhooks.md`, `django.md`, `http.md`, `db.md`, `alembic.md` move to their siblings. |
| **D6** | Cross-framework recipes stay in mgf-common | `framework-owned-logging.md`, `cloud-native-logging.md` — they apply across multiple siblings. |
| **D7** | `mgf-fed init-project` stays in mgf-common | Federation orchestrator role; templates live in `mgf-common/templates/<kind>/` and pull in sibling deps via pyproject snippets. |
| **D8** | Each sibling has independent semver | Independent CHANGELOG, FEEDBACK, cutover guides, CI per Codeberg repo. |
| **D9** | Per-minor staging, not big-bang | Validates the sibling-creation flow per piece; reduces cross-package mistake risk. |
| **D10** | Consumers (PlasmaMapper, inthewords) face one rename per release | They're co-designers in the 0.x window; rename is part of their role. |
| **D11** | Tight-coupling-runs-adapter→core | mgf-common changes drag every sibling. Accepted as the cost of clean separation. |
| **D12** | Per-sibling Codeberg repo (not monorepo) | Mirrors the apiprobe pattern. Independent issues, PRs, releases. |
| **D13** | `mgf-website-template` is parallel, not in the dependency graph | It's a cookiecutter, not a Python package. PAPER-30. |
| **D14** | v1.0 bump waits for explicit maintainer green-light | Per [stay in 0.x](../../FEEDBACK.md) memory. v0.32+ stabilization may run multiple minors. |
| **D15** | Standards docs don't fragment per-sibling | Even after the split, the per-kind subtree (`mgf-standard/docs/standards/web/`) lives in mgf-standard — applies to mgf-fastapi + mgf-django + future mgf-flask collectively. |

---

## Open questions

Things to resolve at the relevant extraction:

| Q | When to decide | Default |
|---|---|---|
| Does `mgf-fastapi` re-export FastAPI primitives, or stay strictly adapter-only? | v0.28 design | Strictly adapter-only — never re-export `fastapi.FastAPI`, `Request`, etc. (closed-box invariant) |
| Does `mgf-fastapi` ship its own `[testing]` extra, or fold it into the base install? | v0.28 design | Separate `[testing]` extra — uvicorn is heavier than the typical web consumer needs at runtime |
| Does the sibling's `__version__` couple to mgf-common's, or float independently? | v0.28 release | Independent; pin via `mgf-common>=X.Y,<X.(Y+1)` |
| For `mgf-sqlalchemy` + `mgf-alembic` — do they merge into one `mgf-db` sibling? | v0.30 design | Separate (alembic is genuinely optional; consumers using sqlalchemy without migrations don't need alembic) |
| Does the federation get a `mgf-meta` package that pins recommended sibling versions for "I want all of it"? | post-v1.0 | No (avoids meta-package drift; consumers pick siblings explicitly) |
| Does init-project move to its own template-orchestrator sibling? | post-v1.0 | No (stays in mgf-common as federation orchestrator) |

---

## Future improvements (post-v1.0 candidates)

Long-horizon ideas not in scope for the v0.28 → v1.0 split:

| Idea | Triggered by | Notes |
|---|---|---|
| **Cross-language standards source-of-truth** | ASPIRE-05 | `docs/standards/` has moved to `mgf-standard`. With 2+ non-Python Magogi projects, verify mgf-standard's cross-language coverage is adequate. |
| **`mgf-flask` sibling** | Two-consumer-benefit bar | If a second consumer needs Flask (foundation site is going Astro per Path X). |
| **`mgf-fastapi-stripe`, `mgf-fastapi-github` etc.** | Webhook-shape diversification | If Stripe / GitHub / Slack signing schemes (deferred from PAPER-26) need to ship as sibling-of-sibling presets. |
| **`mgf-django-drf` sibling** | DRF-specific patterns | inthewords uses DRF; if patterns generalise, file follow-up paper. |
| **Replay-cache hook for HmacWebhookVerifier** | Stripe recommends it | Pluggable storage interface; deferred from PAPER-26. |
| **`mgf-cli-template`, `mgf-fastapi-template`, `mgf-django-template`** | Template-out-of-mgf-common pattern | When init-project's per-kind templates grow enough to warrant their own repos. |
| **`mgf-meta` sibling** | If consumers ask for "everything Magogi" pinning | Deferred per Q above. |

Each row would file as its own ASPIRE / PAPER entry when triggered.

---

## How to use this document

| If you are… | Read |
|---|---|
| **Maintainer driving v0.28** | The "v0.28 — mgf-fastapi" per-sibling spec + Quality gates + Decisions log. Update this doc with retrospective when v0.28 ships. |
| **Maintainer driving v0.29 / v0.30 / v0.31** | The relevant per-sibling spec + Open questions for that release. Re-confirm Decisions log still applies. |
| **AI agent in a future session continuing the split** | Decisions log + Open questions + the per-sibling spec for the current release. The decisions are LOAD-BEARING — don't re-litigate them without an updated FEEDBACK paper. |
| **Consumer (PlasmaMapper / inthewords / vm-vmanager-app) reading after a release** | The relevant cutover guide; this doc is the maintainer-side plan. |

---

## Cross-references

- [`FEEDBACK.md ASPIRE-06`](../../FEEDBACK.md) — the design paper
  this document executes against.
- [`FEEDBACK.md ASPIRE-05`](../../FEEDBACK.md) — long-horizon
  cross-language extension question.
- [`FEEDBACK.md PAPER-30`](../../FEEDBACK.md) — first concrete
  non-Python sibling (`mgf-website-template`).
- [`docs/design/federation.md`](../design/federation.md) — the
  federation pattern (this document executes ITS plan).
- [`RELEASING.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/RELEASING.md) —
  per-release discipline; every extraction follows it.
- [`API_DESIGN.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/API_DESIGN.md) —
  AP-* rules including AP-03 (semver) + AP-09 (stability tiers)
  + AP-10 (PUBLIC_API.md contract) + AP-12 (deprecation cycle).

---

## Retrospective log (per-release)

*(Filled as each extraction ships.)*

| Release | Sibling | Shipped on | Retrospective |
|---|---|---|---|
| v0.28.0 | mgf-fastapi | 2026-05-08 | mgf-fastapi 0.1.0 published to PyPI; PUBLIC_API.json modules 23→19, names 201→184; `HmacVerificationError` moved with sibling per D3. Clean ship — no follow-up papers filed. |
| v0.29.0 | mgf-http | 2026-05-09 | mgf-http 0.1.0 published to PyPI; PUBLIC_API.json modules 19→18, names 184→181; `HttpClientError` renamed to `HttpTransportError` on sibling side (name-collision fix). Clean ship — no follow-up papers filed. |
| v0.30.0 | mgf-sqlalchemy + mgf-alembic + mgf-fastapi v0.2 | 2026-05-10 | mgf-sqlalchemy 0.1.0 + mgf-alembic 0.1.0 + mgf-fastapi 0.2.0 (paired triple ship); PUBLIC_API.json modules 18→16, names 181→175. **Design refinement at extraction time:** the FastAPI-shaped helpers `get_session` + `setup_db` from `mgf.common.db` moved to `mgf.fastapi.db` (gated behind `mgf-fastapi[sqlalchemy]`) instead of mgf-sqlalchemy — keeps mgf-sqlalchemy framework-agnostic per the roadmap intent (Starlette/FastAPI types stayed out of its dep graph). Clean ship — no follow-up papers filed. |
| v0.31.0 | mgf-django | 2026-05-10 | mgf-django 0.1.0 published to PyPI; PUBLIC_API.json modules 16→15, names 175→170. App label rebrand `"mgf_common"` → `"mgf_django"` at the rename (Django labels can't contain dots; rename aligns label with new module path). The single Django consumer (inthewords) doesn't actually import from the moved surface, so only a pin bump + doc cosmetics needed there. **Federation milestone:** final framework-adapter extraction. mgf-common is now the federation leaf with pure-Python infrastructure only; v0.32+ stabilization window opens. Clean ship — no follow-up papers filed. |
| v0.32.0 | (no extraction; first stabilization release) + mgf-fastapi v0.3 companion | 2026-05-10 (commits) / 2026-05-11 (PyPI) | **First v0.32+ stabilization-window release.** No new mgf-common public surface per the roadmap. Closes three papers + lands the first stable-tier walk: (1) [**PAPER-15**](../../FEEDBACK.md) — full pip-tools manifest audit in `mgf-fed catch-up` (was partial info-level workaround in v0.17.2). Pin reader + four-gate audit + auto-rewrite + editable-install guard all work uniformly across `pyproject.toml` and `requirements/*.{txt,lock}` layouts. 17 new tests. (2) [**PAPER-06**](../../FEEDBACK.md) — full restructure of consumer-specific evidence into new [`docs/reference-consumers/`](../reference-consumers/) folder (3 per-consumer profile files: vm-vmanager-app / inthewords / PlasmaMapper). `docs/standards/README.md` caveat banner generalised from "reference consumer = vm-vmanager-app" to "three reference consumers; see `reference-consumers/`". (3) **First experimental → stable walk:** 12 foundation names promoted to `stable` (`bootstrap`, `current_context`, `AppContext`, `app_name`, `app_version`, `AppError` + the 6 typed-exception category bases `ConfigError` / `ProviderError` / `OperationError` / `GuestError` / `VaultError` / `SchedulerError`). Deliberately conservative — names that have survived 12+ minor cycles AND have 3-consumer evidence. HTTP-01 hierarchy + newer concretes held for next walk. PUBLIC_API.json modules 15→15, names 170→170 (no surface change; tier-only). **Companion sibling release in the same chapter:** mgf-fastapi v0.3.0 ships [PAPER-29](../../FEEDBACK.md) — `bearer_session` + `AuthVerifier` Protocol — under the federation's independent-semver rule for siblings. **PyPI publish status (2026-05-11):** mgf-common 0.32.0 + mgf-fastapi 0.3.0 live; mgf-sqlalchemy 0.1.0 + mgf-alembic 0.1.0 fresh-published (closing the v0.30 PyPI gap); mgf-django 0.1.0 still 429-blocked (third new-project create in one batch; retry +24h). Clean ship — no follow-up papers filed. |
| v1.0.0 | (lock) | TBD | TBD |
