重置项目上下文与规范文档

This commit is contained in:
2026-08-07 16:18:07 +08:00
parent 6611ca5226
commit 79e2d9ff92
1900 changed files with 1552 additions and 348365 deletions

149
ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,149 @@
# 系统架构地图
## 系统职责与非职责
本系统保存物联网卡、设备、套餐、订单、钱包、分佣、审批、通知和审计的本地业务事实并协调支付、运营商、Gateway、企业微信、短信和对象存储。第三方内部状态、审批流配置、支付清算和运营商网络行为不是本系统事实外部契约见 [`docs/integrations/`](docs/integrations/)。
## Composition Roots 与运行单元
| 单元 | 入口 | 启动链与外部依赖 | 验证 |
| --- | --- | --- | --- |
| HTTP API | `cmd/api/main.go` | Viper 配置 → 日志目录 → PostgreSQL → Redis/Asynq Client → JWT/验证码 → Storage/Gateway → `internal/bootstrap.Bootstrap` → Fiber 中间件与路由;启动时写 `logs/openapi.yaml` | `go build ./cmd/api`;启动后请求 `/health``/ready` |
| Worker | `cmd/worker/main.go` | PostgreSQL、Redis、Storage、Gateway → `internal/bootstrap.BootstrapWorker` → Task Handler、Outbox Relay、任务救援角色决定单例调度模块 | `go build ./cmd/worker`;从应用日志核对角色、模块和任务注册 |
| OpenAPI 生成 | `cmd/gendocs/main.go` | 使用占位 Handler 复用 `internal/routes.RegisterRoutesWithDoc`,生成接口文档 | `go run cmd/gendocs/main.go`;它证明路由元数据,不单独证明真实 Bootstrap 可达性 |
| 治理 CLI | `cmd/foundation-check``cmd/audit-coverage``cmd/migration-finalize``cmd/audit-retention-simulate` | 读取源码、迁移或数据库状态并输出门禁/模拟结果 | 逐命令检查输入;`audit-coverage` 当前仍依赖已删除路径,见工程约束 BLOCKED 项 |
启动、隔离数据库、smoke 与日志命令见 [`README.md`](README.md)。
## Worker 角色
`pkg/config/config.go` 接受 `all``leader``consumer`
- 三种角色都启动 Asynq 消费服务、Outbox Relay 和未完成导入任务救援。
- `leader``all` 额外启动轮询初始化器、轮询调度器和 Asynq Scheduler。
- `consumer` 不运行单例调度模块,适合横向扩展消费能力。
- 实际启停判断位于 `cmd/worker/main.go``buildWorkerModuleStatus``runsSingletonModules`
## HTTP 路由与信任边界
总入口是 `internal/routes/routes.go`
| 路由域 | 认证/信任边界 | 主要入口 | 当前 Spec 索引 |
| --- | --- | --- | --- |
| `/health``/ready` | 公开,只返回进程健康/就绪状态 | `internal/routes/health.go` | `openspec/specs/operations-audit/spec.md` |
| `/api/auth` | 后台账号登录、刷新、登出与当前身份;认证中间件在路由组装配 | `internal/routes/auth.go` | `openspec/specs/identity-access/spec.md` |
| `/api/admin` | 后台认证、角色权限、店铺/企业数据范围;业务层仍需资源级校验 | `internal/routes/admin.go` | `identity-access``asset-device``package-lifecycle``order-payment-wallet``operations-audit` |
| `/api/c/v1` | 个人客户 Token 与资产归属边界 | `internal/routes/personal.go` | `openspec/specs/personal-customer/spec.md` |
| `/api/open/v1` | 代理 Open API 独立认证/签名,不复用后台账号权限 | `internal/routes/open.go` | `openspec/specs/agent-open-api/spec.md` |
| `/api/callback` | 无登录认证;每类渠道必须在 Handler/Adapter 内验签、解密、校验金额或事件身份 | `internal/routes/order.go``wecom_callback.go` 及运营商回调注册 | `openspec/specs/external-integration/spec.md``order-payment-wallet` |
HTTP 入参、回调 Body/Header、上传文件和代理签名材料均是不可信输入。Handler 只做绑定、边界校验与响应;状态和金额不变量必须由业务用例重新判断。
## 分层与实际共存结构
- `internal/routes`:可达 HTTP 入口与 RouteSpec。
- `internal/handler`Fiber 信任边界、参数绑定和统一响应。
- `internal/application`新用例编排、事务脚本、Port 和可靠副作用边界。
- `internal/domain`:状态、金额与并发不变量;不依赖 Fiber、GORM、Redis、Asynq 或外部 SDK。
- `internal/query`:只读权限、联表、分页和 DTO 投影。
- `internal/service`:旧用例;允许直接使用 Store/GORM按完整用例渐进迁移。
- `internal/infrastructure`Port Adapter、GORM Repository、Outbox、审计与外部交互。
- `internal/store/postgres``internal/model`:旧持久化模型与显式查询。
- `internal/bootstrap`API/Worker 依赖装配,不承载业务规则。
- `pkg`:跨模块基础能力和第三方客户端。
- `migrations`Schema 演进事实。
允许方向Handler → Application/Query/旧 ServiceApplication → Domain + PortInfrastructure → Application/Domain Port旧 Service → Store/GORM。禁止 Domain 依赖框架或基础设施、Query 修改状态、Handler 拼装领域规则、Infrastructure 定义业务状态机。
```bash
! grep -RIlE 'gofiber|gorm.io|go-redis|hibiken/asynq' internal/domain --include='*.go'
```
## 关键业务模块导航
以下表是入口地图,不替代业务 Specs事务与副作用必须按具体调用链证明。
| 业务能力 | HTTP/异步入口 | 用例与领域 | 持久化/外部边界 | Spec |
| --- | --- | --- | --- | --- |
| 后台身份、账号、角色、权限、店铺 | `routes/auth.go``account.go``role.go``permission.go``shop.go` | `handler/auth|admin`;旧 `service/auth|account|role|permission|shop`;新 `application/role|shop|accessaudit|accountaudit` | `store/postgres`、RBAC 中间件、审计 Writer | [`identity-access`](openspec/specs/identity-access/spec.md) |
| 卡、设备、资产与企业授权 | `iot_card.go``device.go``asset*.go``enterprise_card.go``enterprise_device.go`;导入/轮询任务 | 旧 `service/iot_card|device|asset|enterprise_*``application/cardobservation``domain/cardobservation`;读取 `query/asset` | GORM、Gateway、运营商、Outbox | [`asset-device`](openspec/specs/asset-device/spec.md) |
| 套餐、系列、授权、订购与到期 | `package*.go`、批量分配/调价/订购路由;激活、到期和失效任务 | 旧 `service/package|package_series|shop_*``domain/package``application/packageexpiry` | GORM、Asynq、Outbox/通知 | [`package-lifecycle`](openspec/specs/package-lifecycle/spec.md) |
| 订单、支付、充值、钱包、退款、分佣与换货 | `order.go``agent_recharge.go``refund.go``commission.go``exchange.go`、支付回调 | 旧 `service/order|recharge|refund|commission_*|exchange``application/agentrecharge|wallet|refundapproval|approval|exchange``domain/agentrecharge|wallet|approval` | GORM、支付 Adapter、企微、Outbox、审计/资金事实 | [`order-payment-wallet`](openspec/specs/order-payment-wallet/spec.md) |
| 个人客户 | `routes/personal.go` 及 C 端子路由 | `handler/app``service/client_*|personal_customer|customer_binding`;通知 Application/Query | Token、资产绑定、钱包、支付、Gateway | [`personal-customer`](openspec/specs/personal-customer/spec.md) |
| 代理 Open API | `routes/open.go` | `handler/openapi``service/agent_open_api` | 独立认证、店铺数据范围、卡/套餐/钱包 Store | [`agent-open-api`](openspec/specs/agent-open-api/spec.md) |
| 轮询、通知、导出、配置与审计调查 | `polling_*.go``notification.go``export_task.go``system_config.go``audit.go`Scheduler/Task/Outbox | `application/notification|systemconfig|auditarchive|outbox``query/audit|notification|outbox|systemconfig`;旧 polling/export Service | Asynq、Outbox、审计库、Integration Log、对象存储 | [`operations-audit`](openspec/specs/operations-audit/spec.md) |
| 外部集成接点 | 支付/运营商/企微回调Gateway 调用,对象存储、短信 | `internal/gateway``internal/infrastructure/wecom|payment|carriercallback|integrationlog``pkg/alipay|wechat|fuiou|sms|storage` | 第三方网络和凭证;协议事实见 integrations | [`external-integration`](openspec/specs/external-integration/spec.md) |
任务 7 会把当前过大的 Spec 索引拆成完整业务能力;拆分后必须同步本表链接。
## 同步数据流
```text
HTTP Route
→ 认证/数据范围中间件
→ Handler绑定与信任边界
→ Application / Query / 旧 Service
→ Domain仅适用于已迁移复杂写
→ Repository / Store / GORM
→ pkg/response 或全局 ErrorHandler
```
并非所有写操作都在统一事务中:旧 Service 可能直接写 Store新 Application 可能使用事务脚本,复杂写可能通过 Domain + Port。审计、状态条件和事务范围必须从具体用例证明不能由这张地图推断。
## 异步与可靠事件
### Asynq Task
Worker 当前处理的任务族包括:卡/设备导入、导出分片与收尾、资产批量购包、订单套餐失效、自动充值后购包、佣金、订单过期、五类轮询、告警、数据/通知清理、套餐到期提醒、每日流量落盘、企微审批同步/恢复、代理充值恢复、审计/集成归档和 Outbox 投递。
发现真实注册与生产位置:
```bash
rg -o 'constants\.TaskType[A-Za-z0-9_]+' cmd/worker/main.go internal/task internal/bootstrap/worker.go internal/infrastructure | sort -u
```
直接 `EnqueueTask` 只证明已提交,不等于业务终态成功;最终状态由 Task Handler 的条件更新、记录或补偿决定。
### Outbox
当前事件族覆盖审批提交/终态、卡实名/流量/网络/系列、代理充值支付确认、代理主钱包扣款/预留/入账/退款,以及后台/个人通知。
```bash
rg -o 'constants\.OutboxEventType[A-Za-z0-9_]+' cmd/worker/main.go internal | sort -u
```
需要业务事实与可靠异步副作用原子提交的用例应同事务写 Outbox是否已经做到必须逐调用链核对。Relay 和消费者按至少一次投递设计,消费者必须容忍重复。
## 外部调用与回调
- 支付:创建本地支付事实后调用渠道;回调需要验签、金额/业务号/状态校验,重复回调不得重复入账。
- 企业微信:本地审批实例 → Outbox 提交 → 渠道审批;加密回调、轮询和人工同步进入统一状态同步语义。
- Gateway/运营商:查询与控制结果来自外部;超时或未知结果不得理想化为成功。
- 对象存储:上传/预签名 URL 是外部副作用,数据库只保存对象引用。
- SMS发送结果是外部通知结果不等同业务事务成功。
外部网络调用不应持有长数据库事务;确需提交后可靠执行时使用 Outbox/Task。实际例外按 As-Is Spec 记录。
## 事务、审计与日志边界
- Access LogHTTP 调试事实。
- Audit Event操作者、资源、动作、前后值和结果。
- Domain Ledger/钱包交易:金额与状态领域事实。
- Integration Log外部调用尝试和脱敏结果。
- Outbox提交后可靠副作用不替代前三者。
成功高风险操作是否与审计同事务必须逐用例核对。业务已回滚后的 failed/denied 审计使用独立短事务。不得用 Access Log 证明资金或状态事实。
## 结构与生成验证
```bash
go build ./cmd/api ./cmd/worker
go run cmd/gendocs/main.go
openspec doctor --json
openspec validate --all
./scripts/context-health.sh
! grep -RIlE 'gofiber|gorm.io|go-redis|hibiken/asynq' internal/domain --include='*.go'
rg 'Register[A-Za-z]*Routes|register[A-Za-z]*Routes' internal/routes
```
OpenAPI 生成器使用占位 Handler因此还要对照 `internal/bootstrap` 与真实路由装配。Schema 事实以 `migrations/` 和隔离数据库为准,禁止使用 Makefile 中的历史连接信息。