(session)
| 160 | } |
| 161 | |
| 162 | _save(session) { |
| 163 | const filePath = path.join(this.sessionsDir, `${session.id}.json`); |
| 164 | // Redact secrets that may have leaked into messages or tool output before |
| 165 | // writing to disk. The redaction is one-way: stored sessions never carry |
| 166 | // raw API keys, bearer tokens, or env-style secret assignments. |
| 167 | const redacted = redactValue(session); |
| 168 | // Atomic write: write to a temp file then rename. Prevents reading a |
| 169 | // half-written session if the process crashes mid-save. |
| 170 | const tmpPath = filePath + `.tmp.${process.pid}.${Date.now()}`; |
| 171 | fs.writeFileSync(tmpPath, JSON.stringify(redacted, null, 2), { mode: FILE_MODE }); |
| 172 | fs.renameSync(tmpPath, filePath); |
| 173 | try { fs.chmodSync(filePath, FILE_MODE); } catch {} |
| 174 | } |
| 175 | |
| 176 | _generateId() { |
| 177 | // Time-descending ID so newest sorts first lexicographically. |
no test coverage detected