[eric] docs: record hardening precedences (compaction trims, ssrf is async loopback-allowed, ports must be stable)

This commit is contained in:
eric
2026-05-31 18:13:06 -07:00
parent 3b42f608ad
commit 0ed5457ca2
2 changed files with 12 additions and 0 deletions
+7
View File
@@ -53,3 +53,10 @@ What runs under `bash backend/run.sh` is not what ships in the DMG/EXE. Test the
- Pinning matters; `requirements.txt` is fully pinned for reproducibility.
- Token middleware already scrubs bearer tokens from logs; don't re-add raw logging.
- MCP bundles in `mcp-bundles/` are esbuild output; regenerate via the bundle script rather than editing.
## Hardening precedences (learned the hard way)
- **Compaction must actually trim, not just mark.** `_build_history_prefix` honors `session.compacted_through_msg_id`; the auto path leaves the SDK session intact (preserves prompt cache, the ~70% aux-cost win), the manual `/compact` button sets `needs_fresh_session=True` because the user is opting in to the cache-loss tradeoff for a visible shrink. Never flatten to `User:/Assistant:` text and never throw away tool turns; the model loses fidelity if you do.
- **SSRF guard is async + multi-record.** `tools/ssrf_guard.py` uses `loop.getaddrinfo` (non-blocking, covers IPv4 + IPv6) and rejects if ANY resolved record is private. Loopback (`127/8`, `::1`) is intentionally ALLOWED because App Builder previews on `127.0.0.1:<random>`; the real desktop-app SSRF threat is cloud metadata (`169.254.169.254`) and corporate LAN, not localhost. Per-redirect re-validation via `safe_fetch`; never use `follow_redirects=True` directly in a fetch path that takes a user-supplied URL.
- **Inline-text attachments need a combined cap, not just per-file.** `prompt/attachments.py` tracks `text_total_chars` so a pile of `.txt` files can't silently blow the context window past the per-file 512KB. Picked 1.5M chars as a 1M-window-model-friendly default.
- **`ENABLE_TOOL_SEARCH=1` (not `auto`) on non-Anthropic paths.** Forces tool schemas to load on demand instead of upfront — saves ~9K first-message tokens. The CLI's `tengu_defer_all_bn4` Statsig flag still defers tools without the env set, so a non-Anthropic path without this loses tools entirely.
+5
View File
@@ -41,3 +41,8 @@ For any change touching paths, subprocess spawning, IPC, deep links, or the auto
- `build-staging/` is regenerated on every build; never commit it.
- Auto-updater reads the latest release feed from GitHub; staging/test builds should use a separate channel to avoid pushing unsigned bits to users.
## Hardening precedences (learned the hard way)
- **Renderer origin (port) must be stable across launches.** `localStorage` is keyed by full origin including port, so `server.listen(0)` (OS-assigned random port) was wiping onboarding state every restart and re-triggering the tour. Pin to a preferred port (currently `4173`), fall back to OS-assigned only if held. Same rule applies to any future renderer-side persisted state.
- **`webSecurity` stays on.** The file:// segfault was fixed by serving over `http://127.0.0.1:<port>`, NOT by disabling web security. Any future "let's just disable CSP" fix is wrong; find the underlying file:// quirk and route around it (loopback HTTP is the canonical workaround).