claude skills
This commit is contained in:
parent
94bf5d94b8
commit
9bbff7b016
40 changed files with 4072 additions and 34 deletions
92
.kiro/steering/error-handling.md
Normal file
92
.kiro/steering/error-handling.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
# Error Handling Standards
|
||||
|
||||
## Philosophy
|
||||
|
||||
Fail fast with a consistent, machine-readable response. Handle errors at the controller boundary; let business logic return typed errors. Never silently swallow errors.
|
||||
|
||||
## Go API Response Pattern
|
||||
|
||||
All HTTP responses go through two helpers in `controllers/response.go`:
|
||||
|
||||
```go
|
||||
// Success (always HTTP 200)
|
||||
ReturnSuccess(ctx, common.SUCCESS_CODE, common.SUCCESS_MSG, data)
|
||||
|
||||
// Error (HTTP status == code parameter)
|
||||
ReturnError(ctx, common.ERROR_AUTH_CODE, common.ERROR_ACCESS_FORBIDDEN_MSG, nil)
|
||||
ctx.Abort() // always Abort() after ReturnError in middleware
|
||||
return // always return immediately after ReturnError in handlers
|
||||
```
|
||||
|
||||
**The early-return pattern is non-negotiable.** Every error path ends with `ReturnError(...); return`.
|
||||
|
||||
## HTTP Status Code Mapping
|
||||
|
||||
| Code | Constant | When to use |
|
||||
|------|----------|-------------|
|
||||
| 200 | `SUCCESS_CODE` | Successful operation |
|
||||
| 201 | `CREATED` | Resource created |
|
||||
| 400 | `INVALID_PARAMS_CODE` | Malformed or invalid input |
|
||||
| 401 | `ERROR_AUTH_CHECK_TOKEN_CODE` | Missing or invalid JWT |
|
||||
| 403 | `ERROR_AUTH_CODE` | Valid JWT but insufficient permission |
|
||||
| 404 | `ERROR_NOT_FOUND_CODE` | Resource not found |
|
||||
| 429 | `ERROR_TOO_MANY_REQUESTS_CODE` | Rate limit exceeded |
|
||||
| 500 | `ERROR_CODE` | Unexpected server error |
|
||||
|
||||
All code constants are defined in `common/common.go`. Add new codes there — do not inline numeric literals in handlers.
|
||||
|
||||
## Structured Logging with Zap
|
||||
|
||||
Log at the call site before returning an error. Use typed field helpers — never `fmt.Sprintf` in zap calls.
|
||||
|
||||
```go
|
||||
// Preferred pattern
|
||||
logger.Error("rate limit exceeded",
|
||||
zap.String("path", path),
|
||||
zap.String("client_ip", ctx.ClientIP()),
|
||||
zap.Int("errorcode", code),
|
||||
)
|
||||
|
||||
// For error values
|
||||
logger.Error("validate token error", zap.Error(err))
|
||||
|
||||
// For complex types
|
||||
logger.Debug("permissions resolved", zap.Any("permsWithType", permsWithType))
|
||||
```
|
||||
|
||||
**Log levels**:
|
||||
- `Error` — operation failed, client or server fault
|
||||
- `Warn` — recoverable edge case (e.g., retried operation succeeded)
|
||||
- `Info` — key lifecycle events (server start, config load)
|
||||
- `Debug` — diagnostic detail, disabled in production
|
||||
|
||||
**Never log**: JWT tokens, passwords, secret keys, or full request bodies containing sensitive data.
|
||||
|
||||
## C Error Propagation
|
||||
|
||||
Return negative errno-style codes for C daemon errors. Use the `errnox.h` definitions from `src/include/xce/`. Check and propagate immediately — do not continue on error:
|
||||
|
||||
```c
|
||||
int rc = xce_send_request(&req);
|
||||
if (rc < 0) {
|
||||
log_error("send_request failed: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
```
|
||||
|
||||
## Input Validation Pattern
|
||||
|
||||
Validate at the controller boundary using a `preCheck{Resource}Request()` helper before touching services:
|
||||
|
||||
```go
|
||||
func (c JobController) SubmitJob(ctx *gin.Context) {
|
||||
req, err := preCheckSubmitJobRequest(ctx)
|
||||
if err != nil {
|
||||
ReturnError(ctx, common.INVALID_PARAMS_CODE, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
// ... service call
|
||||
}
|
||||
```
|
||||
|
||||
Keep `preCheck*` functions in the same file as the handler. They bind, validate, and return the typed request struct or an error.
|
||||
Loading…
Add table
Add a link
Reference in a new issue