Skip to main content

add-api-resource

Add or change a REST API resource in agent-manager-service (the Go control plane). Use when the user asks to add/modify an endpoint, resource, route, or API operation in agent-manager-service — anything that touches the OpenAPI spec, controllers, services, repositories, or RBAC. Enforces the spec-first, codegen, and per-route-authz workflow so generated code and permissions stay consistent.

소스 정보

저장소
wso2/agent-manager
최근 소스 활동
2026년 8월 5일 10:56
감지된 SKILL.md 언어
영어
스타
105
포크
76

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
add-api-resource
description
Add or change a REST API resource in agent-manager-service (the Go control plane). Use when the user asks to add/modify an endpoint, resource, route, or API operation in agent-manager-service — anything that touches the OpenAPI spec, controllers, services, repositories, or RBAC. Enforces the spec-first, codegen, and per-route-authz workflow so generated code and permissions stay consistent.
# Add/change an API resource (agent-manager-service) Spec-first, layered, per-route-authz workflow for the Go control plane. The request/response types and mocks are **generated** — never hand-write them. **Read first:** `agent-manager-service/AGENTS.md` → "Golden path", "Layering", "Permissions (RBAC)", "Code generation". This skill is the executable checklist; that guide has the *why*. ## Steps (do in order) 1. **Edit the OpenAPI spec** — `agent-manager-service/docs/api_v1_openapi.yaml`. Add/modify the path, operation, and schemas. This is the source of truth for request/response shapes. 2. **`make spec`** (needs Docker) — regenerates `spec/` from the YAML. The whole `spec/` dir is deleted and rebuilt, so **never** hand-edit a struct there; your edits would be lost. 3. **Add permission(s)** in `rbac/permissions.go` — name them `resource:verb` (`:create`/`:read`/`:update`/`:delete`, or `:manage` only where peers already do). 4. **Implement controller → service → repository** (`controllers/` → `services/` → `repositories/`): - Controller: HTTP only — parse/validate, map result→status, translate sentinel errors→HTTP. - Service: business logic; depend on repo/client **interfaces**, never concrete types. - Repository: persistence only (interface + impl). Add an interface if you introduce a new one. 5. **Register the route with authz** in `api/<resource>_routes.go` using `HandleFuncWithValidationAndAuthz(pattern, rbac.<Perm>, ctrl.<Handler>)`. Every route declares its own permission. 6. **Grant the permission to at least one role** in `rbac/predefined_roles.go` (`PredefinedRolePermissions`). An ungranted permission is unreachable. 7. **`make codegen`** — only if you added/changed an interface (regenerates wire DI + mocks; needs `moq` on PATH). A new repo interface needs a `//go:generate moq ...` directive above its declaration — copy an existing one. 8. **Write a service unit test** — use the `add-service-unit-test` skill. ## Audit logging Step 5 audits the route automatically — a mutating route cannot ship unaudited, and `api/audit_coverage_test.go` fails the build if one does. Two cases need you: - **The build says `cannot derive an action for audited route`**, or the route's `rbac.Permission` does not describe what it does (one permission gating several operations, or naming a different resource). Add one line to `actionOverrides` in `audit/policy.go`. - **The operation touches credentials, privileges, membership, deployment or deletion.** The envelope record cannot say *what changed*, so add a semantic event — use the **`add-audit-event` skill**. Never read a request or response body into a record; pass named fields via `audit.Detail`, which takes scalars and `[]string` only. ## Guardrails - **Multi-tenancy:** the service must validate the caller's org against the **target resource it loads**, not just the path (`RequireOrgMatch` is a first-pass filter, not the enforcement layer). - **Errors:** map `gorm.ErrRecordNotFound` → the specific `utils.ErrXxxNotFound`; wrap everything else with `%w`. Never flatten an unexpected error into not-found; never silently fall back to a default on a real error. Compare with `errors.Is`. - **Context:** every I/O method takes `context.Context` first and propagates it. - **Don't re-fetch** a resource already loaded earlier in the request path — pass it down. ## Done checklist - [ ] `spec/` regenerated (`make spec`) and committed if the YAML changed. - [ ] New permission exists in `rbac/permissions.go` **and** is granted in `rbac/predefined_roles.go`. - [ ] Route registered with an authz registrar (not plain `HandleFuncWithValidation` unless deliberate). - [ ] `make codegen` run + mocks committed if an interface changed. - [ ] Service unit test added; `make test-unit` passes (includes `TestEveryMutatingRouteIsAudited`). - [ ] Semantic audit event added if the operation is security-critical (`add-audit-event` skill). - [ ] `go build -tags=integration ./...` compiles. - [ ] CI lint clean: `golangci-lint run --config .github/linters/.golangci.yaml ./...`
GitHub에서 보기