gorig-cli 1.0.24 → 1.0.26

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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -40
  3. package/commands/create.js +267 -112
  4. package/commands/doc.js +21 -8
  5. package/commands/init.js +316 -255
  6. package/commands/skill.js +55 -17
  7. package/package.json +1 -1
  8. package/templates/config.go.ejs +6 -5
  9. package/templates/config.yaml.ejs +3 -38
  10. package/templates/controller.go.ejs +11 -42
  11. package/templates/crud.controller.go.ejs +71 -0
  12. package/templates/crud.doc.md.ejs +60 -0
  13. package/templates/crud.dto.go.ejs +103 -0
  14. package/templates/crud.integration.init_test.go.ejs +17 -0
  15. package/templates/crud.integration_test.go.ejs +66 -0
  16. package/templates/crud.model.go.ejs +25 -0
  17. package/templates/crud.module.README.md.ejs +70 -0
  18. package/templates/crud.mongo.config.yaml.ejs +19 -0
  19. package/templates/crud.mysql.config.yaml.ejs +14 -0
  20. package/templates/crud.router.go.ejs +18 -0
  21. package/templates/crud.service.go.ejs +179 -0
  22. package/templates/crud.test.go.ejs +52 -0
  23. package/templates/dto.go.ejs +16 -0
  24. package/templates/gitignore.ejs +18 -49
  25. package/templates/hello.controller.go.ejs +19 -0
  26. package/templates/hello.router.go.ejs +12 -0
  27. package/templates/hello.service.go.ejs +31 -0
  28. package/templates/hello.test.go.ejs +34 -0
  29. package/templates/init.go.ejs +1 -27
  30. package/templates/main.go.ejs +2 -5
  31. package/templates/model.go.ejs +3 -4
  32. package/templates/project.README.md.ejs +35 -0
  33. package/templates/router.go.ejs +4 -8
  34. package/templates/service.go.ejs +25 -77
  35. package/templates/skills/gorig-backend/SKILL.md +89 -0
  36. package/templates/skills/gorig-backend/agents/openai.yaml +4 -0
  37. package/templates/skills/gorig-backend/assets/api-doc-template.md +59 -0
  38. package/templates/skills/gorig-backend/assets/gorig.gitignore +65 -0
  39. package/templates/skills/gorig-backend/assets/module-readme-template.md +58 -0
  40. package/templates/skills/gorig-backend/references/advanced-data-access.md +275 -0
  41. package/templates/skills/gorig-backend/references/auth-security.md +194 -0
  42. package/templates/skills/gorig-backend/references/business-scenarios.md +155 -0
  43. package/templates/skills/gorig-backend/references/cache.md +301 -0
  44. package/templates/skills/gorig-backend/references/capability-matrix.md +37 -0
  45. package/templates/skills/gorig-backend/references/configuration.md +48 -0
  46. package/templates/skills/gorig-backend/references/framework-api.md +190 -0
  47. package/templates/skills/gorig-backend/references/messaging.md +143 -0
  48. package/templates/skills/gorig-backend/references/onboarding-files.md +46 -0
  49. package/templates/skills/gorig-backend/references/outbound-http.md +162 -0
  50. package/templates/skills/gorig-backend/references/persistent-crud.md +332 -0
  51. package/templates/skills/gorig-backend/references/project-bootstrap.md +128 -0
  52. package/templates/skills/gorig-backend/references/scheduled-tasks.md +231 -0
  53. package/templates/skills/gorig-backend/references/service-lifecycle.md +51 -0
  54. package/templates/skills/gorig-backend/references/source-map.md +43 -0
  55. package/templates/skills/gorig-backend/references/source-policy.md +58 -0
  56. package/templates/skills/gorig-backend/references/sse.md +121 -0
  57. package/templates/skills/gorig-backend/references/testing.md +171 -0
  58. package/templates/skills/gorig-backend/scripts/check-source-links.sh +48 -0
  59. package/templates/skills/gorig-backend/scripts/detect-gorig-context.sh +67 -0
  60. package/templates/skills/gorig-backend/scripts/verify-basic-project.sh +108 -0
  61. package/npm_publish copy.sh +0 -65
  62. package/templates/internal.go.ejs +0 -49
  63. package/templates/req.go.ejs +0 -8
  64. package/templates/resp.go.ejs +0 -8
  65. package/templates/service.pub.go.ejs +0 -22
  66. package/templates/skills/claude/gorig-backend/SKILL.md +0 -766
  67. package/templates/skills/claude/gorig-backend/assets/api-doc-template.md +0 -50
  68. package/templates/skills/claude/gorig-backend/assets/module-readme-template.md +0 -46
  69. package/templates/skills/claude/gorig-backend/references/onboarding-files.md +0 -44
  70. package/templates/skills/codex/gorig-backend/SKILL.md +0 -766
  71. package/templates/skills/codex/gorig-backend/agents/openai.yaml +0 -4
  72. package/templates/skills/codex/gorig-backend/assets/api-doc-template.md +0 -50
  73. package/templates/skills/codex/gorig-backend/assets/module-readme-template.md +0 -46
  74. package/templates/skills/codex/gorig-backend/references/onboarding-files.md +0 -44
@@ -0,0 +1,51 @@
1
+ # Service Lifecycle
2
+
3
+ ## Built-in Startup
4
+
5
+ Use one application entry point:
6
+
7
+ ```go
8
+ func main() {
9
+ bootstrap.StartUp()
10
+ }
11
+ ```
12
+
13
+ In the verified baseline, `bootstrap.StartUp()` registers the built-in HTTP service, prints registered routes, and calls `serv.Running()`.
14
+
15
+ Do not also register an application-specific service whose `Startup` and `Shutdown` are `httpx.Startup` and `httpx.Shutdown`; that creates duplicate lifecycle entries for one HTTP server.
16
+
17
+ ## Registration Through Imports
18
+
19
+ Gorig projects commonly register routes, migrations, scheduled tasks, and services from package `init()` functions. Entry points use explicit blank imports to activate the intended packages:
20
+
21
+ ```go
22
+ import _ "example.com/demo/domain"
23
+ ```
24
+
25
+ Keep the import graph visible. Do not add a component import merely to make a package compile; every blank import changes application startup behavior.
26
+
27
+ ## Custom Service
28
+
29
+ Register a distinct lifecycle component only when it owns a distinct resource:
30
+
31
+ ```go
32
+ err := serv.RegisterService(serv.Service{
33
+ Code: "WORKER",
34
+ Startup: workerStartup,
35
+ Shutdown: workerShutdown,
36
+ })
37
+ ```
38
+
39
+ Requirements:
40
+
41
+ - Use a unique stable code.
42
+ - Return startup failures.
43
+ - Honor the shutdown context.
44
+ - Make shutdown idempotent.
45
+ - Do not rely on service map iteration order.
46
+
47
+ ## Graceful Shutdown
48
+
49
+ The verified baseline waits for `os.Interrupt`, then gives registered services a five-second shutdown context. Test graceful shutdown with `SIGINT` and require the process to exit successfully.
50
+
51
+ Do not claim `SIGTERM` support without checking the resolved version; signal handling is version-specific.
@@ -0,0 +1,43 @@
1
+ # Source Map
2
+
3
+ Prefer an exact version or commit over the moving `master` links below.
4
+
5
+ ## Core Framework
6
+
7
+ - Repository: `https://github.com/jom-io/gorig`
8
+ - Startup: `https://github.com/jom-io/gorig/blob/master/bootstrap/startup.go`
9
+ - Service lifecycle: `https://github.com/jom-io/gorig/blob/master/serv/serv.go`
10
+ - HTTP: `https://github.com/jom-io/gorig/tree/master/httpx`
11
+ - API helpers: `https://github.com/jom-io/gorig/tree/master/apix`
12
+ - Data access: `https://github.com/jom-io/gorig/tree/master/domainx`
13
+ - dx facade: `https://github.com/jom-io/gorig/blob/master/domainx/dx/dx.go`
14
+ - Cache: `https://github.com/jom-io/gorig/tree/master/cache`
15
+ - Scheduled tasks: `https://github.com/jom-io/gorig/tree/master/cronx`
16
+ - Messaging: `https://github.com/jom-io/gorig/tree/master/mid/messagex`
17
+ - Authentication: `https://github.com/jom-io/gorig/tree/master/mid/tokenx`
18
+ - Auth middleware: `https://github.com/jom-io/gorig/blob/master/httpx/mid.sign.go`
19
+ - Security middleware: `https://github.com/jom-io/gorig/blob/master/httpx/mid.cors.go`, `https://github.com/jom-io/gorig/blob/master/httpx/mid.debounce.go`
20
+ - Outbound HTTP: `https://github.com/jom-io/gorig/blob/master/httpx/http.go`
21
+ - Tests: `https://github.com/jom-io/gorig/tree/master/test`
22
+
23
+ To inspect a release, replace `/master/` with the tag, for example `/v0.0.52/`, after confirming the tag exists.
24
+
25
+ ## Ecosystem
26
+
27
+ - Service registry: `https://github.com/jom-io/gorig-hub`
28
+ - Service node/client: `https://github.com/jom-io/gorig-node`
29
+ - Operations and deployment: `https://github.com/jom-io/gorig-om`
30
+
31
+ Check each repository's `go.mod`; ecosystem projects may pin different Gorig versions.
32
+
33
+ ## Local Sibling Discovery
34
+
35
+ When working inside a directory such as `<workspace>/gorig-cli`, check sibling directories only after resolving the target dependency:
36
+
37
+ ```sh
38
+ find .. -maxdepth 2 -name go.mod -print
39
+ git -C ../gorig branch --show-current
40
+ git -C ../gorig log -1 --oneline
41
+ ```
42
+
43
+ Useful local examples may exist in business repositories, but they are evidence of usage, not a replacement for the framework API source. Avoid copying product-specific dependencies, secrets, or architecture without evaluating fit.
@@ -0,0 +1,58 @@
1
+ # Source and Version Policy
2
+
3
+ Use this policy before selecting any Gorig API or example.
4
+
5
+ ## Evidence Order
6
+
7
+ 1. Read the target project's `go.mod` and all `replace` directives.
8
+ 2. Prefer the exact resolved dependency source in the Go module cache.
9
+ 3. Use a local sibling Gorig checkout only when it matches the project version or the task explicitly targets that checkout.
10
+ 4. Use the matching public GitHub tag or commit for versioned work.
11
+ 5. Use GitHub `master` only for explicit latest-version, framework-development, or upgrade work.
12
+ 6. Use bundled examples only as offline fallbacks and re-check their signatures before editing.
13
+
14
+ ## Required Version Report
15
+
16
+ Before a material change, report:
17
+
18
+ - Target module name and Go version.
19
+ - Required Gorig version or pseudo-version.
20
+ - Active `replace` target, if any.
21
+ - Source directory used for verification.
22
+ - Whether the work preserves the current version or upgrades it.
23
+
24
+ Do not silently run `go get ...@latest` in an existing project.
25
+
26
+ ## Source Resolution
27
+
28
+ Run:
29
+
30
+ ```sh
31
+ scripts/detect-gorig-context.sh /path/to/project
32
+ ```
33
+
34
+ If the script cannot locate an exact source directory:
35
+
36
+ 1. Run `go env GOMODCACHE` from the target project.
37
+ 2. Use `go list -m -json github.com/jom-io/gorig` when dependencies are available.
38
+ 3. Inspect a compatible local checkout.
39
+ 4. Ask before downloading or upgrading dependencies when that changes external state.
40
+
41
+ ## Compatibility Decisions
42
+
43
+ - Preserve the current dependency for feature work unless the user requests an upgrade or the requested capability is unavailable.
44
+ - Treat a pseudo-version as commit-specific. Do not substitute the nearest release without comparison.
45
+ - When local `master` differs from the resolved module, compare signatures and behavior explicitly.
46
+ - Prefer APIs already used by the target repository when both legacy and newer APIs exist.
47
+ - Mark version-dependent advice in code comments or delivery notes when future maintenance could otherwise misread it.
48
+
49
+ ## Capability Maturity
50
+
51
+ Use these labels:
52
+
53
+ - `verified`: Confirmed by source plus a compiling or behavioral test for the selected version.
54
+ - `experimental`: Present in source but incomplete, risky, or lacking sufficient behavioral verification.
55
+ - `deprecated`: Explicitly deprecated by source or replaced by a preferred API.
56
+ - `unsupported`: Stubbed, absent, or known not to work for the required scenario.
57
+
58
+ Never convert `experimental` or `unsupported` into a working example without first proving it.
@@ -0,0 +1,121 @@
1
+ # Server-Sent Events
2
+
3
+ Use this reference when a task needs SSE streaming, event/error payloads, GET-only stream routes, disconnect handling, or message-to-SSE composition.
4
+
5
+ Always inspect the target project's resolved Gorig source first. The examples below reflect the locally inspected Gorig `master` commit `35bbefb`.
6
+
7
+ ## Route Setup
8
+
9
+ Use `github.com/jom-io/gorig/httpx/ssex`.
10
+
11
+ ```go
12
+ func init() {
13
+ httpx.RegisterRouter(func(root *gin.RouterGroup) {
14
+ root.GET("/orders/events", ssex.Mid(), streamOrderEvents)
15
+ })
16
+ }
17
+ ```
18
+
19
+ `ssex.Mid()`:
20
+
21
+ - allows only `GET`,
22
+ - returns HTTP `405` JSON for non-GET requests,
23
+ - sets `Content-Type: text/event-stream`,
24
+ - sets `Cache-Control: no-cache`,
25
+ - sets `Connection: keep-alive`,
26
+ - sets `Access-Control-Allow-Origin: *`,
27
+ - flushes headers before calling the handler.
28
+
29
+ ## Sending Events
30
+
31
+ ```go
32
+ func streamOrderEvents(ctx *gin.Context) {
33
+ if err := ssex.SendOK(ctx, "ready", map[string]any{"ok": true}); err != nil {
34
+ return
35
+ }
36
+ if err := ssex.SendError(ctx, "warning", "temporary degraded state"); err != nil {
37
+ return
38
+ }
39
+ }
40
+ ```
41
+
42
+ The wire format is:
43
+
44
+ ```text
45
+ event: ready
46
+ data: {"status":"ok","data":{"ok":true}}
47
+ ```
48
+
49
+ Error events use:
50
+
51
+ ```json
52
+ {"status":"error","message":"temporary degraded state"}
53
+ ```
54
+
55
+ `SendOK` and `SendError` return ordinary Go errors from JSON encoding or response writing. Treat a write error as a disconnect or broken stream and stop sending.
56
+
57
+ ## Long-Lived Streams
58
+
59
+ For long-lived streams, block on either application events or request cancellation:
60
+
61
+ ```go
62
+ func stream(ctx *gin.Context) {
63
+ ticker := time.NewTicker(30 * time.Second)
64
+ defer ticker.Stop()
65
+
66
+ for {
67
+ select {
68
+ case <-ctx.Request.Context().Done():
69
+ return
70
+ case <-ticker.C:
71
+ if err := ssex.SendOK(ctx, "heartbeat", map[string]any{"ts": time.Now().Unix()}); err != nil {
72
+ return
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ Rules:
80
+
81
+ - SSE endpoints must be `GET`.
82
+ - Do not call `apix.HandleData` after starting an SSE stream.
83
+ - Do not write unrelated JSON responses to the same stream.
84
+ - Always watch `ctx.Request.Context().Done()`.
85
+ - Keep per-connection goroutines bounded and unregister subscribers on disconnect.
86
+
87
+ ## Message to SSE Composition
88
+
89
+ When the event source is `messagex`, register a subscriber for the connection and unregister it on exit:
90
+
91
+ ```go
92
+ func streamOrderUpdates(ctx *gin.Context) {
93
+ broker := messagex.Ins(messagex.Local)
94
+ subID, err := broker.RegisterTopic("order.updated", func(msg *messagex.Message) *errors.Error {
95
+ if sendErr := ssex.SendOK(ctx, "order.updated", msg.Content); sendErr != nil {
96
+ return errors.Sys(sendErr.Error())
97
+ }
98
+ return nil
99
+ })
100
+ if err != nil {
101
+ _ = ssex.SendError(ctx, "order.updated", err.Error())
102
+ return
103
+ }
104
+ defer broker.UnRegisterTopic("order.updated", subID)
105
+
106
+ <-ctx.Request.Context().Done()
107
+ }
108
+ ```
109
+
110
+ This simple pattern is appropriate for low-volume same-process streams. For high fan-out, backpressure, or cross-process delivery, design a bounded stream loop and verify Redis-backed messaging behavior.
111
+
112
+ ## Verification Checklist
113
+
114
+ - Compile against the target project's resolved Gorig version.
115
+ - Verify GET responses include SSE headers.
116
+ - Verify non-GET requests return HTTP 405 with the framework error JSON.
117
+ - Verify `SendOK` writes the expected `event:` and JSON `status:"ok"` payload.
118
+ - Verify `SendError` writes `status:"error"` and message payload.
119
+ - Verify long-lived handlers exit on `ctx.Request.Context().Done()`.
120
+ - Verify write errors or disconnects stop the loop and unregister any message subscribers.
121
+ - For message-to-SSE, verify publish -> receive -> SSE event output and cleanup.
@@ -0,0 +1,171 @@
1
+ # Testing and Effect Verification
2
+
3
+ Prefer repository-specific commands from `AGENTS.md`, CI, or existing scripts. Otherwise use the checks below.
4
+
5
+ ## Standard Go Gates
6
+
7
+ ```sh
8
+ go fmt ./...
9
+ go vet ./...
10
+ go build ./...
11
+ go test ./... -v -race -cover
12
+ ```
13
+
14
+ Narrow the test command while iterating, then run the full applicable suite before delivery.
15
+
16
+ ## Test Placement
17
+
18
+ Prefer the project-level `test/` package for Gorig feature tests because it centralizes configuration, database setup, cache setup, and framework initialization. Add package-local tests only when the target project already follows that convention or the code under test has no Gorig initialization dependency.
19
+
20
+ ## Effect Verification
21
+
22
+ Match verification to the delivered behavior:
23
+
24
+ - Business scenario: verify the observable business outcome, not only the framework primitive.
25
+ - Project bootstrap: start the binary, request `/ping`, then stop it gracefully.
26
+ - HTTP API: exercise success, required-parameter, invalid-parameter, not-found, and service-error responses.
27
+ - Database: verify migration/index creation plus read/write/update/delete and pagination.
28
+ - Cache: verify miss, hit, expiry, invalidation, and concurrency behavior.
29
+ - Cron: verify execution count, timeout, panic recovery, deduplication, and shutdown.
30
+ - Messaging: verify publish/consume, ordering, retry, DLQ, unsubscribe, and cross-process behavior when Redis-backed.
31
+ - SSE: verify event shape, error event, timeout, disconnect, and cleanup.
32
+ - Authentication and security: verify valid, missing, malformed, expired, refreshed, revoked/logout, and forbidden tokens; verify user and trace context, CORS preflight, debounce behavior, exception paths, and secret hygiene.
33
+ - Outbound HTTP: verify GET, form, JSON, XML, headers, context/header propagation, timeout, bad responses, malformed payloads, and image fetching against a local server.
34
+ - Deployment: verify startup, health, business endpoint, graceful stop, and rollback in a disposable target.
35
+
36
+ ## External Infrastructure
37
+
38
+ Use disposable containers or explicitly supplied development services for MySQL, MongoDB, and Redis integration checks. Do not silently target shared or production infrastructure.
39
+
40
+ If required infrastructure is unavailable, keep the capability unverified and report the exact missing check.
41
+
42
+ ## Business Scenario Tests
43
+
44
+ For ordinary user requests, write tests around the business behavior first, then prove the selected Gorig component supports it.
45
+
46
+ Examples:
47
+
48
+ - A "customer follow-up reminder" test should prove a customer without follow-up becomes pending follow-up after the delay, while a customer already followed up is not changed.
49
+ - A "send notification after order paid" test should prove the order-paid event triggers exactly the intended subscribers and is safe to retry.
50
+ - A "live progress page" test should prove the browser stream receives the expected event and subscriber cleanup happens on disconnect.
51
+ - A "speed up customer detail" test should prove cache miss, hit, invalidation after update, and fallback when cache is unavailable.
52
+
53
+ When the selected solution requires Redis, MySQL, MongoDB, or another external service, split tests into:
54
+
55
+ - ordinary tests for business decision logic and framework error paths, and
56
+ - integration tests for runtime delivery against disposable or explicitly supplied infrastructure.
57
+
58
+ Do not claim the business feature is verified when only the ordinary tests ran and the required integration service was unavailable.
59
+
60
+ ## Advanced Data Access Tests
61
+
62
+ For advanced `domainx/dx` work:
63
+
64
+ - Ordinary compile and unit tests must cover query construction and service validation without external services when possible.
65
+ - MySQL and MongoDB behavior must be proven with tagged or container-backed integration tests before it is claimed verified.
66
+ - Verify optional filters with empty values and intentional zero values.
67
+ - Verify sorting, projection, count, sum, existence checks, pagination, update/delete guards, migrations, and indexes.
68
+ - Verify list/page implementations use database-backed filtering, sorting, and pagination. Do not accept tests that pass only because a small fixture was loaded into memory and sliced.
69
+ - Verify direct-driver escape hatches and transactions only against the backend where they are used.
70
+ - Record backend-specific differences and unsupported operations in delivery notes or module documentation.
71
+
72
+ ## Cache Tests
73
+
74
+ For cache work:
75
+
76
+ - Memory, JSON, and SQLite cache behavior should run locally without Redis or database services.
77
+ - Verify miss, hit, expiry, delete, invalidation, counter, flush, and persistence when the backend is persistent.
78
+ - Verify multi-level cache by testing L1 miss, lower-layer hit backfill, full miss loader, delete across layers, and concurrent same-key loading.
79
+ - Redis behavior must run only with disposable or explicitly supplied Redis configuration.
80
+ - State whether cache is an acceleration layer or a source of state. Do not use cache as source of truth unless loss, expiry, and cross-process behavior are acceptable and tested.
81
+
82
+ ## Generated Persistent CRUD Tests
83
+
84
+ For CLI-generated persistent CRUD modules:
85
+
86
+ - Keep validation tests in `test/<module>_test.go`; ordinary `go test ./...` must not require a database.
87
+ - Keep real database tests behind backend-specific build tags in `test/<module>_integration_test.go`.
88
+ - Initialize only the selected backend in `test/init_mysql_integration_test.go` or `test/init_mongo_integration_test.go`.
89
+ - Synchronize non-secret connection skeletons into `test/_bin/local.yaml`. Gorig tests normally read this file because the package working directory is `test/`.
90
+ - Run `go test -tags=integration,mysql ./test/... -v` or `go test -tags=integration,mongo ./test/... -v` after local connection values are available.
91
+
92
+ Never claim database behavior is verified merely because a tagged integration test compiles.
93
+
94
+ ## Scheduled Task Tests
95
+
96
+ For `cronx` work:
97
+
98
+ - Prefer short deterministic schedules such as `@every 1s` in tests; keep the test bounded with channel waits or deadlines.
99
+ - Verify duplicate registration with a stable named function and the same spec.
100
+ - Verify timeout by asserting the handler observes `ctx.Done()`.
101
+ - Verify panic recovery by proving a later task still runs or the wrapper returns without terminating the process.
102
+ - Verify delay and once jobs run exactly once.
103
+ - Call `cronx.Shutdown("CRON", context.Background())` at the end of the test.
104
+ - Verify `AddEveryTask` registration returns promptly and the interval task executes when the target version includes commit `92c28b5` or an equivalent fix.
105
+ - For persistent delay tasks, verify handler registration rejects anonymous functions, scheduling rejects unregistered handlers, and non-JSON payloads fail before enqueue.
106
+ - Run persistent delay/once runtime tests only with disposable or explicitly supplied Redis. Assert payload delivery, timeout/failure behavior when relevant, task key cleanup, and worker shutdown.
107
+
108
+ ## Messaging Tests
109
+
110
+ For `messagex` work:
111
+
112
+ - Use unique topic names per test and always unregister subscribers.
113
+ - Verify local publish/consume with typed getters because payload keys are lowercased.
114
+ - Verify multiple subscribers each receive the same published message.
115
+ - Verify sequential subscribers preserve publish order.
116
+ - Verify retry and DLQ behavior with `RegisterTopicSeq`.
117
+ - Verify unsubscribe by publishing after unregister and asserting no new delivery occurs.
118
+ - Verify local `ReplayDLQ` returns the expected store-not-initialized error; verify replay behavior only with Redis configured.
119
+ - Run Redis broker checks only against disposable or explicitly supplied Redis configuration.
120
+
121
+ ## SSE Tests
122
+
123
+ For SSE work:
124
+
125
+ - Use `httptest` for header and payload verification.
126
+ - Verify GET streams return `Content-Type: text/event-stream`.
127
+ - Verify non-GET requests return HTTP 405 and the framework JSON body.
128
+ - Verify `SendOK` and `SendError` event shapes.
129
+ - For long-lived streams, cancel the request context and assert the handler exits.
130
+ - For message-to-SSE composition, verify subscriber cleanup on disconnect.
131
+
132
+ ## Authentication and Security Tests
133
+
134
+ For auth/security work:
135
+
136
+ - Build a minimal login -> protected route -> logout flow in tests or smoke routes.
137
+ - Use `tokenx.Get(tokenx.Jwt, tokenx.Memory)` for simple local single-process auth tests. Use `tokenx.Get(tokenx.Jwt, tokenx.Redis)` and `httpx.SignRedis()` when the target version includes `mid/tokenx/redis.manager.go` or an equivalent Redis manager implementation and the business needs Redis-backed token state.
138
+ - For Gorig `master` and releases containing `test/tokenx_redis_test.go`, run `go test ./test -run TestRedisTokenManager -v` when Redis is configured. If the test skips with `redis is not configured`, report the missing Redis configuration and rerun after Redis is provided; do not downgrade the capability to memory token unless the user accepts that behavior change.
139
+ - Verify valid token success and that protected handlers read user id from `apix.GetUserID`, not from request input.
140
+ - Verify missing header, malformed `Authorization`, expired JWT through `IsNotExpired`/`IsEffective`, destroyed token, refreshed old token, refreshed new token, and forbidden role/attribute. Also verify protected-route behavior for manager-expired or unrecorded tokens according to the resolved version.
141
+ - Verify middleware writes user id into both gin context and request context, and trace context remains available.
142
+ - Verify CORS `OPTIONS` response status, origin, credentials, and allowed headers.
143
+ - Verify debounce returns HTTP 429 for repeated requests within the window and allows whitelisted paths.
144
+ - Scan generated examples and fixtures for real-looking secrets, raw bearer tokens, production hosts, and passwords.
145
+
146
+ ## Outbound HTTP Tests
147
+
148
+ For outbound client work:
149
+
150
+ - Use `httptest.Server` or a controlled local server, not a real third-party API.
151
+ - Assert query parameters for `Get`/`GetHeader`.
152
+ - Assert form body and content type for `PostForm`.
153
+ - Assert JSON body and response parsing for `PostJSONResp` or `PostJSON`.
154
+ - Assert XML body and parse behavior; wrap `ParseXML` when malformed XML is expected.
155
+ - Assert custom headers and intentional `Authorization` forwarding through context-aware helpers.
156
+ - Exercise timeout using a slow handler and a bounded client/helper.
157
+ - Exercise non-success status and malformed JSON/XML response behavior.
158
+ - Exercise `FetchImage` only with a controlled local image response, and document size/content-type/host boundaries when user URLs are accepted.
159
+
160
+ ## Delivery Evidence
161
+
162
+ Report:
163
+
164
+ - Exact command.
165
+ - Exit status.
166
+ - Important output or assertion.
167
+ - Environment and dependency version.
168
+ - Skipped checks and reason.
169
+ - Known limitations discovered during verification.
170
+
171
+ "Tests passed" without commands and effect evidence is insufficient.
@@ -0,0 +1,48 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ skill_dir=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
5
+ online=${1:-}
6
+
7
+ required_files="
8
+ $skill_dir/SKILL.md
9
+ $skill_dir/references/source-policy.md
10
+ $skill_dir/references/onboarding-files.md
11
+ $skill_dir/references/capability-matrix.md
12
+ $skill_dir/references/framework-api.md
13
+ $skill_dir/references/project-bootstrap.md
14
+ $skill_dir/references/configuration.md
15
+ $skill_dir/references/service-lifecycle.md
16
+ $skill_dir/references/testing.md
17
+ $skill_dir/references/source-map.md
18
+ $skill_dir/assets/api-doc-template.md
19
+ $skill_dir/assets/module-readme-template.md
20
+ $skill_dir/scripts/detect-gorig-context.sh
21
+ $skill_dir/scripts/verify-basic-project.sh
22
+ "
23
+
24
+ for file in $required_files; do
25
+ if [ ! -f "$file" ]; then
26
+ echo "missing=$file" >&2
27
+ exit 1
28
+ fi
29
+ done
30
+
31
+ echo "local_sources=ok"
32
+
33
+ if [ "$online" != "--online" ]; then
34
+ echo "online_sources=skipped"
35
+ exit 0
36
+ fi
37
+
38
+ if ! command -v curl >/dev/null 2>&1; then
39
+ echo "error=curl is required for --online" >&2
40
+ exit 1
41
+ fi
42
+
43
+ urls=$(sed -n 's/.*`\(https:\/\/github\.com\/[^`]*\)`.*/\1/p' "$skill_dir/references/source-map.md")
44
+ printf '%s\n' "$urls" | xargs -n 1 -P 4 sh -c '
45
+ url=$1
46
+ curl --fail --silent --show-error --location --range 0-0 --connect-timeout 10 --max-time 20 "$url" >/dev/null
47
+ echo "online_source=ok $url"
48
+ ' _
@@ -0,0 +1,67 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ project_root=${1:-.}
5
+
6
+ if [ ! -d "$project_root" ]; then
7
+ echo "error=project directory not found: $project_root" >&2
8
+ exit 1
9
+ fi
10
+
11
+ project_root=$(cd "$project_root" && pwd)
12
+ go_mod="$project_root/go.mod"
13
+
14
+ if [ ! -f "$go_mod" ]; then
15
+ printf 'project_root=%s\n' "$project_root"
16
+ echo "go_mod=missing"
17
+ exit 2
18
+ fi
19
+
20
+ module_name=$(awk '$1 == "module" { print $2; exit }' "$go_mod")
21
+ go_version=$(awk '$1 == "go" { print $2; exit }' "$go_mod")
22
+ gorig_version=$(awk '$1 == "github.com/jom-io/gorig" { print $2; exit }' "$go_mod")
23
+ replace_target=$(awk '
24
+ $1 == "replace" && $2 == "github.com/jom-io/gorig" && $3 == "=>" { print $4; exit }
25
+ in_replace && $1 == "github.com/jom-io/gorig" && $2 == "=>" { print $3; exit }
26
+ $1 == "replace" && $2 == "(" { in_replace = 1; next }
27
+ in_replace && $1 == ")" { in_replace = 0 }
28
+ ' "$go_mod")
29
+
30
+ source_kind=unresolved
31
+ source_dir=
32
+
33
+ case "$replace_target" in
34
+ ./*|../*|/*)
35
+ if [ "${replace_target#/}" != "$replace_target" ]; then
36
+ candidate=$replace_target
37
+ else
38
+ candidate="$project_root/$replace_target"
39
+ fi
40
+ if [ -d "$candidate" ]; then
41
+ source_kind=replace
42
+ source_dir=$(cd "$candidate" && pwd)
43
+ fi
44
+ ;;
45
+ esac
46
+
47
+ if [ -z "$source_dir" ] && [ -n "$gorig_version" ] && command -v go >/dev/null 2>&1; then
48
+ module_cache=$(cd "$project_root" && go env GOMODCACHE 2>/dev/null || true)
49
+ candidate="$module_cache/github.com/jom-io/gorig@$gorig_version"
50
+ if [ -d "$candidate" ]; then
51
+ source_kind=module_cache
52
+ source_dir=$candidate
53
+ fi
54
+ fi
55
+
56
+ if [ -z "$source_dir" ] && [ -d "$project_root/../gorig" ]; then
57
+ source_kind=sibling
58
+ source_dir=$(cd "$project_root/../gorig" && pwd)
59
+ fi
60
+
61
+ printf 'project_root=%s\n' "$project_root"
62
+ printf 'module=%s\n' "${module_name:-unknown}"
63
+ printf 'go_version=%s\n' "${go_version:-unknown}"
64
+ printf 'gorig_version=%s\n' "${gorig_version:-not_required}"
65
+ printf 'replace=%s\n' "${replace_target:-none}"
66
+ printf 'source_kind=%s\n' "$source_kind"
67
+ printf 'source_dir=%s\n' "${source_dir:-not_found}"
@@ -0,0 +1,108 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ project_root=${1:-.}
5
+ mode=${2:-local}
6
+
7
+ case "$mode" in
8
+ local|dev|prod) ;;
9
+ *)
10
+ echo "error=mode must be local, dev, or prod" >&2
11
+ exit 1
12
+ ;;
13
+ esac
14
+
15
+ project_root=$(cd "$project_root" && pwd)
16
+ config="$project_root/_bin/$mode.yaml"
17
+
18
+ if [ ! -f "$project_root/go.mod" ] || [ ! -f "$config" ]; then
19
+ echo "error=not a generated Gorig project or configuration missing" >&2
20
+ exit 1
21
+ fi
22
+
23
+ port=$(sed -n 's/^[[:space:]]*addr:[[:space:]]*":\([0-9][0-9]*\)"[[:space:]]*$/\1/p' "$config" | head -n 1)
24
+ if [ -z "$port" ]; then
25
+ echo "error=unable to read api.rest.addr from $config" >&2
26
+ exit 1
27
+ fi
28
+
29
+ cache_root=${GOCACHE:-/tmp/gorig-skill-go-cache}
30
+ binary="$project_root/.cache/verify-basic-project"
31
+ log_file="$project_root/.cache/verify-basic-project-$mode.log"
32
+ pid=
33
+
34
+ cleanup() {
35
+ status=$?
36
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
37
+ kill -INT "$pid" 2>/dev/null || true
38
+ wait "$pid" 2>/dev/null || true
39
+ fi
40
+ return "$status"
41
+ }
42
+ trap cleanup EXIT INT TERM
43
+
44
+ mkdir -p "$project_root/.cache"
45
+
46
+ unformatted=$(cd "$project_root" && gofmt -l .)
47
+ if [ -n "$unformatted" ]; then
48
+ echo "error=unformatted Go files" >&2
49
+ echo "$unformatted" >&2
50
+ exit 1
51
+ fi
52
+
53
+ (cd "$project_root" && GOCACHE="$cache_root" go vet ./...)
54
+ (cd "$project_root" && GOCACHE="$cache_root" go build -o "$binary" ./_cmd)
55
+ (cd "$project_root" && GOCACHE="$cache_root" go test ./... -v)
56
+
57
+ previous_dir=$(pwd)
58
+ cd "$project_root"
59
+ GORIG_SYS_MODE="$mode" "$binary" >"$log_file" 2>&1 &
60
+ pid=$!
61
+ cd "$previous_dir"
62
+
63
+ base_url="http://127.0.0.1:$port"
64
+ ready=false
65
+ ping_response=
66
+ attempt=0
67
+ while [ "$attempt" -lt 40 ]; do
68
+ if ping_response=$(curl --fail --silent --max-time 2 "$base_url/ping" 2>/dev/null); then
69
+ ready=true
70
+ break
71
+ fi
72
+ if ! kill -0 "$pid" 2>/dev/null; then
73
+ echo "error=project exited before becoming ready" >&2
74
+ cat "$log_file" >&2
75
+ exit 1
76
+ fi
77
+ attempt=$((attempt + 1))
78
+ sleep 0.25
79
+ done
80
+
81
+ if [ "$ready" != true ]; then
82
+ echo "error=project did not become ready on $base_url" >&2
83
+ cat "$log_file" >&2
84
+ exit 1
85
+ fi
86
+
87
+ hello_response=$(curl --fail --silent --max-time 5 "$base_url/hello?name=Gorig")
88
+
89
+ echo "$ping_response" | grep '"code":200' > /dev/null
90
+ echo "$hello_response" | grep '"code":200' > /dev/null
91
+ echo "$hello_response" | grep "\"mode\":\"$mode\"" > /dev/null
92
+ echo "$hello_response" | grep '"message":"hello Gorig"' > /dev/null
93
+
94
+ kill -INT "$pid"
95
+ if ! wait "$pid"; then
96
+ echo "error=project did not shut down cleanly" >&2
97
+ cat "$log_file" >&2
98
+ exit 1
99
+ fi
100
+ pid=
101
+
102
+ grep 'Shutting down the system \[OK\]' "$log_file" > /dev/null
103
+
104
+ echo "mode=$mode"
105
+ echo "base_url=$base_url"
106
+ echo "ping=$ping_response"
107
+ echo "hello=$hello_response"
108
+ echo "graceful_shutdown=ok"