---
name: feedback_prod_config_inspect_before_change
description: "For prod server/IIS config changes — inspect the LIVE config first (runbook can be stale), then backup → apply → verify-on-live → THEN commit version-controlled"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: f9f0e3ed-a5c6-40ea-8bec-f67112be9957
---

When changing a **production server config** (IIS web.config, app pool, headers, routing), do NOT trust the runbook/docs for paths or current rules — they drift. **Inspect the live config first.**

**Concrete (S88 — SPA `index.html` no-cache hardening):**
- The `iis-deploy-runbook` documented `C:\inetpub\apps\SolutionErp\{Admin,User}` — **STALE** (that dir was empty). Real paths (via `appcmd list site /text:*`) = `C:\inetpub\solution-erp\{api,fe-admin,fe-user}`. The runbook also described `/api` + `/hubs` ARR-proxy rewrite rules that **don't exist** in the live web.config (the FE calls `api.solutions.com.vn` directly via CORS). Had I trusted the runbook, I'd have written to the wrong path / replicated wrong rules and broken routing.
- **Find truth, don't guess:** `appcmd list site /text:*` (physical paths) · `ssh … Get-Content web.config -Raw` (exact live rules) · `curl -I` (current headers) · `curl /deep-link` (does SPA fallback work today?).

**Safe sequence for a prod config change (do them in order):**
1. **Inspect** the live config exactly (the file I'll overwrite + how routing works today).
2. **Author** the new config replicating EVERY existing rule verbatim + the delta (a config file overwrite replaces the whole thing — miss a rule = break it).
3. **Backup** the live file (`Copy-Item web.config web.config.bak`).
4. **Apply to live** (base64-transfer over ssh avoids scp `C:` path + quoting issues; IIS hot-reloads web.config).
5. **Verify on the LIVE server** (headers + routing + http→https + no config-lock 500) BEFORE committing — restore from `.bak` if broken.
6. **THEN commit** the version-controlled copy (here: `fe-*/public/web.config` → Vite copies to `dist/` → deploy `Copy-Item -Force` ships it). Confirm `live-sha === committed-sha`.

**Deploy-interaction gotcha:** `deploy.yml` did `Remove-Item site\* -Exclude 'web.config'` — i.e. web.config was *manually managed* on the server, preserved across deploys, NOT from the build. Adding it to `public/` flips it to build-managed (Copy-Item -Force overwrites). Always check whether the deploy cleans/overlays before assuming a repo file reaches the server.

**Fix the doc too:** after discovering the drift, update the runbook (paths + actual rules) so the next session isn't misled. Related: [[feedback_multi_entity_create_self_committing_codegen]].
