235 lines
20 KiB
Markdown
235 lines
20 KiB
Markdown
# 三端问题检测报告
|
||
|
||
> 检测对象:`chunyu_project`(Django 后端)、`chunyu_project_react`(React Web)、`android-chunyu`(Android)
|
||
> 检测方式:3 个并行深度审计(后端/前端/Android)+ 独立交叉验证(所有 🔴 级发现均经第二人核实源码,部分经运行时复现)
|
||
> 日期:2026-09-06
|
||
|
||
---
|
||
|
||
## ⭐ 修复状态更新(2026-09-06 第二轮)
|
||
|
||
以下 P0 问题已在本轮修复(修改清单见文末「已执行修复」章节):
|
||
|
||
| 问题 | 状态 | 修复方式 |
|
||
|---|---|---|
|
||
| 13 个 API 断链(Android 4 + Web 9) | ✅ 已修复 | Web request.ts 9 处 `/users/`→`/user/`;Android 4 路径改指真实端点并补齐请求体字段;后端新增统一 `user/favorites/toggle/` 端点 |
|
||
| 滑块验证码防爆破失效 | ✅ 已修复 | 后端不再下发 x_position;验证成败均销毁 key;x 上限收到可拖动范围;React 组件新增服务端 1:1 坐标渲染模式 |
|
||
| `/user/user-login/` 无防护 | ✅ 已修复 | 补齐失败计数 + 滑块验证码门控;双端点限流标识改用 X-Real-IP+账号(不可伪造) |
|
||
| 存储型 XSS | ✅ 已修复 | `htmlSanitizer.ts` 重写为 DOMPurify 白名单模式(新增 dompurify 依赖) |
|
||
| 百度密钥硬编码 | ✅ 已修复(需人工轮换) | 改为 `BAIDU_FANYI_APPID/BAIDU_FANYI_APPKEY` 环境变量注入,endpoint 升级 https;**旧密钥已泄露,需在百度控制台轮换** |
|
||
| refresh token 三端死代码 | ✅ 已修复 | 后端挂载 `/user/token/refresh/` + 注册 token_blacklist + 开启轮换;Web axios 401 自动刷新重试(单飞锁);Android OkHttp Authenticator 同机制 |
|
||
| `logs/tasks.py` 每日统计崩溃 | ✅ 已修复 | `Count(filter=Q(is_error=True))`,编译验证通过 |
|
||
|
||
**修复过程中新发现并一并修复的 🔴**:`ChangeEmailAPIView`/`ChangePhoneAPIView` 此前从未调用 `avalidate()`,验证码校验为死代码(任何已登录用户可无码改绑邮箱/手机号)——已补上校验调用。
|
||
|
||
**验证结果**:后端 9 个改动文件 py_compile/AST 全过 + `manage.py check` 0 错误 + 路由可解析 + blacklist 模型可用 + 滑块验证码行为经 4 项运行时测试全过(旧 dict 写法确认编译失败、新 Q 写法编译通过);前端 `tsc` 0 错误 + `pnpm run build`(tsc+vite)exit 0 + eslint 相对基线无新增错误;Android 无 Gradle 环境(无 wrapper、本机无 gradle/SDK platforms),改动经逐文件精读复查,**建议在 Android Studio 中编译验证**。
|
||
|
||
**部署注意事项**:① 后端需执行 `migrate`(token_blacklist 表);② 设置 `BAIDU_FANYI_APPID`/`BAIDU_FANYI_APPKEY` 环境变量;③ Android 需在 IDE 中编译并安装新包。
|
||
|
||
### 已执行修复 · 文件清单
|
||
|
||
**后端 `chunyu_project`(10 文件)**:
|
||
- `utils/slider_captcha.py` — 响应去除 x_position;验证成败均销毁 key;x 上限 239(可拖动范围)
|
||
- `user/views/user.py` — UserLoginAPIView 补失败计数+滑块门控;双登录端点标识改 X-Real-IP+账号
|
||
- `user/views/email.py` / `user/views/phone.py` — 补调 avalidate 验证码校验(新发现 🔴)
|
||
- `user/views/favorites.py` — 新增 FavoriteToggleView(tool/article/course/api 统一切换)
|
||
- `user/urls.py` — 新增 `favorites/toggle/`、`token/refresh/` 路由
|
||
- `chunyu_project/settings.py` — 注册 token_blacklist;ROTATE_REFRESH_TOKENS=True
|
||
- `logs/tasks.py` — Count(filter=Q(is_error=True))
|
||
- `api/views/info/baidu_fanyi_appid.py` — 密钥改环境变量,endpoint 升 https
|
||
- `templates/test_slider_captcha.html` — 提示文案同步(该页本就不依赖下发答案)
|
||
|
||
**前端 `chunyu_project_react`(6 文件 + lockfile)**:
|
||
- `src/utils/request.ts` — 9 处 `/users/`→`/user/`(git diff 逐行确认)
|
||
- `src/utils/axios.ts` — 401 自动刷新(single-flight)+ 重放原请求;auth 端点豁免
|
||
- `src/utils/htmlSanitizer.ts` — 重写为 DOMPurify 白名单消毒(新增 dompurify 3.4.14)
|
||
- `src/components/SliderCaptcha/SliderCaptcha.tsx` + `captchaUtils.ts` — 服务端模式:1:1 坐标渲染后端图/拼图块,不再需要下发答案
|
||
- `package.json` / `pnpm-lock.yaml` — 新增 dompurify 依赖
|
||
|
||
**Android `android-chunyu`(4 文件)**:
|
||
- `data/api/UserApi.kt` — bind-email→change-email、bind-phone→change-phone、user/{id}→public-profile/{id};请求体字段对齐(new_email/new_phone)
|
||
- `data/repository/UserRepository.kt` — 传参改为命名参数对齐新字段
|
||
- `data/api/RetrofitClient.kt` — OkHttp Authenticator 401 自动刷新重放;release 关闭 BODY 日志
|
||
- `data/local/TokenManager.kt` — 新增 getRefreshToken/saveAccessOnly
|
||
|
||
---
|
||
|
||
## 总览
|
||
|
||
| 端 | 🔴 严重 | 🟡 中等 | 🟢 低 | 权威命令结果 |
|
||
|---|---|---|---|---|
|
||
| 后端 Django | 7 | 20 | 9 | 277 个 .py 全部通过 py_compile;`makemigrations --check` 检出 4 处迁移漂移;`Count(filter=dict)` 运行时 bug 实测复现 |
|
||
| 前端 React | 3 | 10 | 7 | `tsc -b --force` 0 错误;`eslint .` **491 errors + 63 warnings** |
|
||
| Android | 4 | 9 | 6 | 未跑 gradle build;仓库仅 93 个 tracked 文件且全为源码(卫生良好),缺 Gradle Wrapper |
|
||
| 跨端断裂 | 2 类 | — | — | **13 个 API 端点必 404**(Android 4 + Web 9);refresh token 三端全链路死代码 |
|
||
|
||
---
|
||
|
||
## 一、跨端断裂问题(多端联合实锤,优先修复)
|
||
|
||
### 🔴 1. 13 个 API 端点前后端路径不一致,调用必 404
|
||
|
||
**Android → 后端(4 个)**,逐一比对过后端各 `urls.py`:
|
||
| Android 声明 | 位置 | 后端实际 | 影响 |
|
||
|---|---|---|---|
|
||
| `POST user/bind-email/` | `UserApi.kt:78` | 无此路由(只有 `send-email-code/`+`change-email/`) | 邮箱绑定必失败(ProfileEmailScreen.kt:122) |
|
||
| `POST user/bind-phone/` | `UserApi.kt:82` | 无此路由(只有 `send-phone-code/`+`change-phone/`) | 手机绑定必失败(ProfilePhoneScreen.kt:112) |
|
||
| `GET user/{id}/` | `UserApi.kt:87` | 公开资料实为 `user/public-profile/<int:user_id>/` | 用户主页必 404(AppNavHost.kt:77,192) |
|
||
| `POST user/favorites/toggle/` | `FavoritesApi.kt:33` | 后端只有 `user/favorites/`,toggle 分散在各业务前缀下 | 收藏切换必 404(FavoritesRepository.kt:22) |
|
||
|
||
**Web → 后端(9 个)**:`request.ts:605-640` 的 activities / uploadCover / privacy(GET/PUT) / notification-settings(GET/PUT) / devices / removeDevice / clearOtherDevices 全部用 **`/users/`(复数)** 前缀,而后端全库只有 `user/` 单数路由(根 `urls.py:67`)。
|
||
- 开发环境:vite 代理 `/user` 前缀恰好也匹配 `/users/*` → 转给后端 → 404
|
||
- 生产环境:nginx 正则 `^/(...|user|...)/` 要求斜杠,`/users/` 不匹配 → 回退 SPA 返回 HTML
|
||
- 两个环境都必失败。其余 43+ 个端点核对过均一致。
|
||
|
||
### 🔴 2. Refresh Token 三端全链路死代码
|
||
|
||
- 后端 grep 全库:**无任何 `TokenRefresh`/`TokenObtainPair` 视图或路由**(`rest_framework_simplejwt.urls` 从未挂载),但登录在 4 处下发 refresh(`user/views/user.py:184,224,690,806`)
|
||
- settings.py:`REFRESH_TOKEN_LIFETIME=30天` + `ROTATE_REFRESH_TOKENS: False` + `BLACKLIST_AFTER_ROTATION: True` + **未注册 `rest_framework_simplejwt.token_blacklist` app** —— 轮换/黑名单双死配置,token 泄露 7 天内无法撤销
|
||
- Web:refresh_token 存 localStorage,全库 0 处刷新调用,401 直接硬登出(axios.ts:108-113)
|
||
- Android:TokenManager 存 REFRESH_TOKEN,无刷新接口无 401 重试(TokenManager.kt:14,27)
|
||
- 结论:30 天长效凭据被三端持久化,却永远无法使用、无法轮换;要么补 `/user/token/refresh/`,要么停止签发
|
||
|
||
---
|
||
|
||
## 二、后端问题(chunyu_project)
|
||
|
||
### 🔴 严重
|
||
|
||
1. **百度翻译 API 密钥硬编码入库**:`api/views/info/baidu_fanyi_appid.py:1-2`(appid/appkey 明文),被 `BaiduFanyiView.py:21`、`api/tasks.py:19` import;endpoint 还是明文 `http://`(:4)
|
||
2. **滑块验证码答案明文下发**:`utils/slider_captcha.py:111-117` 返回体含 `x_position/y_position`,脚本读 JSON 即 100% 通过
|
||
3. **滑块验证失败不销毁 key**:`slider_captcha.py:120-133` 只有成功才删 key;x 取值空间仅 200、容差 ±5 → 单 key 平均 19 次重试即过,与上条叠加 = **防爆破链路完全失效**
|
||
4. **双登录端点,无保护的绕过有保护的**:`/user/user-login/`(user.py:652-727)无失败计数无验证码,攻击者绕过带滑块的 `/user/login/` 直接无限爆破密码
|
||
5. **限流标识可伪造**:`user.py:733-737` 取 `X-Forwarded-For` 第一段做限流 key,每次伪造不同 XFF 即绕过失败计数(utils/captcha.py:88-102)
|
||
6. **JWT 三重配置问题**:access 7 天过长 + 轮换/黑名单互斥死配置 + blacklist app 未注册(settings.py:113-116,135-169)
|
||
7. **每日统计任务必然崩溃(已实测复现)**:`logs/tasks.py:46` `Count('id', filter={'is_error': True})` 传 dict 应传 Q 对象,Django 5.2 实测抛 `AttributeError` → beat 任务 `generate_daily_stats` 每天执行必失败
|
||
|
||
### 🟡 中等(摘要,完整清单见子审计记录)
|
||
|
||
- `SECRET_KEY` 公开兜底值 + `DEBUG` 默认 True(settings.py:24-27)——生产漏配即弱密钥+debug 全开,建议 fail-fast
|
||
- MySQL 分支是定时炸弹:视图大量用异步 ORM(aget/asave),MySQL 后端不支持,切 `DB_ENGINE=mysql` 即抛 `SynchronousOnlyOperation`(settings.py:184-216)
|
||
- **4 处迁移漂移**(`makemigrations --check` 实测):history 的 TYPE_CHOICES 加了 `api/utility` 但迁移未生成(history/models.py:5-11 vs 0002_add_learn_type.py:16)
|
||
- 扫码登录:`QRStatusView` AllowAny 轮询即拿完整 JWT(qr_login.py:58-65);`QRStatusConsumer` 的实时推送是**死功能**——全项目无任何 `group_send` 发往 qr 组,前端只能轮询
|
||
- `handle_typing`/`handle_read_receipt` 不校验会话成员(chat/consumers.py:86-120 vs save_message:177 的校验),任意连接者可向任意会话广播 typing 指示器
|
||
- "清空会话"物理删除双方全部消息(chat/views.py:447-459),与 swagger 描述矛盾
|
||
- `ConversationClearView` 类体内混入"标记已读"方法的复制粘贴事故,REST 已读接口实际缺失(chat/views.py:460-478 + chat/urls.py:16 注释路由)
|
||
- FileUploadView 无类型/大小限制(chat/views.py:546-564)→ 存储 DoS/恶意文件托管
|
||
- **SSRF**:FavoriteStickerFromMessageView 对消息内容中任意 http URL 发起服务端 GET,无内网黑名单(chat/views.py:692-713),可探测 169.254.169.254 等
|
||
- 翻译内容进 URL:`requests.post(url, params=payload)` 应为 `data=`(api/tasks.py:38,65);Celery 调用不在 try 内,broker 挂了把成功翻译打成 500(BaiduFanyiView.py:105-116)
|
||
- 邮箱验证码:错误不计数、成功不清除可复用(user/views/user.py:151-250);换绑验证码 6 位纯数字无失败限制(user_serializers.py:267,421)
|
||
- 注册生成随机密码但从不告知用户(user_serializers.py:62-78)
|
||
- 用户可控 ordering 未白名单(article/views.py:80-81、apidirectory/views.py:62-68)→ FieldError 500 / 排序 oracle;对照 learn/views.py:51-67 有正确白名单
|
||
- CDNStaticFileView AllowAny 不校验 published/is_free,未发布章节可匿名读(learn/views.py:507-541)
|
||
- 短链 AllowAny 无限流 + 任意 URL 重定向 → 钓鱼跳转服务(shorturl/views.py:39-105,171)
|
||
- `?page=abc` 直接 500 的复制粘贴模式(shorturl:186、search:49、chat:365、wallet:68)
|
||
- tool 路由双重挂载:`urls.py:77`(`tool/`)与 `api/urls.py:31`(`api/tool/`)同一份 tool.urls(Android 端用的正是后一份,勿直接删)
|
||
- 每请求新建 daemon 线程写日志库(logs/middleware.py:60-69)+ query_string 未脱敏(qr token 明文入库:113)
|
||
- 依赖矛盾:aioredis(零引用)/redis 6.4 并存、psycopg2/psycopg3 并存、mysqlclient 与异步架构矛盾、gunicorn/granian 并存、simplejwt 5.2.2(2022) 对 Django 5.2 兼容性待确认、django_celery_results 注册但 RESULT_BACKEND 用 Redis、public_profile analytics 全 0 硬编码(user.py:888-899)
|
||
- 31 处宽泛 `except Exception:`(业务视图含 user.py:882/997、learn:537;真裸 `except:` 仅 test_all_apis.py:17)
|
||
|
||
### 🟢 低
|
||
|
||
- 21 个一次性脚本散落根目录(含硬编码 admin123456/test1234);2 个 SQLite 入库(实测 0 行无泄露,schema 暴露);53 个 `__pycache__` 入库(310/312 双版本混杂);user.py.bak;三套 requirements 并存
|
||
- python-dotenv 装了但从未 load_dotenv,环境变量机制实际不可用
|
||
- 点赞无事务无唯一约束,并发计数漂移(article/views.py:438-452);ToolCategorySerializer N+1(tool/serializers.py:15-16)
|
||
- cache `IGNORE_EXCEPTIONS: True` → Redis 挂时验证码触发判定静默放行(settings.py:248 + utils/captcha.py:88-93)
|
||
- swagger/redoc public=True 全量暴露 schema;CORS_ALLOW_CREDENTIALS 与纯 Bearer 组合无必要
|
||
|
||
---
|
||
|
||
## 三、前端问题(chunyu_project_react)
|
||
|
||
### 🔴 严重
|
||
|
||
1. **存储型 XSS(文章正文)**:`ArticleDetail.tsx:412` `dangerouslySetInnerHTML` 渲染用户文章,唯一防线 `htmlSanitizer.ts` 4 条正则可绕过——EVENT_HANDLERS(:6)要求引号,`<img src=x onerror=alert(1)>` 穿透;DANGEROUS_TAGS(:5)缺 svg/math/style;:3 注释自认该换 DOMPurify。链路:ArticleEditor contentEditable(:81,1122) → 后端 → 详情页
|
||
2. **JWT 存 localStorage**(与 XSS 叠加=完整身份窃取链):axios.ts:33-49、authSlice.tsx:83-123、LoginModalContext.tsx:94
|
||
3. **守卫形同虚设**:MobileGuard 无条件渲染 children(MobileGuard.tsx:63-115);`/console`、`/article-manage`、`/bug-detail`、`/article-editor`、`/learn-manage`、`/learn-editor` 六个管理路由零守卫裸奔(App.tsx:181-186,对比 :154/:167 有真守卫)
|
||
|
||
### 🟡 中等
|
||
|
||
- 依赖冗余(import 实测):zustand 0 引用、react-lorem-ipsum 0 引用、components/ui 整目录 0 引用(Chakra 全链死代码)、Markdown.tsx 0 引用(react-syntax-highlighter 死代码)、qrcode 双库并存、@types/qrcode 误放 dependencies
|
||
- **三锁文件并存**且全被 git 追踪(package-lock 369KB + pnpm-lock 210KB + yarn.lock 193KB),packageManager 声明 pnpm@11
|
||
- ApiDocs.tsx:64 硬编码 `http://localhost:8000/swagger.json`(后端实际 8002),生产必挂
|
||
- WebSocket token 走 URL 查询串(request.ts:491-495)→ 进代理日志
|
||
- 无 token 刷新机制(见跨端问题 2)
|
||
- i18n 6 语言 JSON 约 694KB 静态打进首屏 bundle(locales/index.ts:1-6)
|
||
- locales 目录 24 个 .cjs 补丁脚本 + zh.json.bak 被 git 追踪,翻译靠脚本打补丁
|
||
- Playwright baseURL 5175 vs dev 端口 5173,默认跑不起来(playwright.config.ts:8)
|
||
- 桌面/移动双实现 28 对约 1.6 万行,多对行数几乎相同(TextDiff 212/211 等),复制粘贴平行维护
|
||
|
||
### 🟢 低
|
||
|
||
- 28 张根目录 PNG、24 个 .cjs 临时脚本、6 个 Python 文件混在前端仓库、tsconfig.tsbuildinfo 入库、README 还是 Vite 模板
|
||
- console.* 残留 51 处;TODO/FIXME 实际 0(粗筛 9 处均为误报已核实)
|
||
- 超大文件:Chat.tsx 1243 行、ArticleEditor.tsx 1228 行
|
||
- SliderCaptchaDemo 死页面(228 行无路由);测试仅 2 个 spec 对 65 个页面
|
||
- vite `/s` 代理靠 bypass hack;allowedHosts 硬编码内网 IP
|
||
|
||
---
|
||
|
||
## 四、Android 问题(android-chunyu)
|
||
|
||
### 🔴 严重
|
||
|
||
1. **硬编码内网 HTTP 地址**:`RetrofitClient.kt:15` `http://192.168.5.7:8000/`,换环境/发版必失效;`AndroidManifest.xml:21` 全局 `usesCleartextTraffic="true"` 无 network_security_config → JWT 明文上网
|
||
2. **BODY 级日志无条件开启**:RetrofitClient.kt:17-19 无 `BuildConfig.DEBUG` 判断,release 包把密码/验证码/JWT 全打进 logcat
|
||
3. **4 个 API 路径与后端不一致必 404**(见跨端问题 1)
|
||
|
||
### 🟡 中等
|
||
|
||
- runBlocking 读 DataStore 且在 Compose 组合中直接调用(TokenManager.kt:18,39 + MessagesScreen.kt:36、ProfileScreen.kt:41)——每次重组同步磁盘 IO
|
||
- `MainScope().launch` 无管理协程 6 处(MessagesScreen 等),永不 cancel、失败也清 UI
|
||
- `RetrofitClient.create()` 每次新建 Retrofit+OkHttpClient,全项目 29 个调用点,连接池零复用
|
||
- Token 明文存 DataStore + allowBackup=true + 空 backup_rules → 云备份带出凭据
|
||
- 扫码页相机/MLKit/executor 不释放(ScanLoginScreen.kt:126-165,无 DisposableEffect)
|
||
- UI 层 `is Resource.Error -> {}` 空分支吞错,空态与失败不可区分;11 个 repository 宽泛 catch
|
||
- release 未混淆(isMinifyEnabled=false)+ 无 signingConfigs,出不了正式签名包
|
||
- 钱包模块全假数据(PointsScreen:27-28 等);Chat 发送按钮只清空输入框(后端无发送接口被调用);忘记密码纯 UI 无网络调用
|
||
- 缺 Gradle Wrapper,Gradle 版本未锁定
|
||
|
||
### 🟢 低
|
||
|
||
- 依赖偏旧(Compose BOM 2024.02、Retrofit 2.9、Coil 2.5);kotlinCompilerExtension 1.5.8↔Kotlin 1.9.22 是官方匹配组合,**无错配**
|
||
- refresh token 存而不用;Gson LOWER_CASE_WITH_UNDERSCORES 与 camelCase 模型混用靠约定维持
|
||
- MessageApi markAsRead 用 String id 对后端 int pk(待确认)
|
||
- ✅ 正面:权限最小化(仅 3 项);DataStore 而非明文 SharedPreferences;仓库无构建产物入库
|
||
|
||
---
|
||
|
||
## 五、部署层问题(Docker / nginx,独立核实)
|
||
|
||
- 🟡 **前端 Dockerfile 弃用 pnpm**:`chunyu_project_react/Dockerfile:9` 用 `npm install`,与 pnpm-lock.yaml 漂移,构建不可复现;且 `npm run build` 含 `tsc -b`,类型错误会直接炸镜像(本次实测 tsc 0 错,暂时安全)
|
||
- 🟡 **后端容器启动自动 migrate**:`chunyu_project/Dockerfile:27` 多副本竞态反模式
|
||
- 🟡 **nginx 与 vite 代理漂移**:nginx.conf:28 正则缺 `/users`(致 Web 9 断链在生产返回 HTML)、缺 `/swagger.json`;`/i18n` 两边都有但前端代码 0 调用(过时规则,🟢)
|
||
- 🟢 后端镜像打包 21 个开发脚本(.dockerignore 未排除);Python 本地 3.10 vs Docker 3.12 漂移
|
||
- ✅ 两份 .dockerignore 本身配置良好(db.sqlite3/media/node_modules 已排除)
|
||
|
||
---
|
||
|
||
## 六、修复优先级建议
|
||
|
||
**P0(立即)**:
|
||
1. 轮换百度翻译 appkey(已泄露入库),迁环境变量 + 改 https
|
||
2. 封死 `/user/user-login/` 无保护登录或补齐其失败计数/验证码;滑块响应去掉 x_position、失败即删 key
|
||
3. 换 htmlSanitizer 为 DOMPurify;管理路由(App.tsx:181-186)包 AuthGuard
|
||
4. Android:修 4 个 404 路径、BASE_URL 走 BuildConfig、日志拦截器加 DEBUG 判断
|
||
5. Web:`/users/` → `/user/`(request.ts 9 处)
|
||
|
||
**P1(本周)**:
|
||
6. 补 `/user/token/refresh/` + 注册 blacklist app + ROTATE 改 True;或全端停止签发 refresh
|
||
7. 修 `logs/tasks.py:46` 的 Count(filter=Q(...));补 4 处迁移
|
||
8. SSRF(chat/views.py:692)加 URL 白名单/内网黑名单
|
||
9. Android RetrofitClient 单例化 + 摘除 runBlocking
|
||
|
||
**P2(迭代内)**:
|
||
10. 统一锁文件(删 package-lock/yarn.lock)、清理死依赖死代码(zustand/Chakra 链/Markdown.tsx)、前端 Dockerfile 改 pnpm --frozen-lockfile
|
||
11. 后端验证码类接口统一加失败计数;shorturl 加限流
|
||
|
||
---
|
||
|
||
## 七、检测方法与覆盖说明
|
||
|
||
- 3 个并行子代理深度审计 + 协调者独立验证:所有跨端结论(13 断链、refresh 死链、XSS 链、Docker/nginx)均经协调者对照源文件二次核实;后端 `Count(filter=dict)` bug 经独立脚本在 Django 5.2 实测复现;`makemigrations --check` 为实际运行输出
|
||
- 已核实正面项(非问题):后端 277 文件无语法错误;Celery beat 注册的 4 个 cleanup 任务存在且签名匹配;ASGI 引用的 consumers/routing 均存在;Android Kotlin/Compose 编译器版本匹配;Android 仓库卫生良好;两份 .dockerignore 配置正确
|
||
- 已知未覆盖:65 个前端页面的逐一业务审查、后端 weather/air_quality/bug/serializers 等部分模块全文、Android 未运行 gradle build、simplejwt 5.2.2 与 Django 5.2 官方兼容性
|