@ai-content-space/loopx 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +343 -56
  2. package/README.zh-CN.md +392 -0
  3. package/package.json +4 -1
  4. package/plugins/loopx/.codex-plugin/plugin.json +1 -1
  5. package/plugins/loopx/scripts/plugin-install.test.mjs +1 -0
  6. package/plugins/loopx/skills/archive/SKILL.md +39 -0
  7. package/plugins/loopx/skills/build/SKILL.md +111 -9
  8. package/plugins/loopx/skills/clarify/SKILL.md +121 -1
  9. package/plugins/loopx/skills/debug/SKILL.md +296 -0
  10. package/plugins/loopx/skills/debug/condition-based-waiting.md +115 -0
  11. package/plugins/loopx/skills/debug/defense-in-depth.md +122 -0
  12. package/plugins/loopx/skills/debug/find-polluter.sh +63 -0
  13. package/plugins/loopx/skills/debug/root-cause-tracing.md +169 -0
  14. package/plugins/loopx/skills/go-style/SKILL.md +71 -0
  15. package/plugins/loopx/skills/kratos/SKILL.md +74 -0
  16. package/plugins/loopx/skills/kratos/references/advanced-features.md +314 -0
  17. package/plugins/loopx/skills/kratos/references/architecture.md +488 -0
  18. package/plugins/loopx/skills/kratos/references/configuration.md +399 -0
  19. package/plugins/loopx/skills/kratos/references/http-customization.md +512 -0
  20. package/plugins/loopx/skills/kratos/references/middleware-logging.md +400 -0
  21. package/plugins/loopx/skills/kratos/references/proto-api-design.md +432 -0
  22. package/plugins/loopx/skills/kratos/references/security-auth.md +411 -0
  23. package/plugins/loopx/skills/kratos/references/troubleshooting.md +385 -0
  24. package/plugins/loopx/skills/plan/SKILL.md +22 -2
  25. package/plugins/loopx/skills/review/SKILL.md +98 -1
  26. package/plugins/loopx/skills/tdd/SKILL.md +371 -0
  27. package/plugins/loopx/skills/tdd/testing-anti-patterns.md +299 -0
  28. package/plugins/loopx/skills/verify/SKILL.md +139 -0
  29. package/scripts/codex-stop-hook.mjs +71 -0
  30. package/scripts/codex-workflow-hook.mjs +153 -0
  31. package/skills/archive/SKILL.md +39 -0
  32. package/skills/build/SKILL.md +111 -9
  33. package/skills/clarify/SKILL.md +121 -1
  34. package/skills/debug/SKILL.md +296 -0
  35. package/skills/debug/condition-based-waiting.md +115 -0
  36. package/skills/debug/defense-in-depth.md +122 -0
  37. package/skills/debug/find-polluter.sh +63 -0
  38. package/skills/debug/root-cause-tracing.md +169 -0
  39. package/skills/go-style/SKILL.md +71 -0
  40. package/skills/kratos/SKILL.md +74 -0
  41. package/skills/kratos/references/advanced-features.md +314 -0
  42. package/skills/kratos/references/architecture.md +488 -0
  43. package/skills/kratos/references/configuration.md +399 -0
  44. package/skills/kratos/references/http-customization.md +512 -0
  45. package/skills/kratos/references/middleware-logging.md +400 -0
  46. package/skills/kratos/references/proto-api-design.md +432 -0
  47. package/skills/kratos/references/security-auth.md +411 -0
  48. package/skills/kratos/references/troubleshooting.md +385 -0
  49. package/skills/plan/SKILL.md +22 -2
  50. package/skills/review/SKILL.md +98 -1
  51. package/skills/tdd/SKILL.md +371 -0
  52. package/skills/tdd/testing-anti-patterns.md +299 -0
  53. package/skills/verify/SKILL.md +139 -0
  54. package/src/build-runtime.mjs +303 -26
  55. package/src/build-stop-gate.mjs +94 -0
  56. package/src/cli.mjs +51 -8
  57. package/src/codex-exec-runtime.mjs +105 -5
  58. package/src/context-manifest.mjs +172 -0
  59. package/src/install-discovery.mjs +352 -5
  60. package/src/next-skill.mjs +85 -0
  61. package/src/plan-runtime.mjs +100 -122
  62. package/src/review-runtime.mjs +378 -0
  63. package/src/runtime-maintenance.mjs +428 -14
  64. package/src/template-governance.mjs +223 -0
  65. package/src/workflow.mjs +1947 -118
  66. package/src/workspace-context.mjs +166 -0
  67. package/src/workspace-memory.mjs +69 -0
  68. package/templates/plan.md +6 -0
@@ -0,0 +1,400 @@
1
+ # Middleware & Logging
2
+
3
+ Guide for middleware development and log management in Kratos.
4
+
5
+ ## When to Use
6
+
7
+ - Creating custom middleware
8
+ - Extracting request context
9
+ - Setting up log filtering
10
+ - Configuring middleware chains
11
+
12
+ ---
13
+
14
+ ## Middleware Skeleton
15
+
16
+ ### Basic Structure
17
+
18
+ ```go
19
+ import (
20
+ "context"
21
+ "github.com/go-kratos/kratos/v2/middleware"
22
+ "github.com/go-kratos/kratos/v2/transport"
23
+ )
24
+
25
+ func MyMiddleware() middleware.Middleware {
26
+ return func(handler middleware.Handler) middleware.Handler {
27
+ return func(ctx context.Context, req interface{}) (interface{}, error) {
28
+ // === PRE-PROCESSING ===
29
+ // Extract info, validate, modify request
30
+
31
+ // === CALL HANDLER ===
32
+ reply, err := handler(ctx, req)
33
+
34
+ // === POST-PROCESSING ===
35
+ // Modify response, handle errors, log
36
+
37
+ return reply, err
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ### Registration
44
+
45
+ ```go
46
+ import (
47
+ "github.com/go-kratos/kratos/v2/middleware/recovery"
48
+ "github.com/go-kratos/kratos/v2/middleware/validate"
49
+ )
50
+
51
+ srv := http.NewServer(
52
+ http.Address(":8000"),
53
+ http.Middleware(
54
+ recovery.Recovery(),
55
+ validate.Validator(),
56
+ MyMiddleware(),
57
+ ),
58
+ )
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Transport Extraction
64
+
65
+ ### Get Request Info
66
+
67
+ ```go
68
+ func MyMiddleware() middleware.Middleware {
69
+ return func(handler middleware.Handler) middleware.Handler {
70
+ return func(ctx context.Context, req interface{}) (interface{}, error) {
71
+ if tr, ok := transport.FromServerContext(ctx); ok {
72
+ // Generic transport info
73
+ operation := tr.Operation()
74
+ kind := tr.Kind() // transport.KindHTTP or KindGRPC
75
+
76
+ // HTTP-specific info
77
+ if hr, ok := tr.(*http.Transport); ok {
78
+ method := hr.Request().Method
79
+ url := hr.Request().URL.String()
80
+ path := hr.Request().URL.Path
81
+
82
+ // Headers
83
+ userAgent := hr.RequestHeader().Get("User-Agent")
84
+ auth := hr.RequestHeader().Get("Authorization")
85
+ contentType := hr.RequestHeader().Get("Content-Type")
86
+
87
+ // Set response header
88
+ hr.ResponseHeader().Set("X-Response-Time", "100ms")
89
+ }
90
+ }
91
+
92
+ return handler(ctx, req)
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Set Response Header in Service
99
+
100
+ ```go
101
+ func (s *UserService) GetUser(ctx context.Context, req *v1.GetUserRequest) (*v1.GetUserResponse, error) {
102
+ if httpCtx, ok := ctx.(http.Context); ok {
103
+ httpCtx.Response().Header().Set("X-Custom", "value")
104
+ }
105
+ // Business logic...
106
+ }
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Log Filtering
112
+
113
+ Kratos provides log filtering for sensitive data:
114
+
115
+ ### Filter by Level
116
+
117
+ ```go
118
+ import "github.com/go-kratos/kratos/v2/log"
119
+
120
+ h := log.NewHelper(
121
+ log.NewFilter(logger,
122
+ log.FilterLevel(log.LevelError), // Only log errors
123
+ ),
124
+ )
125
+ ```
126
+
127
+ ### Filter by Key
128
+
129
+ ```go
130
+ h := log.NewHelper(
131
+ log.NewFilter(logger,
132
+ log.FilterKey("password"), // Hide password field
133
+ ),
134
+ )
135
+
136
+ h.Info("password", "secret123") // Output: password "***"
137
+ ```
138
+
139
+ ### Filter by Value
140
+
141
+ ```go
142
+ h := log.NewHelper(
143
+ log.NewFilter(logger,
144
+ log.FilterValue("secret"), // Hide exact value "secret"
145
+ ),
146
+ )
147
+
148
+ h.Info("token", "secret") // Output: token "***"
149
+ ```
150
+
151
+ ### Custom Filter Function
152
+
153
+ ```go
154
+ h := log.NewHelper(
155
+ log.NewFilter(logger,
156
+ log.FilterFunc(func(level log.Level, keyvals ...interface{}) bool {
157
+ // keyvals is alternating: key, value, key, value...
158
+ for i := 0; i < len(keyvals); i += 2 {
159
+ key := keyvals[i]
160
+ value := keyvals[i+1]
161
+
162
+ if key == "token" {
163
+ keyvals[i+1] = "***MASKED***"
164
+ }
165
+ if key == "password" {
166
+ keyvals[i+1] = "***"
167
+ }
168
+ }
169
+ return false // Return false to continue logging
170
+ }),
171
+ ),
172
+ )
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Recovery Middleware
178
+
179
+ Catch panics and return proper errors:
180
+
181
+ ```go
182
+ import "github.com/go-kratos/kratos/v2/middleware/recovery"
183
+
184
+ srv := http.NewServer(
185
+ http.Address(":8000"),
186
+ http.Middleware(
187
+ recovery.Recovery(), // Always first in chain
188
+ ),
189
+ )
190
+ ```
191
+
192
+ With custom recovery handler:
193
+
194
+ ```go
195
+ srv := http.NewServer(
196
+ http.Middleware(
197
+ recovery.Recovery(
198
+ recovery.WithHandler(func(ctx context.Context, req, err interface{}) error {
199
+ log.Errorf("panic recovered: %v", err)
200
+ return errors.New(500, "INTERNAL_ERROR", "internal server error")
201
+ }),
202
+ ),
203
+ ),
204
+ )
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Validate Middleware
210
+
211
+ Kratos provides two approaches for protovalidate integration:
212
+
213
+ ### Approach 1: Middleware-level Validation
214
+
215
+ Use `validate.Validator()` middleware for automatic request validation:
216
+
217
+ ```go
218
+ import (
219
+ "buf.build/go/protovalidate"
220
+ "github.com/go-kratos/kratos/v2/middleware/validate"
221
+ )
222
+
223
+ func provideValidator() (protovalidate.Validator, error) {
224
+ v, err := protovalidate.New()
225
+ if err != nil {
226
+ return nil, err
227
+ }
228
+ return v, nil
229
+ }
230
+
231
+ srv := http.NewServer(
232
+ http.Middleware(
233
+ validate.Validator(provideValidator()), // Validates all proto requests
234
+ ),
235
+ )
236
+ ```
237
+
238
+ ### Approach 2: Service-level Validation
239
+
240
+ For selective validation or custom error handling, validate in service layer:
241
+
242
+ ```go
243
+ type MyService struct {
244
+ v1.UnimplementedMyServiceServer
245
+ validator protovalidate.Validator
246
+ uc *biz.MyUseCase
247
+ log *log.Helper
248
+ }
249
+
250
+ func NewMyService(uc *biz.MyUseCase, logger log.Logger, validator protovalidate.Validator) *MyService {
251
+ return &MyService{
252
+ uc: uc,
253
+ validator: validator,
254
+ log: log.NewHelper(logger),
255
+ }
256
+ }
257
+
258
+ func (s *MyService) GetUser(ctx context.Context, req *v1.GetUserRequest) (*v1.GetUserResponse, error) {
259
+ // Validate request before business logic
260
+ if err := s.validator.Validate(req); err != nil {
261
+ return nil, v1.ErrorInvalidArgument("validation failed: %v", err)
262
+ }
263
+ return s.uc.GetUser(ctx, req.UserId)
264
+ }
265
+ ```
266
+
267
+ **When to use each approach:**
268
+ - **Middleware-level**: All requests need validation, consistent error format
269
+ - **Service-level**: Selective validation, partial updates, custom error messages
270
+
271
+ **Note:** For partial updates (PATCH), you may need to skip validation on optional fields. Use service-level validation for this case.
272
+
273
+ ---
274
+
275
+ ## Middleware Chain Ordering
276
+
277
+ Recommended order for HTTP server:
278
+
279
+ ```go
280
+ srv := http.NewServer(
281
+ http.Middleware(
282
+ // 1. Recovery - catch panics first
283
+ recovery.Recovery(),
284
+
285
+ // 2. Tracing - set trace context
286
+ tracing.Server(),
287
+
288
+ // 3. Logging - log requests
289
+ logging.Server(logger),
290
+
291
+ // 4. Authentication - verify identity
292
+ jwt.Server(signingKey),
293
+
294
+ // 5. Authorization - check permissions
295
+ casbinM.Server(enforcer),
296
+
297
+ // 6. Validate - check request format
298
+ validate.Validator(),
299
+
300
+ // 7. Rate limiting - prevent abuse
301
+ ratelimit.Server(),
302
+
303
+ // 8. Business middleware
304
+ MyBusinessMiddleware(),
305
+ ),
306
+ )
307
+ ```
308
+
309
+ **Order rationale:**
310
+ - Recovery first: catch all panics
311
+ - Tracing/logging early: capture full request
312
+ - Auth before validate: don't validate unauthorized requests
313
+ - Validate before business: don't process invalid requests
314
+ - Rate limit last before business: allow legitimate requests through
315
+
316
+ ---
317
+
318
+ ## Logging Helper Pattern
319
+
320
+ ```go
321
+ import "github.com/go-kratos/kratos/v2/log"
322
+
323
+ type MyUseCase struct {
324
+ log *log.Helper
325
+ }
326
+
327
+ func NewMyUseCase(logger log.Logger) *MyUseCase {
328
+ return &MyUseCase{
329
+ log: log.NewHelper(
330
+ log.With(logger,
331
+ "module", "biz/myUseCase",
332
+ "service", "myService",
333
+ ),
334
+ ),
335
+ }
336
+ }
337
+
338
+ func (uc *MyUseCase) DoSomething(ctx context.Context) {
339
+ // Log with context (includes trace info)
340
+ uc.log.WithContext(ctx).Infof("doing something")
341
+
342
+ // Log error
343
+ uc.log.WithContext(ctx).Errorf("error occurred: %v", err)
344
+ }
345
+ ```
346
+
347
+ ---
348
+
349
+ ## Request/Response Logging
350
+
351
+ ```go
352
+ func LoggingMiddleware(logger log.Logger) middleware.Middleware {
353
+ h := log.NewHelper(logger)
354
+
355
+ return func(handler middleware.Handler) middleware.Handler {
356
+ return func(ctx context.Context, req interface{}) (interface{}, error) {
357
+ // Log request
358
+ if tr, ok := transport.FromServerContext(ctx); ok {
359
+ h.WithContext(ctx).Infof(
360
+ "request: operation=%s kind=%s",
361
+ tr.Operation(),
362
+ tr.Kind(),
363
+ )
364
+ }
365
+
366
+ // Call handler
367
+ start := time.Now()
368
+ reply, err := handler(ctx, req)
369
+ duration := time.Since(start)
370
+
371
+ // Log response
372
+ h.WithContext(ctx).Infof(
373
+ "response: duration=%dms error=%v",
374
+ duration.Milliseconds(),
375
+ err,
376
+ )
377
+
378
+ return reply, err
379
+ }
380
+ }
381
+ }
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Custom Operation for Non-Proto Routes
387
+
388
+ ```go
389
+ func (s *UploadService) uploadFile(ctx http.Context) error {
390
+ // Set operation for middleware to identify
391
+ http.SetOperation(ctx, "/upload.v1.UploadService/Upload")
392
+
393
+ // Now middleware can use tr.Operation() = "/upload.v1.UploadService/Upload"
394
+ h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) {
395
+ return s.uc.Upload(ctx, req.(*UploadRequest))
396
+ })
397
+
398
+ resp, err := h(ctx, &req)
399
+ return ctx.JSON(200, resp)
400
+ }