Unknown origins get **403 with no `Access-Control-Allow-Origin`**, for OPTIONS too. Requests with **no Origin** (curl, Node scripts) are allowed but still need the token for anything that changes state. 5. **Host guard.** The Host header must be `127.0.0.1[:port]` or `localhost[:port]`. That's the DNS-rebinding defense. 6. **Body cap: 8 MiB.** `docs/app.html` is about 2.94 MB, and `/code/write` must still carry it. Over the cap the bridge drains the rest and answers 413. Bad JSON gets 400 now (today it silently becomes `{}`). 7. **No shell.** - git: `execFileSync('git', ['add','--', ...rels])`, `['commit','-m', message]`, `['rev-parse','HEAD']`. - grep: `execFileSync('grep', [..., '-e', query, '--', rel])`. - smoke: `spawnSync(process.execPath, ['tests/smoke.js'])`. ## Exact source excerpt, characters 10286–10717 The `--` separators stop a file named `-x` from becoming a flag. 8. **Path lock (`lockedPath`).** It refuses: - control characters (400); - absolute paths (403); - anything outside the realpath of the project root, compared with `path.relative` rather than `startsWith` (403); - `.git/`, `.ssh/` and `.env*` (403); - any path whose nearest existing ancestor realpaths outside the root, i.e. symlink escapes (403). ## Exact source excerpt, characters 10719–11939 The old `safePath` stays as a thin wrapper, so old callers keep working. 9. **Commit ledger.** `~/.freelattice/bridge-ledger.jsonl`, append-only, fixed key order. Fields: `ts, kind, route, origin, agent(8), result, filesCount, filesSha256, messageSha256, commitSha, prev, self`, where `self = sha256(JSON of the other fields)`. It never holds message text or file content, matching the privacy discipline of `fl_searchLedger`. Refusals are logged too: `refused:origin`, `refused:token`, `refused:message`, `refused:files`, `refused:path:`, plus `pair` events. 10. **Two small heals that ride along:** - `/code/patch` uses a replacer function, so `$` in the replacement stays literal. - `/code/tree` skips symlinks. 11. **The bridge never pushes.** No push route exists, and this brick adds none. Autonomous Mode still only commits locally. The hourly cap is Brick 3. 12. **Browser note.** Chrome 142+ shows a one-time "local network access" prompt before a public site can reach loopback (https://developer.chrome.com/blog/local-network-access). That's good, and it's independent of this lock. Our lock still matters for Firefox and Safari, older Chrome, anyone who clicks Allow, and LAN reachability. ## Exact source excerpt, characters 11941–11952 ## 4. Files ## Exact source excerpt, characters 11954–13443 | File | Change | |---|---| | `tools/agent-bridge.js` | Layer blocks A-E below (about +310 lines, nothing removed except the superseded bodies of the lines named above) | | `docs/modules/agent-bridge-client.js` | **New** (`window.FLAgentBridge`) | | `docs/app.html` | One comment and one `