Add file-based logging#451
Conversation
5e85cdf to
c4af781
Compare
| // Both must run even if one throws. Losing the session-end entry | ||
| // because stopServer() rejected (or vice versa) defeats the point of | ||
| // having a log on failure paths. | ||
| await Promise.allSettled([proxy.stopServer(), closeFileLogger()]); |
There was a problem hiding this comment.
Single-line concurrent shutdown using Promise.allSettled with multiple IO operations; split into named steps or separate awaits to improve clarity.
| await Promise.allSettled([proxy.stopServer(), closeFileLogger()]); | |
| const stopServerPromise = proxy.stopServer(); | |
| const closeLoggerPromise = closeFileLogger(); | |
| await Promise.allSettled([stopServerPromise, closeLoggerPromise]); |
Details
✨ AI Reasoning
This change introduced a single-line shutdown using Promise.allSettled to run two independent shutdown/cleanup operations concurrently. Packing both operations into one expression increases cognitive load when reasoning about shutdown order, error handling, and which side effects may occur. Splitting into clearer steps or naming the promises improves readability and makes failure semantics easier to follow.
Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info
Summary
Adds opt-in file logging to Safe Chain. When configured, every message Safe Chain writes to the terminal is also appended to a file — useful for debugging CI runs, capturing what Safe Chain saw on a developer's machine, and producing artifacts security teams can grep later.
File logging is off by default and only turns on when a path is configured. It does not change anything about the existing terminal output.
Configuration
Three settings, each accepts a CLI flag, an env var, or a config-file key (priority: CLI > env > config). Bracketed each session with
Log started, command: ...andLog ended, command: ...so individual invocations can be told apart in a long-running file.--safe-chain-log-fileSAFE_CHAIN_LOG_FILElogFile--safe-chain-log-file-formatSAFE_CHAIN_LOG_FILE_FORMATlogFileFormatjson--safe-chain-log-file-verbositySAFE_CHAIN_LOG_FILE_VERBOSITYlogFileVerbosityverboseFormat
json- newline-delimited JSON, one self-contained object per line. Suitable forjqand log shippers.plain-[timestamp] [level] message. Intended for quick human inspection.Verbosity controls which levels reach the file. Independent from
--safe-chain-logging, so users can keep their terminal quiet while still capturing diagnostics.verbose(default) - every entry, including diagnostic output the terminal hides under the default logging level.normal- info, warning, error. Drops verbose.silent- errors only.Path accepts
~/and creates parent directories on demand. The file is opened in append mode so existing contents are preserved across runs.Example
npm install express --safe-chain-log-file=~/safe-chain.log{"timestamp":"2026-05-08T12:00:00.000Z","level":"info","message":"Log started, command: npm install express"} {"timestamp":"2026-05-08T12:00:00.123Z","level":"verbose","message":"Fetching malware lists from https://malware-list.aikido.dev"} {"timestamp":"2026-05-08T12:00:01.456Z","level":"info","message":"✔ Safe-chain: Scanned 142 packages, no malware found."} {"timestamp":"2026-05-08T12:00:01.789Z","level":"info","message":"Log ended, command: npm install express"}Behavior on failure
File logging is best-effort and never blocks the wrapped package manager. If the configured path can't be opened or a write fails, Safe Chain emits a single warning and continues without file logging — the install / scan / audit still completes.
Summary by Aikido
🚀 New Features
⚡ Enhancements
More info