# Pre-release additions — feature roadmap, evidence-backed

> **Status:** working document. First pass 2026-05-17, immediately
> after the [`pre_release_check.md`](pre_release_check.md) audit
> and the four-consumer evidence sweep.
> **Audience:** the maintainer + future Claude sessions driving
> federation feature work.
> **Companion docs:**
> [`pre_release_check.md`](pre_release_check.md) (v1.0 blockers),
> [`federation_roadmap.md`](federation_roadmap.md) (split plan +
> quality gates), [`strategic_review.md`](strategic_review.md)
> (org/community strategy).
> **Scope:** every Magogi federation project + the four real
> consumers (vm-vmanager-app, inthewords, PlasmaMapper, iosRecovery).

---

## §1 TL;DR

If we ship only **three things** before v1.0, ship these — they're
each backed by 2+ real consumer signals and replace boilerplate
that consumers are currently hand-rolling:

1. **C-1 feature flags** (mgf-common) — kill-switch discipline for
   every web consumer; ~80 LOC removed per consumer.
2. **S-1 audit-trail mixin** (mgf-sqlalchemy) — PlasmaMapper +
   inthewords both add `created_at` / `updated_at` /
   `created_by_id` per-model today.
3. **H-N resumable HTTP download** (mgf-http) — iosRecovery (IPSW
   restoration) + vm-vmanager-app (VM image downloads) both need
   chunked + integrity-checked + resumable. New evidence; high ROI.

Two patterns previously DEFERRED are now unblocked by real
consumer evidence:

- **PAPER-10 (entry-point plugin auto-discovery)** — PlasmaMapper's
  `TelematicsProvider` is the live evidence (Teltonika first;
  Queclink + Ruptela queued for Phase 8). Promote from
  "deferred" to Wave 1.
- **C-10 background-task protocol** — PlasmaMapper (arq) +
  inthewords (Celery) confirm the protocol-only ship shape; do
  NOT pick a backend.

---

## §2 Methodology — how I gathered evidence

For each candidate feature in [`pre_release_check.md`](pre_release_check.md)
§3, I cross-checked against the actual usage in four real
consumer projects:

1. **vm-vmanager-app** — `/home/bassam/PycharmProjects/vm-vmanager-app`
   (Qt desktop KVM/QEMU manager; mature; on mgf-common 0.33).
2. **inthewords** — `/home/bassam/PycharmProjects/inthewords`
   (Django web app for discussion/debate rooms; on mgf-common
   0.31 — three minors behind).
3. **PlasmaMapper** — `/home/bassam/PycharmProjects/PlasmaMapper`
   (multi-tenant FastAPI SaaS; heaviest sibling adopter; on
   mgf-common 0.33 + observability extra + mgf-fastapi +
   mgf-sqlalchemy + mgf-alembic).
4. **iosRecovery** —  `/home/bassam/PycharmProjects/iosRecovery`
   (Ubuntu CLI/GUI for iOS device recovery; pre-code Phase 0
   scaffolding; on mgf-common 0.33 + mgf-http).

For each, I read:
- `pyproject.toml` — runtime dependency reveals
- `README.md` / `STARTHERE.md` — project shape + intent
- `docs/inprogress/` — open trackers (mostly RA/SH/PC/UX)
- `MGF_ADOPTION.md` / `MGF_COMMON_ADOPTION.md` (PlasmaMapper +
  inthewords) — explicit adoption-friction logs
- Top-level layout — apps / docker-compose / deploy shapes

Memory: [`project_consumers`](../../../.claude/projects/-home-bassam-PycharmProjects-mgf-common/memory/project_consumers.md)
captures the consumer profiles for future sessions.

---

## §3 Consumer profiles (one-paragraph each)

### vm-vmanager-app
Qt desktop application — KVM/QEMU virtual-machine manager for
Linux. Mature reference consumer; first to adopt mgf-common.
Uses paramiko (SSH), croniter (cron-shape scheduling),
secretstorage (keyring), cryptography, cachetools, dpkt. Has
its own RA/SH/PC + OPERABILITY trackers. CLI + PySide6 GUI
sharing a typed Python core. **Federation surface needs:** local
artifact cache, scheduler primitive, cron, doctor bundle.

### inthewords
Django web app — discussion + debate rooms. Second consumer.
On mgf-common 0.31 (three minors behind!). Uses Django 5.1 +
channels + channels_redis (WebSockets), Celery +
django_celery_beat (background tasks), django_otp (2FA),
allauth (OAuth), DRF, boto3 + django-storages (S3), qrcode,
sentry_sdk, django_ratelimit. Had a **parallel implementation
problem** — pre-existing `apps/core/exceptions.py` +
`apps/core/logging.py` (CENTRAL-01..08 lint-enforced central
interfaces) before adopting mgf-common. Adoption strategy:
re-base on mgf-common where it fits; ship documented
non-adoption (CONFIG-01 / LOG-01 carve-outs) where it doesn't.
Ships `docs/standards/web/mypy-stubs-workarounds.md` — 10
reusable patterns for django-stubs / DRF / Channels / Celery
stub gaps. **Federation surface needs:** Celery integration
helpers, channels integration helpers, OAuth helpers, feature
flags, brute-force throttle.

### PlasmaMapper
Multi-tenant FastAPI SaaS (scientific/telematics platform;
Iraq go-live targeted). Third consumer; FIRST web-shape;
HEAVIEST sibling adopter; uses every framework-adapter sibling.
Postgres-asyncpg + Redis + arq (background jobs) + Clerk-via-
pyjwt + full OTel instrumentation. `apps/web/` single-app shape.
Plugin-shape extensions (TelematicsProvider for
Teltonika / Queclink / Ruptela). **Concrete federation-value
case study:** their `MGF_ADOPTION.md` documents ~250 LOC saved
by adopting `HmacWebhookVerifier` + `IpAllowlist` +
`run_test_app` (the three v0.27 primitives). i18n gaps
(UX-09/10/11) flagged. **Federation surface needs:** plugin
auto-discovery (PAPER-10), JWT helper, i18n primitive, arq
integration, feature flags, audit-trail mixin.

### iosRecovery
Ubuntu CLI/GUI for iOS device recovery (jailbreak / restore /
SHSH-blob orchestration). PRE-CODE — Phase 0 scaffolding
landed (commit `6e0d102`, 40 files / 3000 LOC of structure).
All 26 ADRs locked. On mgf-common 0.33 + mgf-http 0.2.
Five-layer architecture with import-linter contracts (PySide6 /
subprocess / httpx / click isolation). Concrete needs in
`STARTHERE.md`: resumable SHA1-verified IPSW download,
systemd-timer SHSH blob saves, guided DFU walkthrough,
redacted diagnostic doctor bundle. **GREENFIELD consumer —
no legacy to migrate. Federation surface needs:** resumable
download (mgf-http), walkthrough/wizard primitive (mgf-common),
doctor bundle primitive (mgf-common).

---

## §4 New insights from consumer evidence

Things I would NOT have proposed without looking at the consumers:

### §4.1 Three-consumer scheduler signal

**vm-vmanager-app** uses `croniter` for periodic VM-snapshot rollups.
**iosRecovery** plans a systemd timer for nightly SHSH-blob
saves. **PlasmaMapper** uses arq for cron-shape recurring
jobs. Three different backends; same shape. **A
`mgf.common.schedule.Scheduler` protocol + cron-expression
parser** is high-confidence shippable.

### §4.2 Two-consumer resumable-download signal

**iosRecovery** downloads IPSW firmware files (gigabyte-scale,
SHA1-verified, resumable) — explicitly called out in
`STARTHERE.md`. **vm-vmanager-app** likely needs the same shape for
VM image downloads. mgf-http already wraps httpx; adding a
`AsyncHttpClient.download(url, dest, *, expected_sha=None,
resume=True)` is incremental.

### §4.3 Plugin auto-discovery unblocked

**PlasmaMapper's TelematicsProvider** is the second-consumer
evidence that PAPER-10 (entry-points-based plugin discovery)
needed. Teltonika ships now; Queclink + Ruptela queued. Without
a federation primitive, PlasmaMapper hand-rolls. **Promote
PAPER-10 from DEFERRED.**

### §4.4 inthewords' "parallel implementation" friction is real

Inthewords adopted mgf-common AFTER building its own
`apps/core/exceptions.py` + `apps/core/logging.py`. The
adoption tracker documents the struggle: re-base on mgf-common
where it fits; ship documented non-adoption where it doesn't.
**This validates the ASPIRE-04 "documented non-adoption" pattern
already in the standards.** Future onboarding docs should
amplify this — "if you have an existing implementation, here's
how to migrate or non-adopt cleanly."

### §4.5 PlasmaMapper's ~250 LOC reduction is the marquee case study

PlasmaMapper's `MGF_ADOPTION.md` documents ~250 LOC saved by
adopting three federation primitives (HmacWebhookVerifier +
IpAllowlist + run_test_app). **This is the canonical
"why ship a primitive" justification** — it's not aesthetic,
it's measurable. Future primitives should target similar
multi-consumer reduction.

### §4.6 iosRecovery as the canary

iosRecovery is PRE-CODE. New mgf-common primitives can ship
with iosRecovery as the first adopter, zero legacy to migrate.
Pattern: feature flags, resumable download, walkthrough,
doctor bundle — all of these have iosRecovery waiting as the
greenfield consumer. **iosRecovery is the federation's perfect
first-adopter canary.**

### §4.7 inthewords pin is stale (0.31 vs 0.34)

Inthewords is THREE minors behind on mgf-common. Either there's
upgrade friction we haven't filed (paper opportunity) or it's
just been deprioritised. Worth a quick check before v1.0 cut —
if there's friction, that's a paper that needs filing.

### §4.8 Consumer-side standard libraries

Both inthewords and PlasmaMapper ship docs they reference
across the federation:
- `inthewords/docs/standards/web/mypy-stubs-workarounds.md` —
  10 patterns for stubs gaps; PlasmaMapper cites as prior art.
- `inthewords/docs/CONSUMER_FACTS.md` — flat key-value snapshot
  shape; PlasmaMapper mirrors.
- `PlasmaMapper/docs/inprogress/MGF_ADOPTION.md` — adoption
  tracker pattern; inthewords mirrors.

**Federation observation:** consumers are building shared
*docs* patterns. Worth a recipe in mgf-common
`docs/recipes/consumer-adoption-tracker-shape.md`.

---

## §5 Updated mgf-common candidates

Sorted by **evidence-backed ROI** = `(Risk + Complexity + Commonness)
× Stability ÷ Effort`, with a Consumer-signal column that names the
real consumers driving each candidate.

| # | Feature | Risk | Cplx | Comm | Effort | Stab | ROI | Consumer signal |
|---|---|--:|--:|--:|---|--:|--:|---|
| **C-1** | **Feature flags** — `FeatureFlag` protocol + env-var default + audit emission | 5 | 5 | 4 | S | 5 | **70** | inthewords (manual env-var-based today), PlasmaMapper (would adopt) |
| **C-NEW-1** | **Scheduler protocol** — cron-expression parser + `Scheduler` protocol; in-process default | 4 | 4 | 5 | S | 5 | **65** | vm-vmanager-app (croniter), iosRecovery (systemd timer), PlasmaMapper (arq cron) — **three-consumer signal** |
| **C-2** | **Rate-limit primitive** — TokenBucket + LeakyBucket | 5 | 4 | 4 | S | 5 | **65** | inthewords (django_ratelimit today), PlasmaMapper (will need) |
| **C-NEW-2** | **Plugin auto-discovery (PAPER-10)** — entry-points-based; gated to known groups | 3 | 5 | 3 | S | 4 | **55** | PlasmaMapper (TelematicsProvider — Teltonika now, Queclink + Ruptela queued) |
| **C-3** | **Idempotency-key store** — `IdempotencyStore` protocol | 5 | 4 | 3 | S | 5 | **55** | PlasmaMapper (webhook + payment-shape work), inthewords (room-creation idempotency) |
| **C-4** | **Health-check primitive** — `HealthCheck` enum + component-level check protocol | 5 | 3 | 3 | XS | 5 | **55** | PlasmaMapper (already hand-rolling `/health`), inthewords (deploy script needs) |
| **C-5** | **Cache abstraction** — `Cache` protocol + LRUCache default + NullCache | 4 | 5 | 4 | M | 4 | **52** | PlasmaMapper (Redis), inthewords (Django cache) |
| **C-NEW-3** | **Doctor-bundle primitive** — promote `mgf-fed app-doctor` to reusable `DoctorBundle` API | 3 | 4 | 4 | S | 5 | **45** | vm-vmanager-app (existing pattern), iosRecovery (Fig Recovery doctor bundle planned) |
| **C-NEW-4** | **Walkthrough / wizard primitive** — Rich-based prompts + persistent state + resume | 3 | 4 | 3 | M | 4 | **40** | iosRecovery (DFU walkthrough), vm-vmanager-app (first-run wizard) |
| **C-8** | **Circuit-breaker primitive** | 4 | 3 | 3 | S | 5 | **40** | PlasmaMapper (vendor APIs), inthewords (3rd-party calls) |
| **C-NEW-5** | **i18n / locale primitive** — string catalogue + locale-aware formatters | 4 | 4 | 2 | M | 4 | **35** | PlasmaMapper UX-09/10/11 (i18n placeholders + locale formatters) — **one-consumer only; defer until 2nd evidence** |
| **C-9** | **Distributed-lock primitive** | 3 | 3 | 2 | S | 5 | **35** | PlasmaMapper (multi-replica), inthewords (Celery beat lock) |
| **C-10** | **Background-task protocol** — TaskQueue protocol + inline default; NO backend lock-in | 4 | 5 | 3 | M | 4 | **35** | PlasmaMapper (arq), inthewords (Celery) — **two backends; protocol-only ship** |
| **C-NEW-6** | **JWT verification helper** — pyjwt-shaped + JWKS-rotation-aware | 3 | 3 | 2 | S | 4 | **32** | PlasmaMapper (Clerk JWT), inthewords (potentially via allauth) |
| **C-6** | **Email-send protocol** — DEMOTED | 3 | 3 | 2 | M | 4 | **24** | inthewords (Resend wiring); PlasmaMapper not yet — **one-consumer; defer** |
| **C-7** | **File-storage protocol** — DEMOTED | 3 | 3 | 1 | M | 4 | **20** | inthewords (S3 via boto3+django-storages only) — **one-consumer; defer** |
| **C-11** | **PII annotation primitive** — `Annotated[str, PII("email")]` | 3 | 3 | 2 | M | 3 | **20** | Speculative; defer |

### Top picks for mgf-common
1. **C-1 feature flags** — universal need; small protocol.
2. **C-NEW-1 scheduler protocol** — three-consumer signal; small.
3. **C-NEW-2 plugin auto-discovery (PAPER-10)** — finally unblocked by PlasmaMapper evidence.

---

## §6 Updated sibling candidates

### §6.1 mgf-fastapi

| # | Feature | Consumer signal | Note |
|---|---|---|---|
| **F-1** | Rate-limit middleware (wires C-2) | PlasmaMapper | Highest sibling-side ROI. |
| **F-3** | Idempotency-key middleware (wires C-3) | PlasmaMapper | Stripe-shaped contract. |
| **F-NEW-1** | **arq integration helpers** — `bootstrap` ↔ arq worker lifecycle, `BackgroundTaskProtocol` impl backed by arq | PlasmaMapper | Concrete evidence; arq is the production backend. |
| **F-NEW-2** | **JWT verification dependency** — `Depends(verify_jwt(...))` wired to C-NEW-6 | PlasmaMapper (Clerk) | Pairs with the mgf-common primitive. |
| **F-2** | Pagination helpers | (no immediate signal) | Defer until consumer asks. |
| **F-4** | Response cache decorator | PlasmaMapper (Redis cache) | Wires C-5. |
| **F-5** | Body-size limit middleware | PlasmaMapper | XS effort. |

**Top pick:** **F-1 rate-limit middleware** + **F-NEW-1 arq
integration**. Both target PlasmaMapper directly; both wire
federation primitives.

### §6.2 mgf-django

| # | Feature | Consumer signal | Note |
|---|---|---|---|
| **D-1** | Login throttle / brute-force protection (wires C-2) | inthewords | django-axes-shaped; replaces django_ratelimit selectively. |
| **D-NEW-1** | **Celery integration helpers** — `bootstrap` ↔ Celery worker, periodic tasks via C-NEW-1 scheduler | inthewords | Concrete production usage. |
| **D-NEW-2** | **django-channels (WebSocket) helpers** — request-id propagation across WS frames, audit-log middleware | inthewords | Channels is in their dep tree; standard adapter would help. |
| **D-NEW-3** | **allauth integration helpers** — `bootstrap` ↔ allauth signals + audit-log emission on login/logout/signup | inthewords (OAuth via allauth) | Common pattern; small. |
| **D-2** | Async-capable middleware variants (re-opens RA-05 deferral) | inthewords (future async views) | Worth doing pre-v1.0. |
| **D-3** | Feature-flag template tag (wires C-1) | inthewords | XS; ships when C-1 ships. |
| **D-5** | Django `check` framework integration | inthewords (catches misconfig early) | XS. |

**Top pick:** **D-1 brute-force throttle** + **D-NEW-1 Celery
integration**. Both target inthewords directly.

### §6.3 mgf-sqlalchemy

| # | Feature | Consumer signal | Note |
|---|---|---|---|
| **S-1** | **Audit-trail mixin** — `created_at`/`updated_at`/`deleted_at`/`created_by_id`/`updated_by_id` | PlasmaMapper + inthewords | Universal data-layer need. |
| **S-3** | UUID v7 primary key helper | PlasmaMapper (new), inthewords (new models) | XS; pairs with S-1 in one release. |
| **S-2** | Soft-delete mixin | PlasmaMapper, inthewords | Common pattern. |
| **S-4** | **Outbox table + dispatcher** (pairs with C-10) | PlasmaMapper (event-driven) | Reliable post-commit messaging. |
| **S-NEW-1** | **Per-tenant migration scaffolding (multi-schema)** — pairs with `tenant_session` | PlasmaMapper (multi-tenant SaaS) | Closes a gap in their stack. |

**Top pick:** **S-1 + S-3 paired** as one release (audit mixin
+ UUIDv7). Universal benefit, low risk.

### §6.4 mgf-alembic

| # | Feature | Consumer signal | Note |
|---|---|---|---|
| **A-1** | Migration drift detector | PlasmaMapper, inthewords | CI-friendly; catches model-vs-DB drift. |
| **A-2** | Online migration helpers (`SET lock_timeout`, `CREATE INDEX CONCURRENTLY`) | PlasmaMapper (Iraq go-live; downtime-sensitive) | Real production risk reducer. |
| **S-NEW-1** | Per-tenant migration helpers — listed under mgf-sqlalchemy above but split-point negotiable | PlasmaMapper | Could live in mgf-alembic instead. |

**Top pick:** **A-1 drift detector** — universal benefit; CI-shape.

### §6.5 mgf-http

| # | Feature | Consumer signal | Note |
|---|---|---|---|
| **H-NEW-1** | **Resumable + integrity-checked download** — `AsyncHttpClient.download(url, dest, *, expected_sha=None, expected_size=None, resume=True)` | iosRecovery (IPSW, SHA1), vm-vmanager-app (VM images) | **NEW high-ROI; two-consumer signal**. |
| **H-1** | Circuit-breaker integration (wires C-8) | PlasmaMapper (vendor APIs) | Completes the resilience triple. |
| **H-2** | Idempotency-key on POST (wires C-3) | PlasmaMapper | Auto-attach on retried POSTs. |
| **H-3** | Cassette/replay mode | All web consumers | vcrpy/respx alternatives exist; lower priority. |

**Top pick:** **H-NEW-1 resumable download** — concrete
two-consumer need; medium effort; clear shape.

### §6.6 mgf-apiprobe

| # | Feature | Consumer signal | Note |
|---|---|---|---|
| **P-1** | Missing security-header checks (CSP / Referrer-Policy / Permissions-Policy) — closes deferred SH-05 | PlasmaMapper (web security audit), inthewords | Concrete federation gap. |
| **P-2** | Contract drift detection | PlasmaMapper (OpenAPI surface) | Catches accidental API breaks. |

**Top pick:** **P-1** — closes the deferred SH-05; valuable for
both web consumers.

### §6.7 mgf-website-template

No new evidence; the template is in good shape. Nice-to-haves
(analytics-respect-DNT, RSS, newsletter-signup) remain
post-v1.0 ideas.

---

## §7 Deliberately NOT recommended

Same as [`pre_release_check.md`](pre_release_check.md) §3.3, plus:

| Idea | Why not now |
|---|---|
| **Single background-task backend adapter** | Confirmed by evidence — PlasmaMapper (arq) ≠ inthewords (Celery). Protocol-only is right; don't pick. |
| **Email-send adapter** | Only inthewords has Resend wiring today. Wait for 2-consumer signal. |
| **S3 / file-storage adapter** | Only inthewords (boto3 + django-storages). Wait. |
| **Custom OAuth / SSO library** | inthewords has allauth; PlasmaMapper has Clerk. Different shapes; consumer wires their provider. |
| **WebSocket framework** | Only inthewords has channels. Ship a Django-Channels integration helper (D-NEW-2) instead of a framework. |

---

## §8 Phasing — revised plan

### Wave 1 — mgf-common primitives (3 protocols)
Ship in mgf-common 0.35.0 → 0.36.0 (one MINOR per item to keep
each release focused):

- **0.35.0**: C-1 (feature flags) + C-NEW-1 (scheduler protocol).
  Both small, evidence-backed, ship together for "one quality
  release" feel.
- **0.36.0**: C-NEW-2 (plugin auto-discovery / PAPER-10) +
  C-NEW-3 (doctor-bundle primitive). Unblocks PlasmaMapper +
  iosRecovery.

### Wave 2 — sibling-side consumption + a high-ROI new primitive
Per sibling, ship the highest-evidence feature:

- **mgf-http 0.4.0**: H-NEW-1 resumable download (iosRecovery
  unblock).
- **mgf-sqlalchemy 0.4.0**: S-1 audit-trail + S-3 UUIDv7
  (PlasmaMapper + inthewords).
- **mgf-fastapi 0.6.0**: F-1 rate-limit + F-NEW-1 arq
  integration (PlasmaMapper).
- **mgf-django 0.4.0**: D-1 throttle + D-NEW-1 Celery integration
  (inthewords).
- **mgf-alembic 0.4.0**: A-1 drift detector.
- **mgf-apiprobe 0.5.0**: P-1 security-header checks (closes
  SH-05).

### Wave 3 — second-tier mgf-common primitives
- C-2 rate-limit primitive (already wired in F-1 / D-1 — just
  formalises the protocol).
- C-3 idempotency-key store.
- C-4 health-check primitive.
- C-5 cache abstraction.

### Wave 4 — convergence on v1.0
Re-audit which experimentals can promote to `stable` per AP-09.
Cut v1.0.

---

## §9 Cross-cutting observations

### §9.1 iosRecovery as canary consumer

iosRecovery is pre-code. Every new mgf-common primitive can be
written WITH iosRecovery's adoption in mind. Feature flags,
resumable download, walkthrough — all of these target iosRecovery
directly. The federation should think of iosRecovery as the
"design-with-this-consumer-from-day-one" project.

### §9.2 Consumer-side patterns worth a federation recipe

- **`MGF_ADOPTION.md` tracker shape** — PlasmaMapper opened
  it; inthewords mirrored. Worth a federation recipe in
  `mgf-common/docs/recipes/consumer-adoption-tracker.md`.
- **`mypy-stubs-workarounds.md` pattern** — inthewords shipped
  first; PlasmaMapper cites as prior art. Worth promoting to
  `mgf-common/docs/standards/web/mypy-stubs.md` (live under
  ASPIRE-03's web subtree).
- **`CONSUMER_FACTS.md` flat-key-value snapshot** — both
  consumers maintain one. Worth a federation recipe.

### §9.3 inthewords pin is stale

Inthewords is on mgf-common 0.31 — three minors behind. Either
upgrade friction we haven't filed OR deprioritisation. Worth
asking the maintainer (yourself) before v1.0. If there's
friction, that's a paper to file.

### §9.4 PlasmaMapper's ROI proof point

PlasmaMapper documented ~250 LOC saved by adopting three v0.27
primitives (HmacWebhookVerifier + IpAllowlist + run_test_app).
**This is the canonical case study.** Future primitives should
target similar multi-consumer reduction. When a primitive
proposal can't show "what does this replace in 2+ consumers,"
it's a sign to defer.

---

## §10 Suggested next step

**If you agree with the direction:**
1. File each Wave-1 candidate as a FEEDBACK paper
   (`PAPER-35` feature flags, `PAPER-36` scheduler,
   `PAPER-37` plugin auto-discovery — replaces the existing
   PAPER-10 entry, `PAPER-38` doctor-bundle primitive).
2. Open trackers in `docs/inprogress/`:
   - `FEATURES_WAVE_1.md` for the mgf-common primitives.
   - Similar in each sibling that's ready.
3. When you say "go", start with C-1 (feature flags) — XS-S
   effort, one focused session.

**If you want to adjust:**
- Tell me which axes I weighted wrong.
- Tell me about consumers I don't know about (anything beyond
  the four).
- Reorder the wave plan.

**Alternative path — finish v1.0 first:**
- Phase 4 in [`pre_release_check.md`](pre_release_check.md) is
  still partial (mgf-alembic awaiting PyPI token; mgf-sqlalchemy
  / mgf-fastapi / mgf-django still pending). Once the private
  PyPI index is up, finish those releases first, THEN start
  Wave 1 cleanly. This is the conservative path.

---

## §11 Retrospective log

| Date | Event |
|---|---|
| 2026-05-17 | Document created. First evidence-backed feature roadmap; promotes PAPER-10 (plugin auto-discovery) and resumable-download from "deferred" to Wave 1 + Wave 2 based on new consumer evidence (PlasmaMapper TelematicsProvider; iosRecovery IPSW download + vm-vmanager-app VM images). |
| 2026-05-18 | **Waves 1–3 SHIPPED.** Closes C-1 / C-NEW-1..3 / H-NEW-1 / S-1 / S-3 / F-1 / D-1 / A-1 / P-1 / C-2 / C-3 / C-4 / C-5 across mgf-common 0.34→0.37 + six sibling minors. 13 new public modules; 2885-test green federation suite. See `release_waves_plan.md` §6–§9 for the per-wave changelog. **Wave 4 audit complete** — see `v1_0_stability_audit.md` + `v1_0_quality_gates.md` for v1.0-readiness verdict and remaining blockers (Q-2 N818 decision, Q-4 PyPI backlog drain, Q-11 promotion sign-off). |

---

## §12 Wave 1–3 outcome scorecard (consumer-evidence verification)

For each evidence-backed candidate in this document, did the shipped feature
match the consumer signal? Closes the loop between "roadmap proposal" and
"v1.0-ready surface."

| Candidate | Status | Notes |
|---|---|---|
| **C-1** feature flags | ✅ Shipped v0.35.0 | `mgf.common.flags` (6 names); env-var-driven default backend matches the pattern every consumer was rolling. |
| **C-NEW-1** scheduler | ✅ Shipped v0.35.0 | `mgf.common.schedule` (7 names); stdlib cron + InProcessScheduler. |
| **C-NEW-2** plugin auto-discovery | ✅ Shipped v0.36.0 | `mgf.common.plugins` (3 names); closes PAPER-10. Protocol filtering + audit emission. |
| **C-NEW-3** doctor bundle | ✅ Shipped v0.36.0 | `mgf.common.doctor` (6 names); atomic 0o600 write per SC-13. |
| **H-NEW-1** resumable download | ✅ Shipped mgf-http v0.4.0 | `download(...)` with sha256 + Range support; closes iosRecovery + vm-vmanager-app pain. |
| **S-1** audit-trail mixin | ✅ Shipped mgf-sqlalchemy v0.4.0 | `AuditTrailMixin` + `set_audit_user` (contextvars-based). |
| **S-3** UUID v7 | ✅ Shipped mgf-sqlalchemy v0.4.0 | `uuid7()` + `uuid7_pk_column()`; draft-rfc4122bis §5.7. |
| **F-1** rate-limit middleware | ✅ Shipped mgf-fastapi v0.6.0 | `RateLimitMiddleware` + TokenBucket; 429 + Retry-After. |
| **D-1** throttle middleware | ✅ Shipped mgf-django v0.4.0 | `ThrottleMiddleware`; settings-driven; sensitive-path defaults. |
| **A-1** drift detector | ✅ Shipped mgf-alembic v0.4.0 | `detect_drift(...)`; categorises missing tables/columns/types. |
| **P-1** security headers checks | ✅ Shipped mgf-apiprobe v0.5.0 | 4 new check classes (CSP / Referrer / Permissions / Cookie attrs). |
| **C-2** rate-limit protocol | ✅ Shipped v0.37.0 | `mgf.common.rate_limit` (2 names); siblings rebase next minor. |
| **C-3** idempotency store | ✅ Shipped v0.37.0 | `mgf.common.idempotency` (4 names); 24h TTL Stripe convention. |
| **C-4** health protocol | ✅ Shipped v0.37.0 | `mgf.common.health` (7 names); liveness/readiness routing. |
| **C-5** cache protocol | ✅ Shipped v0.37.0 | `mgf.common.cache` (4 names); LRU + TTL. |
| Other Wave-1 + Wave-3 candidates | Not shipped this cycle | Parked for v1.x — webhook audit, request-id correlation, …; tracked in `extraction_watch_list` memory. |

**Net surface delta:** +50 public names across the federation, 0 deprecated,
0 breaking changes to pre-0.34 contracts. The roadmap-to-ship ratio is
**15 of 15 selected candidates** delivered.
