Borrowing it
Nothing to install: this file belongs to ArtisanCloud/PowerX. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/ArtisanCloud/PowerX/release/v1.0.0/.codex/skills/crud/repository/SKILL.mdgit clone --depth 1 https://github.com/ArtisanCloud/PowerXWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/artisancloud/powerx/repository)<a href="https://agentmods.dev/skills/artisancloud/powerx/repository"><img src="https://agentmods.dev/badge/skills/artisancloud/powerx/repository/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/artisancloud/powerx/repository"><img src="https://agentmods.dev/badge/skills/artisancloud/powerx/repository.svg" alt="Reviewed on agentmods" width="80" height="20"></a>- NVIDIA SkillSpector pass
What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00021 | $0.02708 |
| Opus 5.5 | $0.00008 | $0.01083 |
| Sonnet 5.5 | $0.00004 | $0.00542 |
| Haiku 4.5 | $0.00002 | $0.00271 |
Grade A, and why
crud-repository scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 1mo ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 268 lines — stays where its author put it; the contents beside it link to each section on GitHub.
PowerX CRUD Repository
步骤
- 打开
本文件内嵌规则。 - 按规则执行实现/校对。
- 完成后按核对清单验收。
核对点
- 与 PowerX 当前代码结构、路径与命名一致。
- 仅在传输层/契约层做职责内改动,不跨层越界。
规则(内嵌)
repository.yaml
kind: ruleset
name: crud_repository
version: 1.0.0
owner: powerx
status: stable
meta:
intent: >
统一 Repository(持久化)层的接口与实现规范:只负责数据访问与映射,
不承载业务逻辑;严格多租户隔离、软删、分页筛选与一致的错误/返回语义。
CoreX 模块仓储统一采用 BaseRepository 泛型封装,便于事务注入与测试。
references:
- constitution.md
- crud_model.yaml
- crud_migration.yaml
- crud_dto.yaml
- crud_di.yaml
scope:
codebase:
repo_globs:
- "internal/repository/**/**_repo.go"
- "pkg/corex/db/persistence/repository/**/**_repo.go"
model_globs:
- "pkg/corex/db/persistence/model/**/**.go"
principles:
- 目录规范:CoreX 仓库实现放置于 `pkg/corex/db/persistence/repository/<domain>/`,目录名使用 snake_case,对应的模型位于同层级 `model/`。
- 职责单一:Repository 只做数据访问(SQL/GORM),禁止业务分支与权限判断。
- 多租户强约束:所有查询均带 TenantID 条件;默认忽略软删(GORM 默认生效)。
- 事务注入:方法接受 *gorm.DB(可为 tx),由 Service 层控制 tx 生命周期。
- 上下文贯穿:方法首参为 context.Context,用于 tracing/超时/审计钩子。
- 错误语义:不存在返回 gorm.ErrRecordNotFound(由 Service 翻译成 404);唯一冲突返回 ErrConflict(由 Service 翻译 409)。
- 可测试性:提供接口与实现;实现命名 `XxxRepoImpl`,禁止全局单例。
- 性能:列表查询必须显式选择字段/建立索引,禁止 N+1(注意 Preload 选择性)。
checks:
# 目录/文件命名
- id: repo.file.naming
level: error
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- must_package_suffix: "repo"
# BaseRepository 形态
- id: repo.base_repository.pattern
level: error
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- must_contain_regex: "type [A-Za-z0-9]+Repository struct {"
- must_contain_regex: "\\*repository.BaseRepository"
- must_contain_regex: "func New[A-Za-z0-9]+Repository\\(db \\*gorm\\.DB\\)"
- must_not_import: ["github.com/gin-gonic/gin"] # 不允许直接耦合 HTTP
# 方法签名(ctx + db)
- id: repo.method.signature
level: error
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- must_contain_regex: "func \\(r \\*.*Repository\\) .*\\(ctx context\\.Context, db \\*gorm\\.DB"
- must_import: ["context","gorm.io/gorm"]
# 多租户条件
- id: repo.must.tenant.scope
level: error
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- contains_any:
- "Where(\"tenant_id = ?\""
- "Scopes(TenantScope("
- "WithTenant("
message: "所有 CRUD 查询必须带 TenantID(直写 Where 或统一 Scopes/TenantScope)"
# 列表与分页(limit/offset 或 cursor)
- id: repo.list.pagination
level: error
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- contains_any: ["Limit(","Offset(","Scopes(Paginate("]
# 冲突与不存在的错误
- id: repo.error.mapping
level: warn
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- contains_any: ["gorm.ErrRecordNotFound","ErrDuplicate","unique"]
message: "建议把 gorm.ErrRecordNotFound 原样返回,由 Service 统一翻译为 404;唯一冲突包装为 ErrConflict"
# 软删(默认开启),如实现硬删需标注
- id: repo.soft_delete
level: warn
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- should_contain_any: ["Delete(&m)","Unscoped().Delete("]
# 性能/索引使用(建议)
- id: repo.index.hint
level: warn
when: { glob: "internal/repository/**/**_repo.go" }
assert:
- should_contain_any: ["Select(","Omit("]
acceptance:
checklist:
- "[ ] 每个仓库文件包含接口 + 实现 + New 构造函数"
- "[ ] 方法签名统一为 (ctx context.Context, db *gorm.DB, ...)"
- "[ ] 所有查询带 TenantID 条件(Where/Scopes/TenantScope)"
- "[ ] 列表查询有分页(Limit/Offset 或 Cursor)"
- "[ ] 不做业务鉴权/分支;错误语义由 Service 统一翻译"
- "[ ] 使用软删;如需硬删必须在 Service 授权并清晰标注"
- "[ ] 可被 DI 装配(由 Deps 提供 *gorm.DB 注入)"
templates:
repo_interface_impl_go: |
// pkg/corex/db/persistence/repository/{{domain}}/{{resource}}_repo.go
package {{domain}}repo
import (
"context"
"gorm.io/gorm"
m "{{module_path}}/pkg/corex/db/persistence/model/{{domain}}"
)
// {{Entity}}Repo 数据访问接口
type {{Entity}}Repo interface {
Create(ctx context.Context, db *gorm.DB, tenantID uint64, in *m.{{Entity}}) error
GetByID(ctx context.Context, db *gorm.DB, tenantID uint64, id string) (*m.{{Entity}}, error)
List(ctx context.Context, db *gorm.DB, tenantID uint64, pg Page, filters map[string]string) ([]*m.{{Entity}}, int64, error)
Update(ctx context.Context, db *gorm.DB, tenantID uint64, in *m.{{Entity}}) error
Delete(ctx context.Context, db *gorm.DB, tenantID uint64, id string, hard bool) error
// Tx 透传辅助(可选)
WithTx(ctx context.Context, db *gorm.DB, fn func(tx *gorm.DB) error) error
}
// 实现
type {{Entity}}RepoImpl struct {
db *gorm.DB
}
func New{{Entity}}Repo(db *gorm.DB) {{Entity}}Repo {
return &{{Entity}}RepoImpl{db: db}
}
// 分页结构(按项目实际放置到共用包)
type Page struct {
Page int
PageSize int
SortBy string
SortOrder string
}
func (r *{{Entity}}RepoImpl) Create(ctx context.Context, db *gorm.DB, tenantID uint64, in *m.{{Entity}}) error {
in.TenantID = tenantID
return db.WithContext(ctx).Create(in).Error
}
func (r *{{Entity}}RepoImpl) GetByID(ctx context.Context, db *gorm.DB, tenantID uint64, id string) (*m.{{Entity}}, error) {
var out m.{{Entity}}
err := db.WithContext(ctx).
Where("tenant_id = ? AND id = ?", tenantID, id).
First(&out).Error
if err != nil {
return nil, err // 由 Service 翻译为 404
}
return &out, nil
}
// 可抽成 Scopes:TenantScope / Filters / Paginate
func (r *{{Entity}}RepoImpl) List(ctx context.Context, db *gorm.DB, tenantID uint64, pg Page, filters map[string]string) ([]*m.{{Entity}}, int64, error) {
q := db.WithContext(ctx).Model(&m.{{Entity}}{}).Where("tenant_id = ?", tenantID)
// 简化:按 filters 动态拼装(生产中建议固定白名单)
if v, ok := filters["status"]; ok { q = q.Where("status = ?", v) }
if v, ok := filters["q"]; ok { q = q.Where("name ILIKE ?", "%"+v+"%") }
// 计数
var total int64
if err := q.Count(&total).Error; err != nil { return nil, 0, err }
// 排序/分页
orderBy := "created_at desc"
if pg.SortBy != "" {
if pg.SortOrder == "" { pg.SortOrder = "desc" }
orderBy = pg.SortBy + " " + pg.SortOrder
}
if pg.Page <= 0 { pg.Page = 1 }
if pg.PageSize <= 0 { pg.PageSize = 20 }
var items []*m.{{Entity}}
err := q.Order(orderBy).
Limit(pg.PageSize).
Offset((pg.Page-1)*pg.PageSize).
Find(&items).Error
if err != nil { return nil, 0, err }
return items, total, nil
}
func (r *{{Entity}}RepoImpl) Update(ctx context.Context, db *gorm.DB, tenantID uint64, in *m.{{Entity}}) error {
return db.WithContext(ctx).
Model(&m.{{Entity}}{}).
Where("tenant_id = ? AND id = ?", tenantID, in.ID).
Updates(map[string]any{
"name": in.Name,
"meta": in.Meta,
"status": in.Status,
}).Error
}
func (r *{{Entity}}RepoImpl) Delete(ctx context.Context, db *gorm.DB, tenantID uint64, id string, hard bool) error {
q := db.WithContext(ctx).Where("tenant_id = ? AND id = ?", tenantID, id)
if hard {
return q.Unscoped().Delete(&m.{{Entity}}{}).Error
}
return q.Delete(&m.{{Entity}}{}).Error
}
func (r *{{Entity}}RepoImpl) WithTx(ctx context.Context, db *gorm.DB, fn func(tx *gorm.DB) error) error {
return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { return fn(tx) })
}
scopes_go: |
// internal/repository/scopes/scopes.go (可选:集中放置)
package scopes
import "gorm.io/gorm"
func TenantScope(tenantID uint64) func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return db.Where("tenant_id = ?", tenantID)
}
}
func Paginate(page, pageSize int) func(*gorm.DB) *gorm.DB {
if page <= 0 { page = 1 }
if pageSize <= 0 { pageSize = 20 }
return func(db *gorm.DB) *gorm.DB {
return db.Limit(pageSize).Offset((page-1)*pageSize)
}
}
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 1mo ago First seen · 268 lines · 21 tokens per session scan A e0e17df7ef31
crud-repository is a skill published in the GitHub repository ArtisanCloud/PowerX (382 stars, last pushed 2d ago), licensed Apache-2.0. It adds 21 tokens to every session and 2,708 once invoked, about $0.0001 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-04.
Other skills, from other repositories
odoo-introspector
MANDATORY for technical discovery. Expertise in Odoo's internal ORM structures, field types, and metadata interpretation.
myb-p-create-entity
Create a complete new custom entity (module) in MyBusiness CRM -- tables, fields, sample data, list page with inline edit, custom JS, and menu integration. Use this skill whenever the user wants to create a new entity, new module, new object type, add a new business concept to the CRM, or build a full CRUD workflow…
schema-authority
Single source of truth authority — define once in Pydantic / SQLModel / OpenAPI / Protobuf, generate TypeScript types, validators, docs, mocks, and contract tests from that canonical definition; schema registry patterns, spec-first API design, consumer-driven contract testing, and database-model alignment.
event-store-design
Design and implement event stores for event-sourced systems. Use when building event sourcing infrastructure, choosing event store technologies, or implementing event persistence patterns.
platform-custom-field-generate
Use when users create, generate, or validate Salesforce Custom Field metadata. Trigger on custom fields, field types, Roll-Up Summary, Master-Detail/Lookup relationships, formula fields, picklists, dependent (controlling) picklists, referencing a value set from a field, or scoping picklist values per record type; also…
implementing-api-schema-validation-security
Implement API schema validation using OpenAPI specifications and JSON Schema to enforce input/output contracts and prevent injection, data exposure, and mass assignment attacks.