Checks / verify (push) Failing after 9m52s
统一单入口 Go 工程与前端依赖目录,增加后台供应商配置、候选审核、计划预算、成交冲正、持仓复盘和站内通知。接入策略版本、Python 回测、可配置 A 股公开行情及 zap 文件轮转日志,补充迁移、契约与验证。
160 lines
12 KiB
Markdown
160 lines
12 KiB
Markdown
# 见势 · Veyra
|
||
|
||
AI 量化投资辅助产品。原始交互原型与全栈设计文档保留在根目录;当前交付包括工程基础、开发登录、管理员用户查询、账户初始化、后台供应商配置与 Expo App 基础流程。
|
||
|
||
## 已实现
|
||
|
||
- Go 模块化 API、JSON 日志、请求 ID、健康检查、超时与优雅停机。
|
||
- PostgreSQL 建库命令、事务迁移、并发迁移锁及历史迁移 checksum 校验。
|
||
- `veyra_user` / `User`、`veyra_account` / `Account`;主键为 `varchar(36)` UUID,Go 使用 string。
|
||
- 所有表、字段、索引按项目规范命名,包括 `veyra_schema_migration`。
|
||
- Vite + React + TypeScript + Tailwind CSS 4 + shadcn/ui 管理端,暖白、炭黑、焦糖橙主题,构建产物通过 Go embed 嵌入 API 二进制。
|
||
- 管理端读取 API 实际探测结果,十个工作区入口已建立,尚未实现的业务页面明确显示建设中。
|
||
- 管理端登录、HttpOnly Cookie 会话、退出撤销、用户列表;Redis 按来源 IP 和登录名限流,依赖失败时拒绝登录。
|
||
- App 开发登录与 Bearer 会话;管理端和 App 会话互相隔离,数据库只存凭据哈希。
|
||
- 账户创建、列表与汇总;模拟账户初始现金与流水原子入账,金额使用整数分,API 使用十进制字符串。真实记录账户现金为未知。
|
||
|
||
- 后台配置主模型、备用模型、审核模型与行情源,初始留空且关闭;密钥加密存储,版本冲突保护、配置历史与审计原子保存。
|
||
|
||
- React Native + Expo App:五个主导航、开发登录、安全会话、账户创建与切换、真实现金账本展示;未接入模块明确提示。
|
||
|
||
## 启动
|
||
|
||
需要 Go 1.26.2 与支持 Vite 的 Node.js,已提交 Go 和 npm 锁文件。根目录执行:
|
||
|
||
```sh
|
||
cp configs/.env.example configs/.env
|
||
```
|
||
|
||
将 PostgreSQL 用户名与密码填写到 `configs/.env`。默认数据库名称 `veyra`,默认管理数据库 `postgres`;创建数据库需要连接角色具有 CREATEDB 权限。Redis 无用户名,有密码:在本地 `configs/.env` 配置 `REDIS_PASSWORD`,保持 `REDIS_USERNAME` 为空。`PGSSLMODE=disable` 是本地模板值,如服务器要求 TLS 则修改。
|
||
|
||
```sh
|
||
go mod download
|
||
npm --prefix web/admin ci
|
||
go run . -command db-create
|
||
go run . -command db-migrate
|
||
go run . -command user-create -role ADMIN
|
||
npm --prefix web/admin run build
|
||
go run .
|
||
```
|
||
|
||
启动后访问 `http://127.0.0.1:8080`,管理端由 Go embed 提供,页面与 API 同源。需要前端热更新时另开终端运行 `npm --prefix web/admin run dev`,访问 Vite 输出的本地地址;开发代理将 `/api` 转发到 `127.0.0.1:8080`。API 可在数据库未配置时启动并如实报告不可就绪。
|
||
|
||
管理端初始登录名与密码由 `configs/.env` 的 `ADMIN_LOGIN` / `ADMIN_PASSWORD` 配置,管理员密码要求 8–72 字节。凭据只保存在本地 `configs/.env`,模板不包含密码。`go run . -command user-create -role ADMIN` 创建身份,不覆盖已有管理员。App 测试身份使用 `DEV_USER_LOGIN` / `DEV_USER_PASSWORD` 和 `go run . -command user-create -role USER` 初始化。数据库的登录账号不用于产品登录。
|
||
|
||
已有数据库只需 `go run . -command db-migrate` 应用所有尚未执行的版本化迁移(当前最新为 `000004_llm_configuration.sql`),无需重新建库。
|
||
|
||
生产编译直接使用 npm 与 Go:
|
||
|
||
```sh
|
||
npm --prefix web/admin run build
|
||
go build -trimpath -o bin/veyra .
|
||
./bin/veyra
|
||
```
|
||
|
||
`npm --prefix web/admin run build` 将前端产物复制到 Go embed 目录,`go build` 输出唯一的 `veyra` 可执行文件。默认读取当前工作目录的 `configs/.env`,也可使用 `-env-file` 指定文件或空值以仅使用进程环境。修改管理端后先重建前端,再重建 Go 二进制;未构建前端时管理端返回明确的 503。
|
||
|
||
常规开发启动直接运行 `go run .`,也可以在 IDE 运行根目录 `main.go`;仓库只有一个 main 函数,不依赖 Makefile。服务启动不自动建库、迁移或修改身份。
|
||
|
||
开发管理员修改使用本地 `configs/.env` 的 `ADMIN_LOGIN` / `ADMIN_PASSWORD`:
|
||
|
||
```sh
|
||
go run . -command admin-set -previous-login <原管理员登录名>
|
||
```
|
||
|
||
已有登录名不变时可省略 `-previous-login`。此命令仅限 local/test,保留原管理员 ID、以 bcrypt 保存新密码并撤销旧会话;登录名冲突时全部回滚。管理员密码为 8–72 字节,App 开发用户仍为 12–72 字节。
|
||
|
||
|
||
### App 开发
|
||
|
||
App 位于 `apps/mobile`,使用 Expo Router + React Native + TypeScript,配色为白底、石墨黑与柔紫。初始化 USER 身份后填写 App 的公开 API 地址并启动:
|
||
|
||
```sh
|
||
go run . -command user-create -role USER
|
||
npm --prefix apps/mobile ci
|
||
cp apps/mobile/.env.example apps/mobile/.env
|
||
npm --prefix apps/mobile run start
|
||
```
|
||
|
||
在 `apps/mobile/.env` 设置 `EXPO_PUBLIC_API_URL`。iOS 模拟器可用后端本机地址,Android 模拟器使用 `10.0.2.2`,真机使用开发电脑内网地址。App 登录身份与管理员隔离;凭据不打包到客户端,供应商信息仍由管理端配置。
|
||
|
||
`npm --prefix apps/mobile run typecheck && npm --prefix apps/mobile run test` 执行 TypeScript 与客户端测试;`npm --prefix apps/mobile run build` 导出两个平台的 Hermes bundle,不生成 APK/IPA。运行和当前功能边界见 [App 说明](apps/mobile/README.md)。
|
||
|
||
### 账户 API 示例
|
||
|
||
测试身份初始化后,`POST /api/v1/auth/login` 使用 `login_name` 和 `password` 返回开发访问凭据。后续请求使用 `Authorization: Bearer <access_token>`。
|
||
|
||
`POST /api/v1/accounts` 的模拟账户请求:
|
||
|
||
```json
|
||
{"mode":"simulation","name":"模拟账户","initial_cash":"100000.00"}
|
||
```
|
||
|
||
真实记录账户请求省略 `initial_cash`,返回 `cash_balance: null`、`ledger_status: INCOMPLETE`。同一用户每种模式只可创建一个账户;重复创建返回 409,不重复生成初始资金。`GET /api/v1/accounts` 返回当前用户账户,`GET /api/v1/accounts/{id}/summary` 查询归属当前用户的账户,其他用户的 ID 返回 404。
|
||
|
||
### 后台供应商配置
|
||
|
||
「模型配置」填写主模型、备用模型和审核模型;「系统设置」填写行情源。供应商名称、HTTPS 地址、模型名称和密钥初始均为空,不预选供应商。未配置时保持关闭;模型启用需要名称、地址、模型名称和密钥,行情源启用需要名称和地址。保存或启用不代表连接已验证,当前尚未实现供应商调用与连通性测试。协议、模型目录、响应存储策略和认证开关均为后台可修改的配置,不预填厂家地址或模型。未填写模型时可先保存关闭状态的连接地址和密钥。模型目录需与接口同源,避免把认证信息指向另一个站点。
|
||
|
||
`SECRET_ENCRYPTION_KEY` 是部署层加密主密钥,使用 Base64 编码的 32 字节随机值,在本地 `configs/.env` 或部署秘密配置中持久保存。本机已生成此值,仓库模板留空。可用 `openssl rand -base64 32` 为新环境生成;主密钥必须与数据库一起备份,切勿在已有密文后直接替换。未配置主密钥时仍可保存无密钥的关闭配置,提交密钥会被拒绝。
|
||
|
||
密钥采用 AES-256-GCM 加密,绑定配置角色;查询只返回 `has_api_key`。密钥留空保留原值,勾选清除后删除当前密钥;修改接口地址时必须重新填写或清除密钥。历史保留加密快照用于追溯,审计日志不含明文密钥。保存使用 `expected_version` 防止覆盖其他管理员的修改;所有接口限制管理员,同源 Origin 保护写操作。
|
||
|
||
### 开发登录边界
|
||
|
||
密码登录和命令行身份初始化仅在 `APP_ENV=local/test` 开启;其他环境拒绝开发登录。正式 App 短信登录、访问凭据刷新、管理端 MFA 与细分 RBAC 尚未实现。当前会话为 8 小时、服务端可撤销;Cookie 写操作要求同来源 Origin。开发模式可使用 Vite 的同源代理,部署代理的 HTTPS 信任配置将在正式认证阶段实现。
|
||
|
||
```sh
|
||
go test -race ./...
|
||
go vet ./...
|
||
```
|
||
|
||
PostgreSQL 集成测试需显式提供测试数据库,测试在独立临时 schema 内运行并清理:
|
||
|
||
```sh
|
||
VEYRA_TEST_DATABASE_URL='postgres://user:password@host:5432/test_db?sslmode=disable' go test -race ./...
|
||
```
|
||
|
||
## 目录
|
||
|
||
```text
|
||
main.go 唯一入口,启动服务或执行明确的初始化命令
|
||
configs/ 后端环境配置与模板(私有配置不提交)
|
||
internal/
|
||
config/ 配置加载与校验
|
||
database/migrations/ 数据库连接与版本化迁移
|
||
model/ User、Account、Session 等模型
|
||
repository/ PostgreSQL 数据访问与事务
|
||
service/ 登录、账户和健康检查业务
|
||
handler/ HTTP 路由、中间件与协议适配
|
||
adminui/ 管理端 embed 资源与静态服务
|
||
apperror/ 跨层业务错误
|
||
ratelimit/ Redis 登录限流
|
||
secret/ 供应商凭据加密
|
||
integration/ 数据库集成测试
|
||
web/admin/ Vite React 管理端
|
||
apps/mobile/ React Native Expo App
|
||
api/openapi.yaml HTTP 契约
|
||
go.mod / go.sum 根目录唯一 Go module
|
||
```
|
||
|
||
仓库采用根目录 Go 单模块结构,管理端放在 `web/admin`,无需 `go.work`。两个前端各自维护 package.json、package-lock.json 和 node_modules,根目录不设置 npm workspace。文件按职责划分,调用方向为 handler → service → repository;接口在 service 中定义,由 repository 实现,避免 service 依赖具体数据库。
|
||
|
||
采用显式 SQL 和结构体 db tag,避免 ORM 隐式推断表名。迁移打包到 Go 二进制,已执行迁移不可改写,后续修改新增版本。API 启动不自动建库或迁移。健康检查不会返回连接串和供应商错误细节。
|
||
|
||
## 待完成
|
||
|
||
2026-10-08 已验证 PostgreSQL、Redis 内网连接,应用全部四版迁移并初始化开发管理员。真实 PostgreSQL 集成测试已在临时 schema 中执行;测试不会修改开发账户或供应商配置。
|
||
|
||
尚未接入候选审核、交易计划、成交账本、行情、AI、Worker 或回测。App 已有基础界面和登录/账户真实 API,偏好、机会、计划、持仓明细、提醒与复盘仍待相应业务接口。下一步建设候选修订、审核发布与计划闭环,再落实成交账本和风险监控。
|
||
|
||
管理端基础组件按 [shadcn/ui 的 Vite 集成方式](https://ui.shadcn.com/docs/installation/vite)维护在 `src/components/ui`,Tailwind 使用[官方 Vite 插件](https://tailwindcss.com/docs/installation/using-vite)。
|
||
|
||
## 日志与 A 股开发数据
|
||
|
||
后端使用 zap,默认在运行目录创建 `logs/veyra.log`,控制台易读、文件 JSON,自动轮转压缩。通过 `configs/.env` 的 `LOG_*` 配置目录、级别和保留规则。
|
||
|
||
后台「系统设置」配置公开行情适配器与地址,启用后启动同步、每五分钟更新沪深报价;「数据健康」查询股票和同步结果。研究回测可直接按代码、交易所和日期获取不复权日线,无需逐只新建股票或导入 CSV。当前公开源为开发研究用途;供应商时间、历史快照与失败状态如实展示。策略筛选、正式行情授权和实际交易规则仍待接入。
|
||
|
||
App 在「机会」→「查看自动同步的 A 股行情」查看数据。当前预览 Metro `exp://192.168.100.2:8081`,API 为 `http://192.168.100.2:8083`,同一内网使用 Expo Go;开发身份读取后端本地 `DEV_USER_*` 配置。尚未完成真机界面验证。
|