* feat(users): limit resource visibility by user group
Admins can create groups and assign members. Skill packages, knowledge
bases, connectors, models, and named storage backends can then be
restricted to those groups without granting extra edit rights.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(users): gate connector and storage use by group and show the catalog
Replace per-instance connector and storage grants with one feature-level control, list every resource kind on the group page, and make skill-package sharing follow a single audience choice.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Scheduled jobs can run once and then stop, personalization tabs can be granted separately, and rotated logs use a date-before-extension name.
Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Store group order, item placement, and hidden entries on the user so navigation can be rearranged without showing items the account cannot access.
Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: admin user batch policies, token UX, default FS root, and media push hardening
Add admin user batch enable/disable/delete and resource policies (token quota,
max experts), improve token inputs with K/M presets, default unrestricted
local backends to host filesystem root, and tighten gateway tool-media push
with clearer path-outside-root stream errors.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(workspace): treat Windows drive roots as host-root sentinels
Default FS-root backends use C:/ on Windows; treating that as a scoped
jail put workspaces under the drive root and broke bootstrap/invite tests.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Add a `user_policies` table (migration v14) backing per-user `workspace_root_dir`
(restricts local backend roots) and `token_quota` (lifetime token limit). Token
quota is enforced in the agent runtime via TokenQuotaMiddleware. Extract slash
command parsing into infra/gateway/slash/parser.py and expose policies on the
users API. Frontend adds admin policy UI, storage/chat/experts restyle, and a
shared TabLabel / PageLoading component.
- Relocate voice and search engine settings from Advanced to Models
page/permission category (nav, routes, permission gates).
- Add /admin/voice/providers/test-configuration endpoint and
VoiceManager.test_configuration() to probe unsaved provider values
before saving.
- Redirect legacy /admin/advanced?tab=voice|search links to the new
Models page location.
Use /invite?code= as the canonical invite URL, fix invite page centering
and mobile scroll under the overflow-hidden shell, show a logo spinner
before JS mounts, align setup email input icons, and remove the chat
remote-phone dock entry.
Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: minimal layout, user email, KB text docs, and remote desktop hub
Add classic/minimal chrome with a unified chat records host, optional user
email (invite/login), in-app markdown/txt knowledge editing, and a combined
remote desktop/phone control surface—plus host path and mobile setup hardening.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(host_dirs): don't jail host-root browse to home drive on Windows
The restrict_to_home=False case allows any absolute host path (no home
jail). On POSIX everything sits under '/'; on Windows the denylist is
empty and windows_neutralize_host_root rewrites root_dir '/' at runtime,
so a drive-relative '/' must stay allowed. The new _path_within_base
containment incorrectly rejected root_dir '/' on Windows when the checkout
drive differed from the home drive, breaking from-expert/local_shell agent
creation.
Also mark test_install_published_expert_accepts_create_options posix_only:
it relies on local_shell workspace file writes unsupported on Windows.
---------
Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(mobile): add Remote Android probe, API, stream, and dashboard
Multi-backend mobile support for self-hosted Octop: install-time host
capability probe, gated /api/mobile routes, adb WebSocket stream, and
Control → Remote Android dashboard page for Mac/emulator dev paths.
* feat(mobile): wire harness agent adb tools for Remote Android
Register mobile_screenshot, mobile_tap, mobile_swipe, mobile_launch_app,
mobile_ui_dump, and mobile_handoff_to_user when capabilities.mobile is
enabled, with permission and readiness checks.
* feat(mobile): polish Remote Phone UX and session-bound agent control
Rename the surface to Remote Phone, add quality presets, device info, AI
panel, and chat-dock phone tab; bind agent tools to the active stream
session and cover with unit tests.
* chore(mobile): drop docs/specs/remote-android.md from the PR
* fix(mobile): ruff I001 import formatting in device_info tests
* fix(mobile): resolve adb via PATH and SDK env only
Drop hardcoded per-OS SDK layout guesses; honor PATH, ANDROID_HOME,
and ANDROID_SDK_ROOT (with adb.exe on Windows).
* style(mobile): apply ruff format to mobile modules
CI runs ruff format --check; keep these files format-clean.
---------
Co-authored-by: jubaoliang <jubaoliang@gmail.com>
* feat: workspace backend sandboxing, execute-env injection, and ephemeral image refs
Workspace file-I/O hardening across backend and dashboard:
- Host directory sandboxing via root_dir allow-list and denied prefixes
- Execute-environment defaults injected into harness backend specs
- Ephemeral workspace image rematerialization for model calls
- Attachment hint expansion and inbound store improvements
- Portable memory backend and skill workspace catalog updates
- Dashboard UI for agent backend fields and root-dir selection
- Bump harness-agent 0.9.23 / harness-memory 0.9.7; docs + install notes
* feat: add user invitation codes with admin management and redeem flow
- Add user_invites table (migration 009) plus SQLite/Postgres reconcile paths
- Add InviteRepo and InviteService for create/revoke/list/redeem
- Expose public validate/redeem endpoints and admin create/revoke/list routers
- Extract default-agent bootstrap into octop.infra.agents.default_agent
- Add invite error codes and en/zh i18n strings
- Dashboard: invite drawer, login redeem UI, users list, and locales
* fix: add Windows cross-platform guards for pre-existing sandbox/rootfs tests
- Guard POSIX/container-only tests (rootfs-absolute /.octop/... workspace
paths) with posix_only in test_thread_artifacts.py and test_agent_manager.py
- Normalize the rendered workspace path assertion in test_octop_builtin_skills.py
(forward slashes on Windows, not str(tmp_path) backslashes)
- Canonicalize ws_dir before the prefix check in attachment hint/path tests
(tempfile may yield an 8.3 short path on Windows while the resolved
attachment path uses the long form)
These failures predate the user-invites commit and are unrelated to it; the
product path logic is correct.
---------
Co-authored-by: jubaoliang <jubaoliang@tencent.com>
* feat: add per-user module permissions (RBAC) with admin bypass
Introduce a module-level permission system so non-admin users can be
scoped to a subset of dashboard modules. Adds a `permissions` TEXT column
on the `users` table (migration 006, SQLite + PostgreSQL), a central
permission catalog in `infra/users/permissions.py`, backend ACL checks
across routers, and dashboard gating via `RequirePermission` /
`ForbiddenPage` keyed by nav module. `admin` always bypasses every gate;
read access and chat/agent use are never gated.
* fix: gate connector install-cli by connectors permission (not admin-only)
The host CLI installer is a connectors-module operation and should be
gated by the `connectors` module permission, consistent with the rest of
the connector routes, instead of being admin-only.
The earlier RBAC change demoted this route from `current_admin` but the
test `test_install_cli_forbidden_for_non_admin` still failed because the
`create_user` test helper grants `BASELINE_PERMISSIONS` (which includes
`connectors`) by default, so the "non-admin" user actually held the
permission. Gate the route with `require_permission("connectors")` and
create the test user with `permissions=[]` so it genuinely lacks the
key and is rejected with 403.
---------
Co-authored-by: jubaoliang <jubaoliang@tencent.com>