feat(server-mode): native-like folder browser, a developer kept to their own folder, no password minimum

- Folder browser (the Browse fallback for a remote browser): back/forward/up,
  a clickable breadcrumb that becomes a path field (Ctrl+L), Places (Home,
  the user's workspaces, recent picks), a filter, Name/Modified columns,
  Show hidden and New folder. A click selects; a double-click or Enter
  opens a folder or picks a file; Backspace goes up; typing jumps to a name.
- GET /api/lanes/browse: `hidden=1` (never the dot entries at the top of a
  non-admin's own folder), each entry's `mtime`, the answer's `home`.
- POST /api/lanes/browse/mkdir: one plain folder name inside an existing
  folder; a non-admin only in their own folder, none in server mode without
  one; under S3 a member's folder is made as the member.
- scope.ownFolder falls back to server.conf's USERS_ROOT under S3, so a
  settings file without AGENTHUB_USERS_ROOT no longer opens the host's home
  to every developer.
- Passwords: any non-empty password is accepted (no 8-character minimum).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 14:43:03 +07:00
parent b0dd5af22f
commit 763759189f
22 changed files with 1174 additions and 110 deletions
+18
View File
@@ -42,6 +42,24 @@
"browse.empty": "This folder is empty.",
"browse.fileTitle": "Browse for a file",
"browse.select": "Select this folder",
"browse.back": "Back (Alt+←)",
"browse.create": "Create",
"browse.editPath": "Type a path (Ctrl+L)",
"browse.filter": "Filter…",
"browse.forward": "Forward (Alt+→)",
"browse.hint": "Double-click or Enter opens · Backspace goes up · type to jump",
"browse.home": "Home",
"browse.modified": "Modified",
"browse.name": "Name",
"browse.newFolder": "New folder",
"browse.newFolderName": "Folder name",
"browse.noMatch": "Nothing matches the filter.",
"browse.places": "Places",
"browse.recent": "Recent",
"browse.selectFile": "Select file",
"browse.showHidden": "Show hidden",
"browse.up": "Up one level (Backspace)",
"browse.workspaces": "Workspaces",
"browse.title": "Browse for a folder",
"changes.back": "All files",
"changes.bin": "bin",
+2 -2
View File
@@ -25,7 +25,7 @@
"username": "Username",
"usernameHint": "Letters, digits, '.', '_' or '-'",
"password": "Password",
"passwordHint": "At least 8 characters",
"passwordHint": "No minimum length",
"newPassword": "New password",
"changeRole": "Change role",
"disable": "Disable",
@@ -64,7 +64,7 @@
"ESELF": "You cannot change your own role or disable yourself.",
"EEXISTS": "That username is taken.",
"EBADUSER": "Username: letters, digits, '.', '_' or '-' (up to 64).",
"EBADPASSWORD": "Password: at least 8 characters."
"EBADPASSWORD": "Password cannot be empty."
},
"readOnly": "Analysts can view accounts but not change them.",
"auditTitle": "Audit log",
+18
View File
@@ -42,6 +42,24 @@
"browse.empty": "Thư mục này trống.",
"browse.fileTitle": "Duyệt chọn tệp",
"browse.select": "Chọn thư mục này",
"browse.back": "Quay lại (Alt+←)",
"browse.create": "Tạo",
"browse.editPath": "Gõ đường dẫn (Ctrl+L)",
"browse.filter": "Lọc…",
"browse.forward": "Tiến (Alt+→)",
"browse.hint": "Nháy đúp hoặc Enter để mở · Backspace để lên · gõ chữ để nhảy tới",
"browse.home": "Thư mục chính",
"browse.modified": "Ngày sửa",
"browse.name": "Tên",
"browse.newFolder": "Thư mục mới",
"browse.newFolderName": "Tên thư mục",
"browse.noMatch": "Không có mục nào khớp bộ lọc.",
"browse.places": "Vị trí",
"browse.recent": "Gần đây",
"browse.selectFile": "Chọn tệp",
"browse.showHidden": "Hiện mục ẩn",
"browse.up": "Lên một cấp (Backspace)",
"browse.workspaces": "Workspace",
"browse.title": "Duyệt chọn thư mục",
"changes.back": "Tất cả file",
"changes.bin": "bin",
+2 -2
View File
@@ -25,7 +25,7 @@
"username": "Tên đăng nhập",
"usernameHint": "Chữ, số, '.', '_' hoặc '-'",
"password": "Mật khẩu",
"passwordHint": "Ít nhất 8 ký tự",
"passwordHint": "Không giới hạn độ dài tối thiểu",
"newPassword": "Mật khẩu mới",
"changeRole": "Đổi vai trò",
"disable": "Khoá",
@@ -64,7 +64,7 @@
"ESELF": "Bạn không thể tự đổi vai trò hay tự khoá chính mình.",
"EEXISTS": "Tên đăng nhập này đã có người dùng.",
"EBADUSER": "Tên đăng nhập: chữ, số, '.', '_' hoặc '-' (tối đa 64 ký tự).",
"EBADPASSWORD": "Mật khẩu: ít nhất 8 ký tự."
"EBADPASSWORD": "Mật khẩu không được để trống."
},
"readOnly": "Analyst chỉ xem được tài khoản, không thay đổi được.",
"auditTitle": "Nhật ký audit",