# 29 — the history layer is off `getOwnerHomeDir` The owner asked me to carry on, so `27`'s "tomorrow" became tonight. This is the change I said I would not make at this hour, made at this hour — review it accordingly, and I would rather you were slow about it than quick. ## What moved **`claude-sessions.ts` no longer knows how to invent a home.** `claudeHome(email)` is gone. Every transcript read now takes a `ChatIdentity { email, home }`, and the home arrives resolved from `resolveHomeDir(userId)`. The old line was `process.env.HOME_DIR ?? join(DATA_PATH, email, 'home')` — which discards its argument whenever `HOME_DIR` is set, i.e. always on a real install. So every read resolved to the owner's `~/.claude` regardless of who asked, and the comment above it asserted "single-user platform" as though that were a property rather than an assumption. Both halves travel together rather than one standing in for the other, because they are genuinely different: `general_chat_sessions` lives under `DATA_PATH/`, not under a home, so those paths stay email-derived. Collapsing them would have been the same class of mistake as `undefined` meaning "the owner". **`chat.ts` resolves the identity per request** (`chatIdentity`), and throws FORBIDDEN rather than falling back — same posture as `resolveTurnIdentity`, for the same reason. **`websocket.ts`'s `resolveCwd` takes a home rather than an email**, so `~` expands against the caller's own home. Its old comment — *"the server owner is the only account, absolute paths are theirs to use"* — is replaced with what is actually true now: an absolute path still passes through, and it is the kernel that decides what a member's turn can open, not a string check here. **Ordering worth checking:** identity is resolved *before* the cwd, because expanding `~` before knowing whose home it is would be exactly the bug this removes. That reordering also let me delete a second `resolveTurnIdentity` call that `25` had left further down the same function. **`agent-runner.ts`** passes `{ email, home: homeDir }` explicitly — it is an owner-only path, and I would rather it state that than inherit it. ## What I am least sure of 1. **`chatIdentity` throws where the old code could not fail.** Every `/chat` route now has a failure mode it did not have. Owner-only today, and `resolveHomeDir` returns `isOwner` from a positive check — but it is the kind of change that turns a database blip into a 403 on a screen that used to always load. 2. **`resolveBaseCwd` is exported.** I changed its parameter from email to home and followed the compiler; if anything outside this diff passes an email, `tsgo` would have caught it, but the *meaning* of a wrong-but- well-typed string would not be caught by anything. 3. **The regex pass.** I rewrote bare `email` references inside `chat.ts` mechanically and then repaired the damage by hand. `tsgo` is clean and 78 tests pass, but that is a weaker guarantee than usual for this file. `tsgo` clean, 78 tests, both gates up, `member` unreachable in production. ## What is left Nothing I can write blind. `deprovisionOsAccount` is still mine and still tomorrow's. A member signing in, the first member turn, and the gates are the owner's.