feat: session-specific sandbox wiring - #425
Conversation
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (9)
📝 WalkthroughWalkthroughIntroduces a session-owned ChangesSession-owned environment for minimald
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Sequence Diagram(s)sequenceDiagram
participant SSH as SSH Connection
participant Handler as ConnectionHandler
participant SessionHandle
participant SessionActor
participant Host as SessionHost
participant Env as Env
SSH->>Handler: shell_request with auth username
Handler->>SessionHandle: paths() to get SessionPaths
SessionHandle->>SessionActor: GetPaths message
SessionActor-->>SessionHandle: SessionPaths { working, home, cache }
Handler->>SessionHandle: attach(conn_username, channel, config)
SessionHandle->>SessionActor: Attach(username, handle, channel, config)
SessionActor->>Host: spawn(name, username, paths, sz, channel)
Host->>Env: build(ctx, graph, EnvArgs)
Env->>Env: resolve packages, build dependencies, create sandbox
Env-->>Host: Env { sandbox, actor }
Host-->>SessionActor: Launched session with PTY and bash
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/sandbox2/src/lib.rs (1)
224-240: 💤 Low valueConsider extracting a helper to derive the session working-directory name.
The pattern
working_name_override.as_ref().cloned().unwrap_or_else(|| SESSION_DEFAULT_WD.to_string())is repeated in three places (rootfs init,command_inner, andnew_container). A small helper onWdSetupwould centralize this logic and simplify call sites.♻️ Example helper method
impl WdSetup { /// Returns the working directory name for Session layouts. /// Panics if called on non-Session variants. pub(crate) fn session_wd_name(&self) -> String { match self { Self::Session { working_name_override, .. } => { working_name_override .clone() .unwrap_or_else(|| SESSION_DEFAULT_WD.to_string()) } _ => panic!("session_wd_name called on non-Session variant"), } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/sandbox2/src/lib.rs` around lines 224 - 240, The pattern for deriving the session working-directory name (working_name_override.as_ref().cloned().unwrap_or_else(|| SESSION_DEFAULT_WD.to_string())) is repeated in three places. Create a helper method called session_wd_name on the WdSetup enum that encapsulates this logic by matching on the Session variant and returning the working directory name. Then replace all three occurrences of this pattern (in the rootfs init section shown, in command_inner, and in new_container) with calls to this new helper method to centralize and simplify the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/sandbox2/src/lib.rs`:
- Around line 224-240: The pattern for deriving the session working-directory
name (working_name_override.as_ref().cloned().unwrap_or_else(||
SESSION_DEFAULT_WD.to_string())) is repeated in three places. Create a helper
method called session_wd_name on the WdSetup enum that encapsulates this logic
by matching on the Session variant and returning the working directory name.
Then replace all three occurrences of this pattern (in the rootfs init section
shown, in command_inner, and in new_container) with calls to this new helper
method to centralize and simplify the logic.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a35b5a84-e111-47e1-b312-20c9fb84c585
📒 Files selected for processing (2)
crates/sandbox2/src/config.rscrates/sandbox2/src/lib.rs
bbb79d1 to
5ea04ef
Compare
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (5)
crates/minimald/src/session.rs (1)
34-38: 💤 Low valueAdd common derives to
SessionPaths.The struct is public and would benefit from
DebugandClonederives for debugging and flexible usage patterns.♻️ Suggested change
+#[derive(Debug, Clone)] pub struct SessionPaths { pub working: DaemonAbsPath, pub cache: DaemonAbsPath, pub home: DaemonAbsPath, }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/minimald/src/session.rs` around lines 34 - 38, Add the `Debug` and `Clone` derives to the `SessionPaths` struct definition. Place a `#[derive(Debug, Clone)]` attribute above the struct declaration to enable debugging output and cloning of struct instances, which improves usability for a public struct.crates/sessions/src/store.rs (1)
106-120: 💤 Low valueConsider extracting the common base path computation.
All three path methods (
workspace_path,home_path,cache_path) duplicate the base path computation. Additionally,DaemonRelPath::try_new(&self.key.dir_key)is called onself.key.dir_keywhich is already aDaemonRelPath(line 80), making the conversion redundant.♻️ Suggested refactor to reduce duplication
impl SessionObject for DiskSession { type Key = DiskSessionKey; + fn session_base(&self) -> DaemonAbsPath { + sub_path!(self.minimal_state_dir, "sessions").join(&self.key.dir_key) + } + fn record(&self) -> &Record { &self.record } fn key(&self) -> &DiskSessionKey { &self.key } fn workspace_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "tree") + sub_path!(self.session_base(), "tree") } fn home_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "home") + sub_path!(self.session_base(), "home") } fn cache_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "cache") + sub_path!(self.session_base(), "cache") } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/sessions/src/store.rs` around lines 106 - 120, The methods workspace_path, home_path, and cache_path contain duplicated code for computing the base path using sub_path and DaemonRelPath::try_new. Extract this common base path computation into a private helper method to eliminate duplication. Additionally, since self.key.dir_key is already a DaemonRelPath (as shown on line 80), remove the redundant DaemonRelPath::try_new wrapper call and directly use self.key.dir_key in the path computation. Update all three methods to call the new helper method instead of repeating the base path logic.crates/minimald/src/env_min_helper.sh (1)
131-136: 💤 Low value
buildandtestsubcommands ignore additional arguments.
min build fooandmin test barwill ignorefooandbarrespectively, running onlymin run buildormin run test. If this is intentional for simplicity, consider adding a comment. Otherwise, forward the arguments.Suggested fix if arguments should be forwarded
build) - min_run build + min_run build "$@" ;; test) - min_run test + min_run test "$@" ;;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/minimald/src/env_min_helper.sh` around lines 131 - 136, The build and test case statements in the switch block are not forwarding additional command-line arguments to the min_run function. In the build case and test case blocks, modify the min_run calls to append the remaining arguments (using the appropriate shell variable for all arguments passed after the subcommand) so that commands like `min build foo` will properly forward `foo` to min_run instead of discarding it.crates/minimald/src/env.rs (2)
410-455: ⚖️ Poor tradeoffConsider reducing repetition in add- command handlers.*
The four
add-*branches share nearly identical structure: parse packages, handle errors, callinstall(), then return the mode. This could be extracted into a helper, though the current implementation is clear and functional.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/minimald/src/env.rs` around lines 410 - 455, Extract the repeated logic from the four add-* command handlers (add-session, add-build, add-runtime, add-task) into a helper method. The common pattern in each branch is: parse packages using parse_pkgs_line, handle errors with the same error message format, call install, and return a result. Create a helper method that accepts the package string and a closure or enum variant to construct the appropriate AddDepMode result, then replace each of the four match arms with a call to this helper to eliminate the duplication while preserving the unique AddDepMode construction logic for each command type.
254-258: 💤 Low valueChained
.unwrap()calls on path conversion could panic.If
sandbox.rootfs()returns a path that isn't valid UTF-8, theUtf8PathBuf::try_from(...).unwrap()will panic. While sandbox rootfs paths are typically UTF-8, consider usingexpect()with a descriptive message or propagating the error for robustness.Suggested improvement
let channel = SessionChannel { - rootfs: DaemonAbsPath::try_new( - Utf8PathBuf::try_from(sandbox.rootfs().to_path_buf()).unwrap(), - ) - .unwrap(), + rootfs: DaemonAbsPath::try_new( + Utf8PathBuf::try_from(sandbox.rootfs().to_path_buf()) + .expect("sandbox rootfs must be valid UTF-8"), + ) + .expect("sandbox rootfs must be absolute"),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/minimald/src/env.rs` around lines 254 - 258, Replace the chained `.unwrap()` calls in the SessionChannel initialization (specifically in the rootfs field where DaemonAbsPath::try_new and Utf8PathBuf::try_from are used) with `.expect()` calls that include descriptive error messages. The inner `.unwrap()` from Utf8PathBuf::try_from should explain that the sandbox rootfs path must be valid UTF-8, and the outer `.unwrap()` from DaemonAbsPath::try_new should explain that the rootfs path must be an absolute path. This provides better debugging information if the conversions fail instead of a generic panic message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/minimald/src/env_min_helper.sh`:
- Around line 143-153: The usage text in the default case block contains a
duplicate echo statement for "Check minimal configuration: min check". Remove
the second occurrence of this duplicate echo line that appears after the "min
run <task name>" line to eliminate the redundant instruction text in the usage
output.
- Line 69: The variable assignment in the packages variable declaration uses
"$@" which will cause word splitting when assigning to a string variable.
Replace "$@" with "$*" in the local packages assignment to properly concatenate
all arguments into a single string variable, ensuring the arguments are treated
as a single concatenated value rather than being split into separate elements.
- Line 58: The condition in the if statement is checking the same variable
`$pkg` twice with `[[ -z "$pkg" || -z "$pkg" ]]`, which is redundant. Replace
the second occurrence of `$pkg` with the appropriate second variable that should
be validated in this condition, so that the logic properly checks if either of
two distinct variables are empty rather than repeating the same check.
- Line 48: The conditional check at line 48 in env_min_helper.sh contains a
redundant condition where the variable $term is checked twice with -z "$term" ||
-z "$term". Remove the duplicate check by keeping only a single -z "$term"
condition, or if the second condition was intended to check a different
variable, replace the second -z "$term" with the correct variable that should be
validated. This appears to be a copy-paste artifact that should be corrected.
- Line 6: In the env_min_helper.sh file, the variable assignment for data is
using "$@" which loses word boundaries when assigned to a scalar variable.
Change the assignment from local data="$@" to local data="$*" so that the
arguments are properly concatenated with spaces as a single string, which is
what is needed when the data variable is used as a single string sent to the
RPC.
In `@crates/minimald/src/env.rs`:
- Around line 869-874: The poll_shutdown method currently returns
Poll::Ready(Ok(())) without flushing any remaining data in self.buf, causing
data without a trailing newline to be silently discarded on shutdown. Modify the
poll_shutdown method to check if self.buf contains any remaining data and flush
it to the output before returning Poll::Ready(Ok(())), ensuring no buffered
content is lost during shutdown even if it lacks a trailing newline.
In `@crates/minimald/src/rpc.rs`:
- Around line 193-199: The async_tar::Archive::unpack() method is vulnerable to
CVE-2025-62518 "TARmageddon" which allows path traversal attacks on untrusted
tarball data from SSH clients. Replace the async_tar crate with a maintained,
vulnerability-free tar library alternative, or if async_tar must remain,
implement strict multi-layered validation before unpacking that includes path
allowlisting, rejecting symlinks, verifying file ownership and permissions, and
isolating the extraction directory at the OS level to prevent arbitrary file
writes.
In `@crates/minimald/src/session.rs`:
- Around line 72-74: The three create_dir_all() calls for
session.workspace_path(), session.home_path(), and session.cache_path() use
unwrap() which will panic if directory creation fails. Since Session::run
already returns a Result<SessionHandle, std::io::Error>, replace each unwrap()
with the ? operator to propagate the errors instead of panicking, allowing the
caller to handle them appropriately.
---
Nitpick comments:
In `@crates/minimald/src/env_min_helper.sh`:
- Around line 131-136: The build and test case statements in the switch block
are not forwarding additional command-line arguments to the min_run function. In
the build case and test case blocks, modify the min_run calls to append the
remaining arguments (using the appropriate shell variable for all arguments
passed after the subcommand) so that commands like `min build foo` will properly
forward `foo` to min_run instead of discarding it.
In `@crates/minimald/src/env.rs`:
- Around line 410-455: Extract the repeated logic from the four add-* command
handlers (add-session, add-build, add-runtime, add-task) into a helper method.
The common pattern in each branch is: parse packages using parse_pkgs_line,
handle errors with the same error message format, call install, and return a
result. Create a helper method that accepts the package string and a closure or
enum variant to construct the appropriate AddDepMode result, then replace each
of the four match arms with a call to this helper to eliminate the duplication
while preserving the unique AddDepMode construction logic for each command type.
- Around line 254-258: Replace the chained `.unwrap()` calls in the
SessionChannel initialization (specifically in the rootfs field where
DaemonAbsPath::try_new and Utf8PathBuf::try_from are used) with `.expect()`
calls that include descriptive error messages. The inner `.unwrap()` from
Utf8PathBuf::try_from should explain that the sandbox rootfs path must be valid
UTF-8, and the outer `.unwrap()` from DaemonAbsPath::try_new should explain that
the rootfs path must be an absolute path. This provides better debugging
information if the conversions fail instead of a generic panic message.
In `@crates/minimald/src/session.rs`:
- Around line 34-38: Add the `Debug` and `Clone` derives to the `SessionPaths`
struct definition. Place a `#[derive(Debug, Clone)]` attribute above the struct
declaration to enable debugging output and cloning of struct instances, which
improves usability for a public struct.
In `@crates/sessions/src/store.rs`:
- Around line 106-120: The methods workspace_path, home_path, and cache_path
contain duplicated code for computing the base path using sub_path and
DaemonRelPath::try_new. Extract this common base path computation into a private
helper method to eliminate duplication. Additionally, since self.key.dir_key is
already a DaemonRelPath (as shown on line 80), remove the redundant
DaemonRelPath::try_new wrapper call and directly use self.key.dir_key in the
path computation. Update all three methods to call the new helper method instead
of repeating the base path logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fecded67-7202-4c3a-854a-c142bf624a9a
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (12)
crates/minimald/Cargo.tomlcrates/minimald/src/env.rscrates/minimald/src/env_min_helper.shcrates/minimald/src/exec.rscrates/minimald/src/lib.rscrates/minimald/src/rpc.rscrates/minimald/src/session.rscrates/minimald/src/session_host.rscrates/minimald/src/sftp.rscrates/sandbox2/src/config.rscrates/sandbox2/src/lib.rscrates/sessions/src/store.rs
✅ Files skipped from review due to trivial changes (1)
- crates/minimald/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (2)
- crates/sandbox2/src/config.rs
- crates/sandbox2/src/lib.rs
| fn poll_shutdown( | ||
| self: Pin<&mut Self>, | ||
| _cx: &mut std::task::Context<'_>, | ||
| ) -> Poll<Result<(), std::io::Error>> { | ||
| Poll::Ready(Ok(())) | ||
| } |
There was a problem hiding this comment.
poll_shutdown does not flush partial lines remaining in the buffer.
If the writer is shut down while self.buf contains data without a trailing newline, that data is silently discarded. Consider flushing any remaining buffer content (even without a trailing newline) in poll_shutdown.
Suggested fix
fn poll_shutdown(
- self: Pin<&mut Self>,
+ mut self: Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
) -> Poll<Result<(), std::io::Error>> {
+ if !self.buf.is_empty() {
+ let line = String::from_utf8_lossy(&self.buf);
+ let _ = writeln!(self.stream.lock().unwrap(), "msg:{line}");
+ self.buf.clear();
+ }
Poll::Ready(Ok(()))
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn poll_shutdown( | |
| self: Pin<&mut Self>, | |
| _cx: &mut std::task::Context<'_>, | |
| ) -> Poll<Result<(), std::io::Error>> { | |
| Poll::Ready(Ok(())) | |
| } | |
| fn poll_shutdown( | |
| mut self: Pin<&mut Self>, | |
| _cx: &mut std::task::Context<'_>, | |
| ) -> Poll<Result<(), std::io::Error>> { | |
| if !self.buf.is_empty() { | |
| let line = String::from_utf8_lossy(&self.buf); | |
| let _ = writeln!(self.stream.lock().unwrap(), "msg:{line}"); | |
| self.buf.clear(); | |
| } | |
| Poll::Ready(Ok(())) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/minimald/src/env.rs` around lines 869 - 874, The poll_shutdown method
currently returns Poll::Ready(Ok(())) without flushing any remaining data in
self.buf, causing data without a trailing newline to be silently discarded on
shutdown. Modify the poll_shutdown method to check if self.buf contains any
remaining data and flush it to the output before returning Poll::Ready(Ok(())),
ensuring no buffered content is lost during shutdown even if it lacks a trailing
newline.
09677fe to
e6974b5
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/sessions/src/store.rs (2)
123-137: 💤 Low valueConsider extracting the common base path computation.
The base path calculation is duplicated across
workspace_path,home_path, andcache_path. A private helper would reduce duplication.♻️ Suggested refactor
+ fn session_base_path(&self) -> DaemonAbsPath { + sub_path!(self.minimal_state_dir, "sessions") + .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()) + } + fn workspace_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "tree") + sub_path!(self.session_base_path(), "tree") } fn home_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "home") + sub_path!(self.session_base_path(), "home") } fn cache_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "cache") + sub_path!(self.session_base_path(), "cache") }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/sessions/src/store.rs` around lines 123 - 137, The base path computation is duplicated identically across the workspace_path, home_path, and cache_path methods. Extract this common computation into a private helper method that returns the base DaemonAbsPath (which combines self.minimal_state_dir, "sessions", and the dir_key). Then refactor each of the three methods to call this helper instead of duplicating the base path calculation logic.
240-240: 💤 Low valueMethod signature could be tightened.
write_recorddoesn't mutateself, so&selfwould suffice. Also,short: &stris more idiomatic thanshort: &String.♻️ Suggested signature
- fn write_record(&mut self, short: &String, record: &Record) -> Result<(), std::io::Error> { + fn write_record(&self, short: &str, record: &Record) -> Result<(), std::io::Error> {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/sessions/src/store.rs` at line 240, The write_record method signature has two issues that can be tightened. First, change the receiver from &mut self to &self since the method does not actually mutate self. Second, change the parameter short from &String to &str, which is the more idiomatic Rust pattern for accepting string data. These changes make the API clearer about the method's intent and follow Rust conventions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/sessions/src/store.rs`:
- Around line 340-360: The in-memory index mutations are happening before the
disk writes are guaranteed to succeed, creating a risk of inconsistent state if
a write fails. In the rename function, the removal of the old name from
self.index.name_to_id (before write_record) and the insertion of the new name
into self.index.name_to_id (before flush_index) should be deferred until after
both write_record and flush_index have completed successfully. Reorder the
operations so that all in-memory index updates happen only after the disk
operations succeed to ensure consistency.
---
Nitpick comments:
In `@crates/sessions/src/store.rs`:
- Around line 123-137: The base path computation is duplicated identically
across the workspace_path, home_path, and cache_path methods. Extract this
common computation into a private helper method that returns the base
DaemonAbsPath (which combines self.minimal_state_dir, "sessions", and the
dir_key). Then refactor each of the three methods to call this helper instead of
duplicating the base path calculation logic.
- Line 240: The write_record method signature has two issues that can be
tightened. First, change the receiver from &mut self to &self since the method
does not actually mutate self. Second, change the parameter short from &String
to &str, which is the more idiomatic Rust pattern for accepting string data.
These changes make the API clearer about the method's intent and follow Rust
conventions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c829c1e3-bfbb-4481-a244-170ca6670034
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (13)
crates/minimald/Cargo.tomlcrates/minimald/src/connection.rscrates/minimald/src/env.rscrates/minimald/src/env_min_helper.shcrates/minimald/src/exec.rscrates/minimald/src/lib.rscrates/minimald/src/rpc.rscrates/minimald/src/session.rscrates/minimald/src/session_host.rscrates/minimald/src/sftp.rscrates/sandbox2/src/config.rscrates/sandbox2/src/lib.rscrates/sessions/src/store.rs
✅ Files skipped from review due to trivial changes (1)
- crates/minimald/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (9)
- crates/minimald/src/sftp.rs
- crates/minimald/src/connection.rs
- crates/minimald/src/exec.rs
- crates/minimald/src/rpc.rs
- crates/minimald/src/session.rs
- crates/sandbox2/src/lib.rs
- crates/minimald/src/session_host.rs
- crates/sandbox2/src/config.rs
- crates/minimald/src/env.rs
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/sessions/src/store.rs (2)
123-137: 💤 Low valueConsider extracting the common base path computation.
The base path calculation is duplicated across
workspace_path,home_path, andcache_path. A private helper would reduce duplication.♻️ Suggested refactor
+ fn session_base_path(&self) -> DaemonAbsPath { + sub_path!(self.minimal_state_dir, "sessions") + .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()) + } + fn workspace_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "tree") + sub_path!(self.session_base_path(), "tree") } fn home_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "home") + sub_path!(self.session_base_path(), "home") } fn cache_path(&self) -> DaemonAbsPath { - let base = sub_path!(self.minimal_state_dir, "sessions") - .join(&DaemonRelPath::try_new(&self.key.dir_key).unwrap()); - sub_path!(base, "cache") + sub_path!(self.session_base_path(), "cache") }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/sessions/src/store.rs` around lines 123 - 137, The base path computation is duplicated identically across the workspace_path, home_path, and cache_path methods. Extract this common computation into a private helper method that returns the base DaemonAbsPath (which combines self.minimal_state_dir, "sessions", and the dir_key). Then refactor each of the three methods to call this helper instead of duplicating the base path calculation logic.
240-240: 💤 Low valueMethod signature could be tightened.
write_recorddoesn't mutateself, so&selfwould suffice. Also,short: &stris more idiomatic thanshort: &String.♻️ Suggested signature
- fn write_record(&mut self, short: &String, record: &Record) -> Result<(), std::io::Error> { + fn write_record(&self, short: &str, record: &Record) -> Result<(), std::io::Error> {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/sessions/src/store.rs` at line 240, The write_record method signature has two issues that can be tightened. First, change the receiver from &mut self to &self since the method does not actually mutate self. Second, change the parameter short from &String to &str, which is the more idiomatic Rust pattern for accepting string data. These changes make the API clearer about the method's intent and follow Rust conventions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/sessions/src/store.rs`:
- Around line 340-360: The in-memory index mutations are happening before the
disk writes are guaranteed to succeed, creating a risk of inconsistent state if
a write fails. In the rename function, the removal of the old name from
self.index.name_to_id (before write_record) and the insertion of the new name
into self.index.name_to_id (before flush_index) should be deferred until after
both write_record and flush_index have completed successfully. Reorder the
operations so that all in-memory index updates happen only after the disk
operations succeed to ensure consistency.
---
Nitpick comments:
In `@crates/sessions/src/store.rs`:
- Around line 123-137: The base path computation is duplicated identically
across the workspace_path, home_path, and cache_path methods. Extract this
common computation into a private helper method that returns the base
DaemonAbsPath (which combines self.minimal_state_dir, "sessions", and the
dir_key). Then refactor each of the three methods to call this helper instead of
duplicating the base path calculation logic.
- Line 240: The write_record method signature has two issues that can be
tightened. First, change the receiver from &mut self to &self since the method
does not actually mutate self. Second, change the parameter short from &String
to &str, which is the more idiomatic Rust pattern for accepting string data.
These changes make the API clearer about the method's intent and follow Rust
conventions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c829c1e3-bfbb-4481-a244-170ca6670034
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (13)
crates/minimald/Cargo.tomlcrates/minimald/src/connection.rscrates/minimald/src/env.rscrates/minimald/src/env_min_helper.shcrates/minimald/src/exec.rscrates/minimald/src/lib.rscrates/minimald/src/rpc.rscrates/minimald/src/session.rscrates/minimald/src/session_host.rscrates/minimald/src/sftp.rscrates/sandbox2/src/config.rscrates/sandbox2/src/lib.rscrates/sessions/src/store.rs
✅ Files skipped from review due to trivial changes (1)
- crates/minimald/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (9)
- crates/minimald/src/sftp.rs
- crates/minimald/src/connection.rs
- crates/minimald/src/exec.rs
- crates/minimald/src/rpc.rs
- crates/minimald/src/session.rs
- crates/sandbox2/src/lib.rs
- crates/minimald/src/session_host.rs
- crates/sandbox2/src/config.rs
- crates/minimald/src/env.rs
🛑 Comments failed to post (1)
crates/sessions/src/store.rs (1)
340-360:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winIn-memory index mutation before disk write risks inconsistent state on failure.
If
write_recordfails after line 351 removes the old name from the in-memory index, the process retains a corrupted view where the old name is gone but the rename never completed on disk. Defer in-memory mutations until after both disk writes succeed.🐛 Proposed fix to reorder operations
fn rename(&mut self, key: &Self::Key, new_name: String) -> Result<(), std::io::Error> { if self.index.find_by_name(&new_name).is_some() { return Err(std::io::Error::new( AlreadyExists, format!("a session with the name `{new_name}` already exists"), )); } let mut obj = self.get(key)?; let short = obj.key.dir_key.to_string(); - if let Some(old_name) = &obj.record.name { - self.index.name_to_id.remove(old_name); - } + let old_name = obj.record.name.clone(); obj.record.name = Some(new_name.clone()); self.write_record(&short, &obj.record)?; + // Only mutate in-memory index after disk writes succeed + if let Some(old_name) = &old_name { + self.index.name_to_id.remove(old_name); + } self.index.name_to_id.insert(new_name, obj.record.id); self.flush_index()?; Ok(()) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/sessions/src/store.rs` around lines 340 - 360, The in-memory index mutations are happening before the disk writes are guaranteed to succeed, creating a risk of inconsistent state if a write fails. In the rename function, the removal of the old name from self.index.name_to_id (before write_record) and the insertion of the new name into self.index.name_to_id (before flush_index) should be deferred until after both write_record and flush_index have completed successfully. Reorder the operations so that all in-memory index updates happen only after the disk operations succeed to ensure consistency.
e6974b5 to
0e2c4c1
Compare
Sandbox env:
/home/workbench, configurable/homeexcept cache, which points into/state(we should probably rename that /cache at this point lol)Duplicated
mctx::Envinto minimald and started specializing it for sessions, as well as removed some of the lifetime crimes we were doing with&mut Context/&mut Graph.NB: The duplication is intentional: we want to support the old
minimal run <task>semantics as long as possible, so duplicating will let us cook on the sessions stuff separately.Summary by CodeRabbit
Summary by CodeRabbit
New Features
minhelper to drive session actions (add/search/run/check/build and related operations).Improvements
Bug Fixes