This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
SAST Shop v2 is a microservice campus commerce backend for NJUPT, built with Go 1.26. The workspace (go.work) contains one shared library and five independently runnable services communicating via Connect-RPC.
# Generate Go from proto (run from repo root)
buf generate
# Lint all workspace modules
make lint
make lint-fix # with auto-fix
# Run a single service (each service starts its own HTTP server)
cd internal/service/userservice && go run ./cmd/appEach service needs PostgreSQL and Redis running. Copy .env.example to .env and fill in credentials. The .env file is loaded from the repo root (services search upward for it).
| Module | Directory | Port (env var) |
|---|---|---|
internal/pkg (shared lib) |
internal/pkg/ |
— |
userservice |
internal/service/userservice/ |
USER_SERVICE_PORT (1323) |
catalogservice |
internal/service/catalogservice/ |
CATALOG_SERVICE_PORT (1324) |
paymentservice |
internal/service/paymentservice/ |
PAYMENT_SERVICE_PORT (1325) |
spotservice |
internal/service/spotservice/ |
SPOT_SERVICE_PORT (1326) |
errandservice |
internal/service/errandservice/ |
ERRAND_SERVICE_PORT (1327) |
All five services import internal/pkg. There are no direct inter-service Go imports — cross-service calls go through generated Connect-RPC clients.
Client → Echo v5 router (e.Any(path+"*"))
→ protovalidate interceptor (validates request messages)
→ auth interceptor (optional — session token or X-Dev-User-ID bypass)
→ Handler struct (implements generated Connect-RPC interface)
→ Service layer (business logic)
→ Repository layer (bun ORM queries)
→ PostgreSQL
→ Redis (session store, key prefix: "session:")
config.Init() // Loads .env, parses into global AppConfig
logger.Init(name) // zerolog — console in dev, JSON in prod
postgres.Init() // bun DB global
redis.Init() // go-redis client global
e := echo.New()
v1.Init(e) // Registers all Connect-RPC handlers for this service
e.Start(":port")Each service's internal/handler/v1/handler.go exposes an Init(e *echo.Echo) that:
- Creates a validation chain (protovalidate + logging interceptor) applied to all handlers
- Creates an auth interceptor (session-token based, with dev bypass via
X-Dev-User-IDheader) - Registers handler structs by calling
e.Any(path+"*", echo.WrapHandler(mux))
Auth-protected handlers get both the validation chain and auth interceptor. Internal handlers (service-to-service) get only the validation chain.
config/— env-var parsing viacaarlos0/env+godotenv. GlobalAppConfig *Config.logger/— zerolog setup. Console writer in dev (zerolog.ConsoleWriter), JSON in prod.bun/postgres/— PostgreSQL connection viauptrace/bun+pgdriver.redis/— go-redis client. Also providesSessionStoreimplementation (key prefixsession:).connect/interceptor/—AuthRequiredinterceptor (reads Bearer token, validates via SessionStore interface), validation+logging chain.constant/— service name strings, session TTL, header names.rpcerror/—NewInternalErrorhelper wrapping protobufBusinessErroroneofs.
Each service defines error codes in its proto file. The handler helper constructs Connect errors:
func userError(code userv1.UserErrorCode, msg string) *connect.Error {
return rpcerror.NewInternalError(&commonv1.BusinessError_UserError{
UserError: &userv1.UserError{Code: code, Message: msg},
}, "")
}Error code ranges: common (0–1000), user (2000+), catalog/payment/spot/errand (each with own range).
All models use uptrace/bun with schema-qualified tables (e.g., user.user_account, catalog.catalog_store, spot.spot_goods). Models are in internal/model/model.go per service. Repository functions accept *bun.DB directly.
Proto files live in proto/sast/sastshopv2/{domain}/v1/. Generated code (.pb.go + .connect.go) goes into gen/ (gitignored). The Buf module is buf.build/sast/sast-shop-v2 with a dependency on buf.build/bufbuild/protovalidate. After changing proto files, run buf generate.
The project is in early development. Only userservice has partial real logic (GetUserInfo, GetByUserIDs). All other handlers return "To be implemented" placeholder errors. No tests exist yet.