تشغيل أي مهارة في Manus
بنقرة واحدة
بنقرة واحدة
تشغيل أي مهارة في Manus بنقرة واحدة
ابدأ الآن$pwd:
$ git log --oneline --stat
stars:٣٣٨
forks:٦٣
updated:٢٥ مارس ٢٠٢٦ في ٠٧:١٦
مستكشف الملفات
SKILL.md
PowerX REST 契约规则(资源命名、分页、错误、版本化)。
PowerX CRUD 依赖注入规则(Deps 单入口、构造注入、跨传输复用)。
PowerX CRUD DTO 规则(输入输出分离、分页、校验)。
PowerX CRUD gRPC 顶层 ruleset 约束。
PowerX CRUD gRPC 开发规范(proto、server、拦截器、错误映射)。
PowerX HTTP Handler 规则(绑定校验、统一回包、无 DB IO)。
| name | crud-http |
| description | PowerX CRUD HTTP 开发规范(管理端路由、绑定、错误桥接、多租户)。 |
本文件内嵌规则。# PowerX 开发规范入口(Dev Guides)
> 本文档是 PowerX 的统一开发规范入口。
>
> - 人类可阅读:开发与评审统一看这里。
> - 工具可扩展:未来可被 `/plan` 与 `/tasks` 解析成可验证规则。
---
## 1. 目的与范围(Scope)
本规范适用于所有 PowerX 核心与插件模块中涉及 **CRUD 能力** 的后端开发,
包括但不限于以下层次:
- 迁移(Migration)
- GORM 模型(Model)
- Repository(仓库层,含 BaseRepository)
- Service(业务服务层)
- DTO(入参/出参)
- Handler(HTTP 层)
- 依赖注入(DI)
- 路由(Routes)
- 契约 / 集成测试(Tests)
---
## 2. 全局策略(Policies)
- **数据库**:统一使用 **GORM 抽象**,默认 **Postgres**。
不允许写死 MySQL 方言或独立 SQL 文件;索引与唯一约束以 GORM tag 或迁移注册为准。
- **HTTP 路由**:统一前缀 `/api/v1/admin/**`(可配置)。
- **多租户**:所有查询与写入都必须携带 `tenant_id`。
- **审计**:所有写操作(Create/Update/Delete/Presign)必须记录审计日志。
- **安全**:预签名链接仅允许受管路径、受限方法(GET/PUT)与 MIME 白名单。
- **依赖注入**:所有仓库与服务实例必须由 `internal/app/shared/deps.go` 统一注册。
---
## 3. 层次结构(Layer Overview)
```plaintext
Model → Repository → Service → Handler → Router
↘ DI(shared) ↙
```
---
## 4. Migration(迁移)
### 约定
- **统一入口**:`cmd/database/migrate.go`
由该入口统筹调用各模块的迁移函数。
- **两种迁移模式**
1. **独立 Server 模块(如 Agent)**:在 `cmd/database/migrate.go` 内实现 `MigrateAgentModels(db *gorm.DB) error`,仅使用 `db.AutoMigrate(...)` 注册模型。
2. **CoreX 内核模块(如 MediaX)**:在 `pkg/corex/db/migration.go` 内实现 `MigrateCoreModels(db *gorm.DB) error`,由其中**直接调用 `AutoMigrate`** 将核心模型(含 MediaX)纳入迁移。
- **不交付任何 `.sql` 文件**,迁移中禁止手写 `db.Exec(...)`。
- **索引/唯一约束**:一律在 **GORM 模型结构体标签**中声明(含唯一索引、GIN 索引、部分索引等)。
- **运行期校验(可选)**:如需校验可用 `db.Migrator().HasIndex()` / `HasConstraint()`,但**不得因此写原生 SQL**。
- **错误处理**:所有迁移函数必须返回 `error`,并在统一入口串联调用。
---
### 示例
#### A. 独立 Server 模块(Agent)
> 在 `cmd/database/migrate.go` 内直接定义并调用:
```go
// cmd/database/migrate.go
package main
import (
"log"
"gorm.io/gorm"
dbmodel "github.com/your/module/internal/server/agent/persistence/model"
)
func MigrateAgentModels(db *gorm.DB) error {
if err := db.AutoMigrate(
&dbmodel.Agent{},
&dbmodel.AgentSetting{},
); err != nil {
return err
}
// 可选:运行期校验(不写 SQL)
if ok := db.Migrator().HasIndex(&dbmodel.Agent{}, "agent_uniq_tenant"); !ok {
log.Println("warn: agent_uniq_tenant not created")
}
return nil
}
func main() {
// init db ...
// 串联调用(示例)
if err := MigrateCoreModels(db); err != nil { log.Fatal(err) }
if err := MigrateAgentModels(db); err != nil { log.Fatal(err) }
}
```
#### B. CoreX 内核模块(含 MediaX)
> 在 `pkg/corex/db/migration.go` 中集中维护 CoreX 的模型清单(例如 MediaX)并 **只用 `AutoMigrate`**:
```go
// pkg/corex/db/migration.go
package corexdb
import (
"gorm.io/gorm"
mediamodel "github.com/your/module/pkg/corex/db/persistence/model/media"
// 其他 CoreX 内核模型...
)
func MigrateCoreModels(db *gorm.DB) error {
return db.AutoMigrate(
&mediamodel.MediaAsset{},
// &mediamodel.MediaSet{}, // 如有
// 其他 CoreX 内核模型...
)
}
```
> 说明:
>
> - **MediaX 等内核能力**作为 CoreX 的一部分,统一纳入 `MigrateCoreModels`;
> - 索引/约束通过模型标签自动创建(如 `unique`、`using:gin`、`where:deleted_at IS NULL` 等);
> - 不再需要也不建议为 MediaX 再单独写 `MigrateMediaModels`。
### 示例
```go
func MigrateAgentModels(db *gorm.DB) error {
db.AutoMigrate(
&dbmodel.Agent{},
&dbmodel.AgentSetting{},
)
if ok := db.Migrator().HasIndex(&dbmodel.Agent{}, "agent_uniq_tenant"); !ok {
log.Println("warn: agent_uniq_tenant not created")
}
return nil
}
```
### 验收要点
- [ ] 模块定义独立的 `Migrate<Module>Models(db *gorm.DB)` 函数
- [ ] 模型通过 `db.AutoMigrate()` 注册,无需 .sql 文件
- [ ] 索引与唯一约束在 GORM 模型 tag 中声明
- [ ] (可选)运行期校验索引 `db.Migrator().HasIndex()`
- [ ] 迁移函数返回 `error` 并在顶层入口统一调用
---
## 5. Model(GORM 模型)
### 约定
- 模型统一基于 **PowerX Base Model**:
- `PowerModel`:自增整型主键;
- `PowerUUIDModel`:双主键(UUID + 自增 ID),在 `BeforeCreate()` 自动生成 UUID。
- 必须显式声明:
- `CreatedAt` / `UpdatedAt` / `DeletedAt`;
- 表名函数 `TableName()` 与 `GetTableName()`;
- 多租户字段:`TenantID uint64`;
- Schema 默认由 `PowerXSchema` 控制;
- 表名常量集中在 `tables.go`;
- JSON 字段使用 `datatypes.JSON`;
- 唯一/复合索引通过 GORM tag 定义;
- 状态字段统一命名 `Status`,默认值 1;
- 模型文件放在 `pkg/corex/db/persistence/model/<domain>/`。
### 示例
```go
type User struct {
model.PowerUUIDModel
Email string `gorm:"column:email;uniqueIndex:uk_user_email"`
DisplayName string `gorm:"type:varchar(128)"`
Meta datatypes.JSON `gorm:"type:jsonb;default:'{}'"`
DeletedAt gorm.DeletedAt `gorm:"index"`
}
func (u *User) TableName() string {
return model.PowerXSchema + "." + model.TableIAMUser
}
```
### 验收要点
- [ ] 模型嵌入 `PowerModel` 或 `PowerUUIDModel`
- [ ] 含软删字段 `DeletedAt` 并建索引
- [ ] 含租户字段 `TenantID`
- [ ] JSONB 字段正确定义
- [ ] 表名函数返回 `${schema}.${table}`
- [ ] 索引通过 GORM tag 定义
- [ ] 状态字段默认 1
- [ ] 模型对应迁移函数已注册
---
## 6. Repository(仓库层)
### 约定
- 所有仓库组合 `BaseRepository[T]`;
- 所有方法均接收 `context.Context`;
- 写操作返回 `error`;
- 禁止直接操作 DB 或外部 IO;
- 唯一冲突用 `IsUniqueViolation()`;
- 在 `deps.go` 统一注册。
### 示例
```go
type UserRepository struct {
*repository.BaseRepository[dbm.User]
db *gorm.DB
}
func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{
BaseRepository: repository.NewBaseRepository[dbm.User](db),
db: db,
}
}
```
### 验收要点
- [ ] 组合 `BaseRepository[T]`
- [ ] 构造函数 `New<ModelName>Repository` 存在
- [ ] 方法首参为 `context.Context`
- [ ] 写操作返回 `error`
- [ ] 在 `deps.go` 注册
- [ ] 不含外部 IO 操作
---
## 7. Service(业务服务层)
### 设计原则
Service 层负责 **业务用例编排、鉴权、事务、审计**。
所有数据库操作必须通过 Repository 完成,不得直接调用 GORM 原语或访问外部 IO。
### 约定
- 命名:`<ModelName>Service`;
- 构造函数:`New<ModelName>Service(db *gorm.DB, …)`;
- 首参 `context.Context`;
- 组合 `*BaseService`;
- 统一在 `deps.go` 注册;
- 写操作必须事务化并记录审计;
- 业务错误集中定义于 `internal/service/errors.go`;
- 更新走白名单更新;
- 删除默认软删,硬删需显式授权;
- 错误包装统一。
### 验收要点
- [ ] 组合 `*BaseService`
- [ ] 构造函数存在
- [ ] 方法首参 `context.Context`
- [ ] 不直接访问 DB
- [ ] 写操作包裹事务与审计
- [ ] 删除默认软删,Force 硬删需权限
- [ ] 错误集中定义
- [ ] 已在 `deps.go` 注册
---
## 8. DTO & Validation(数据传输与校验)
### 统一响应与分页
- 成功/失败结构:`ResponseSuccess`、`ResponseError`、`ResponseList`;
- 分页结构:`PaginationRequest`, `PaginationResponse`。
### 参数绑定与校验
- 使用 `ValidateRequestWithContext(c, req)`;
- DTO 字段带 `validate` 标签;
- 校验失败返回统一结构。
### 错误桥接
- 统一错误结构:`AppError{HTTPCode, Message, Details}`;
- 桥接方法:`RespondErrorFrom(c, err)`,成功时直接使用 `ResponseSuccess/ResponseList`,**不得再使用 `MustOK`**。
### SSE / WS
- 事件名统一:`start/intent/plan/token/data/action/final/end/error/heartbeat`;
- SSE 写入:`WriteToSSE(c, flowID, execID, sr, heartbeat)`;
- WS 信封:`WSEnvelope{Type, Data, Timestamp}`。
### 验收要点
- [ ] DTO 独立定义,不复用模型;
- [ ] 参数绑定使用统一函数;
- [ ] 响应结构统一;
- [ ] 错误使用 AppError;
- [ ] 流式接口事件名统一;
---
## 9. Handler & Routes(HTTP)
### 目录结构
```bash
internal/transport/http/
admin/<domain>/
api.go # 路由注册
<feature>_handler.go # 纯 Handler:绑定/校验/DTO映射/调用Service/统一回包
```
### 路由示例
```go
func RegisterMediaRoutes(rg *gin.RouterGroup, deps *shared.Deps) {
h := NewMediaHandler(deps.MediaService)
g := rg.Group("/media/assets")
{
g.POST("", h.Create)
g.GET("", h.List)
g.GET("/:id", h.Get)
g.PATCH("/:id", h.Update)
g.DELETE("/:id", h.Delete)
}
}
```
### 验收要点
- [ ] `api.go` 只注册路由;
- [ ] Handler 只做绑定/校验/调用 Service;
- [ ] 使用统一回包函数;
- [ ] 前缀 `/api/v1/admin`;
- [ ] 动词与路径符合 REST 语义;
- [ ] 契约测试覆盖 CRUD。
---
## 10. Dependency Injection(依赖注入)
### 约定
- 所有依赖集中在 `internal/app/shared/deps.go`;
- 统一构造函数 `NewDeps(db, opts)`;
- 所有服务在 `Deps` 结构体中注册;
- Handler 层通过 `*shared.Deps` 访问;
- 不在模块中重复创建连接;
- Audit 与 Auth 统一实例。
### 验收要点
- [ ] 所有依赖集中初始化;
- [ ] Handler 统一接收 `*shared.Deps`;
- [ ] Service 不自行创建连接;
- [ ] Audit 回调注册成功;
- [ ] 新模块扩展遵循 Deps + Options 模式。
---
## 11. API 契约(REST)
### 路径与版本
- 管理后台:`/api/v1/admin`
- 开放接口:`/api/v1/open`
- Web 前台:`/api/v1/web`
- URL 版本化策略,破坏性变更才升级。
### 错误与分页
- 统一错误结构:`{ code, message, details?, request_id }`;
- 状态码:400/401/403/404/409/429/500;
- 分页响应带 `pagination{total,page,pageSize,pages}`。
### 验收要点
- [ ] API 路径与版本规范;
- [ ] 错误结构统一;
- [ ] 分页字段完整;
- [ ] 幂等与权限策略明确;
- [ ] SSE/WS 事件一致。
---
## 12. 测试(Contracts & Integration)
### 约定
- 契约测试覆盖鉴权/分页/筛选/软删;
- 集成测试覆盖完整业务流;
- 使用 `httptest`;
- 模拟外部依赖可使用 mock。
### 验收要点
- [ ] 契约测试完整;
- [ ] 集成测试覆盖 CRUD;
- [ ] 测试使用 httptest;
- [ ] mock 外部依赖。
---
## 13. 附录:文件结构参考
```
pkg/corex/db/persistence/model/<feature>/
pkg/corex/db/persistence/repository/<feature>/
internal/service/<feature>/
internal/transport/http/admin/<feature>/
internal/app/shared/deps.go
specs/<domain>/<feature>/ # 功能规格与规划 (spec.md / plan.md / tasks.md)
```