# Web-domain standards subtree

> **Audience:** consumers building web applications and APIs on
> top of `mgf-common` — Django, FastAPI, Flask, Pyramid,
> aiohttp, plus DRF / Starlette / Channels / Celery as
> downstream concerns. The canonical topic docs in
> [`docs/standards/`](../) remain authoritative for cross-domain
> MUSTs; this subtree is the **narrative wrapper** that says
> "for a web consumer, here's how those rules land + here's
> the durable shape we've learned across two web consumers'
> adoption walks."

This subtree was opened in v0.20.0 as the first half of
[`ASPIRE-03`](../../../FEEDBACK.md). Approach A (incremental):
this README ships as the navigation page; per-recipe promotion
from cutover guides + scattered cross-doc sections trickles in
over subsequent releases. Each promotion lands as one focused PR
with a cross-link added here.

---

## Why a per-kind subtree

The canonical topic docs (`CONFIGURATION.md`, `LOGGING.md`,
`ERROR_HANDLING.md`, etc.) historically encoded the
CLI/desktop reference shape. Two web consumers
(`inthewords` Django + `PlasmaMapper` FastAPI) joined in
v0.18 / v0.19 and surfaced systematic friction: rules that
read as universal but encode VManager-shaped assumptions.

Three release rounds of carve-out work landed:

- **CONFIG-01** (v0.18.0) — `CONFIGURATION.md` §0a framework-
  native carve-out: CF-01 / CF-04 / CF-08 / CF-09 declared
  N/A for Django / Rails-equivalent consumers.
- **LOG-01** (v0.18.0) — `LOGGING.md` LG-06 cloud-native
  branch: stdout-only + ephemeral-filesystem deployments.
- **LOG-02** (v0.18.0) — per-rule `applies_to:` column on
  every LG-* rule + per-kind compliance matrix.
- **HTTP-01** (v0.18.0) — `HttpError` category in
  `mgf.common.exceptions` (12 names, all `experimental`).
- **PAPER-24** (v0.19.0) — the HTTP-01 keystone:
  `ExceptionTranslationMiddleware` reads `HttpError.http_status`
  automatically.
- **BOOTSTRAP-01** (v0.19.0) — Django adoption blocker, both
  parts: `MgfSettings` `.env` honours `env_prefix`;
  `bootstrap(setup_logging=False)` flag.

The carve-outs are scattered across topic-doc sub-sections.
A new web consumer reading `docs/standards/` end-to-end has
to mentally cross-reference. This subtree is the front door
that says "for a web consumer, read these recipes in this
order."

---

## Read-in-order for a new web consumer

If you're starting an mgf-common adoption from a fresh web
project:

1. **[`docs/standards/README.md`](../README.md)** — the master
   index. Skim the conformance levels (L0 / L1 / L2) and the
   index of MUSTs. Don't try to satisfy every MUST yet —
   subsequent steps tell you which apply to your shape.
2. **[`docs/standards/CONFIGURATION.md`](../CONFIGURATION.md)
   §0a** — framework-native carve-out. Read this BEFORE the
   per-CF-rule sections; it tells you which apply.
3. **[`framework-owned-logging.md`](#framework-owned-logging)**
   below — `bootstrap(setup_logging=False)` is the canonical
   shape when your framework owns logging. Read this next; it
   shapes every other adoption decision.
4. **[`docs/public/recipes/cloud-native-logging.md`](../../public/recipes/cloud-native-logging.md)**
   — if you deploy via container orchestrator (Kubernetes,
   Docker, Heroku, Cloud Run, Fly, etc.), this is the
   `LOGGING.md` LG-06 cloud-native branch + the JSON wire-shape
   guidance.
5. **[`docs/standards/ERROR_HANDLING.md`](../ERROR_HANDLING.md)**
   — read with HTTP-01 in mind. The `HttpError` hierarchy is
   the natural home for HTTP-domain exceptions; the canonical
   seven-category taxonomy is for systems-management consumers.
6. **[`docs/public/recipes/fastapi.md`](../../public/recipes/fastapi.md)**
   or **[`docs/public/recipes/django.md`](../../public/recipes/django.md)**
   — framework-specific wiring (the `ExceptionTranslationMiddleware`
   composition with `HttpError.http_status` lives here for
   FastAPI; the Django dispatcher wiring lives in the django
   recipe).
7. **[`docs/standards/principles/non-adoption-is-valid.md`](../principles/non-adoption-is-valid.md)**
   — the principle behind every carve-out. If a primitive's
   default behaviour conflicts with your deployment-coupled or
   policy-specific constraint, declining it WITH documented
   rationale is L1/L2 conformant. See the worked examples.

---

## Recipes index (cross-cutting; web-domain)

These live at their canonical path; the table below is the
"web consumer's-eye view." A recipe is referenced from this
subtree if a web consumer is likely to read it during adoption.

| Recipe | Path | Closes | What it covers |
|---|---|---|---|
| **Framework-owned logging** | [`docs/public/recipes/framework-owned-logging.md`](../../public/recipes/framework-owned-logging.md) | PAPER-25 | `bootstrap(setup_logging=False)` for Django / FastAPI / Flask / Pyramid. The full set of trade-offs you accept (no JSON wire shape, no `level_overrides`, no mgf-handler redaction) plus what's preserved (identity, OTel, excepthooks, AppContext, buffer replay). |
| **Cloud-native logging** | [`docs/public/recipes/cloud-native-logging.md`](../../public/recipes/cloud-native-logging.md) | LOG-01 | LG-06 cloud-native branch: stdout-only emission for container-orchestrated deployments. Pairs with the framework-owned-logging recipe when the framework's handlers are the ones writing to stdout. |
| **FastAPI integration** | [`docs/public/recipes/fastapi.md`](../../public/recipes/fastapi.md) | (multiple) | Wiring `mgf.common.fastapi.*` — `ExceptionTranslationMiddleware` + `RequestIdMiddleware` + the `setup_db` lifespan helper. Includes the post-PAPER-24 simplification: HTTP-01-rooted exceptions need no `status_map` entries. |
| **Django integration** | [`docs/public/recipes/django.md`](../../public/recipes/django.md) | (multiple) | Wiring `mgf.common.django.*` — `MgfCommonConfig` `AppConfig` + the settings bridge. Includes the post-BOOTSTRAP-01 pattern: shared `.env` + `setup_logging=False`. |
| **HTTP / web** | [`docs/public/recipes/http.md`](../../public/recipes/http.md) | HTTP-01, PAPER-24 | The `HttpError` hierarchy + the consumer-domain pattern (`MyDomainError(HttpNotFound, MyDomainBase)`) + middleware composition. |
| **Testing** | [`docs/public/recipes/testing.md`](../../public/recipes/testing.md) | PAPER-23 | Pytest plugin auto-registration + the editable-install caveat (`uv sync` from `[tool.uv.sources]`). |

---

## Per-rule applicability for web consumers

The canonical topic docs use the `applies_to:` column
introduced in v0.18.0 (LOG-02). For a web consumer the
relevant slice is:

| Topic doc | What applies | What's N/A or carved-out |
|---|---|---|
| `DESIGN_PRINCIPLES.md` | All MUSTs apply. The 5-layer architectural map is illustrative for desktop/CLI; web consumers map cleanly to the 3-layer (views → services → models) shape without a carve-out. |
| `ERROR_HANDLING.md` | `AppError` taxonomy applies. Use the `HttpError` hierarchy (HTTP-01, v0.18.0) for HTTP-domain exceptions; the seven-category EH-* taxonomy is for systems-management. |
| `LOGGING.md` | LG-01 / LG-02 / LG-03 / LG-04 / LG-05 apply universally. **LG-06**: cloud-native branch for container-orchestrated; rotating-file branch for desktop/single-server. **LG-07** (GUI log viewer): N/A. |
| `CONFIGURATION.md` | CF-02 / CF-05 / CF-10 / CF-12 apply universally. **CF-01 / CF-04 / CF-08 / CF-09**: N/A under framework-native (Django settings module IS the singleton — and that's correct; per CONFIG-01). |
| `TESTING.md` | All apply. Use `mgf.common.pytest_plugin` (PAPER-23 editable-install caveat noted). |
| `RELEASING.md` | Applies for libraries; web services typically deploy via Ansible / Docker rather than PyPI publish. The `[observability]` extra and `[fastapi]` / `[django]` extras still gate framework-specific dependencies. |

---

## Cross-references

- [`FEEDBACK.md`](../../../FEEDBACK.md) — the working canon of
  consumer entries. Web-relevant: ASPIRE-02 (second-consumer
  arrival framing), ASPIRE-03 (this subtree), CONFIG-01,
  LOG-01, LOG-02, HTTP-01, BOOTSTRAP-01, PAPER-22, PAPER-24,
  PAPER-25.
- [`docs/cutover/`](../../cutover/) — the per-release cutover
  guides where carve-out content first lands. Promotion to
  this subtree is the durable-content path.
- [`docs/standards/principles/non-adoption-is-valid.md`](../principles/non-adoption-is-valid.md)
  — the principle that lets a web consumer correctly decline a
  primitive when adopting it would violate a deployment-coupled
  or policy-specific constraint.

## Promotion roadmap (incremental)

This README ships first; per-recipe promotion is one PR each:

- [x] `web/README.md` — this file (v0.20.0)
- [x] `docs/public/recipes/framework-owned-logging.md` —
  PAPER-25 (v0.20.0)
- [ ] `web/http-exceptions.md` — promote PAPER-24 cutover-guide
  content + the consumer-pattern from `recipes/http.md`
  (future release)
- [ ] `web/framework-config.md` — promote `CONFIGURATION.md`
  §0a's inthewords worked example to a standalone recipe
  (future release)
- [ ] `web/stub-gaps.md` — the django-stubs/DRF/Channels/Celery
  workaround library (10 patterns from inthewords' Phase 2.5
  + FastAPI extensions as PlasmaMapper hits them; future
  release, contingent on inthewords' upstream contribution)
- [ ] `web/adoption-walk.md` — the canonical onboarding
  narrative (read-in-order list above expanded to a worked
  step-by-step; future release, after the per-recipe pieces
  exist)

Each entry above corresponds to a future small PR. Tracking
in [`FEEDBACK.md`](../../../FEEDBACK.md) ASPIRE-03's
**Retrospective** field as each promotion ships.
