+```
+
+### Anti-Patterns to Avoid
+- **Writing temp files and not cleaning up:** Always use `try/finally: shutil.rmtree(tmpdir)` — unhandled exceptions skip cleanup
+- **Including all files in inner ZIP including uninstall/detect:** build_intunewin() packages everything in tmpdir; if uninstall.ps1 should be separate, do NOT put it in tmpdir — it becomes part of the .intunewin payload, which is fine for Intune (it uses SetupFile="install.ps1" as the entry point)
+- **Using os.path.join with driver SHA256 directly:** SHA256 is 64 hex chars — safe as a filename but must use `cfg.DRIVERS_DIR` dynamically (monkeypatch pattern from Phase 2)
+- **Reading ICONS_DIR as a module-level constant:** Same pattern as DRIVERS_DIR — read `cfg.DATA_DIR` at call time, not import time, so tests can monkeypatch
+
+---
+
+## Don't Hand-Roll
+
+| Problem | Don't Build | Use Instead | Why |
+|---------|-------------|-------------|-----|
+| AES-256-CBC encryption | Custom crypto | `pycryptodome` (already installed) | Padding oracle attacks, IV reuse bugs |
+| ZIP assembly | Custom byte writer | `zipfile.ZipFile` + `io.BytesIO` | ZIP format edge cases (compression flags, CRC, central directory) |
+| PNG format detection + dimensions | Manual byte parsing | Pillow `Image.open()` | PNG IHDR chunk parsing is 20 lines of struct code that breaks on edge cases |
+| Filename sanitization in ZIPs | Custom strip | Explicit allowlist + `replace()` | Zip-slip paths (`../` prefix) — already handled in drivers.py |
+
+**Key insight:** The hard crypto work (intunewin format) is already done. Phase 5 is assembly and routing only.
+
+---
+
+## Common Pitfalls
+
+### Pitfall 1: Temp Directory Leaking on Exception
+**What goes wrong:** `tempfile.mkdtemp()` creates a directory that persists if an exception is raised before `shutil.rmtree()`
+**Why it happens:** Any error in script rendering, driver extraction, or `build_intunewin()` bypasses cleanup
+**How to avoid:** Always wrap in `try/finally` block; alternatively use `tempfile.TemporaryDirectory()` as a context manager (auto-cleanup on `__exit__`)
+**Warning signs:** `/tmp` fills up with `tmp*` directories after repeated export calls
+
+### Pitfall 2: build_intunewin() Includes Unexpected Files
+**What goes wrong:** `build_intunewin()` walks the entire `source_dir` recursively — any extra file added to tmpdir ends up in the package
+**Why it happens:** The function design is "pack everything in this directory"
+**How to avoid:** Only write `install.ps1`, `detect.ps1`, `uninstall.ps1`, and `drivers/` into tmpdir; if icon is embedded in the .intunewin, add it as a known filename (e.g., `icon.png`) at tmpdir root
+
+### Pitfall 3: driver.sha256 File Not Found
+**What goes wrong:** Driver file on disk was deleted but ORM record remains, causing `FileNotFoundError` during export
+**Why it happens:** No referential integrity between ORM and filesystem
+**How to avoid:** Check `Path(cfg.DRIVERS_DIR, driver.sha256).exists()` before proceeding; return HTTP 422 with descriptive message
+
+### Pitfall 4: Icon Model Unique Constraint Violation
+**What goes wrong:** `Icon` model has `unique=True` on the `printer` ForeignKey — second upload raises `IntegrityError`
+**Why it happens:** `Icon.create()` called without checking/deleting existing record
+**How to avoid:** Use `Icon.get_or_none(Icon.printer == printer_id)` then `.delete_instance()` before `Icon.create()`, or use `INSERT OR REPLACE` via Peewee's `replace()` method
+
+### Pitfall 5: driver_desc JSON Parse Failure in Export Endpoint
+**What goes wrong:** `driver.driver_desc` contains malformed JSON or None
+**Why it happens:** Edge case — driver was saved without running INF parsing
+**How to avoid:** Reuse `_get_printer_and_driver()` helper from `scripts.py` — it already handles this with HTTP 422 responses
+
+### Pitfall 6: .intunewin Not Accepted by Intune Tenant
+**What goes wrong:** Real Intune upload rejects the package despite passing all unit tests
+**Why it happens:** The byte-level format was reverse-engineered from community documentation (svrooij.io), not from Microsoft's official spec
+**How to avoid:** Manual validation gate — upload a test `.intunewin` to a real Intune tenant before Phase 5 is marked complete (documented as Phase 5 blocker in STATE.md)
+
+### Pitfall 7: Alpine.js Clipboard on HTTP (non-HTTPS)
+**What goes wrong:** `navigator.clipboard.writeText()` throws `NotAllowedError` in some browsers when page is served over plain HTTP
+**Why it happens:** Clipboard API requires secure context (HTTPS or localhost) in modern browsers
+**How to avoid:** This tool runs on internal network, typically accessed via IP address. Provide a fallback: show the command text in a `