This file provides guidance to Claude Code, Codex, GitHub Copilot, and other AI coding agents working in this repository.
admin-api is the HTTP microservice for the SweetRPG platform's cross-cutting admin concerns.
The first capability is banner messages - platform/service/page-scoped notices with severity and
expiration, consumed by every frontend that wants to show them. It's a thin Gin-based layer:
server/*.go wires routes directly to MongoDB via mongodb.go's generic
Get/Query/Insert/Update/Delete functions (no separate admin-data.go library - this
service is small enough that a data-access layer split isn't justified yet).
Depends on api-core.go (tracing, health checks, shared VOs/constants), common.go (logging),
and mongodb.go (database connection lifecycle and generic CRUD). Nothing in the platform
depends on this repo yet - admin-web (a separate repo) and consuming frontends
(main-web, catalog-web) call it over HTTP, not as a Go dependency.
Every POST/PUT/DELETE route requires a forwarded user bearer token carrying the admin
role, verified against auth-api's /authz/check via the authz package - see
server/middleware/writeauth.go and sweetrpg/platform's api-client-auth OpenSpec change.
admin-web forwards the acting admin's own Auth0 access token from its shared session as the
bearer credential. The former shared-secret fallback (X-Internal-Service-Token) was removed
once all known callers had migrated.
HTTP access logs output in JSON format via slog-gin middleware, configured in cmd/admin-api/main.go.
Application logs remain under common.go/logging control. This provides structured logs suitable for
log aggregation systems while keeping HTTP and application concerns separate.
- No
gin-contrib/cacheper-route caching. Banner reads need to reflect admin edits promptly (an "expire this now" action should take effect immediately), and consuming frontends already do their own bounded-TTL caching client-side - a second cache layer here would only add staleness without a clear benefit for this service's read volume.
Per-client/IP rate limiting is on by default via the shared api-core.go/ratelimit middleware
(Redis-backed counters keyed by X-API-Key else client IP, cheap tier for /status/*,
fail-closed 503 when Redis is unreachable, 429 on exceed). This replaced the process-wide
rate.NewLimiter bucket, which one busy caller could exhaust for everyone. REDIS_HOST/
REDIS_PORT are in the dev configmap; REDIS_PASS comes from the api-cache ExternalSecret.
Tune with RATE_LIMIT_CHEAP/RATE_LIMIT_CHEAP_WINDOW_SECONDS/RATE_LIMIT_STANDARD/
RATE_LIMIT_STANDARD_WINDOW_SECONDS. See platform's
openspec/changes/fix-rate-limiting-per-client-ip.
Use Conventional Commits:
<type>(<scope>): <description>
develop- integration branch, default branch, target for all PRs.master- latest released state, nothing committed directly.feature/*,fix/*branched fromdevelop;hotfix/*branched frommaster.
See CONTRIBUTING.md for the full workflow.
go build -v ./...
go vet ./...
go test -v -coverprofile coverage.out ./...Regenerate Swagger docs after changing handler annotations:
go run github.com/swaggo/swag/cmd/swag@latest init -d cmd/admin-api/,server/,models/ --parseDependency --parseInternal