Stop relying on a global server.Use(CloudEPJWT) that was invisible from
the .api source. Protected routes now declare middleware explicitly in
each @server block and goctl chains them into routes.go — the .api file
is the single source of truth for "who needs Bearer / who needs RBAC".
Concretely:
- Rewrite middleware to go-zero's standard struct + Handle() pattern.
AuthJWT becomes strict: missing/invalid Bearer returns 28501000 (was
soft passthrough). CasbinRBAC stays nil-tolerant so dev/test boots
without a policy.
- Files renamed to goctl's stringx convention (authjwt_middleware.go,
casbinrbac_middleware.go) so future `make gen-api` runs see them as
already-generated and skip the empty stub.
- Move actor context helpers (Actor, WithActor, ActorFromContext) into
internal/library/actor so middleware and BOTH logic packages share
one context key. Previously each logic package had its own private
actorKey struct{}, so an actor injected for member was invisible to
permission — the permission RBAC chain would always see "missing
actor". member/permission actor.go are now thin type-alias shims.
- .api files declare middleware per group:
auth.api (public) → no middleware (register/login/token/...)
auth.api (logout) → middleware: AuthJWT
member.api → middleware: AuthJWT
permission.api (catalog,me) → middleware: AuthJWT
permission.api (admin ops) → middleware: AuthJWT,CasbinRBAC
normal.api (/health) → no middleware
- ServiceContext exposes AuthJWT / CasbinRBAC as rest.Middleware; the
global server.Use(...) in gateway.go is removed.
- Document the pattern in AGENTS.md (cross-agent rules) and
generate/api/README.md (detailed examples + filename rules) so any
future AI agent or human follows the same convention.
make gen-api / gen-doc / lint / build all pass.
Co-authored-by: Cursor <cursoragent@cursor.com>
Make the generated docs/openapi/gateway.yaml usable by adding three things
go-doc parses out of the .api source:
- @server tags + summary on every block → Swagger UI groups endpoints
(Auth / Member / Permission / Normal) instead of dumping everything
under "default".
- backtick end-of-line // 中文 on every Request field → property
descriptions in the schema. go-doc only reads the trailing comment,
not the line above, so all comments are placed on the same line as
the tag.
- options=A|B|C in json/form tags wherever validate:"oneof=..." exists
→ enum dropdowns. The validate tag is kept for runtime validation;
go-zero also enforces options= at bind time.
Codify the rules in generate/api/README.md (tags / 行末註解 / options=)
and add AGENTS.md at repo root so any AI agent (Claude / Cursor / Codex)
picks them up automatically when working on the project.
types.go regenerated via make gen-api to keep json tags in sync.
Co-authored-by: Cursor <cursoragent@cursor.com>