# Item 2 — ownership-boundary execution

> Item 2: *make every library's ownership boundary explicit and verified
> (grep-proven, not implied).* Scoping is in [`item2-ownership.md`](item2-ownership.md)
> + [`item2-boundaries.md`](item2-boundaries.md). This is the **execution** log.

## The mechanism (DONE) — `scripts/fleet_ownership_audit.py`

The boundary is now **verified, explicit, and drift-gated**:

- **Verified** — the audit AST-scans every repo's `src/`, builds the fleet-wide
  third-party import matrix, and computes each library's **sole-owned** deps
  (imported by *only* that repo), **shared** deps (>1 importer = a boundary
  question), and **federation deps** (the `mgf.*` siblings it pulls). Rigorous
  signal = imports; string-greps are triage only.
- **Explicit** — `item2-boundaries.md` states every python library's verified
  boundary stanza (the authoritative, regenerable source). `--inject` mirrors
  the same stanza into each repo's `SCOPE.md` between
  `<!-- BEGIN/END BOUNDARY -->` markers (idempotent).
- **Drift-gated (Item 3 seed)** — `fleet_ownership_audit.py --check` exits 1 if
  the committed central doc, OR any adopted `SCOPE.md` block, no longer matches
  live imports. The stanzas carry only module *names* (never counts), so the
  gate fires on a **real** boundary change (a new/lost sole-owner, a new shared
  dep, a new sibling import) — not on import-count noise. A not-yet-injected
  repo is a *note*, never a failure (opt-in adoption). Run it from any checkout
  of the full on-disk federation; it's a **fleet-level** gate (a single repo's
  CI can't see its siblings), so it lives with the audit, not in per-repo CI.

`mgf-cloud` carries the first landed in-repo block (bundled with F-B, #33) as
the reference example.

## Findings — verdicts + disposition

**F-B (mgf-cloud raw `fastapi`/`uvicorn` vs "via mgf-fastapi" claim) — RESOLVED as documentation drift (mgf-cloud #33).**
Not a real boundary violation: mgf-fastapi is deliberately *adapter-shaped*
(middleware/deps/webhooks — **no** app-factory or production `serve`), so a
web-GUI app *must* construct its own `FastAPI()` + run uvicorn (exactly like the
`mgf-logship` collector). mgf-cloud already has the correct posture — `[web]`
optional extra + import-linter `core-light` + it consumes `RequestIdMiddleware`.
The defect was **overstated prose** claiming "exception translation, lifespan"
adoption the code never used (only request-id). Corrected the 5 prose sites.

**F-SVIX (Svix HMAC verification duplicated) — ✅ SHIPPED in mgf-common 0.49** (`mgf.common.webhooks.verify_svix_hmac`, PAPER-26); auth + fastapi adopted it and deleted their duplicated crypto. [orig: REAL; scheduled into 0.49.]
The Svix HMAC dance is hand-rolled **3×** across 2 repos (`mgf-auth`
`clerk_webhook.py:91` + `mock.py:199`; `mgf-fastapi` `webhooks/_verifier.py:133`)
and has **already diverged 3 ways** (whitespace split RA-02, non-UTF-8 body
guard, `whsec_` handling) — concrete proof it's real, not benign. The naive
"mgf-fastapi calls mgf-auth (the owner)" is **blocked both ways** — they're
siblings (neither depends on the other) and mgf-auth's charter forbids importing
a web framework. The right fix is the long-noted **PAPER-26**: extract the pure
HMAC primitive (replay window + multi-version split + constant-time compare +
`whsec_` codec, stdlib-only) into **mgf-common** (`mgf.common.webhooks.verify_svix_hmac`),
and have all 3 sites delegate while keeping their own value-add (mgf-auth: the
`WebhookVerifier` seam + `whsec_`→`WebhookEvent`; mgf-fastapi: the FastAPI
transport adapter + body-cap/audit + `HmacVerificationError` per decision D3).
This needs a **mgf-common 0.49 minor** — **bundle it with the 3 mgf-fed
`_DEFERRED` private promotions** (`_identity`/`_lifecycle`/`_doctor_snapshot`)
already pending for the same minor, then one fleet pin-walk. Post-consolidation
boundary wording for common/auth/fastapi (and: mgf-http's 2 refs are benign
`Retry-After` prose — no change) is in the agent report / task #22.

## Legit shared-dep patterns (documented, NOT findings)

The audit's other MULTI-IMPORTER flags are **intentional** federation patterns,
recorded in the boundary stanzas as "Shared third-party (intentional)":
- `fastapi` — `mgf-fastapi` owns the adapter surface; `mgf-livepush` /
  `mgf-logship` / `mgf-cloud` legitimately build their own apps/integrations
  behind optional extras (core-light, import-linter-enforced). The rule is
  "mgf-fastapi owns the *adapters*, not every `FastAPI()`."
- `sqlalchemy` — `mgf-sqlalchemy` owns the wrapper; `mgf-alembic` (migrations
  intrinsically need it) + `mgf-fastapi` (a type import) are expected.
- `httpx` — `mgf-http` owns the client wrapper; `mgf-apiprobe` / `mgf-logship`
  shipping a thin direct use is acceptable (revisit if it grows).
- `defusedxml` — shared by `mgf-vm-interchange` + `mgf-vm-libvirt` (both parse
  untrusted libvirt/OVF XML; the safe-parser is a leaf util, not a wrapper-worthy
  boundary).

## Remaining (tracked)

1. **Per-repo `SCOPE.md` block fan-out** — `--inject` mirrors the central stanza
   into all 24 python `SCOPE.md`. **Deferred**: it's a 24-PR doc-only fan-out
   that re-incurs the Gitea PR-title rate-limit + the alembic/hrb heavy-pipeline
   CI wedge for marginal value over the authoritative central doc. Ready to run
   (`--inject` + the pin-walk-style engine, distinct titles) whenever wanted.
   The central `item2-boundaries.md` already makes every boundary explicit.
2. **F-SVIX consolidation** — execute with mgf-common 0.49 (task #22).
3. **SCOPE.md for the 10 non-python repos** (brand, cost-watch, website(-template),
   6 zig) — they have no third-party *import* boundary; they need a *functional*
   scope policy (closer to Item 1 doc work). Lightweight, deferred.
4. **Wire `--check` into a fleet-audit job** — the natural home is the same
   place the conformance audit runs (a checkout of the whole federation), which
   is the **Item 3** doc↔code drift-sync mechanism. `--check` is its first
   concrete gate.
