Skip to content

fix(workspace): make folder selection reliable - #6100

Draft
RaresKeY wants to merge 18 commits into
odysseus-dev:devfrom
RaresKeY:fix/workspace-picker-ux
Draft

fix(workspace): make folder selection reliable#6100
RaresKeY wants to merge 18 commits into
odysseus-dev:devfrom
RaresKeY:fix/workspace-picker-ux

Conversation

@RaresKeY

@RaresKeY RaresKeY commented Aug 17, 2026

Copy link
Copy Markdown
Member

Summary

Make workspace selection one server-owned transaction instead of a browser-local hint. Use this folder now validates the current typed value without requiring Enter, reports exact failures, offers safe creation for missing folders below a managed default workspace, refreshes the selected folder before persisting it, and keeps the signed-in user's selection consistent across browsers and computers.

Startup and setup defensively create the named default workspace under the application data root. The picker opens there, lists its folders, adds a New folder action and visible selection status, and updates the shell wording for the process-sandbox core contract in #6120. Server validation rejects broad, sensitive, application-data, malformed, and unsafe symlink paths at both the picker and execution boundaries.

Stack

This PR is a direct sibling follow-up to the process-sandbox core in PR #6120. Its implementation consumes that core contract for workspace validation and policy reporting; it does not inherit #6084, #5819, or #5821.

After #6119, #6118, and PR #6120 land, this branch should be restacked onto current dev so reviewers see only the picker delta. This PR remains a draft until running-app desktop/mobile evidence is attached, and the restack is pending.

Target branch

  • This PR targets dev, not main. All PRs land in dev; main is curated by the maintainer at each release. If your PR is on main by accident, click "Edit" on this PR and change the base.

Linked Issue

Fixes #6099

Part of #6091

Part of #5815

Depends on PR #6120

Related: #3104, #5914, and Discussion #4438

Type of Change

  • Bug fix (non-breaking — fixes a confirmed issue)
  • New feature (non-breaking — adds new behaviour)
  • Breaking change (changes or removes existing behaviour)
  • Refactor / cleanup (behaviour unchanged)
  • Documentation only
  • CI / tooling / configuration

Checklist

How to Test

  1. Run python -m pytest -q tests/test_workspace_picker.py tests/test_workspace_confine.py tests/test_execution_sandbox.py tests/test_tool_path_confinement.py tests/test_slash_autocomplete_static.py tests/test_session_context_excludes_slash.py; the validated exact head reports 101 passing tests.
  2. Run node --check static/js/workspace.js, node --check static/js/chat.js, node --check static/js/slashCommands.js, Python compilation for the changed Python modules, and git diff --check origin/dev...HEAD; each should exit successfully.
  3. Start the app, open Select workspace, type an existing folder, and click Use this folder without pressing Enter. Verify the canonical folder is selected and its contents are refreshed.
  4. Enter a missing child below the managed default workspace. Verify the picker offers creation, creates it only after confirmation, and rejects missing paths outside that root, sensitive paths, application data, filesystem roots, files, malformed paths, and symlink escapes with a visible reason.
  5. Use New folder, clear the selection, reload, and open the same account in a second browser. Verify selected and explicitly cleared state synchronizes through server preferences and is available before the first chat or slash-command action.
  6. Simulate a failed folder refresh after validation and confirm the previously selected workspace remains active rather than persisting a half-completed change.

Focused exact-head validation passed 101 tests. A network-disabled full-suite run on the preceding picker head reached 5,782 passed and 11 skipped with three failures that reproduced unchanged on clean current dev: the runner omits .env.example, one mocked integration test performs DNS validation with networking disabled, and an existing Node browser-smoke fixture does not define navigator. The final follow-up only sanitizes public errors, documents the already-validated admin path sinks for code scanning, and adds two focused regressions; hosted pytest is the full-suite evidence for the final head.

Not run: live application interaction, Docker/native runtime, desktop/mobile rendering, or screenshot/clip capture.

Visual / UI changes — REQUIRED if you touched anything that renders

This changes workspace-picker controls, inline status, and folder-creation interaction. Running-app visual evidence is required before marking the PR ready for review.

  • Screenshot or short clip of the change in the running app, attached below. Mobile screenshot too if the change affects mobile.
  • Style match: the change reuses the existing modal, button, input, muted-text, border, and color-variable system without adding a parallel visual language.
  • No new component patterns. The existing workspace modal is extended rather than replaced.
  • I am not an LLM agent submitting a bulk PR. This is a focused, one-off, user-directed fix rather than an automated or mass submission.

Screenshots / clips

Pending running-app desktop/mobile capture of existing-folder selection, missing-folder creation, visible disabled reason, and second-browser synchronization.

@github-actions

Copy link
Copy Markdown

⚠️ PR description is complete; validation evidence is still outstanding

Changed-file classification: UI-sensitive.

Author-reported runtime / visual state

  • The author explicitly reports that app/runtime validation was not performed.
  • The screenshot/clip checkbox is not checked for this UI-sensitive change.
  • The Screenshots / clips section does not contain an actual attachment or link.

Checkboxes are author attestations. GitHub Actions results remain the execution evidence for CI; this check does not prove that a local command ran.


This comment updates automatically when the description or changed files change.

@github-actions github-actions Bot added needs runtime validation Runtime validation not attested — tick the app-run box after running it, or state the gap needs visual evidence UI-sensitive change without an attested screenshot or clip from the running app labels Aug 17, 2026
Comment thread routes/workspace_routes.py Dismissed
Comment thread routes/workspace_routes.py Dismissed
Comment thread routes/workspace_routes.py Dismissed
Comment thread routes/workspace_routes.py Dismissed
Comment thread routes/workspace_routes.py Dismissed
Comment thread src/tool_execution.py Dismissed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread routes/workspace_routes.py Fixed
Comment thread src/tool_execution.py Fixed
Comment thread src/tool_execution.py Fixed
@RaresKeY
RaresKeY force-pushed the fix/workspace-picker-ux branch from 88d1c27 to 1fed344 Compare August 17, 2026 13:44
@RaresKeY
RaresKeY force-pushed the fix/workspace-picker-ux branch from 1fed344 to d6491f7 Compare August 17, 2026 16:30
@RaresKeY
RaresKeY force-pushed the fix/workspace-picker-ux branch from d6491f7 to 2af64a0 Compare August 17, 2026 16:43
@RaresKeY
RaresKeY requested a balanced review from Copilot August 18, 2026 03:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Makes workspace selection server-owned and reliable while incorporating the stacked Linux process-sandbox foundation.

Changes:

  • Adds persisted workspace validation, creation, synchronization, and picker UI.
  • Introduces Bubblewrap, seccomp, and brokered-network process isolation.
  • Expands regression coverage across workspace and sandbox behavior.

Reviewed changes

Copilot reviewed 47 out of 47 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
THREAT_MODEL.md Documents sandbox behavior.
tests/test_workspace_picker.py Tests picker workflows and persistence.
tests/test_workspace_confine.py Extends workspace confinement tests.
tests/test_seccomp_policy.py Verifies generated seccomp policy.
tests/test_seccomp_launcher.py Tests launcher security and failures.
tests/test_seccomp_generator.py Tests architecture verification.
tests/test_sandbox_network_policy.py Tests network-policy propagation.
tests/test_foreground_model_routing.py Tests web-toggle network mapping.
tests/test_agent_bash_windows.py Tests unsupported-platform blocking.
tests/seccomp_probe.c Probes runtime syscall restrictions.
static/style.css Styles picker status and controls.
static/js/workspace.js Implements server-synchronized picker behavior.
static/js/slashCommands.js Integrates workspace persistence with commands.
static/js/chat.js Synchronizes workspace before chat actions.
src/tool_schemas.py Updates workspace tool description.
src/tool_index.py Updates indexed tool description.
src/tool_execution.py Adds workspace and network-policy enforcement.
src/teacher_escalation.py Propagates sandbox network profiles.
src/execution_sandbox.py Constructs the process sandbox.
src/constants.py Defines managed workspace and log paths.
src/bg_monitor.py Restores background-job network policy.
src/bg_jobs.py Sandboxes detached jobs.
src/agent_tools/subprocess_tools.py Sandboxes Bash, Python, and tmux.
src/agent_tools/filesystem_tools.py Updates workspace status wording.
src/agent_loop.py Propagates sandbox network profiles.
setup.py Creates the managed workspace during setup.
security/seccomp/README.md Documents seccomp generation and installation.
security/seccomp/policy.json Defines sandbox syscall policy.
security/seccomp/odysseus-seccomp-launcher.c Implements the trusted launcher.
security/seccomp/Makefile Builds and installs the launcher.
security/seccomp/generated_inner_policy.h Supplies generated syscall allowlists.
security/seccomp/generate.py Generates deterministic policy artifacts.
security/egress/README.md Documents brokered egress.
security/egress/odysseus_egress_bridge.py Bridges sandbox traffic to the broker.
security/egress/Makefile Installs trusted egress helpers.
routes/workspace_routes.py Adds workspace persistence and creation APIs.
routes/chat_routes.py Maps web preference to network policy.
Dockerfile Installs sandbox dependencies and helpers.
docker-compose.yml Applies the outer seccomp profile.
docker-compose.gpu-nvidia.yml Applies seccomp to NVIDIA deployment.
docker-compose.gpu-amd.yml Applies seccomp to AMD deployment.
app.py Creates the default workspace at startup.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/tool_execution.py
Comment on lines +320 to 321
resolved, _reason = validate_workspace(raw)
return resolved
Comment thread static/js/workspace.js
Comment on lines +25 to +27
export function whenWorkspaceReady() {
if (!_workspaceReadyPromise) _workspaceReadyPromise = _syncServerWorkspace();
return _workspaceReadyPromise;
Comment on lines +131 to +134
else:
# Non-POSIX fallback retains the lexical precheck and canonical
# postcheck around this intentionally admin-selected managed path.
Path(candidate).mkdir(mode=0o700, parents=True, exist_ok=True)
Comment on lines +308 to +309
_save_selected_workspace(owner, "")
return {"ok": True, "path": "", "default_path": ensure_default_workspace()}
Comment on lines 397 to 405
if session_id and not IS_WINDOWS and shutil.which("tmux"):
stdout, stderr, rc, timed_out = await _run_tmux_bash(
content,
session_id=str(session_id),
cwd=agent_cwd(),
env=_subproc_env,
cwd=workspace,
timeout=DEFAULT_BASH_TIMEOUT,
progress_cb=progress_cb,
network_profile=network_profile,
)
Comment thread THREAT_MODEL.md
These are open, acknowledged, and contributor help is welcome:

1. **No shell/filesystem sandbox.** The agent `bash` and `read_file`/`write_file` tools run as the app process user with no network egress filtering or filesystem confinement. A successful prompt-injection reaching a shell-enabled admin session can make outbound requests to internal services. See #1058 for the sandbox proposal.
1. **Linux sandbox portability.** Agent `bash`, Python, tmux, and detached background commands run through a networkless bubblewrap profile with a cleared environment, private temp/home, a single writable workspace, credential-path overlays, read-only `.git` metadata, resource limits, and explicit hiding of Odysseus data/log roots even when they sit below a broader selected workspace. The Docker image includes bubblewrap. Sandboxed process execution fails closed when that profile is unavailable; a portable equivalent for non-Linux hosts is not implemented yet. The sandbox intentionally omits `/proc`, so commands that require process inspection degrade rather than gaining access to the app process namespace.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs runtime validation Runtime validation not attested — tick the app-run box after running it, or state the gap needs visual evidence UI-sensitive change without an attested screenshot or clip from the running app

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Workspace picker ignores typed paths and lacks a server-owned default

3 participants