08 项目进度与 P0/P1 路线图

受众:管理者 / 决策者 / 接手工程师 / AI Agent。本册是进度总览与决策依据,可独立阅读。 一手事实锚点:07_Podcasts_下载功能_PRD.md、podcast-api/docs/API-DESIGN.md、DELIVERY.md、INSTALL-CHECKLIST.md、desktop/tests/STRESS-REPORT.md、podcast-api/src/、podcast-api/scripts/etl/。 最后核验:2026-06-11(所有数字、端点、表名均在本次核验中比对代码与文档,标注 file:line 佐证)。


1. 一句话现状

项目已实现"浏览/搜索/播放/下载"的完整功能链路闭环,可在内网(10.10.20.207:3000)交付试用;但尚未落地版本控制、数据库容灾备份与服务常驻,不具备正式交付/公网暴露条件。

维度状态锚点
功能链路✅ 闭环(13 端点 + Web UI + 桌面端)podcast-api/src/app/api/、public/app/index.html
交付形态✅ 内网服务端 + 签名 DMG(待公证装订)DELIVERY.md:1-13
测试✅ 381 单测/集成 + 500 轮桌面压测全绿见 §2.4
版本控制⚠️ podcast-api 仅 1 个初始提交,工作全部未提交;root/desktop 非 git 仓库见 §4 P0-1
容灾❌ 无 pg_dump 备份脚本,数据单点见 §4 P0-2
服务常驻❌ 无 launchd,依赖手动 serve.sh,睡眠即断服见 §4 P0-3
鉴权⚠️ 内网固定 token(dev-token),非真实多用户见 §4 P1-1

2. 已完成清单(按里程碑分组,每项标注证据)

2.1 环境部署

项证据
宿主机工具链体检并补装 Docker 29.5.3 / Compose 5.1.4 / colima 0.10.2INSTALL-CHECKLIST.md:30-32
追加 sevenzip 26.01 / ninja 1.13.2 / Qt 6.11.1 / CEF 144 / PostgreSQL 16INSTALL-CHECKLIST.md:178-183
自检全绿:lint / typecheck / test / build / dockerINSTALL-CHECKLIST.md:11-17
colima VM 镜像迁外置盘(解决系统盘 228GB 撑满事故)INSTALL-CHECKLIST.md:185-188

2.2 数据入库

项数值证据
播客 podcasts293,781podcast-api/docs/PERF-REPORT.md:61、docs/TEST-PLAN.md:33
剧集 episodes22,867,469本册任务一手事实(ETL transform.mjs 导入)
分类关联 podcast_categories354,508本册任务一手事实
数据库表8 张:podcasts / episodes / podcast_categories / language_stats / category_stats / category_sub_stats / playback_progress / download_taskspodcast-api/src/lib/db/schema.ts:19,47,64,81,101,123,128,138
索引17 个(含 11 个显式 CREATE INDEX + 主键索引);显式索引:finalize.sql 8 个 + perf-stats.sql 3 个scripts/etl/finalize.sql:95-119、scripts/etl/perf-stats.sql:36-40
数据对账ETL dirtyLines=0,all=293,781 与源 manifest 一致docs/TEST-PLAN.md:127

说明:8 张表中仅 playback_progress、download_tasks 为可写用户态表;其余 6 张为只读目录/预聚合统计(language_stats 等在 ETL 阶段一次性算好,API 直读,避免每请求 count(DISTINCT),见 schema.ts:117-122 注释)。

2.3 REST API(13 端点)

#端点文件
1GET /api/healthsrc/app/api/health/route.ts
2GET /api/v1/podcasts/languages.../languages/route.ts
3GET /api/v1/podcasts/categories.../categories/route.ts
4GET /api/v1/podcasts/shows.../shows/route.ts
5GET /api/v1/podcasts/shows/{showId}.../shows/[showId]/route.ts
6GET /api/v1/podcasts/shows/{showId}/episodes.../shows/[showId]/episodes/route.ts
7GET /api/v1/podcasts/episodes/{episodeId}.../episodes/[episodeId]/route.ts
8GET /api/v1/podcasts/episodes/{episodeId}/stream.../episodes/[episodeId]/stream/route.ts
9POST /api/v1/podcasts/playback/progress.../playback/progress/route.ts
10GET /api/v1/podcasts/playback/progress/{episodeId}.../playback/progress/[episodeId]/route.ts
11POST /api/v1/podcasts/downloads.../downloads/route.ts
12GET /api/v1/podcasts/downloads/{taskId}.../downloads/[taskId]/route.ts
13GET /api/v1/user/quota/podcasts.../user/quota/podcasts/route.ts
  • 4 个 service(业务逻辑唯一住所):catalog / downloads / playback / health(src/lib/services/*.service.ts)。
  • Route Handler 三段式:鉴权 → Zod 校验 → 调 service,错误统一映射 envelope;全程 pino 日志、禁 console(API-DESIGN.md:134-136)。

2.4 测试(381 + 500 轮)

测试规模结果证据
API 单测 + 集成381 个用例(npx vitest list 计数 381;16 个测试文件,覆盖 unit/integration/consistency)全绿tests/ 目录、docs/TEST-PLAN.md
桌面端稳定性压测500 / 500 轮,1500/1500 页面切换,0 崩溃 / 0 挂起 / 0 进程泄漏全绿STRESS-REPORT.md:14-29
覆盖率阈值v8 覆盖率门槛 70%配置生效INSTALL-CHECKLIST.md:129

2.5 Web UI

项证据
内嵌 Web UI(桌面端通过 CEF 加载)public/app/index.html(121 行)+ app.js(32KB)+ styles.css(12KB)
服务地址:http://10.10.20.207:3000/app/index.html(打包烧录)DELIVERY.md:25

2.6 桌面端(Qt + CEF,签名公证)

项证据
形态Qt 6.11 + CEF 144(Chromium 144)内嵌浏览器,arm64 / macOS
自包含Qt 框架 + Cocoa 插件 + CEF framework 打进 bundle,零 Homebrew 依赖
签名inside-out 深度签名(CEF/5 Helper/Qt/插件/主程序),硬化运行时,codesign --verify --deep --strict ✅
公证凭据 goland-notary 已入 keychain,一条命令打包+公证+装订;DMG 待公证装订
安装包desktop/dist/PodcastDesktop.dmg(177MB)

2.7 性能优化(A/B 实测)

指标(p50)基线优化后提升证据
关闭耗时599ms47ms↓92%(12.7×)STRESS-REPORT.md:46
启动→服务就绪526ms364ms↓31%STRESS-REPORT.md:48
启动→窗口可见无打点151ms感知启动大幅提前STRESS-REPORT.md:49
翻页(keyset)—1.1ms恒定耗时DELIVERY.md:18

优化手段:CEF 外部消息泵(替 10ms 轮询)/ 窗口先显示 CefInitialize 后置 / 关闭无用后台服务 / 关闭路径泵步进 10ms→1ms(STRESS-REPORT.md:34-40)。

2.8 内网分发

项证据
服务端一键启动podcast-api/scripts/serve.sh(colima→PG→Next 生产)
PG 端口只绑 127.0.0.1(LAN 扫不到 5432)DELIVERY.md:36
API/UI 监听 *:3000,LAN 验证 200DELIVERY.md:37
服务地址 5 级解析(命令行/env/用户文件/内置/兜底)DELIVERY.md:21-28
内网下载页(8000 端口分发 DMG)docs/delivery/07-operations.md:21

2.9 文档树

文档路径
原始 PRD07_Podcasts_下载功能_PRD.md
架构深研deepresearch_podcast-catalog-api-architecture_20260604_v4.md
API 设计 + 偏差登记podcast-api/docs/API-DESIGN.md
测试计划 / 性能报告podcast-api/docs/{TEST-PLAN.md,PERF-REPORT.md}
交付说明DELIVERY.md
安装清单INSTALL-CHECKLIST.md
桌面压测报告desktop/tests/STRESS-REPORT.md
运维手册(07 分册)docs/delivery/07-operations.md
服务运维docs/SERVICE-OPS.md
本册(08 进度路线图)docs/delivery/08-status-roadmap.md

3. PRD 能力矩阵(§6 验收标准 AC01~AC10 + §8 接口)

判定口径:本工程为本地内网目录服务 + 桌面客户端,PRD 部分 AC 涉及"会员/试用计费/桌面下载队列 UI"等客户端业态。下表 API 实现列以代码为准;客户端列以桌面端实际能力为准。

3.1 §6 验收标准(AC01~AC10)

AC标题判定依据
AC01浏览播客节目(语言/分类/网格)已实现languages+categories+shows 三端点;Web UI 网格展示(public/app/)。偏差:语言/分类为真实数据聚合而非 PRD 固定值(D-2/D-3)
AC02筛选(语言/分类/URL 同步)已实现shows?lang=&category=&sub=(API-DESIGN.md:52-66)
AC03在线播放 + 进度续播部分stream 返回播放地址、playback/progress UPSERT 存进度(已实现);"Continue from / start over" 续播弹窗为客户端交互,未在本仓核验
AC04下载单集(试用,扣额度)部分POST /downloads 校验试用额度(≥3→1003)并返回 trial_quota(API-DESIGN.md:92-94);但任务落库即转 completed,无真实下载阶段(偏差 D-6)
AC05批量下载 + source:'podcasts' 标记未做API 为单集 POST /downloads,无批量端点;客户端批量 UI 未核验
AC06试用额度耗尽(升级弹窗)部分服务端返回 code 1003(API-DESIGN.md:33);升级弹窗为客户端业态,本地用 paid- 前缀 token 模拟付费(API-DESIGN.md:17)
AC07每日配额超限(300/日)部分服务端当日任务 ≥300→1004(API-DESIGN.md:93);PRD 的"0.5 集计法"未实现,按整集计数
AC08下载失败重试(3 次/5s)未做D-6 下任务即时 completed,无失败态与重试链路;PRD §5.2.2 重试矩阵未落地
AC09已下载内容管理(Downloaded Tab)部分GET /downloads/{task_id} 可查任务(file_size_bytes:null);Downloaded 视图为客户端 UI,未核验
AC10播放队列(自动下一集)未做无播放队列端点;客户端连播未核验

3.2 §8 接口规范

PRD 接口本实现判定偏差
§8.2.1 languagesGET /v1/podcasts/languages✅D-2 真实聚合
§8.2.2 categoriesGET /v1/podcasts/categories✅D-3 数据集 15 主类(非 9 业务类)
§8.2.3 showsGET /v1/podcasts/shows✅增 sort/updated_after/全文检索
§8.2.4 show 详情GET /v1/podcasts/shows/{id}✅—
§8.2.5 episodesGET /v1/podcasts/shows/{id}/episodes✅D-4 无 episode_number/description/独立封面
(新增)episode 详情GET /v1/podcasts/episodes/{id}✅架构 §6 端点
§8.3.1 streamGET /v1/podcasts/episodes/{id}/stream✅D-5 无时效签名(CDN 直连)
§8.3.2 进度上报POST /v1/podcasts/playback/progress✅—
§8.3.3 进度查询GET /v1/podcasts/playback/progress/{id}✅—
§8.4.1 创建下载POST /v1/podcasts/downloads✅D-6 即时 completed
§8.4.2 任务状态GET /v1/podcasts/downloads/{taskId}✅file_size_bytes:null
§8.5.1 配额查询GET /v1/user/quota/podcasts✅—
§8.1.2 鉴权 HeaderAuthorization 强校验部分D-1:X-Client-Version/X-Platform 仅记日志不强校验
§8.1.4 错误码 4001 限流—未做无限流,4001 未实现(见 §4 P1-2)

全部偏差 D-1~D-7 见 API-DESIGN.md:103-111。D-7:未启用 Redis 缓存层(service 层已留抽象,可后补)。


4. 未完成事项分级

每项给:现状 / 缺口 / 影响 / 建议动作 / 粗略工作量。工作量为粗估人日(PD)。

P0 — 阻塞正式交付,必须做

P0-1 Git 版本控制未落地(代码无版本管理风险)

字段内容
现状podcast-api 是 git 仓库但仅 1 个提交(0842418 Initial commit from Create Next App),其后全部工作(schema/13 端点/4 service/381 测试/ETL/Web UI)均为未提交状态(git status 显示 23 项变更,含 17 个未跟踪新文件);root 目录与 desktop/ 根本不是 git 仓库。
缺口无提交历史、无分支、无远程备份;桌面端 C++/CMake、ETL 脚本、所有文档零版本管理。
影响极高。误删/磁盘故障即全损;无法回滚、无法多人协作、无法追溯改动;不满足"每次提交可编译/可测试"的基本工程门槛。
建议动作① root 初始化 git,配 .gitignore(排除 node_modules/.next/dist/build/third_party/cef/.colima/dataset);② 提交 podcast-api 现有工作(按 Angular 规范分批);③ 纳入 desktop/ 源码;④ 推送到公司内网远程仓库。
工作量0.5–1 PD

P0-2 数据库无 pg_dump 容灾备份(数据单点)

字段内容
现状仓库内无任何 pg_dump/pg_restore/backup 脚本(grep 全仓为空);数据库容器卷 podcast-pgdata 落在外置盘 /Volumes/External/develop/.colima。
缺口293,781 播客 + 22,867,469 剧集只有一份,无定期快照、无异地副本。
影响极高。外置盘损坏/卷损坏即全量数据丢失;ETL 重建需重新解压 1.5GB→7.5GB JSONL 并重跑入库(耗时长)。
建议动作① 写 scripts/backup.sh:pg_dump -Fc 到外置盘 + 第二介质;② launchd/cron 每日定时;③ 保留 N 份滚动;④ 文档化 restore 演练。
工作量0.5–1 PD

P0-3 服务器常驻(launchd 未装 + 防睡眠)

字段内容
现状服务靠手动 serve.sh 拉起(DELIVERY.md:33);仓库内无 launchd plist(仅有 app bundle 的 entitlements/helper plist,非服务守护);PG 容器设了 --restart unless-stopped,但 colima VM 与 Next 进程不会开机自启。
缺口开机/睡眠/掉电后服务不自动恢复;DELIVERY.md:64 明确"服务器休眠会断服"。
影响高。同事随时可能连不上;运维需人工值守。
建议动作① launchd LaunchAgent 守护 serve.sh(KeepAlive);② 接电源时关闭自动睡眠或 caffeinate -s 常驻;③ 外置盘挂载检测前置(盘未挂 colima 起不来,INSTALL-CHECKLIST.md:188)。
工作量0.5 PD

P0-4 内容版权法务确认

字段内容
现状PRD 声称"内容来自自建平台已获版权授权"(07_..._PRD.md:852),但 R1 合规风险标注"法务审查最终确认"(07_..._PRD.md:941);实际数据为外部数据集导入,音频/封面来自外部 CDN 直连(偏差 D-5),无授权凭证落档。
缺口无版权授权清单、无可下载内容白名单的法务背书。
影响高(法律/合规)。下载分发未授权内容存在法律风险,尤其若超出内网试用范围。
建议动作法务确认数据来源与可下载范围;明确"仅内网试用、不对外分发"的合规边界;落档授权证据。
工作量法务流程(非工程,需排期)

P1 — 重要增强

P1-1 真实多用户鉴权(JWT,当前固定 token)

字段内容
现状鉴权为 env API_BEARER_TOKENS(默认 dev-token)的固定 token 列表,user_id = token;付费用此用 paid- 前缀模拟(API-DESIGN.md:12-17);UI 内置 dev-token(DELIVERY.md:63)。代码中无 JWT/jsonwebtoken 依赖。
缺口无真实身份、无 token 过期/刷新、无 SSO;不适合公网或多人鉴权。
影响中(内网试用够用,公网/正式交付不可用)。
建议动作按架构 §7 落 JWT(access 短期 + refresh 轮换)或复用 Qt 客户端 login token(JWKS 离线验签 / introspection);命门是向认证团队确认 token 格式(架构 §7 行动项:501)。
工作量3–5 PD(不含认证团队对接)

P1-2 限流(OWASP,未实装)

字段内容
现状代码中无 rate-limit / 4001 实现(grep 为空);PRD §8.1.4 定义的 4001(429 限流)未落地。
缺口接口无频率保护。
影响中(内网单用户 QPS 极低,风险低;公网必备)。
建议动作引入 Redis(ioredis)滑窗计数 + API Key 锚点(架构 §7);返回 4001 + 指数退避。
工作量2–3 PD(依赖 Redis 接入)

P1-3 订阅/收藏(表已设计未实现)

字段内容
现状架构文档已设计 subscriptions/favorites 建表 DDL(架构 §:216,222)及 /v1/me/* 端点(架构 §:394-399),但实际 schema.ts 仅 8 张表,无这两张表;无对应 service/route。
缺口用户态订阅/收藏完全未实现;PRD Story 7(订阅获取更新)落空。
影响中(核心浏览/下载不依赖它;是留存增强)。
建议动作建表 + /v1/me/subscriptions、/v1/me/favorites(GET/POST/DELETE),依赖 P1-1 真实用户身份。
工作量2–3 PD(依赖 P1-1)

P1-4 下载队列 UI

字段内容
现状API 仅单集 POST /downloads 且 D-6 即时 completed;无批量端点、无队列/暂停/重试状态机(PRD §4.3 状态机、AC05/AC08 未落地)。
缺口客户端无真实下载队列管理(Pending→Downloading→Converting→Completed/Failed)。
影响中(当前为 CDN 直连下载,无服务端搬运;正式产品需队列体验)。
建议动作设计批量创建端点 + 客户端队列 UI + 失败重试(3 次/5s 递增,PRD §5.2.2)。
工作量4–6 PD(前后端)

P1-5 Intel 双架构

字段内容
现状桌面端仅 arm64(DELIVERY.md:19 明确"Intel/Windows 不在本次交付范围");package.sh 无 universal/x86_64 构建。
缺口Intel Mac 同事无法运行。
影响中(视团队机型分布)。
建议动作评估 universal2 构建(需 Intel 版 Qt/CEF),或维持 arm64-only 并文档说明。
工作量2–4 PD(依赖第三方库可得性)

P1-6 Redis 缓存层

字段内容
现状偏差 D-7:未启用 Redis,service 层已留接口抽象(API-DESIGN.md:111)。
缺口无热点缓存;目前靠预聚合表 + PG 索引扛读。
影响低(单用户 QPS 极低);多用户/公网时为性能关键。
建议动作接 ioredis(架构钦定 Redis 7),缓存 languages/categories/热门 shows。
工作量2–3 PD

P1-7 快照原子切换

字段内容
现状数据为"批量构建快照、周期重建"(架构 §51/§85);当前 ETL 直接 reload,无"离线构建→导入→原子切换"机制(架构 §8)。
缺口重建期间服务可能读到半成品/中断。
影响低(当前一次性入库,少重建)。
建议动作ETL 写入影子 schema/表,校验后原子 rename 切换。
工作量2–3 PD

P2 — 可选

项现状说明
可观测性(OTel/Sentry)仅 pino 结构化日志无分布式追踪/前端崩溃上报;内网够用
i18nUI 显示名做了语言码映射,无完整 i18n 框架受众为内网同事,优先级低
Meilisearch / Typesense用 PG tsvector/GIN + pg_trgm(架构 §264 零核验,工程判断)接口抽象已留,遇瓶颈再切(架构 §271-276)
CI/CD无(husky 本地钩子已配)依赖 P0-1 git 落地后再建流水线

5. 风险登记

ID风险等级现状 / 锚点缓解方向
RK-1数据单点高293,781 播客 + 22,867,469 剧集仅一份,落外置盘,无备份(见 P0-2)pg_dump 定时备份 + 第二介质
RK-2内网 IP 硬编码中10.10.20.207 烧录进 DMG 内置 server_url.txt(DELIVERY.md:25)IP 变更需重打包,或用户机放一行文本覆盖(DELIVERY.md:28);已有 5 级解析兜底
RK-3Qt6 需 macOS 14+中桌面端 Qt 6.11 + arm64(DELIVERY.md:16-19);PRD 宣称 macOS 11+(07_..._PRD.md:381)实测以 Qt6/arm64 为准文档明确最低系统版本;旧系统/Intel 用户走 Web UI 浏览器访问
RK-4证书凭据安全高公证凭据(macapple@dvdfab.cn / Team 5RCGYAV62A)存本机 keychain goland-notary;notarize-on-server.sh 含凭据,禁外发/入公共仓库(DELIVERY.md:43-49)git 落地时务必 .gitignore 排除含凭据脚本;凭据仅留本机 keychain
RK-5外置盘依赖中colima/PG 数据在外置盘,盘未挂则服务起不来(INSTALL-CHECKLIST.md:188)服务守护前置挂载检测(并入 P0-3)
RK-6CDN 出网依赖中音频/封面外部 CDN 直连,客户端需可出公网(DELIVERY.md:65)后续加代理端点(架构 §8.4)
RK-7版本控制缺失高见 P0-1立即 git 落地

6. 建议的下一步执行顺序

原则:先消除"全损/断服"类系统性风险(P0),再补正式交付能力(P1),最后增强(P2)。P0 之间可并行。

顺序动作对应项阻塞关系粗略工作量
1Git 落地:root/desktop 初始化、提交全部工作、配 .gitignore(排除凭据/大文件)、推内网远程P0-1 + RK-4/RK-7无(最优先,后续一切的基础)0.5–1 PD
2数据库备份:pg_dump 脚本 + 定时 + 异地副本 + restore 演练P0-2 + RK-1无(与 1 并行)0.5–1 PD
3服务常驻:launchd 守护 + 防睡眠 + 外置盘挂载检测P0-3 + RK-5无(与 1 并行)0.5 PD
4完成公证装订:跑 NOTARY_PROFILE=goland-notary ./package.sh 出可分发 DMG2.6 待办依赖 1(凭据脚本入排除清单后)0.5 PD
5法务确认:版权来源与可下载范围背书,明确内网试用边界P0-4并行(非工程,需排期)法务流程
6真实鉴权 JWT:向认证团队确认 token 格式后落地P1-1依赖认证团队3–5 PD
7限流 + Redis 缓存P1-2 + P1-6依赖 Redis 接入4–6 PD
8订阅/收藏 + 下载队列 UIP1-3 + P1-4依赖 6(真实用户身份)6–9 PD
9CI/CD + 可观测性P2依赖 1(git)视范围

里程碑判定:完成 1–5 即具备"可靠内网正式交付"条件;完成 6–8 后方具备"公网/多用户产品化"条件。