Develop #16

Merged
tao.chen merged 273 commits from develop into main 2026-08-21 10:42:09 +08:00
273 Commits
Author SHA1 Message Date
tao.chen 3dc049f46e fix: optimize ArtifactListImpl 2026-08-20 20:29:22 +08:00
tao.chen 05c2157c4a fix: monaco-editor offline build error 2026-08-20 20:22:11 +08:00
tao.chen 3dfa055698 fix: monaco-editor offline build error 2026-08-20 20:16:03 +08:00
tao.chen 6a8bdf6b16 fix: monaco-editor offline 2026-08-20 20:11:06 +08:00
tao.chen d3259ba452 fix: monaco-editor offline 2026-08-20 19:30:23 +08:00
tao.chen 5c15e68a40 Merge branch 'feat/schedule-cleanup-handover' into develop 2026-08-20 19:27:32 +08:00
tao.chen e4d010ec76 fix: monaco-editor offline 2026-08-20 19:23:42 +08:00
Winnie bc62034241 feat: improve schedule cleanup and handover 2026-08-20 19:12:44 +08:00
tao.chen ae3b6d63e2 Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-20 12:08:10 +08:00
tao.chen b600c6810b fix: P0-5 — upload-status rollback, streaming copy (LOCAL only), user re-verify, honest lock
B1: `_mark_upload_failed_and_raise` now commits on a separate session
  - Helper takes `request + upload_id`, opens a fresh session from
    `request.app.state.session_factory` and commits there before raising.
  - Closes the named-lock connection-pool leak Codex flagged: the old
    "commit-on-the-same-session" implementation could return the
    GET_LOCK connection to the pool before the enclosing
    `finally: release_named_lock` ran, leaking `mp:<hash>` for up to
    `pool_recycle` and re-opening the same-key upload race.
  - Same helper now used by `create_server_object_payload`'s put-failure
    branch — two failure paths have identical semantics.

B2: streaming copy for soft-delete + restore (`get_stream() + put()`)
  - LOCAL backend: zero-copy (aiofiles stream write). OOM fixed.
  - S3 backend: still OOMs on multi-GB objects — `put()` materializes
    the async iter via `b"".join(chunks)`. Multipart `put` is a
    follow-up; do NOT claim "OOM fixed on production" since production
    defaults to S3.

C1: worker re-verifies `Users.status='active' AND is_deleted=0`
  - `_assert_user_active` called from `_execution_context` after
    resolving `triggered_by`; skips `SYSTEM_CRON_USER_ID`.
  - `USER_DISABLED` error_code goes into the `NODE_FINISHED_EVENT`
    outbox payload — `schedule_node_runs` has no `error_code` column,
    the row only carries the `message` text. Docstrings corrected to
    say so explicitly (previous docstring falsely promised row-level
    observability).

F1: honest browser-local file lock
  - `api.ts` `acquireFileLock/heartbeatFileLock/releaseFileLock/
    releaseFileLockOnUnload` are now no-ops with comments stating they
    never call the network.
  - `scriptWorkspaceStore` dropped `tickHeartbeats`; `tickCleanup`
    simplified to just clear cache.
  - `useEditSessionLifecycle` dropped its 15s heartbeat `setInterval`.
  - `ScriptWorkspace.tsx` renders `.local-lock-banner` info bar when
    `isEditing`. Two tabs may still silently last-write — banner is the
    only guard (acceptable disclosure-only tradeoff).

Dead code: deleted the duplicate `upload_bytes_to_session` in
`backend/src/backend/storage_api.py`. The `services.storage` import
is now the only source of the function; `create_upload_record`'s
docstring updated to point at `backend.resources`.
2026-08-20 12:07:52 +08:00
tao.chen cc8ac220a5 perf(schedule): 减少重渲染与冗余动画
- useCanvasNodeDrag.moveDrag 改 ref 直改 DOM,松手才写 store,避免拖拽期间反复重渲染 SchedulePage
- runs 轮询改 setTimeout 链式 + 移除 runs 依赖,避免每 1.5s 重建 interval
- SchedulePage 拆 PositionDraftBadge / RunNowButton,删除冗余的 runs/runsLoading/positionDraftCount 订阅
- 拆 ScheduleEdge 组件 + React.memo + useMemo,切换 edge 选中时不再重算所有 edgePath
- 删除 schedule.css 中引用未定义 keyframes 的 modal-in/spin 死动画
- 删除 .schedule-edge-line transition、.schedule-run-result-backdrop backdrop-filter;补 .artifact-card transition

Refs: kaneo #19-#24
2026-08-20 11:27:45 +08:00
tao.chenandClaude Fable 5 4acfbb162f fix: P0-4 schedule node janitor + runtime reaper/lock invariants
S2: schedule worker add janitor task that force-terminals node_runs
whose deadline (timeout_seconds + retry_count*retry_interval + 120s
slack from started_at) has passed. Closes the gap where outbox retry
exhaustion (5 tries, capped 30s backoff) marked the *event* failed
but left the *node_run* stuck in queued/running forever. Re-reads the
row under FOR UPDATE before writing so a worker that races us to a
real terminal state is not overwritten; idempotency key uses
:timed_out variant so the :finished path cannot collide.

R1: extract _reap_once() from _reap_loop for testability; in the
dead-process branch, re-verify (process.pid, started_at) against the
live JUPYTER_PROCESSES entry before del. A start_workspace that
replaced the dead record mid-cycle used to have its new entry
silently erased by the reaper's stale snapshot — leaked the port.

R2: delete _drop_workspace_lock and its two call sites
(stop_workspace tail, get_workspace 404 path). Popping the lock
object after release breaks mutual exclusion for any coroutine still
holding the old reference while a fresh caller gets a new lock
object — same ws_id can race two starts. The dict is bounded by the
number of workspaces so the leak is negligible; invariant lives on
WORKSPACE_LOCKS in a comment.

Tests:
- schedule/tests/test_janitor.py — 8 tests covering normal kill /
  healthy-skip / worker-race / never-started / multi-row batch /
  cancellation propagation / per-iteration self-heal
- runtime/tests/test_process.py — 7 tests covering reaper identity
  match / replacement-skip / alive-preserved + lock
  same-object / concurrent-serialize / survives-stop /
  helper-removed guard

uv run --package schedule pytest schedule/tests → 14 passed
uv run --package runtime pytest runtime/tests  →  7 passed

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 10:49:47 +08:00
tao.chen e5633cc95a fix: artifact_bucket 2026-08-20 10:26:44 +08:00
tao.chen d8a31bde95 fix: update_script rewrite metadata 2026-08-20 09:57:46 +08:00
Winnie 3b0229f018 修复失败策略运行逻辑 2026-08-18 11:10:10 +08:00
Winnie ff700d8db4 fix: stabilize cron scheduling and run history 2026-08-17 18:55:31 +08:00
xiaozhu 23823325e6 fix:writeText不可用问题 2026-08-17 17:31:12 +08:00
tao.chen 3cbf04bcba merge develop-2 → develop: P0-1 security fix
Brings the P0-1 service-token auth, /internal/* 端点收紧到 1, and
docker-compose 端口映射删除到 develop. rclone RC 子项按用户决定
明确忽略。详见 develop-2 commit dfe3f0b.
2026-08-17 16:49:53 +08:00
tao.chenandClaude Fable 5 dfe3f0b118 fix(security): P0-1 — port exposure + service-token auth on /internal/* + jupyter RPC
The fix lands in three concentric layers, all backed by a single
INTERNAL_SERVICE_TOKEN shared secret so we have one mechanism
instead of three:

1. docker-compose: drop the backend.ports: 8891:8000 and
   runtime.ports: 8892:8000 mappings. Nginx is the only host
   ingress again (architecture §2.2).
2. /internal/v1/*: the storage control plane had six endpoints, five
   of which were dead code (frontend already migrated to
   /api/v1/data-resources/* with JWT; schedule only ever called
   POST /internal/v1/objects). Delete the dead routes, mount the
   one survivor with Depends(require_internal_service) that
   compares the X-Internal-Service-Token header against
   settings.internal_service_token with secrets.compare_digest.
3. POST /api/v1/jupyter on the runtime container: previously open
   inside the Docker network. Same token mechanism — backend's
   runtime_http_client now carries the header, runtime's
   handle_jupyter_action requires the same header. /api/v1/health
   stays open for the Nginx and compose healthchecks.

The schedule worker was already configured to call
POST /internal/v1/objects; build_storage_http_client now
sets the token header so its existing call site keeps working
without changes.

Files touched:
  backend/src/backend/storage_api.py   # 5 dead routes deleted + token guard
  backend/src/backend/main.py          # runtime_http_client header
  runtime/src/runtime/main.py          # require_internal_service Depends
  common/src/common/config.py          # internal_service_token setting
  schedule/src/schedule/service.py     # httpx client header
  docker-compose.yml                   # ports dropped, INTERNAL_SERVICE_TOKEN env
  .env.example                         # INTERNAL_SERVICE_TOKEN placeholder
  API.md / README.md / DEVELOP.md      # §9 trimmed to 1 endpoint

Verified:
  compileall -> 0 errors
  pytest backend/tests -> 37 passed
  in-process ASGI smoke:
    POST /internal/v1/objects no/wrong/correct token -> 401/401/200
    POST /api/v1/jupyter   no/wrong/correct token -> 401/401/200
    5 deleted internal routes -> 404
  docker compose config (with env) -> OK

P0-1 still has one open sub-item (rclone RC --rc-no-auth) that
the user has explicitly deferred; not touched here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 16:48:46 +08:00
tao.chen 6258cf5d12 fix: offline deploy 2026-08-17 15:59:19 +08:00
tao.chen 0974881fbb fix: offline deploy 2026-08-17 15:30:21 +08:00
tao.chen cbfbee7fe0 chore: add CODE_REVIEW.md 2026-08-14 20:55:59 +08:00
tao.chen b6eb069849 fix(backend): enhance storage/resource concurrency, idempotency, and deletion safety
Summary of changes:

- Resources Bind Idempotency (High 1+2):
  - Check existing active storage object bindings before duplicate check.
  - Return existing binding (`reused: true`) on retry with same upload_id.
  - Filter by `status == "active"` to bypass dead/deleted rows during reuse check.

- Storage Concurrent Overwrite (High 3):
  - Add `acquire_named_lock` and `release_named_lock` helpers using MySQL `GET_LOCK`/`RELEASE_LOCK` hashed to <= 64 chars.
  - Wrap `upload_bytes_to_session` PUT+INSERT critical section with named lock on `object_key`.
  - Re-check key collision inside lock; append ULID suffix on collision.

- Shared Reference Deletion Protection (Medium 4):
  - Check active references before deleting storage objects in `delete_resource`.
  - Delete only `DataResources` record if storage object is still referenced elsewhere.

- Robust Usage Type Fallback (Medium 5):
  - Replace direct dict lookup for `USAGE_TYPE_TO_PURPOSE[item.usage_type]` with `.get(..., "workspace")` default.

- Idempotency Key Path Matching (Medium 6):
  - Move `file_name`/`target_path` validation forward and include path dimension in comparison.
  - Strip uniqueness suffix via `_strip_uniqueness_suffix` before key comparison to avoid false 409s on valid retries.

- Usage Type & Bind Concurrency Control (Low 7 & 8):
  - Reject bind requests with 409 if upload session purpose is not `data_resource`.
  - Wrap resource duplicate check and creation in named lock using `(owner, directory, name)`.

- Trash Key Uniqueness & Restore Compatibility (Low 9):
  - Update `trash_key` format to `{purpose}/{object_key}-{storage_object_id}` to prevent collisions.
  - Update `object_key_hash` on trash move.
  - Update restore logic in `storage_api.py` to strip suffix while maintaining backward compatibility with legacy keys.

- Dead Code Removal (Low 10):
  - Remove unreachable `upload_status = "failed"` and redundant `session.rollback()` in `IntegrityError` block.

- Tests & Mocks:
  - Add/update 5 test cases covering non-data_resource bind rejection, suffix stripping, and path recovery.
  - Add named lock statement mocks for DB testing.
2026-08-14 20:53:07 +08:00
tao.chen f72dfd10e8 fix: delete bug 2026-08-14 20:37:25 +08:00
tao.chen 1079b62f0a update 2026-08-14 20:08:51 +08:00
tao.chen 85b2916850 fix: local_storage_base_dir 2026-08-14 20:03:40 +08:00
tao.chen 25e563dcaa update: ruff check --fix 2026-08-14 19:51:58 +08:00
tao.chen d855912791 fix: soft delete helper 2026-08-14 19:39:09 +08:00
tao.chen 76af0f763c update: README.md 2026-08-14 19:30:25 +08:00
tao.chen 139f2c02c1 fix: delete error 2026-08-14 19:19:41 +08:00
tao.chen 2e070fae78 fix: pre check 2026-08-14 19:13:17 +08:00
tao.chen 5c5dec9a4a fix: allows_same_name_different_parent 2026-08-14 18:49:27 +08:00
tao.chen 5d49ff5e34 fix: file upload error 2026-08-14 18:22:46 +08:00
tao.chen c65d6dc684 fix: build error 2026-08-14 17:19:07 +08:00
tao.chen 45cb2f8409 fix: build error 2026-08-14 17:16:53 +08:00
tao.chen de1682c00d update: Dockerfile 2026-08-14 17:03:27 +08:00
tao.chen 341cc77a79 update: Dockerfile 2026-08-14 16:02:19 +08:00
tao.chen 2014d59681 update: Dockerfile 2026-08-14 15:55:00 +08:00
tao.chen 7347b409e5 update: port 2026-08-14 15:32:34 +08:00
tao.chen af9466c4e6 update: UV_HTTP_TIMEOUT 2026-08-14 15:27:16 +08:00
tao.chen e9a7e1a24e update: docker-compose.yml 2026-08-14 15:19:29 +08:00
Winnie be475dd0d9 fix: support local storage runtime and schedule logs 2026-08-14 15:06:36 +08:00
tao.chen 65d14b8610 update: dir tree 2026-08-14 15:02:55 +08:00
tao.chen 4530811441 update: spec 2026-08-14 14:40:34 +08:00
tao.chen d415154f41 update: migrate 2026-08-14 14:32:44 +08:00
tao.chen c45687ef18 fix: update unique key 2026-08-14 13:44:57 +08:00
tao.chen 7330f313ff update: add custom dep 2026-08-14 13:15:18 +08:00
tao.chen 518853cbb0 fix 2026-08-14 12:40:36 +08:00
tao.chen 604e66ffe0 fix: DataResourceUploadModal.tsx 2026-08-14 12:28:22 +08:00
tao.chen 480e1cc638 update: data source 2026-08-14 11:59:06 +08:00
tao.chen 225a585499 update: validate_target_path 2026-08-14 11:32:15 +08:00
tao.chen b9becffab2 update: 数据资源文件上传 2026-08-14 11:31:48 +08:00
tao.chen 462617b66d feat: datasource 2026-08-13 20:13:37 +08:00
tao.chen 0b5b50edb9 update: rel path 2026-08-13 19:51:20 +08:00
tao.chen 63a14b1884 fix: params error
NameError: name 'session' is not defined
2026-08-13 19:20:36 +08:00
tao.chen f5cb22e8cd feat: upload resource 2026-08-13 19:09:13 +08:00
tao.chen 912c0ed22d Merge branch 'refactor/storage' into develop 2026-08-13 18:11:50 +08:00
tao.chen 19157ad20b test 2026-08-13 18:08:12 +08:00
xiaozhu bcddaac083 fix:修复只读文件切换编辑文件时iframe重新加载问题 2026-08-13 17:24:55 +08:00
xiaozhu 9160175d51 update:只读文件隐藏操作按钮 2026-08-13 16:05:16 +08:00
tao.chen 532f0d6c91 fix: dir tree 2026-08-13 12:12:58 +08:00
tao.chen 3094a47298 fix: path error 2026-08-13 11:48:24 +08:00
tao.chen 83d0e0adca fix: bug
1. Cannot find name 'PythonEditorBuffer'
2. Cannot find name 'PythonEditor'
2026-08-13 11:26:31 +08:00
tao.chen 1ad0ec9dbf update: docker-compose.yml 2026-08-13 11:03:08 +08:00
tao.chen dc68739216 Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-13 11:01:43 +08:00
tao.chen 49c8a27841 update: update storage struct 2026-08-13 11:01:37 +08:00
xiaozhu a2f515cf87 fix:锁定文件只读 2026-08-13 10:26:01 +08:00
xiaozhu 7b10f08484 Merge branch 'develop' of http://8.153.151.51:8888/team_group/model-develop into develop 2026-08-13 10:06:46 +08:00
tao.chen da9a1ec472 update: storage path 2026-08-13 09:35:27 +08:00
tao.chen 302bda2ee9 fix: directory tree 2026-08-12 20:45:29 +08:00
tao.chen d600d5dbb1 fix: directory cached 2026-08-12 20:41:44 +08:00
tao.chen b1ceaeb173 fix: storage and directories bug 2026-08-12 20:18:29 +08:00
tao.chen 0bcdbb1068 fix: add logging limit 2026-08-12 19:52:14 +08:00
tao.chen 9d0ca1e8b6 fix: READINESS_TARGETS 2026-08-12 19:49:05 +08:00
tao.chen 8abe505d17 fix: multi owner 2026-08-12 18:58:18 +08:00
tao.chen 495018de34 update: workspace lazy load 2026-08-12 18:36:17 +08:00
tao.chen c6c2481b96 feat: workspace 目录树服务端懒加载
- api.ts: listWorkspaceDirectories 支持 parent_path 查询; WorkspaceDirectory 增加 has_children; 同步 WorkspaceBoundApi 签名
- AuthContext: 绑定透传 parentPath
- scriptWorkspaceStore: 新增 expandedPaths/loadingChildrenPaths/loadedChildPaths, loadChildren/toggleExpanded, 局部刷新 createFolder/deleteDirectory
- WorkspaceTree: 移除 useState, 改为受控展开/加载状态
- ScriptExplorer: 从 store 读取并透传展开状态与 toggle
2026-08-12 18:06:35 +08:00
tao.chen a09551bd3c update: workspace members 403 2026-08-12 17:14:47 +08:00
tao.chen 6b9f851810 update: scripts.py api 2026-08-12 17:14:18 +08:00
tao.chen a86432b102 update: PythonEditor.tsx 2026-08-12 16:58:00 +08:00
tao.chen 2fcdf51cfc update: PythonEditor.tsx 2026-08-12 16:49:21 +08:00
xiaozhu 04447abfb0 fix: Dockerfile 移除 --frozen 参数 2026-08-12 16:38:31 +08:00
xiaozhu 55e37b5a69 fix: Dockerfile 中先更新 uv.lock 再安装 2026-08-12 16:32:35 +08:00
xiaozhu 8d83adf1aa fix:路由优化 2026-08-12 15:27:10 +08:00
xiaozhu e4b8c320a3 fix:css报错 2026-08-12 14:55:09 +08:00
xiaozhu fe65034aa8 feat:脚本只读 2026-08-12 14:34:31 +08:00
tao.chen dc4d190935 fix: python script 404 2026-08-12 13:45:15 +08:00
tao.chen 91339aa993 update: docker-compose.yml 2026-08-12 13:33:29 +08:00
tao.chen 416ff4d06a feat: add logger 2026-08-12 12:43:31 +08:00
tao.chen 3981c32781 refactor: directory 2026-08-12 12:23:19 +08:00
tao.chen a378ea5352 feat: add pytest in dev 2026-08-12 12:21:48 +08:00
tao.chen e23df83e0d fix: bugs 2026-08-11 22:03:01 +08:00
tao.chen bff7b7f9a6 fix: bugs 2026-08-11 21:53:52 +08:00
tao.chen dd6f176ca8 fix: file lock 2026-08-11 21:26:55 +08:00
tao.chen d4013a07a9 rollback 2026-08-11 20:41:15 +08:00
tao.chen e1360c5c38 test: backend 2026-08-11 20:09:44 +08:00
xiaozhu a8a54f1b78 fix:光标 2026-08-11 19:02:22 +08:00
tao.chen e80cbbd81c feat: execute node python version 2026-08-11 19:00:55 +08:00
tao.chen 38cd06ee7a update: clean dockerfile 2026-08-11 18:57:34 +08:00
tao.chen 05091c425a update: filter by owner / visibility 2026-08-11 18:56:47 +08:00
xiaozhu 064403ad70 fix:新建项目更新项目选项 2026-08-11 18:53:11 +08:00
tao.chen c63f745374 fix: error 2026-08-11 18:42:15 +08:00
tao.chen ca12646387 update: env error 2026-08-11 18:26:37 +08:00
tao.chen 78e83e1765 fix: migrate bug 2026-08-11 18:13:15 +08:00
tao.chen ed7a6cd858 fix: migrate bug 2026-08-11 18:05:34 +08:00
tao.chen 1b0083be47 refactor: kernel spec 2026-08-11 17:47:39 +08:00
tao.chen 6c6e7e6500 update: python script run in python intercept 2026-08-11 16:20:40 +08:00
tao.chen ec9effc254 update: npm registry 2026-08-11 16:19:34 +08:00
tao.chen b49d804718 update: upgrade base image 2026-08-11 16:12:24 +08:00
tao.chen fe7f1a744e feat: schedule node add python version 2026-08-11 15:56:05 +08:00
tao.chen e28bc39328 fix: default user 2026-08-11 15:13:26 +08:00
tao.chen 4269eed018 fix: 422 error 2026-08-11 15:13:13 +08:00
tao.chen b44d057241 feat: preview components 2026-08-11 15:02:16 +08:00
tao.chen 5969f2f749 reformatter 2026-08-11 11:13:13 +08:00
xiaozhu 144d931f00 fix:禁工作台跳系统管理 2026-08-10 11:24:04 +08:00
tao.chen b00a0e9ae1 fix: hook 2026-08-07 20:42:36 +08:00
tao.chen 567786215e refactor: SchedulePage.tsx 2026-08-07 20:40:41 +08:00
tao.chen 084de5b2d6 fix: storage.py 2026-08-07 20:14:29 +08:00
tao.chen a97aad3179 fix: schedule error 2026-08-07 19:59:04 +08:00
tao.chen e7bce03794 fix: storage_api.py 2026-08-07 19:58:42 +08:00
tao.chen 7b4b752109 fix: import workspace member 2026-08-07 19:25:04 +08:00
tao.chen 45808192e0 refactor: SchedulePage.tsx 2026-08-07 19:19:37 +08:00
tao.chen 6ff2127de7 update: add logger info 2026-08-07 19:19:25 +08:00
tao.chen ed517c488b Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-07 18:50:57 +08:00
tao.chen 14c41a22b6 fix: runtime timeout 2026-08-07 18:50:48 +08:00
xiaozhu 646c809c65 feat:菜单 2026-08-07 18:43:10 +08:00
tao.chen 37d89c74d6 Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-07 18:22:08 +08:00
xiaozhu f90d15bbe9 update:系统管理 2026-08-07 18:08:16 +08:00
tao.chen e2615be2e8 refactor: extract components 2026-08-07 17:38:28 +08:00
tao.chen 873a464629 fix: auth error 2026-08-07 16:14:13 +08:00
tao.chen 10347efa73 update: exclude hidden dir 2026-08-07 15:08:36 +08:00
tao.chen 2ee36b48ec update: auth
update auth api
2026-08-07 14:41:20 +08:00
tao.chen 984894d797 refactor: SchedulesPageRoute.tsx, UserManagementPage.tsx, ProjectManagementPage.tsx 2026-08-07 14:40:46 +08:00
tao.chen ec57fb6c7e update: storage
update storage base path
2026-08-07 14:37:56 +08:00
tao.chen 6b2db5c613 fix: docker-compose.yml
env var error
2026-08-07 14:03:01 +08:00
tao.chen edd560cf84 fix: docker-compose.yml
env var error
2026-08-07 14:01:17 +08:00
tao.chen 96f9a5c644 update: docker-compose.yml
add volumes
2026-08-07 13:58:04 +08:00
tao.chen ffd1db45fc fix: workspace refresh 2026-08-07 13:12:07 +08:00
tao.chen 03096a8951 feat: user permission 2026-08-07 13:00:14 +08:00
tao.chen a891f1f649 fix: db version 2026-08-07 12:59:41 +08:00
tao.chen 586d9fa645 update: API.md 2026-08-07 12:58:54 +08:00
tao.chen 2369dc3dda rollback vite 2026-08-07 12:56:52 +08:00
tao.chen e8de719523 feat: add SchedulesPageRoute.tsx 2026-08-07 12:55:25 +08:00
tao.chen 6f574073e3 fix: frontend routes 2026-08-07 12:47:37 +08:00
tao.chen d7934a42ab refactor: uiStore.ts 2026-08-07 12:23:50 +08:00
tao.chen 2272e1f390 feat: add user api 2026-08-06 19:26:57 +08:00
tao.chen 2894b1f06f fix: storage_api.py 2026-08-06 19:02:11 +08:00
xiaozhu 5fa61d7146 fix:上传文件点击编辑没反应 2026-08-06 17:21:46 +08:00
xiaozhu fcc0964765 update:多iframe 2026-08-06 16:32:39 +08:00
tao.chen 245b522d36 feat: add seed to venv 2026-08-06 12:30:33 +08:00
tao.chen 6e6f880eb0 rollback 2026-08-06 11:00:41 +08:00
tao.chen a7963406b3 fix: default kernel 2026-08-06 10:55:12 +08:00
tao.chen e2329ea429 fix: default kernel 2026-08-06 10:46:21 +08:00
tao.chen d813508461 feat: create user api 2026-08-06 10:42:17 +08:00
tao.chen bf2cd9bd69 update: rename JUPYTER_VENV 2026-08-06 10:40:03 +08:00
tao.chen 53999cbd5b docs: add API 2026-08-06 10:26:16 +08:00
tao.chen a220afdb0b update: schedule add multi python 2026-08-06 10:26:07 +08:00
tao.chen 485d324d39 update: list users 2026-08-06 10:25:50 +08:00
tao.chen b9a028a1db update: multi python version 2026-08-06 10:03:58 +08:00
taochen dcc2088999 add port 2026-08-06 09:45:40 +08:00
tao.chen f63ddc59b5 update: remove jupyter env install kernel /opt/venv/python3.12 2026-08-05 19:16:09 +08:00
tao.chen 90c3b5ee6f fix: save version error 2026-08-05 19:14:05 +08:00
tao.chen c4529782b5 test: Isolation jupyter env 2026-08-05 18:59:33 +08:00
tao.chenandClaude Fable 5 d5de1a63d4 fix: eager-load server defaults on StorageObjects to avoid MissingGreenlet
publish_version -> create_server_object_payload -> storage_payload reads
item.created_at on a sync helper. Without eager_defaults, server-default
columns stay unloaded after INSERT, the next sync read triggers a lazy
refresh through the async driver, and MissingGreenlet fires.

Enable mapper-level eager_defaults on StorageObjects so server-default
columns (created_at, updated_at, ...) are round-tripped into the ORM
object immediately after INSERT. No other table or session config
touched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 18:36:26 +08:00
Winnie 78c3f1e954 Merge remote-tracking branch 'origin/develop' into develop 2026-08-05 17:53:49 +08:00
tao.chen 264faecb0d fix: python3.10 build error 2026-08-05 17:49:53 +08:00
Winnie cec6a4468e Merge remote-tracking branch 'origin/develop' into develop 2026-08-05 17:49:29 +08:00
tao.chen 450609d868 feat: support python3.10 2026-08-05 17:46:13 +08:00
Winnie 2bfe43a63f Merge branch 'develop' of http://8.153.151.51:8888/team_group/model-develop into develop 2026-08-05 17:46:05 +08:00
tao.chen c2617da61c feat: support python3.8 2026-08-05 17:10:53 +08:00
tao.chen 8519393895 update: admin valid 2026-08-05 17:10:36 +08:00
Winnie 30cde4a56c 添加查看调度运行结果 2026-08-05 16:34:35 +08:00
xiaozhu 1ef9961307 fix:切换空间脚本目录未更新问题 2026-08-05 16:25:00 +08:00
tao.chen 5e68435dd9 Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-05 16:01:34 +08:00
tao.chen e997e6cf56 fix: bucket name error 2026-08-05 16:01:28 +08:00
xiaozhu 9b5de51a68 chore:调度文件拆分 2026-08-05 15:58:18 +08:00
xiaozhu 8c4d2c0517 chore:系统管理拆分 2026-08-05 15:13:34 +08:00
tao.chen d851f98581 fix: runtime error 2026-08-05 15:04:07 +08:00
tao.chen 5b88f81e4b update: alembic baseline 2026-08-05 15:00:57 +08:00
tao.chen 07d2423c13 update: remove workspace operation table and refactor 2026-08-05 14:43:48 +08:00
tao.chen c3b078a827 Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-05 14:29:14 +08:00
xiaozhu 394081b613 feat:项目管理 2026-08-05 13:50:24 +08:00
tao.chen f4cabe6e20 update: remove storage 2026-08-05 13:41:13 +08:00
tao.chen 309b657d35 docs: align with new storage architecture (s3 + local + server-proxied PUT)
All operator- and developer-facing docs updated to reflect:

  - The unified AsyncStorageBackend abstraction (s3 + local backends).
  - The STORAGE_BACKEND toggle ("s3" default, "local" for dev /
    single-node / air-gapped deployments).
  - The 4-purpose-bucket layout (workspace / version / run_log / trash)
    in both modes — 4 separate S3 buckets in s3 mode, 4 subdirectories
    of LOCAL_STORAGE_BASE_DIR in local mode.
  - The S3_* env var naming (was RUSTFS_*).
  - The server-proxied upload flow (was browser-direct presign-PUT):
    POST /internal/v1/uploads → PUT /internal/v1/uploads/{id} with
    raw bytes → server calls backend.put().
  - The factory helpers workspaces_root() (runtime's view of the
    workspace bucket on disk) and rclone_remote_spec() (s3-mode mount
    source).
  - The "two settings describing the same thing" cleanup: the deleted
    settings.workspace_root, settings.workspaces_root, and
    settings.remote_bucket fields.

Files touched:
  - API.md (§5 data-resource upload flow, §9 storage control plane,
    §10 readiness example)
  - ARCHITECTURE.md (storage layer diagram)
  - CLAUDE.md (architecture description + volume-preservation note)
  - DEVELOP.md (settings list, Storage section, "Wire a new bucket"
    how-to, dev-export example, troubleshooting network hint)
  - README.md (architecture diagram, container table, quick-start
    credentials note, tear-down note, Storage layout section)
  - REFACTOR_NOTES.md (final container list with s3 explanation)
  - backend/README.md (storage backend description)
  - migrations/data/README.md (step 11/12 record mentioning object
    storage)

A handful of historical "RustFS" mentions are intentionally retained
where they name a specific S3-compatible product (e.g. as an example
in REFACTOR_NOTES.md's container list) or document the pre-2026
abstraction name (DEVELOP.md Storage section).
2026-08-05 13:13:20 +08:00
tao.chen 4e290bd80a storage: add UploadSessions columns for server-proxied upload metadata
The server-proxied upload flow (replaces presign-PUT) stores the
file-level metadata directly on the UploadSessions row at session
creation, so step 2 (PUT bytes) can build the StorageObjects row
without re-sending metadata through a separate CompleteUploadRequest.

New columns on upload_sessions:
  file_name    VARCHAR(255) NOT NULL DEFAULT ''
  usage_type   VARCHAR(32)  NOT NULL DEFAULT 'working_copy'
  visibility   VARCHAR(16)  NOT NULL DEFAULT 'private'
  is_immutable TINYINT(1)   NOT NULL DEFAULT 0

The SQLAlchemy model already declares these columns; this migration
applies the schema change to MySQL.

Migration: c3d4e5f6a7b8_upload_session_object_metadata.py
(chains off a2b3c4d5e6f7)
2026-08-05 13:11:55 +08:00
tao.chen d2bb450d30 storage: add local filesystem backend option (STORAGE_BACKEND toggle)
The factory now picks between two backends based on
settings.storage_backend ("s3" default, "local" for dev / single-node /
air-gapped deployments). The new factory helper build_storage_config()
takes one of the 4 PURPOSE_BUCKETS ("workspace" | "version" |
"run_log" | "trash") and returns the kwargs for create_storage(...).

  s3   mode: AsyncStorageBackend over an S3-compatible service
           (S3_WORKSPACE_BUCKET etc. as separate buckets).
  local mode: AsyncStorageBackend over on-disk files; the 4 buckets
           become subdirectories of LOCAL_STORAGE_BASE_DIR (default
           "/data"), so the same 4-bucket layout works in both modes.

Concretely:
  - common/config.py: add storage_backend (default "s3") +
    local_storage_base_dir (default "/data").
  - common/storage/factory.py: add PURPOSE_BUCKETS constant +
    build_storage_config(bucket_name) helper.
  - backend/main.py + backend/storage_api.py: lifespan collapses the
    4-instance construction into one dict comprehension:
      app.state.object_stores = {
        name: create_storage(build_storage_config(name))
        for name in PURPOSE_BUCKETS
      }
    (was 4x ~10-line dicts, one per bucket).
  - runtime/mount.py: when STORAGE_BACKEND=local, skip the rclone mount
    entirely (the shared docker volume at LOCAL_STORAGE_BASE_DIR is the
    store; runtime reads directly).
  - docker-compose.yml: mount the shared local-storage volume at /data
    in both backend and runtime containers.
  - .env.example: document STORAGE_BACKEND + LOCAL_STORAGE_BASE_DIR.

Dependencies added to support both backends:
  - aiofiles>=25.1.0 (local async I/O) to backend + common + runtime.
  - aioboto3>=15.5.0 (async S3) to common.
  - uv.lock regenerated.

After this commit, both modes deploy end-to-end. The s3 mode is the
production default; local mode is opt-in via STORAGE_BACKEND=local.
2026-08-05 13:10:05 +08:00
tao.chen 4b2a67ae5d storage: extract unified AsyncStorageBackend abstraction + migrate from RustFS
Replace the old RustFS-specific storage layer (common.storage.client /
RustFSObjectStore) with a minimal sync/async abstraction:

  AsyncStorageBackend: put / get / get_stream / delete / exists / stat /
                       list / get_url / copy
  StorageBackend:      same surface, sync implementations
  create_storage({"type": "s3" | "local", "mode": "async", ...})
  backends/s3.py:      S3-compatible (boto3 / aioboto3)
  backends/local.py:   on-disk filesystem (aiofiles)

Concretely:
  - Drop RustFSObjectStore + common.storage.client (deleted).
  - Drop the RustFS-specific ensure_bucket / presign_put / move_to_trash /
    rewrite_to_public_path / sha256 / put_bytes methods.
  - Migrate backend/storage_api.py + backend/main.py + backend/scripts.py
    + schedule/service.py + schedule/worker.py to the new abstraction.
  - Migrate backend/storage_client.py + schedule/storage_client.py to
    stub status (HTTP wrapper is dead code post-migration; rewrite pending).
  - Rename all RUSTFS_* env vars to S3_* across .env.example,
    docker-compose.yml, default.conf, scripts/nginx-entrypoint.sh,
    common/config.py.
  - Replace hardcoded rclone remote name "rustfs" with "s3" in
    docker-compose.yml + config.py default.
  - Rename "rustfs" SQLAlchemy column comments + table comments to
    provider-neutral wording; StorageObjects.storage_backend enum
    value moves from "rustfs" to "s3" (DB rows with the old value will
    fail the != "s3" check until a one-shot migration is applied).
  - Drop unused common/src/common/migrations/{README,env.py,script.py.mako}
    (the alembic setup lives in /migrations/, not here).

Migration of the old abstractions has been done in one pass; per-route
method calls (delete / stat / put / get_url) are now direct one-liners
against AsyncStorageBackend.

After this commit:
  - All Python imports resolve; routes compile (compileall green).
  - s3 mode is fully wired.
  - Routes that depended on removed methods (presign_put, move_to_trash,
    rewrite_to_public_path, head() metadata) raise NotImplementedError
    with a one-line TODO; rewriting these route handlers is the next step.
2026-08-05 13:08:32 +08:00
tao.chen 7c456a04ce update: update custom css 2026-08-05 11:07:54 +08:00
tao.chen fdf49a9ece Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-04 18:48:24 +08:00
tao.chen bbf166f3c8 feat: front base dockerfile 2026-08-04 18:48:15 +08:00
tao.chen 00f50d4603 refactor: update frontend Dockerfile 2026-08-04 18:47:59 +08:00
xiaozhu 4e95399d4f chore:platform文件拆分 2026-08-04 18:46:18 +08:00
tao.chen 87382d7bda refactor: update Dockerfile 2026-08-04 18:39:30 +08:00
tao.chen 7cf3a9d02a fix: runtime build failed 2026-08-04 18:00:06 +08:00
tao.chen a6692338cc fix: runtime build failed 2026-08-04 17:58:10 +08:00
tao.chen 004d7289ca update: update jupyter css 2026-08-04 17:45:23 +08:00
tao.chenandClaude Fable 5 45f0ff534f feat: workspace CRUD at platform scope + drop audit_logs
新增系统管理模块 /api/v1/platform/*:
- workspace 实体 CRUD(创建/列表/详情/更新/软删除)
- workspace 成员 CRUD(添加/列表/更新/移除)
- SystemAdminContext 依赖,仅 platform_role_id 指向 admin 角色的用户可访问
- /api/v1/auth/me 与 /auth/login 增 is_system_admin 派生字段
- 不变量:每个 workspace 至少保留一个 admin;系统管理员无法自我移除成员
- 软删除 workspace 级联软删除其成员

清理 audit_logs(无运行时写入,纯死特性):
- baseline 移除 audit_logs 建表与三索引(20 → 19 tables)
- 删除 AuditLogs 模型定义与 __init__.py 导出
- 清理 migrate_system_json / migrate_legacy_workspaces 中的 audit 写入与回填代码

API.md 增 §七系统管理,§七/§八/§九 顺延为 §八/§九/§十,附录 A/B 同步更新。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 17:20:42 +08:00
Winnie c263ae6a5f Merge branch 'develop' of http://8.153.151.51:8888/team_group/model-develop into develop 2026-08-04 16:08:04 +08:00
tao.chen 78e8affc94 Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-04 16:06:00 +08:00
Winnie 333284460b Merge branch 'develop' of http://8.153.151.51:8888/team_group/model-develop into develop 2026-08-04 16:05:57 +08:00
tao.chen 85eb19546e feat: add password 2026-08-04 16:05:54 +08:00
xiaozhu a4019b1a74 fix:脚本文件标签栏 2026-08-04 15:53:17 +08:00
xiaozhu eace1109ac 系统管理页面部分更改 2026-08-04 14:49:10 +08:00
Winnie f3cc83c5fa Merge branch 'develop' of http://8.153.151.51:8888/team_group/model-develop into develop
# Conflicts:
#	schedule/src/schedule/orchestrator.py
#	schedule/src/schedule/worker.py
2026-08-04 14:41:22 +08:00
tao.chen 94a1aef7c7 fix: script not found 2026-08-04 14:24:55 +08:00
Winnie a2deae2f22 修复调度运行失败 2026-08-04 14:09:03 +08:00
tao.chen 1cf2eecbc9 chore: frontend and schedule module 2026-08-04 13:58:19 +08:00
tao.chen e18a7a34a3 update: save version 2026-08-04 13:35:16 +08:00
tao.chen 14e84b6ce2 fix: path error 2026-08-04 13:05:18 +08:00
tao.chen 2a23030d6f fix: path error 2026-08-04 12:57:40 +08:00
tao.chen 4919fe0909 update: create file 2026-08-04 12:40:38 +08:00
tao.chen a27cda5a0c fix: jupyter start params 2026-08-04 12:03:43 +08:00
tao.chen 60b17f5bef update: jupyter start dir 2026-08-04 11:59:04 +08:00
tao.chen ddf112034d update: jupyter api payload, wire os.environ 2026-08-04 11:29:33 +08:00
tao.chen 173d562bd1 update: debug create file by jupyter 2026-08-04 11:06:52 +08:00
tao.chen d45109916a chore: update docker-compose.yml 2026-08-04 10:30:24 +08:00
tao.chen 078d8f8687 update: delete vfs refresh 2026-08-04 09:37:14 +08:00
tao.chen 1bd7da384c feat: add loguru 2026-08-03 20:45:00 +08:00
tao.chen 939a579b07 feat: rclone client 2026-08-03 20:37:56 +08:00
tao.chen 134f8ca552 feat: refresh VFS 2026-08-03 20:23:18 +08:00
tao.chen e1172a0091 update: rclone add remote control 2026-08-03 20:02:42 +08:00
tao.chen 85791ab1ea update: rclone add remote control 2026-08-03 19:57:29 +08:00
tao.chen e19340332a update: hide top-panel 2026-08-03 19:51:24 +08:00
tao.chen 6c4bf47487 update: hide top-panel 2026-08-03 19:43:51 +08:00
tao.chen 2c54f88181 fix: notebook-dir 2026-08-03 19:12:40 +08:00
Winnie feae98cc24 第一次合并develop-fech 2026-08-03 18:27:53 +08:00
Winnie d7bd88335c merge: integrate feat/auth into develop 2026-08-03 17:44:00 +08:00
tao.chen 386efb4d98 update: add volumes 2026-08-03 13:55:41 +08:00
Winnie fd5ea4d33e fix(frontend): support HTTP UUID fallback and bundle Inter fonts 2026-08-03 13:30:03 +08:00
tao.chen 76a572af0d Merge remote-tracking branch 'aliyun/develop' into develop 2026-08-03 11:14:16 +08:00
tchen 48414cb958 Merge branch 'main' into 'develop'
# Conflicts:
#   default.conf
#   docker-compose.yml
#   frontend/Dockerfile
#   frontend/README.md
#   frontend/app/app.css
#   frontend/app/root.tsx
#   frontend/app/routes.ts
#   frontend/package.json
#   frontend/vite.config.ts
2026-08-03 02:56:26 +00:00
tao.chen 7a3c2452e1 feat: auth 2026-08-03 10:51:55 +08:00
tao.chen bededeb101 optimize: add routes 2026-08-03 10:49:39 +08:00
tao.chen a44b984203 chore: rollback mount path 2026-07-31 19:49:02 +08:00
Winnie 4ac8485d3e Merge branch 'develop' of http://8.153.151.51:8888/team_group/model-develop into develop 2026-07-31 19:17:24 +08:00
Winnie 49ee2c0a4a feat: 完善模型平台相关功能 2026-07-31 19:10:37 +08:00
tao.chen 838cbfdc16 chore: else bug 2026-07-31 18:39:44 +08:00
tao.chen fb073c6f99 feat: auth 2026-07-31 17:22:25 +08:00
tao.chen 1994937349 chore: fix dockefile 2026-07-31 15:52:49 +08:00
tao.chen d31fde6abc chore: fix debian source 2026-07-31 15:48:16 +08:00
tao.chen ba96f4f52a chore: update debian source 2026-07-31 15:45:17 +08:00
tao.chen 86988bdaef chore: frontend build 2026-07-31 15:08:31 +08:00
tao.chenandClaude 9fc886a55e perf: decouple notebook execution and tune pools
schedule:
- New _execution_loop runs alongside _database_event_loop. It claims
  job.node.execute rows, sets a 30-min lease on available_at, then
  dispatches each as asyncio.create_task under a Semaphore(N).
  Polling loop is back to sub-millisecond turnaround for
  schedule.run.requested and job.node.finished. Long notebook
  execution no longer blocks DAG advance events.
- _process_pending_events filters by event_type IN
  ('schedule.run.requested', 'job.node.finished'); the executor
  loop owns job.node.execute exclusively.
- _process_outbox_event builds a plain dict envelope before
  handler dispatch; the previous ORM-row handoff risked
  DetachedInstanceError once the outer session closed.
- _sync_once uses get_job + reschedule_job for existing job ids
  instead of add_job(replace_existing=True). Each cron schedule
  no longer removed-and-readded every 5s.
- service.py threads settings.schedule_execution_concurrency into
  the orchestrator (default 4).

common:
- create_async_engine gets explicit pool_size=10, max_overflow=20,
  pool_recycle=1800. No more relying on SQLAlchemy defaults.
- New schedule_execution_concurrency setting.

runtime:
- scan_workspaces: add missing 'import os' (NameError on startup)
  and switch to asyncio.gather bounded by Semaphore(4) so N
  workspaces start in parallel instead of sequentially.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-31 15:07:57 +08:00
tao.chenandClaude b0f93d976f build: switch services to gunicorn with per-service config
Replace uvicorn with gunicorn + UvicornWorker in backend, runtime,
and schedule Dockerfiles. New gunicorn.conf.py per service exposes
bind/workers/timeout/graceful_timeout as GUNICORN_* env knobs.

Notable details:
- schedule: timeout=0 (disables gunicorn worker heartbeat) so long
  notebook execution isn't killed by gunicorn's silent-worker kill.
- All three configs: drop dead threads=4 setting; UvicornWorker is
  async and ignores threads.
- Pin gunicorn>=26.0.0 in each pyproject; uv.lock regenerated.
- Drop stale 'COPY contracts ./contracts' from runtime and schedule
  Dockerfiles (contracts dir was deleted in an earlier refactor;
  builds would have failed).
- backend Dockerfile: switch to uv sync layout matching runtime/
  schedule; add build deps for native wheels.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-31 15:07:45 +08:00
tao.chenandClaude 245f4d346d fix: repair storage hot-path bugs and missing imports
- scripts.update_script: repoint script.current_object_id to the
  newly uploaded StorageObject and best-effort delete the old
  working copy. Previously the old row was mutated with the new
  content_hash while the script still pointed at it, silently
  losing user edits on the next publish_version.
- scripts.publish_version: read object bytes via the new
  RustFSObjectStore.get_bytes() instead of the non-existent
  .get_object(); publish 500'd on every call.
- scripts.upload_script / storage_api.complete_upload_record:
  Path(file_name) raised NameError (only PurePosixPath imported),
  crashing every upload and every upload finalization. Use
  PurePosixPath.
- RustFSObjectStore: add get_bytes() helper (sync, body.close in
  finally) for in-process callers that need raw bytes.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-31 15:07:35 +08:00
tao.chen 76b3edd018 refactor: add API md 2026-07-31 13:41:37 +08:00
tao.chen 72b7adb8c4 refactor: delete contracts 2026-07-31 13:41:18 +08:00
tao.chen 2874ccdce3 docs: README + DEVELOP — code map, Settings, bucket routing, troubleshooting
- README: refresh "what it does", "architecture at a glance", "containers"
  table, "configuration", "storage layout" (with usage_type→bucket
  routing table), and add "documentation" section pointing to
  ARCHITECTURE / HANDOVER / DEVELOP / CLAUDE.

- DEVELOP: add the developer-facing guide that was previously only in
  CLAUDE.md. Covers code layout, the Settings singleton, conventions
  (DB / Storage / Auth / Permission gates / Outbox / async-sync
  signatures), local dev workflow, common tasks (adding a DAG endpoint,
  env var, MySQL table, RustFS bucket, schedule node type), tests
  status, and a troubleshooting section with the four real bugs hit
  this session (greenlet, MySQL, Jupyter 401, Schedule not advancing).
2026-07-31 13:37:14 +08:00
tao.chen d377ba3cfe refactor: object_key flat layout + usage_type→bucket routing + Settings singleton
- common.config.Settings: pydantic-settings with @lru_cache singleton;
  all env vars now declared in one place (database / JWT / RUSTFS_*
  credentials + 3 purpose-named buckets / workspace FS roots / etc.).
  Replaces os.environ / os.getenv in backend / schedule / runtime /
  common modules.

- storage_api: object_key layout flattens from
  "{ws}/{usage_type}/{ulid}/{name}" to "{ws}/{ulid}". File name, type,
  and logical path live in the StorageObjects / Scripts row, not in
  the S3 key, so the bucket can be re-organised without a DB rewrite.

- storage_api: new BUCKET_FOR_USAGE map and resolve_bucket() helper
  route uploads by usage_type to the right purpose-named bucket:
    working_copy / public_script / data_resource / snapshot
      → RUSTFS_WORKSPACE_BUCKET (workspaces)
    version_artifact
      → RUSTFS_VERSION_BUCKET (versions)
    run_log / run_result
      → RUSTFS_RUN_LOG_BUCKET (run-logs)
  workspace.artifact_bucket override wins over the default for that
  workspace. Unknown usage_type falls through to the workspace bucket
  so uploads are never silently dropped.

- backend.main lifespan: ensure_bucket loops over all three buckets at
  startup.

- common.storage.schemas: extend usage_type Literal to include
  working_copy / public_script (consumed by scripts.py after the local
  FS removal).

- common.storage.client: raise StorageClientError / StorageUnavailable /
  StorageRequestFailed instead of FastAPI HTTPException, so the client
  is usable from non-FastAPI contexts (e.g. schedule worker). The
  register_workspace_object method is removed (the local-FS path it
  routed to no longer exists).

- common.pyproject.toml: add greenlet>=3.0.0 (SQLAlchemy 2.0 async
  engine.dispose() requires it) and pydantic-settings>=2.14.2.

Verified: backend.main 57 routes; docker compose config; 20 SQLAlchemy
tables, 0 ForeignKey; grep os.environ / os.getenv in
backend|schedule|runtime|common = 0.
2026-07-31 13:37:04 +08:00
tao.chen 2e066db04a feat: add DEVELOP.md 2026-07-31 13:34:55 +08:00
tao.chen 5cbbe8213a review 2026-07-31 13:34:33 +08:00
tao.chen 28069f516b refactor: delete table 2026-07-31 13:21:15 +08:00
tao.chen f288c90d37 refactor: remove local fs, add config class to common pacakge 2026-07-31 12:46:31 +08:00
tao.chen 872388775a update: rename default bucket 2026-07-31 12:40:01 +08:00
tao.chen a052f97dbc update: remove local fs 2026-07-31 12:39:41 +08:00
tao.chen 4621d62301 feat: add nginx entrypoint 2026-07-31 12:24:01 +08:00
tao.chen 6244dd88b5 refactor: refact schedule module 2026-07-31 12:23:08 +08:00
tao.chen 2ff23acb6d chore: update Makefile to add env file 2026-07-31 12:22:28 +08:00
tao.chen d63c66f5ee chore: update env variable 2026-07-31 11:17:58 +08:00
tao.chen fb69275195 update: delete env file 2026-07-31 11:14:54 +08:00
tao.chen 77612d6f8b update: add .nvmrc 2026-07-31 09:43:33 +08:00
tao.chen 5c61f1814e refactor 2026-07-31 09:35:53 +08:00
tao.chen 62c7d7465e Merge branch 'optimize-by-taochen' into develop
# Conflicts:
#	.env.example
#	backend/src/backend/main.py
#	common/src/common/db/models.py
#	common/src/common/eventing.py
#	docker-compose.yml
#	runtime/Dockerfile
#	runtime/pyproject.toml
#	runtime/src/runtime/main.py
#	schedule/src/schedule/main.py
#	schedule/src/schedule/service.py
2026-07-31 09:29:03 +08:00
tao.chen 91767461d6 refactor 2026-07-30 20:52:46 +08:00
tao.chen c32e6e4cae Merge branch 'refactor/remove-redis' into develop
# Conflicts:
#	.env.example
#	CLAUDE.md
#	backend/Dockerfile
#	backend/pyproject.toml
#	backend/src/backend/main.py
#	backend/src/backend/schedule_runs.py
#	common/src/common/db/models.py
#	common/src/common/eventing.py
#	contracts/README.md
#	contracts/demo-core-v1.md
#	contracts/events/README.md
#	contracts/events/event-envelope-v1.json
#	contracts/locks/README.md
#	contracts/locks/file-edit-lock-v1.md
#	contracts/schedules/schedule-definition-api-v1.md
#	docker-compose.yml
#	frontend/README.md
#	migrations/README.md
#	migrations/versions/20260724_0001_v1_schema_baseline.py
#	runtime/Dockerfile
#	runtime/README.md
#	runtime/pyproject.toml
#	runtime/src/runtime/main.py
#	schedule/Dockerfile
#	schedule/README.md
#	schedule/pyproject.toml
#	schedule/src/schedule/main.py
#	schedule/src/schedule/service.py
2026-07-30 20:14:53 +08:00
tao.chen 7d684a6736 Chore: remove .pnpm_store, .claude, and .idea from repository 2026-07-30 20:08:33 +08:00
tao.chen b6a029fe7e chore: add gitignore 2026-07-30 20:06:25 +08:00
tao.chen ec53edbce5 refactor 2026-07-30 20:02:19 +08:00
Winnie c74b2abb48 重构模型平台前后端并移除Redis依赖 2026-07-30 19:03:00 +08:00
tao.chen c1e15758a3 refactor 2026-07-30 18:57:18 +08:00
tao.chen ff7fc4ef1d chore: delete nginx package 2026-07-30 15:28:04 +08:00
tao.chen 01d4555cf0 chore: upgrade fastjsonschema 2.22.0 to 2.22.1 2026-07-30 15:24:59 +08:00
Winnie 6d6c70cea8 refactor: integrate model platform backend 2026-07-30 13:43:29 +08:00