feat(backend): 后端全栈实现——基础设施 + 领域模块 + 用户认证 + API 契约 - #75
Closed
xiaocheny214 wants to merge 92 commits into
Closed
Conversation
Describe the backend package layout (common/framework/app) and the server domain module split: user, project, asset, character with action/character_template/wearable subdomains, generation and media. All modules currently define abstract interfaces only.
Add the shared response/exception kernel in windup_common: Response/ListResponse unified bodies (HTTP always 200, business code in body), BizException base, ModelException for LLM calls, and the BizCode/ModelErrorType enums. Add the app-level global exception handlers that convert these into Response.fail.
Add windup_framework infrastructure abstractions: SQLAlchemy db base/session, config loaders (database/provider/storage), LLM provider protocols (chat/image/video) and Kodo object storage.
Add abstract service interfaces and domain models for the server modules: user, project, asset, character (with action/character_template/wearable subdomains), generation and media. Drop the now-obsolete .gitkeep placeholders.
Drop the placeholder health router and its registration in create_app; the web layer now revolves around the global exception handlers.
Expose the windup CLI entrypoint (windup_app.bootstrap.app:main) and add python-multipart for form/file uploads; refresh uv.lock accordingly.
Point the sub-entity references at the nested character subpackages (character.action / character_template / wearable) instead of the old top-level paths.
Remove unused imports flagged by ruff F401 in generation/interface.py and user/model.py.
将 validate-branch 与 validate-commits 从 backend.yml 拆到独立的 naming.yml。命名规范门禁不局限于 backend 范畴,应作为仓库级 CI 单独维护(PR review:@minorcell 建议)。 backend.yml 仅保留 lint-and-test;naming.yml 用独立 concurrency group 避免与 backend 共用 group 互相取消。
Add SqlAlchemyProjectService inheriting ProjectService; implements create/get/list/delete plus project_name_exists against SQLAlchemy. - interface: reconcile ProjectService to session-per-call; session is passed per request via get_session, create_project takes **fields. - service: stateless impl as a module-level `service` singleton; flush only, commit/rollback handled by get_session; list ordered by id desc. - model: id uses BigInteger().with_variant(Integer, "sqlite") so the in-memory SQLite test DB autoincrements; Postgres unchanged. - api/bootstrap: import service from the service module, register project_router, add a print_banner startup stub.
Add SQLite in-memory test fixtures and project module tests. - conftest: SQLite in-memory fixtures (StaticPool, single connection) with no Docker Postgres dependency; get_session override for the API TestClient. - test_project_service: 14 unit tests for create/exists/get/list/delete covering the unique constraint, pagination, id-desc ordering and user filter. - test_project_api: 9 end-to-end tests via TestClient covering CRUD and the unified response contract (HTTP 200, code in body, 400/404).
Reflect character/media/generation/user module redesigns in the split document.
Replace strategy pattern with typed submit methods.
- model: add CharacterImageOutput/CharacterActionOutput/CharacterActionFrame
as typed task results, remove generic GenerationResult
- interface: split submit into generate_character_image and
generate_character_action with typed inputs
- document SSE streaming flow (GET /generation/tasks/{id}/stream)
replacing frontend polling
Remove OAuth abstract methods and models from UserService. Commented-out methods: get_oauth_authorize_url, login_by_oauth, bind_oauth, get_oauth_bindings. Related imports OAuthCallbackInput and UserOAuth removed from interface. The OAuth region is preserved as a placeholder for future extension.
Add ObjectStorageMediaService implementing MediaService. - service: upload to Kodo via KodoStorage adapter, auto-generated object keys with category prefix, no user filenames in keys - app: register media router (POST /media/upload) in create_app
refactor:asset character media
ci: split naming gate into its own workflow
feat:project module
跨层契约(common,无内部依赖):ActionType/GenRoute/CharacterCard/ActionSpec/AssetPackageRef。ai_engine 与 app 均依赖此。Refs 1024XEngineer#53。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SufyVideoProvider(kling i2v,OpenAI 兼容异步 /videos)+ OnnxU2NetMatteProvider(onnxruntime 直跑 u2netp,替代 rembg 在 3.12 无轮子的 numba 链)+ 能力接口(Image/Video/MatteProvider)。同时声明 framework 代码实际 import 的依赖(langchain-openai/onnxruntime/qiniu/pillow/numpy)——补齐 1024XEngineer#64 机器审指出的缺依赖。Refs 1024XEngineer#53 #35。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
填充空骨架:slicing(抽帧 + 周期/一次性选帧)、strategy(ROUTE_MATRIX 分流 + VideoFrameStrategy 图生视频)、prompt(walk/jump/attack/idle 提示词库)、postprocess(像素化 + 脚线对齐 + 打包 + 逐帧时长)、generator 串联。MVP:root_motion 暂不做(character_data.frames 无该字段,见 1024XEngineer#63);graph/ 留占位非本 PR。Refs 1024XEngineer#53 #35 #21。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove dead storage module (empty __init__.py and kodo.py) from framework - Implement actual Qiniu Kodo SDK upload in ObjectStorageMediaService - Move MediaCategory to windup_common.enums.media, remove duplicate from media/model - Update media __init__ to import MediaCategory from common
Move qiniu import inside upload() so module collection does not fail when qiniu is not installed (e.g. CI test runs).
按 MVP 边界(与作者对齐):CharacterGeneratorPort.generate(card, action, master, progress) → GeneratedAction(frames/durations/fps);母版由 server 以 bytes 传入,不再经 ArtifactStore;去掉 sprite sheet 打包与存储引用(上传/落库/导出在 server/export 侧)。补 VideoFrameStrategy.derive 离线端到端测试(monkeypatch 抽帧,不解码 mp4/不联网)。Refs 1024XEngineer#53。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
refactor(media): implement Qiniu upload and deduplicate MediaCategory
- POST /generation/image: user_id 从 JWT 取,校验 project 归属
- POST /generation/action: 同上
- GET /generation/tasks/{task_id}: 改用 get_task_by_user 校验归属
- 请求模型移除 user_id 字段
CharacterCreate.name 未传入 service.create_character(),导致返回 name=None。 补上 name=body.name 并新增 3 个集成测试覆盖命名场景。
后端验证码/refresh_token 依赖 Redis,原 compose 只有 Postgres。 新增 redis:7-alpine 服务(含健康检查),backend depends_on 等待就绪, 环境变量 REDIS_URL=redis://redis:6379/0。
ORM 声明了 UniqueConstraint(user_id, project_name),但 init.sql 建表时遗漏。 生产 Postgres 并发创建同名项目不会触发 IntegrityError,API 兜底失效。 补上 CONSTRAINT uq_windup_project_user_name UNIQUE (user_id, project_name)。
合并 main 时丢掉了 1024XEngineer#76 刚加入的两个 router 注册,合并后 /workflow-runs 与 /ai/chat 由可用变 404,而两个 api 文件仍在仓库里,静默失效无报错。 CORS 两处:去掉写死的 vercel 通配正则,并把 allow_credentials 置 False (鉴权走 Authorization 头不走 cookie);默认来源补 4173(vite preview)。 实测:端点数 16 → 19,恢复 /ai/chat 与 /workflow-runs{,/{run_id}}; 4173 过预检且响应无 allow-credentials 头,任意 vercel 域不再放行。 Refs 1024XEngineer#143 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fix(app): 补回 workflow-run / ai 两个 router,收紧 CORS(Refs 1024XEngineer#143)
johnnyzhang-eng
dismissed
their stale review
August 6, 2026 09:40
不阻塞合并。两条已由 xiaocheny214#35 修复(Refs #143),其余四条记在 #145 备查。
johnnyzhang-eng
approved these changes
Aug 6, 2026
johnnyzhang-eng
left a comment
There was a problem hiding this comment.
Approve。
合并顺序提醒:xiaocheny214#35 若未先合进 feat/backend-dev,本 PR 会把 #76 刚加入 main 的 workflow_run / ai 两个 router 注册删掉,/workflow-runs 与 /ai/chat 变 404。那个 PR 只改 1 个文件、门禁全绿。
其余四条记在 #145,不阻塞。
This was referenced Aug 6, 2026
Contributor
Author
Contributor
Author
|
更新:补充了遗漏的 ai_engine 模块,现在共 5 个小 PR:
|
This was referenced Aug 6, 2026
feat(sse): SSE 推送替代前端轮询
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
本 PR 实现 Windup 后端完整能力:基础设施层、领域业务层、用户认证体系、生成管线,以及配套的 Docker 部署与测试覆盖。
新增能力
基础设施层(framework)
领域业务层(app/server)
API 层(web)
Response[T]/ListResponse[T]BizException继承体系)request.state.current_user注入)部署与 CI
init.sql建表脚本(含唯一约束)安全修复
BizException跳过ExceptionMiddlewareJSONResponseuser_id,可越权project_id无归属校验create_character漏传name,名称丢失init.sql缺唯一约束,生产可重名测试覆盖
test_user_service.py:22 用例(注册/登录/验证码/登出/刷新/改密/限流)test_project_api.py:9 用例(CRUD + 权限归属)test_character_api.py:3 用例(命名持久化)test_generation_orchestration.py:生成编排test_sufy_video_download.py:视频下载重试关联 Issue