Files
lingxi/docs/开发计划/灵犀_A0工程骨架与契约基线_实施报告_V0.1.md
T
Stev_Wang 620cb93a46
ci / 质量门禁 (push) Canceled after 0s
fix(infra): 本地 PG/Redis 复用已有 Docker 服务
背景:此前误将宿主端口冲突当作新建 compose 服务的理由,实际应按技术架构使用本机已有 PostgreSQL/Redis。

改动:
- 删除 lingxi-pg / lingxi-redis 容器及数据卷,不再另起数据库;
- DATABASE_URL 改回 127.0.0.1:5432/lingxi,REDIS_URL 改回 127.0.0.1:6379;
- 在已有 docker-postgres-1 中创建 lingxi 库并执行迁移/seed;
- compose 仅保留无法拉取镜像的 S3 兼容服务;
- README、A0 报告同步依赖来源。

影响面:仅本地开发依赖与文档;代码/接口/数据模型不变。
回滚方式:git revert 本提交,并按旧 compose 重新初始化(不推荐)。
验证:migrate deploy、db:seed、test:int、pnpm ci:local(85.9s)全部通过。
2026-11-02 18:21:09 +08:00

108 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 灵犀 · A0 工程骨架与契约基线 实施报告 V0.1
> 对应开发计划:`docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md` §6.1「A0 工程骨架与契约基线」
> 交付方式:仅 `main` 直推,仓库不再保留任何短分支
> 日期:2026-11-02
## 1. 完成范围
| WBS | 状态 | 落地内容 |
| --- | --- | --- |
| A0-INF-01 Monorepo / 工具链 | 完成 | pnpm workspace + Turborepo;TS strict、ESLint 9 flat + Prettier + commitlint + lint-staged + husky;`.nvmrc` / `engines` / `packageManager` / preinstall 仅允许 pnpm;目录与 AGENTS.md §5 一致 |
| A0-INF-02 本地依赖与迁移种子 | 完成(种子范围受限,见 §4.4) | 复用本机 `docker-postgres-1`(PostgreSQL 18,5432)与 `docker-redis-1`(6379);`infra/docker-compose.dev.yaml` 仅管理 S3 兼容服务;`.env.example`;Prisma 初始化与首版迁移;`system_configs` 幂等种子 |
| A0-INF-03 CI 与质量门禁 | 完成 | `.gitea/workflows/ci.yml`:install → format → lint → typecheck → test → build → migrate → test:int → openapi:export/diff → e2e;新增 `pnpm ci:local` 在无 runner 时本地执行同一门禁;失败阻断 |
| A0-BE-01 API 骨架 | 完成 | NestJS 11 + Fastify;Pino + `trace_id`;统一错误体 `{code,message,details,trace_id}`;`GET /health`;`/api/docs` 与 OpenAPI JSON;Zod 管道;CORS / Helmet |
| A0-BE-02 Prisma 基线 | 完成 | `PrismaService` 封装;`outbox_events` / `idempotency_keys` / `system_configs`;ULID `char(26)`、软删/时间字段约定;首版迁移可重复执行 |
| A0-SH-01 shared 包 | 完成 | 20 个错误码(40001–50003)、权限点常量与 `模块:动作` 规范、ULID、游标分页、时间/命名工具、通用 Zod schema;前后端共同引用 |
| A0-FE-01 Web 骨架 | 完成 | Vite 6 + React 19 + Router 7 + TanStack Query 5 + Zustand 5;Semi `@douyinfe/semi-ui-19` 与 React19 适配入口;路径别名;fetch 请求层(token 注入、单飞 401 刷新、统一错误提示) |
| A0-FE-02 UI 包基线 | 完成 | Semi 二次封装(表格/查询表单/弹窗/空态/错误态/加载骨架);`icons.ts` 统一图标出口;locale;主题 token;ESLint 拦截越过出口的图标/UI 库与内联色值 |
| A0-FE-03 布局与登录壳 | 完成 | 顶部模块菜单 + 左侧功能菜单 + 面包屑;用户菜单、任务角标占位;401/403/404/500 页;登录页;导航集中配置并按权限过滤 |
| A0-QA-01 冒烟与报告 | 完成 | 健康检查冒烟、OpenAPI 冒烟、Playwright 登录/403/404/模块切换 4 条;覆盖率报告;CI 归档 |
## 2. 关键实现位置
- 契约与工具:`packages/shared/src/`(`errors/codes.ts`、`errors/api-error.ts`、`permissions.ts`、`ulid.ts`、`naming.ts`、`schemas/`)
- UI 基线:`packages/ui/src/`(`icons.ts`、`components/`、`theme/tokens.css`、`locale.ts`)
- API:`apps/api/src/`(`bootstrap.ts`、`common/filters`、`common/pipes`、`modules/platform/health/`、`openapi/document.ts`、`scripts/export-openapi.ts`)
- 数据:`prisma/schema.prisma`、`prisma/migrations/20261102083445_init_platform_baseline/`、`prisma/seed.ts`、`prisma/SEED.md`
- Web:`apps/web/src/`(`layout/`、`navigation/nav-config.ts`、`api/client.ts`、`pages/`、`stores/auth-store.ts`、`styles/`)
- 基础设施:`infra/docker-compose.dev.yaml`、`infra/compose.dev.yaml`、`.env.example`
- 契约快照:`openapi/lingxi.openapi.json`、`apps/web/src/api/generated/openapi.d.ts`
## 3. 本地门禁实测
| 命令 | 结果 |
| --- | --- |
| `pnpm format:check` | 通过 |
| `pnpm lint` | 通过(0 error / 0 warning) |
| `pnpm typecheck` | 通过(10/10 turbo tasks) |
| `pnpm test` | 通过(shared 42、api 20、web 12) |
| `pnpm build` | 通过(8/8 turbo tasks) |
| `pnpm test:int` | 通过(真实 PostgreSQL + Redis,`/health` 200) |
| `pnpm test:e2e` | 通过(4/4,Playwright/Chrome) |
| `pnpm openapi:export` + `pnpm openapi:diff` | 通过;快照含 20 个错误码,OpenAPI `3.1.0` |
| `pnpm compose:up` | 通过;`lingxi-s3` healthy;PG / Redis 使用本机已运行容器,`/health` 与 `test:int` 验证连通 |
| API 启动 | `/health` 200、`/api/docs` 200、`/api/openapi.json` 200 |
| Worker 启动 | 连接 Redis 成功,收到 SIGTERM 后正常退出 |
| 种子幂等 | 连续执行两次,`system_configs` 保持 7 条 |
## 4. 与文档的差异与待确认
### 4.1 本地依赖来源(环境适配)
本地 PostgreSQL 与 Redis **复用本机已有 Docker 服务**,不另起容器:`docker-postgres-1`(PostgreSQL 18,`127.0.0.1:5432`,库 `lingxi`、用户 `postgres`、密码 `postgres`)与 `docker-redis-1`(`127.0.0.1:6379`)。`infra/docker-compose.dev.yaml` 仅保留 S3 兼容服务(宿主 `19000/19001`)。CI services 使用标准 5432/6379,凭据同为 `postgres/postgres`。
### 4.2 对象存储镜像不可得(环境适配)
当前 Docker 环境无法拉取 `minio/minio` 与 `minio/mc`(registry denied),`dl.min.io` 二进制返回 410。A0 使用 **`adobe/s3mock`** 并在启动时创建 `assets / renders / temp / archive` 四个桶,仅用于本地开发;CI / 生产接入真实 MinIO 时替换 compose 中 `s3` 服务即可,应用侧仍只依赖 S3 协议与环境变量。
### 4.3 演示登录(A0 临时)
A1 才实现真实鉴权。A0 登录页在 `VITE_PUBLIC_DEMO_SESSION` 非 `false` 时使用本地演示会话进入布局,便于验收布局与权限过滤;A1 接入真实登录后删除该分支。
### 4.4 种子范围【待确认 Q-A0-01】
开发计划 A0-INF-02 要求种子包含「超管、示例角色、核心字典、电商行业包占位」,但 `users / roles / dict_* / industry_packages` 等表分别在 A1 / A3 / A4 / B0 批次建立。A0 不提前建业务表,仅 seed `system_configs` 7 项,并在 `prisma/SEED.md` 登记待补种子清单。**请确认是否接受该拆分**;若要求 A0 内建表,则需调整开发计划批次顺序。
### 4.5 错误码 HTTP 映射
工程规范 04 未规定 50002 / 50003 的 HTTP 状态。A0 将 `50002 依赖不可用` 映射为 **503**(与 `/health` 依赖异常返回值一致),`50003 超时` 映射为 504;如需改为 502 / 504,请确认后调整 `packages/shared/src/errors/codes.ts` 与 `codes.spec.ts`。
### 4.6 Prisma CLI 与环境文件
Prisma CLI 只自动读取 `.env`,不读取 `.env.local`。本地需执行 `cp .env.local .env`(两者均在 `.gitignore`);应用与种子脚本同时兼容 `.env.local` 与 `.env`。
### 4.7 OpenAPI 破坏性检查实现
npm 上 `oasdiff` 为占位包(0.0.1-security),A0 暂用自研 `scripts/openapi-diff.mjs` 做路径/操作/字段级破坏性检查;CI 可后续替换为 oasdiff 官方二进制,命令仍为 `pnpm openapi:diff`。
### 4.9 本地 CI 与数据库凭据
当前离线 Gitea 未部署 Actions runner,推送后远程 CI 会停留在 `queued`。A0 增加 `pnpm ci:local`:按 `.gitea/workflows/ci.yml` 的顺序在本地执行 compose、格式、Lint、类型、单测、构建、迁移与种子、集成、OpenAPI 契约与 e2e,全部通过才退出 0;runner 就绪后远程工作流可直接接管。
本地开发库为 `lingxi` / `postgres` / `postgres`,直接连接本机已有 PostgreSQL 容器;`.env.example` 与 CI services 保持一致。
### 4.8 前端视觉方向
已按 oil-ui-pro 流程产出两轮方案:
- v1(概念化:剪辑台 / 稿纸 / 调度台)被否决;
- v2(传统且现代化:云白蓝 / 石墨 / 暖白青)经产品负责人选择 **A · 云白蓝**,已落地到 `packages/ui/src/theme/tokens.css`、`apps/web/src/styles/`、`apps/web/index.html`:
- 顶部模块菜单 + 左侧功能菜单 + 面包屑;
- 白色顶栏、`#F5F7FA` 工作区、白卡片、`#1677FF` 主色、6px 圆角;
- 工作台:4 指标卡 + 生产任务表 + 快速入口 + 最近素材;
- 登录页:左上品牌、居中白卡、浅灰背景。
设计探索产物位于 `design/a0-ui-v2/`(含 6 屏、对比页与截图),按 `.gitignore` 约定不入库,仅本地留存评审。
## 5. 已知风险与后续动作
1. **A1 必须移除演示登录**并接入真实 JWT / 刷新令牌 / 权限守卫。
2. 种子业务数据待 A1 / A3 / A4 / B0 表就绪后补齐(Q-A0-01)。
3. MinIO 本地替代方案需在具备镜像的环境回归;生产 compose 与 CI 镜像另行处理。
4. Web 主包约 599 kB(Semi 全量 CSS 689 kB),A0 接受;M1 前做路由级拆分与 Semi 按需样式。
5. 远程 CI 待 Gitea Actions runner 就绪后验证 services 与 Playwright 浏览器安装;当前以 `pnpm ci:local` 为准(已实测通过)。
## 6. 下一步(A1)
按开发计划进入 A1:identity / client 模块、真实登录与 RBAC、`ScopeContext`、客户与组织基础表、登录与权限三态测试。