# 见势 · 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 `。 `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-09 已验证 PostgreSQL、Redis 内网连接,应用全部十四版迁移并初始化开发管理员。真实 PostgreSQL 集成测试已在临时 schema 中执行;测试不会修改开发账户或供应商配置。 候选审核、计划预算、不可覆盖模拟成交与冲正、FIFO 持仓与账本复盘、站内提醒、公开行情、异步 Python 回测和自动日线筛选已接通。App 对应 API 与页面已实现,真机流程仍待验证。AI、偏好/关注、正式认证、远程推送与生产交易规则尚未完成;详细验证事实见 docs/development-state.md。 管理端基础组件按 [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_*` 配置。尚未完成真机界面验证。 ## 自动候选筛选与提醒 管理端「策略中心」修订研究版本,勾选自动候选筛选,从自动同步股票搜索选择沪深范围(最多 100 只),配置整数基点价格规则和有效时长,再选用此版本。已有策略默认不启用此功能,价格规则留空由后台配置。无需手工新建股票或逐条录入候选证据。 Worker 每轮最多处理 20 个目标,完成后间隔 5 分钟再次检查。仅使用完整未复权日线,最近报价观察不超过 24 小时,来源与日期必须一致。符合 SMA 上穿规则时自动提交候选待审核;没有信号或数据不足不生成候选。候选经人工审核发布后才进入 App「机会」。参数、日线快照、来源与版本摘要可在筛选记录中查看,不代表已验证策略收益。 暂停或切换策略版本会使其自动候选及未完成计划失效并释放保留预算;手工候选独立维护,成交事实与持仓保留。行情同步为有效计划生成近期报价事件,只允许最近一分钟的供应商报价触发一次站内提醒,重复报价及失效来源跳过。提醒不产生成交、不改变资金,五分钟轮询不保证捕获所有瞬时行情。 管理端总览现以股票为核心,展示实际行情、证券代码、日线与待审核信号;“股票行情”提供股票池与历史走势,“候选审核”可立即请求自动筛选并查看运行状态。固定范围每批最多检查 20 只;重复点击运行中的任务不会另起 Worker。后台已启用开发基线的固定 96 只范围,并从真实日线生成两条待审核候选,尚未自动发布。参数仅用于开发研究,可在策略中心修订。 ## CI/CD 自动部署 开发使用 `dev`,通过 PR 合并进入受保护的 `master`;仅 `master` push 触发 CI/CD。Gitea Runner 验证后,通过 SSH 部署内嵌管理端的 Go 镜像至 `192.168.100.132:/home/workspace/sundynix-veyra`,执行版本化迁移、依赖就绪检查与应用回滚。详见 [部署说明](deploy/README.md)。