Summary
SessionManager.resumeSessions() walks transcriptStore.loadAllMeta()
and constructs a Session for each persisted meta file with no
upper bound and no per-session timeout. A corrupt transcript dir, a
bunch of huge transcripts, or a stuck restoreScrollback can block
daemon startup indefinitely or OOM the process before it gets to
listen.
Why it matters
- The daemon currently starts up by serially constructing a Session
per meta file, loading its full JSONL transcript into memory.
- A handful of multi-MB transcripts is fine; a few hundred is not.
- A bad meta file that throws during
loadTranscript is caught by
the outer try/catch (good) but a meta file that produces a
malformed transcript that crashes inside restoreScrollback
isn't well-bounded.
- More urgently: there's no
MAX_SESSIONS_TO_RESUME ceiling, so an
attacker (or just a runaway dev session) leaving 10 k transcript
files in ~/.codeoid/transcripts/ makes startup unusable.
Proposed fix
- Add
RESUME_MAX_COUNT (default 100) — only resume the N most-
recently-active sessions; archive the rest in place (no delete,
user can /import them back).
- Add a per-session deadline (
AbortSignal.timeout(2000)?) around
the loadTranscript + restoreScrollback pair so a single bad
file can't stall the boot.
- Surface a startup info-log: "resumed N of M sessions; M-N
archived".
- Bonus: parallelise resumes (Promise.all over the kept set) since
they're independent — current serial loop is unnecessarily slow
even on healthy data.
Source pointers
src/daemon/session-manager.ts:72-110
Severity
P1 for production; P2 for single-user dev. Worth landing before any
multi-tenant deploy. Surfaced in the 2026-05-08 daemon audit.
🤖 Generated with Claude Code
Summary
SessionManager.resumeSessions()walkstranscriptStore.loadAllMeta()and constructs a
Sessionfor each persisted meta file with noupper bound and no per-session timeout. A corrupt transcript dir, a
bunch of huge transcripts, or a stuck
restoreScrollbackcan blockdaemon startup indefinitely or OOM the process before it gets to
listen.Why it matters
per meta file, loading its full JSONL transcript into memory.
loadTranscriptis caught bythe outer try/catch (good) but a meta file that produces a
malformed transcript that crashes inside
restoreScrollbackisn't well-bounded.
MAX_SESSIONS_TO_RESUMEceiling, so anattacker (or just a runaway dev session) leaving 10 k transcript
files in
~/.codeoid/transcripts/makes startup unusable.Proposed fix
RESUME_MAX_COUNT(default 100) — only resume the N most-recently-active sessions; archive the rest in place (no delete,
user can /import them back).
AbortSignal.timeout(2000)?) aroundthe
loadTranscript+restoreScrollbackpair so a single badfile can't stall the boot.
archived".
they're independent — current serial loop is unnecessarily slow
even on healthy data.
Source pointers
src/daemon/session-manager.ts:72-110Severity
P1 for production; P2 for single-user dev. Worth landing before any
multi-tenant deploy. Surfaced in the 2026-05-08 daemon audit.
🤖 Generated with Claude Code