@dewtech/dare-cli 3.3.0 → 3.4.0
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.
- package/LICENSE +21 -0
- package/README.md +764 -764
- package/dist/__tests__/confidence.test.js +13 -13
- package/dist/__tests__/dag-converter.test.js +56 -56
- package/dist/__tests__/mcp-server/server.test.js +3 -16
- package/dist/__tests__/mcp-server/server.test.js.map +1 -1
- package/dist/__tests__/project-generator.test.js +2 -2
- package/dist/__tests__/project-generator.test.js.map +1 -1
- package/dist/__tests__/refine.test.js +49 -49
- package/dist/__tests__/reverse-collection.test.js +6 -6
- package/dist/__tests__/review.test.js +38 -38
- package/dist/__tests__/security-hardening.test.d.ts +2 -0
- package/dist/__tests__/security-hardening.test.d.ts.map +1 -0
- package/dist/__tests__/security-hardening.test.js +101 -0
- package/dist/__tests__/security-hardening.test.js.map +1 -0
- package/dist/__tests__/validate.test.js +65 -65
- package/dist/bin/dare.js +0 -0
- package/dist/commands/__tests__/init-validation.test.d.ts +2 -0
- package/dist/commands/__tests__/init-validation.test.d.ts.map +1 -0
- package/dist/commands/__tests__/init-validation.test.js +81 -0
- package/dist/commands/__tests__/init-validation.test.js.map +1 -0
- package/dist/commands/__tests__/init.integration.spec.js +6 -4
- package/dist/commands/__tests__/init.integration.spec.js.map +1 -1
- package/dist/commands/__tests__/init.spec.d.ts +2 -0
- package/dist/commands/__tests__/init.spec.d.ts.map +1 -0
- package/dist/commands/__tests__/init.spec.js +88 -0
- package/dist/commands/__tests__/init.spec.js.map +1 -0
- package/dist/commands/blueprint.js +122 -122
- package/dist/commands/design.js +20 -20
- package/dist/commands/init-validation.d.ts +22 -0
- package/dist/commands/init-validation.d.ts.map +1 -0
- package/dist/commands/init-validation.js +54 -0
- package/dist/commands/init-validation.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +26 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/graphrag/graph-rag.js +24 -24
- package/dist/mcp-server/__tests__/auth.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/auth.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/auth.test.js +72 -0
- package/dist/mcp-server/__tests__/auth.test.js.map +1 -0
- package/dist/mcp-server/__tests__/boot-config.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/boot-config.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/boot-config.test.js +29 -0
- package/dist/mcp-server/__tests__/boot-config.test.js.map +1 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.js +66 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.js.map +1 -0
- package/dist/mcp-server/__tests__/path-confinement.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/path-confinement.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/path-confinement.test.js +135 -0
- package/dist/mcp-server/__tests__/path-confinement.test.js.map +1 -0
- package/dist/mcp-server/bin/server.js +18 -6
- package/dist/mcp-server/bin/server.js.map +1 -1
- package/dist/mcp-server/boot-config.d.ts +6 -0
- package/dist/mcp-server/boot-config.d.ts.map +1 -0
- package/dist/mcp-server/boot-config.js +17 -0
- package/dist/mcp-server/boot-config.js.map +1 -0
- package/dist/mcp-server/middleware/auth.d.ts +10 -0
- package/dist/mcp-server/middleware/auth.d.ts.map +1 -0
- package/dist/mcp-server/middleware/auth.js +44 -0
- package/dist/mcp-server/middleware/auth.js.map +1 -0
- package/dist/mcp-server/middleware/cors.d.ts +6 -0
- package/dist/mcp-server/middleware/cors.d.ts.map +1 -0
- package/dist/mcp-server/middleware/cors.js +30 -0
- package/dist/mcp-server/middleware/cors.js.map +1 -0
- package/dist/mcp-server/middleware/error-handler.d.ts +11 -0
- package/dist/mcp-server/middleware/error-handler.d.ts.map +1 -0
- package/dist/mcp-server/middleware/error-handler.js +14 -0
- package/dist/mcp-server/middleware/error-handler.js.map +1 -0
- package/dist/mcp-server/server.d.ts +7 -2
- package/dist/mcp-server/server.d.ts.map +1 -1
- package/dist/mcp-server/server.js +185 -105
- package/dist/mcp-server/server.js.map +1 -1
- package/dist/skills/registry-mock.json +109 -109
- package/dist/skills/tests/manifest.spec.js +20 -20
- package/dist/stacks/__tests__/dna-emitter.spec.js +6 -6
- package/dist/stacks/dna-emitter.js +69 -69
- package/dist/stacks/ruby-rails-8/scaffold.js +15 -15
- package/dist/utils/project-generator.d.ts.map +1 -1
- package/dist/utils/project-generator.js +254 -252
- package/dist/utils/project-generator.js.map +1 -1
- package/dist/utils/stack-bootstrap.js +371 -371
- package/dist/utils/templates.js +394 -394
- package/dist/verification/__tests__/anti-tamper.test.js +13 -13
- package/package.json +96 -93
- package/templates/DARE-dag-example.yaml +280 -280
- package/templates/UPDATE-MANIFEST.json +68 -68
- package/templates/backend/node-nestjs/.env.example +9 -9
- package/templates/backend/node-nestjs/nest-cli.json +8 -8
- package/templates/backend/node-nestjs/package.json +50 -50
- package/templates/backend/node-nestjs/src/app.controller.ts +12 -12
- package/templates/backend/node-nestjs/src/app.module.ts +15 -15
- package/templates/backend/node-nestjs/src/app.service.ts +8 -8
- package/templates/backend/node-nestjs/src/main.ts +24 -24
- package/templates/backend/node-nestjs/tsconfig.json +21 -21
- package/templates/backend/php-laravel/.env.example +22 -22
- package/templates/backend/php-laravel/app/Http/Controllers/HealthController.php +15 -15
- package/templates/backend/php-laravel/composer.json +40 -40
- package/templates/backend/python-fastapi/.env.example +4 -4
- package/templates/backend/python-fastapi/app/api/router.py +8 -8
- package/templates/backend/python-fastapi/app/core/config.py +20 -20
- package/templates/backend/python-fastapi/main.py +35 -35
- package/templates/backend/python-fastapi/requirements.txt +13 -13
- package/templates/backend/rust-axum/.env.example +3 -3
- package/templates/backend/rust-axum/Cargo.toml +23 -23
- package/templates/backend/rust-axum/src/errors.rs +30 -30
- package/templates/backend/rust-axum/src/main.rs +32 -32
- package/templates/backend/rust-axum/src/routes.rs +6 -6
- package/templates/frontend/leptos-csr/.cargo/config.toml +2 -2
- package/templates/frontend/leptos-csr/Cargo.toml +16 -16
- package/templates/frontend/leptos-csr/Trunk.toml +10 -10
- package/templates/frontend/leptos-csr/index.html +11 -11
- package/templates/frontend/leptos-csr/src/lib.rs +20 -20
- package/templates/frontend/leptos-csr/style/main.scss +19 -19
- package/templates/frontend/leptos-fullstack/.cargo/config.toml +4 -4
- package/templates/frontend/leptos-fullstack/Cargo.toml +56 -56
- package/templates/frontend/leptos-fullstack/src/app.rs +49 -49
- package/templates/frontend/leptos-fullstack/src/lib.rs +9 -9
- package/templates/frontend/leptos-fullstack/src/main.rs +29 -29
- package/templates/frontend/leptos-fullstack/style/main.scss +19 -19
- package/templates/frontend/react/index.html +12 -12
- package/templates/frontend/react/package.json +35 -35
- package/templates/frontend/react/src/App.tsx +25 -25
- package/templates/frontend/react/src/main.tsx +9 -9
- package/templates/frontend/vue/package.json +32 -32
- package/templates/frontend/vue/src/App.vue +7 -7
- package/templates/frontend/vue/src/main.ts +10 -10
- package/templates/frontend/vue/src/router/index.ts +14 -14
- package/templates/frontend/vue/src/views/HomeView.vue +6 -6
- package/templates/hooks/pre-commit-dare-validate +24 -24
- package/templates/ide/antigravity/.agents/skills/dare-ax/SKILL.md +152 -152
- package/templates/ide/antigravity/.agents/skills/dare-bench/SKILL.md +21 -21
- package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +368 -368
- package/templates/ide/antigravity/.agents/skills/dare-bootstrap/SKILL.md +32 -32
- package/templates/ide/antigravity/.agents/skills/dare-bugfix-design/SKILL.md +76 -76
- package/templates/ide/antigravity/.agents/skills/dare-dag/SKILL.md +32 -32
- package/templates/ide/antigravity/.agents/skills/dare-dag-build/SKILL.md +154 -154
- package/templates/ide/antigravity/.agents/skills/dare-dag-run/SKILL.md +130 -130
- package/templates/ide/antigravity/.agents/skills/dare-dag-runner/SKILL.md +203 -203
- package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +180 -180
- package/templates/ide/antigravity/.agents/skills/dare-discover/SKILL.md +33 -33
- package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +63 -63
- package/templates/ide/antigravity/.agents/skills/dare-docker/SKILL.md +315 -315
- package/templates/ide/antigravity/.agents/skills/dare-execute/SKILL.md +264 -264
- package/templates/ide/antigravity/.agents/skills/dare-feature-design/SKILL.md +74 -74
- package/templates/ide/antigravity/.agents/skills/dare-frontend-design/SKILL.md +192 -192
- package/templates/ide/antigravity/.agents/skills/dare-graph/SKILL.md +35 -35
- package/templates/ide/antigravity/.agents/skills/dare-info/SKILL.md +31 -31
- package/templates/ide/antigravity/.agents/skills/dare-init/SKILL.md +35 -35
- package/templates/ide/antigravity/.agents/skills/dare-laravel-api/SKILL.md +337 -337
- package/templates/ide/antigravity/.agents/skills/dare-layered-design/SKILL.md +166 -166
- package/templates/ide/antigravity/.agents/skills/dare-llm-integration/SKILL.md +217 -217
- package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +61 -61
- package/templates/ide/antigravity/.agents/skills/dare-quality-telemetry/SKILL.md +187 -187
- package/templates/ide/antigravity/.agents/skills/dare-realtime/SKILL.md +217 -217
- package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +114 -114
- package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +108 -108
- package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +111 -111
- package/templates/ide/antigravity/.agents/skills/dare-rust-leptos/SKILL.md +263 -263
- package/templates/ide/antigravity/.agents/skills/dare-rust-workspace/SKILL.md +275 -275
- package/templates/ide/antigravity/.agents/skills/dare-security/SKILL.md +274 -274
- package/templates/ide/antigravity/.agents/skills/dare-skill/SKILL.md +35 -35
- package/templates/ide/antigravity/.agents/skills/dare-tasks/SKILL.md +265 -265
- package/templates/ide/antigravity/.agents/skills/dare-telemetry/SKILL.md +188 -188
- package/templates/ide/antigravity/.agents/skills/dare-update/SKILL.md +33 -33
- package/templates/ide/antigravity/.agents/skills/dare-validate/SKILL.md +33 -33
- package/templates/ide/antigravity/.agents/skills/dare-welcome/SKILL.md +30 -30
- package/templates/ide/antigravity/.agents/skills/skill-fastapi-api/SKILL.md +343 -343
- package/templates/ide/antigravity/.agents/skills/skill-go-gin-api/SKILL.md +377 -377
- package/templates/ide/antigravity/.agents/skills/skill-mcp-server/SKILL.md +382 -382
- package/templates/ide/antigravity/.agents/skills/skill-nestjs-api/SKILL.md +326 -326
- package/templates/ide/antigravity/.agents/skills/skill-rails-api/SKILL.md +393 -393
- package/templates/ide/antigravity/templates/BLUEPRINT-template.md +193 -193
- package/templates/ide/antigravity/templates/DESIGN-template.md +129 -129
- package/templates/ide/antigravity/templates/TASK-SPEC-template.md +141 -141
- package/templates/ide/antigravity/templates/TASKS-template.md +26 -26
- package/templates/ide/antigravity/templates/TELEMETRY-template.md +125 -125
- package/templates/ide/claude/.claude/commands/dare-ax.md +131 -131
- package/templates/ide/claude/.claude/commands/dare-bench.md +18 -18
- package/templates/ide/claude/.claude/commands/dare-blueprint.md +134 -134
- package/templates/ide/claude/.claude/commands/dare-bootstrap.md +27 -27
- package/templates/ide/claude/.claude/commands/dare-bugfix-design.md +119 -119
- package/templates/ide/claude/.claude/commands/dare-dag-build.md +151 -151
- package/templates/ide/claude/.claude/commands/dare-dag-run.md +109 -109
- package/templates/ide/claude/.claude/commands/dare-dag-runner.md +117 -117
- package/templates/ide/claude/.claude/commands/dare-dag-viz.md +197 -197
- package/templates/ide/claude/.claude/commands/dare-dag.md +27 -27
- package/templates/ide/claude/.claude/commands/dare-design.md +69 -69
- package/templates/ide/claude/.claude/commands/dare-discover.md +28 -28
- package/templates/ide/claude/.claude/commands/dare-dna.md +75 -75
- package/templates/ide/claude/.claude/commands/dare-docker.md +207 -207
- package/templates/ide/claude/.claude/commands/dare-execute.md +152 -152
- package/templates/ide/claude/.claude/commands/dare-feature-design.md +147 -147
- package/templates/ide/claude/.claude/commands/dare-frontend-design.md +149 -149
- package/templates/ide/claude/.claude/commands/dare-graph.md +30 -30
- package/templates/ide/claude/.claude/commands/dare-info.md +26 -26
- package/templates/ide/claude/.claude/commands/dare-init.md +30 -30
- package/templates/ide/claude/.claude/commands/dare-laravel-api.md +211 -211
- package/templates/ide/claude/.claude/commands/dare-layered-design.md +124 -124
- package/templates/ide/claude/.claude/commands/dare-llm-integration.md +148 -148
- package/templates/ide/claude/.claude/commands/dare-migrate.md +72 -72
- package/templates/ide/claude/.claude/commands/dare-quality-telemetry.md +166 -166
- package/templates/ide/claude/.claude/commands/dare-realtime.md +159 -159
- package/templates/ide/claude/.claude/commands/dare-refine.md +145 -145
- package/templates/ide/claude/.claude/commands/dare-reverse.md +139 -139
- package/templates/ide/claude/.claude/commands/dare-review.md +113 -113
- package/templates/ide/claude/.claude/commands/dare-rust-leptos.md +269 -269
- package/templates/ide/claude/.claude/commands/dare-rust-workspace.md +209 -209
- package/templates/ide/claude/.claude/commands/dare-security.md +232 -232
- package/templates/ide/claude/.claude/commands/dare-skill.md +30 -30
- package/templates/ide/claude/.claude/commands/dare-tasks.md +70 -70
- package/templates/ide/claude/.claude/commands/dare-telemetry.md +132 -132
- package/templates/ide/claude/.claude/commands/dare-update.md +28 -28
- package/templates/ide/claude/.claude/commands/dare-validate.md +28 -28
- package/templates/ide/claude/.claude/commands/dare-welcome.md +25 -25
- package/templates/ide/claude/.claude/commands/skill-fastapi-api.md +205 -205
- package/templates/ide/claude/.claude/commands/skill-go-gin-api.md +232 -232
- package/templates/ide/claude/.claude/commands/skill-mcp-server.md +228 -228
- package/templates/ide/claude/.claude/commands/skill-nestjs-api.md +210 -210
- package/templates/ide/claude/.claude/commands/skill-rails-api.md +236 -236
- package/templates/ide/claude/.claude/settings.example.json +35 -35
- package/templates/ide/claude/CLAUDE.md +146 -146
- package/templates/ide/claude/templates/BLUEPRINT-template.md +193 -193
- package/templates/ide/claude/templates/DESIGN-template.md +129 -129
- package/templates/ide/claude/templates/TASK-SPEC-template.md +141 -141
- package/templates/ide/claude/templates/TASKS-template.md +26 -26
- package/templates/ide/claude/templates/TELEMETRY-template.md +125 -125
- package/templates/ide/cursor/.cursor/commands/dare-bench.md +18 -18
- package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +86 -86
- package/templates/ide/cursor/.cursor/commands/dare-bootstrap.md +27 -27
- package/templates/ide/cursor/.cursor/commands/dare-bugfix-design.md +64 -64
- package/templates/ide/cursor/.cursor/commands/dare-dag-run.md +110 -110
- package/templates/ide/cursor/.cursor/commands/dare-dag-viz.md +139 -139
- package/templates/ide/cursor/.cursor/commands/dare-dag.md +27 -27
- package/templates/ide/cursor/.cursor/commands/dare-design.md +35 -35
- package/templates/ide/cursor/.cursor/commands/dare-discover.md +28 -28
- package/templates/ide/cursor/.cursor/commands/dare-dna.md +75 -75
- package/templates/ide/cursor/.cursor/commands/dare-docker-compose.md +18 -18
- package/templates/ide/cursor/.cursor/commands/dare-dockerfile.md +17 -17
- package/templates/ide/cursor/.cursor/commands/dare-execute.md +19 -19
- package/templates/ide/cursor/.cursor/commands/dare-feature-design.md +64 -64
- package/templates/ide/cursor/.cursor/commands/dare-graph.md +30 -30
- package/templates/ide/cursor/.cursor/commands/dare-info.md +26 -26
- package/templates/ide/cursor/.cursor/commands/dare-init.md +30 -30
- package/templates/ide/cursor/.cursor/commands/dare-migrate.md +72 -72
- package/templates/ide/cursor/.cursor/commands/dare-refine.md +107 -107
- package/templates/ide/cursor/.cursor/commands/dare-reverse.md +139 -139
- package/templates/ide/cursor/.cursor/commands/dare-review.md +91 -91
- package/templates/ide/cursor/.cursor/commands/dare-skill.md +30 -30
- package/templates/ide/cursor/.cursor/commands/dare-tasks.md +184 -184
- package/templates/ide/cursor/.cursor/commands/dare-telemetry.md +42 -42
- package/templates/ide/cursor/.cursor/commands/dare-update.md +28 -28
- package/templates/ide/cursor/.cursor/commands/dare-validate.md +28 -28
- package/templates/ide/cursor/.cursor/commands/dare-welcome.md +25 -25
- package/templates/ide/cursor/.cursor/rules/skill-ax.mdc +263 -263
- package/templates/ide/cursor/.cursor/rules/skill-bugfix-design.mdc +51 -51
- package/templates/ide/cursor/.cursor/rules/skill-dag-build.mdc +173 -173
- package/templates/ide/cursor/.cursor/rules/skill-dag-run.mdc +134 -134
- package/templates/ide/cursor/.cursor/rules/skill-dag-runner.mdc +221 -221
- package/templates/ide/cursor/.cursor/rules/skill-dna.mdc +63 -63
- package/templates/ide/cursor/.cursor/rules/skill-docker.mdc +33 -33
- package/templates/ide/cursor/.cursor/rules/skill-fastapi-api.mdc +352 -352
- package/templates/ide/cursor/.cursor/rules/skill-feature-design.mdc +43 -43
- package/templates/ide/cursor/.cursor/rules/skill-frontend-design.mdc +244 -244
- package/templates/ide/cursor/.cursor/rules/skill-go-gin-api.mdc +371 -371
- package/templates/ide/cursor/.cursor/rules/skill-laravel-api.mdc +44 -44
- package/templates/ide/cursor/.cursor/rules/skill-layered-design.mdc +266 -266
- package/templates/ide/cursor/.cursor/rules/skill-llm-integration.mdc +295 -295
- package/templates/ide/cursor/.cursor/rules/skill-mcp-server.mdc +367 -367
- package/templates/ide/cursor/.cursor/rules/skill-migrate.mdc +58 -58
- package/templates/ide/cursor/.cursor/rules/skill-nestjs-api.mdc +346 -346
- package/templates/ide/cursor/.cursor/rules/skill-quality-telemetry.mdc +248 -248
- package/templates/ide/cursor/.cursor/rules/skill-rails-api.mdc +400 -400
- package/templates/ide/cursor/.cursor/rules/skill-realtime.mdc +262 -262
- package/templates/ide/cursor/.cursor/rules/skill-reverse.mdc +107 -107
- package/templates/ide/cursor/.cursor/rules/skill-rust-leptos.mdc +281 -281
- package/templates/ide/cursor/.cursor/rules/skill-rust-workspace.mdc +312 -312
- package/templates/ide/cursor/.cursor/rules/skill-security.mdc +245 -245
- package/templates/ide/cursor/.cursor/rules/skill-telemetry.mdc +156 -156
- package/templates/ide/cursor/templates/BLUEPRINT-template.md +193 -193
- package/templates/ide/cursor/templates/DESIGN-template.md +129 -129
- package/templates/ide/cursor/templates/TASK-SPEC-template.md +141 -141
- package/templates/ide/cursor/templates/TASKS-template.md +26 -26
- package/templates/ide/cursor/templates/TELEMETRY-template.md +125 -125
- package/templates/shared/docker-compose.yml +41 -41
- package/templates/stacks/go-gin/.dare/skills.yml +11 -11
- package/templates/stacks/go-gin/.env.example +24 -24
- package/templates/stacks/go-gin/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/go-gin/README.md.tpl +38 -38
- package/templates/stacks/go-gin/cmd/server/main.go.tpl +78 -78
- package/templates/stacks/go-gin/db/migrations/0001_create_users.down.sql +2 -2
- package/templates/stacks/go-gin/db/migrations/0001_create_users.up.sql +12 -12
- package/templates/stacks/go-gin/db/queries/users.sql +23 -23
- package/templates/stacks/go-gin/gitignore +7 -7
- package/templates/stacks/go-gin/go.mod.tpl +17 -17
- package/templates/stacks/go-gin/internal/config/config.go +41 -41
- package/templates/stacks/go-gin/internal/db/postgres.go.tpl +25 -25
- package/templates/stacks/go-gin/internal/handler/auth_handler.go.tpl +72 -72
- package/templates/stacks/go-gin/internal/handler/users_handler.go.tpl +72 -72
- package/templates/stacks/go-gin/internal/handler/ws_handler.go +37 -37
- package/templates/stacks/go-gin/internal/llm/dummy.go +14 -14
- package/templates/stacks/go-gin/internal/llm/provider.go +8 -8
- package/templates/stacks/go-gin/internal/middleware/jwt.go.tpl +58 -58
- package/templates/stacks/go-gin/internal/middleware/rate_limit.go +55 -55
- package/templates/stacks/go-gin/internal/model/user.go +17 -17
- package/templates/stacks/go-gin/internal/repository/users_repository.go.tpl +79 -79
- package/templates/stacks/go-gin/internal/service/auth_service.go.tpl +55 -55
- package/templates/stacks/go-gin/internal/service/users_service.go.tpl +53 -53
- package/templates/stacks/go-gin/llms.txt.tpl +54 -54
- package/templates/stacks/go-gin/openapi.json.tpl +46 -46
- package/templates/stacks/go-gin/sqlc.yaml +14 -14
- package/templates/stacks/go-gin/tests/smoke_test.go.tpl +22 -22
- package/templates/stacks/go-stdlib/.dare/skills.yml +11 -11
- package/templates/stacks/go-stdlib/.env.example +24 -24
- package/templates/stacks/go-stdlib/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/go-stdlib/README.md.tpl +41 -41
- package/templates/stacks/go-stdlib/cmd/server/main.go.tpl +82 -82
- package/templates/stacks/go-stdlib/db/migrations/0001_create_users.down.sql +2 -2
- package/templates/stacks/go-stdlib/db/migrations/0001_create_users.up.sql +12 -12
- package/templates/stacks/go-stdlib/db/queries/users.sql +23 -23
- package/templates/stacks/go-stdlib/gitignore +6 -6
- package/templates/stacks/go-stdlib/go.mod.tpl +15 -15
- package/templates/stacks/go-stdlib/internal/config/config.go +41 -41
- package/templates/stacks/go-stdlib/internal/db/postgres.go.tpl +24 -24
- package/templates/stacks/go-stdlib/internal/handler/auth_handler.go.tpl +71 -71
- package/templates/stacks/go-stdlib/internal/handler/users_handler.go.tpl +84 -84
- package/templates/stacks/go-stdlib/internal/handler/ws_handler.go +36 -36
- package/templates/stacks/go-stdlib/internal/httpx/json.go +32 -32
- package/templates/stacks/go-stdlib/internal/llm/dummy.go +14 -14
- package/templates/stacks/go-stdlib/internal/llm/provider.go +8 -8
- package/templates/stacks/go-stdlib/internal/middleware/chain.go +21 -21
- package/templates/stacks/go-stdlib/internal/middleware/cors.go +27 -27
- package/templates/stacks/go-stdlib/internal/middleware/jwt.go.tpl +51 -51
- package/templates/stacks/go-stdlib/internal/middleware/rate_limit.go +81 -81
- package/templates/stacks/go-stdlib/internal/model/user.go +17 -17
- package/templates/stacks/go-stdlib/internal/repository/users_repository.go.tpl +75 -75
- package/templates/stacks/go-stdlib/internal/service/auth_service.go.tpl +55 -55
- package/templates/stacks/go-stdlib/internal/service/users_service.go.tpl +53 -53
- package/templates/stacks/go-stdlib/llms.txt.tpl +60 -60
- package/templates/stacks/go-stdlib/openapi.json.tpl +46 -46
- package/templates/stacks/go-stdlib/sqlc.yaml +14 -14
- package/templates/stacks/go-stdlib/tests/smoke_test.go.tpl +45 -45
- package/templates/stacks/mcp-go/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-go/.env.example +14 -14
- package/templates/stacks/mcp-go/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/mcp-go/README.md.tpl +50 -50
- package/templates/stacks/mcp-go/cmd/server/main.go.tpl +62 -62
- package/templates/stacks/mcp-go/gitignore +6 -6
- package/templates/stacks/mcp-go/go.mod.tpl +9 -9
- package/templates/stacks/mcp-go/internal/prompts/summarize.go +9 -9
- package/templates/stacks/mcp-go/internal/server/server.go.tpl +80 -80
- package/templates/stacks/mcp-go/internal/tools/echo.go +15 -15
- package/templates/stacks/mcp-go/internal/transports/http.go.tpl +21 -21
- package/templates/stacks/mcp-go/internal/transports/sse.go.tpl +17 -17
- package/templates/stacks/mcp-go/internal/transports/stdio.go.tpl +14 -14
- package/templates/stacks/mcp-go/llms.txt.tpl +60 -60
- package/templates/stacks/mcp-go/openapi.json.tpl +31 -31
- package/templates/stacks/mcp-go/tests/echo_test.go.tpl +37 -37
- package/templates/stacks/mcp-node-ts/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-node-ts/.env.example +16 -16
- package/templates/stacks/mcp-node-ts/.github/workflows/dare-ci.yml +54 -54
- package/templates/stacks/mcp-node-ts/README.md.hbs +49 -49
- package/templates/stacks/mcp-node-ts/gitignore +7 -7
- package/templates/stacks/mcp-node-ts/llms.txt.hbs +61 -61
- package/templates/stacks/mcp-node-ts/openapi.json.hbs +39 -39
- package/templates/stacks/mcp-node-ts/package.json.hbs +35 -35
- package/templates/stacks/mcp-node-ts/src/cli.ts.hbs +71 -71
- package/templates/stacks/mcp-node-ts/src/prompts/index.ts +36 -36
- package/templates/stacks/mcp-node-ts/src/server.ts.hbs +45 -45
- package/templates/stacks/mcp-node-ts/src/tools/echo.ts +23 -23
- package/templates/stacks/mcp-node-ts/src/tools/index.ts +18 -18
- package/templates/stacks/mcp-node-ts/src/transports/http.ts +68 -68
- package/templates/stacks/mcp-node-ts/src/transports/sse.ts +58 -58
- package/templates/stacks/mcp-node-ts/src/transports/stdio.ts +5 -5
- package/templates/stacks/mcp-node-ts/tests/echo.test.ts +50 -50
- package/templates/stacks/mcp-node-ts/tsconfig.json +17 -17
- package/templates/stacks/mcp-python/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-python/.env.example +14 -14
- package/templates/stacks/mcp-python/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/mcp-python/README.md.j2 +49 -49
- package/templates/stacks/mcp-python/gitignore +12 -12
- package/templates/stacks/mcp-python/llms.txt.j2 +56 -56
- package/templates/stacks/mcp-python/openapi.json.j2 +33 -33
- package/templates/stacks/mcp-python/pyproject.toml.j2 +37 -37
- package/templates/stacks/mcp-python/src/cli.py.j2 +68 -68
- package/templates/stacks/mcp-python/src/prompts/summarize.py +10 -10
- package/templates/stacks/mcp-python/src/server.py.j2 +28 -28
- package/templates/stacks/mcp-python/src/tools/echo.py +12 -12
- package/templates/stacks/mcp-python/src/transports/http.py +12 -12
- package/templates/stacks/mcp-python/src/transports/sse.py +13 -13
- package/templates/stacks/mcp-python/src/transports/stdio.py +6 -6
- package/templates/stacks/mcp-python/tests/test_echo.py +28 -28
- package/templates/stacks/mcp-rust/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-rust/.env.example +14 -14
- package/templates/stacks/mcp-rust/.github/workflows/dare-ci.yml +38 -38
- package/templates/stacks/mcp-rust/Cargo.toml.tera +35 -35
- package/templates/stacks/mcp-rust/README.md.tera +50 -50
- package/templates/stacks/mcp-rust/gitignore +5 -5
- package/templates/stacks/mcp-rust/llms.txt.tera +60 -60
- package/templates/stacks/mcp-rust/openapi.json.tera +31 -31
- package/templates/stacks/mcp-rust/src/cli.rs.tera +33 -33
- package/templates/stacks/mcp-rust/src/lib.rs +6 -6
- package/templates/stacks/mcp-rust/src/main.rs.tera +30 -30
- package/templates/stacks/mcp-rust/src/prompts/mod.rs +1 -1
- package/templates/stacks/mcp-rust/src/prompts/summarize.rs +5 -5
- package/templates/stacks/mcp-rust/src/server.rs.tera +38 -38
- package/templates/stacks/mcp-rust/src/tools/echo.rs +18 -18
- package/templates/stacks/mcp-rust/src/tools/mod.rs +22 -22
- package/templates/stacks/mcp-rust/src/transports/http.rs +27 -27
- package/templates/stacks/mcp-rust/src/transports/mod.rs +3 -3
- package/templates/stacks/mcp-rust/src/transports/sse.rs +33 -33
- package/templates/stacks/mcp-rust/src/transports/stdio.rs +14 -14
- package/templates/stacks/mcp-rust/tests/echo_test.rs.tera +27 -27
- package/templates/stacks/node-nestjs/.dare/skills.yml +11 -11
- package/templates/stacks/node-nestjs/.env.example +21 -21
- package/templates/stacks/node-nestjs/.github/workflows/dare-ci.yml +54 -54
- package/templates/stacks/node-nestjs/README.md.hbs +35 -35
- package/templates/stacks/node-nestjs/gitignore +7 -7
- package/templates/stacks/node-nestjs/llms.txt.hbs +47 -47
- package/templates/stacks/node-nestjs/nest-cli.json +16 -16
- package/templates/stacks/node-nestjs/openapi.json.hbs +75 -75
- package/templates/stacks/node-nestjs/package.json.hbs +57 -57
- package/templates/stacks/node-nestjs/prisma/schema.prisma +25 -25
- package/templates/stacks/node-nestjs/prisma/seed.ts.hbs +25 -25
- package/templates/stacks/node-nestjs/src/app.module.ts +39 -39
- package/templates/stacks/node-nestjs/src/auth/auth.controller.ts +29 -29
- package/templates/stacks/node-nestjs/src/auth/auth.module.ts +25 -25
- package/templates/stacks/node-nestjs/src/auth/auth.service.ts +36 -36
- package/templates/stacks/node-nestjs/src/auth/dto/login-response.dto.ts +9 -9
- package/templates/stacks/node-nestjs/src/auth/dto/login.dto.ts +17 -17
- package/templates/stacks/node-nestjs/src/auth/jwt.strategy.ts +25 -25
- package/templates/stacks/node-nestjs/src/common/filters/problem-details.filter.ts +38 -38
- package/templates/stacks/node-nestjs/src/common/interceptors/json-response.interceptor.ts +13 -13
- package/templates/stacks/node-nestjs/src/main.ts.hbs +44 -44
- package/templates/stacks/node-nestjs/src/prisma/prisma.module.ts +9 -9
- package/templates/stacks/node-nestjs/src/prisma/prisma.service.ts +9 -9
- package/templates/stacks/node-nestjs/src/users/dto/create-user.dto.ts +22 -22
- package/templates/stacks/node-nestjs/src/users/dto/user.dto.ts +15 -15
- package/templates/stacks/node-nestjs/src/users/users.controller.ts +41 -41
- package/templates/stacks/node-nestjs/src/users/users.module.ts +11 -11
- package/templates/stacks/node-nestjs/src/users/users.repository.ts +38 -38
- package/templates/stacks/node-nestjs/src/users/users.service.ts +38 -38
- package/templates/stacks/node-nestjs/tsconfig.build.json +4 -4
- package/templates/stacks/node-nestjs/tsconfig.json +28 -28
- package/templates/stacks/php-laravel/.dare/skills.yml +11 -11
- package/templates/stacks/php-laravel/.env.example +41 -41
- package/templates/stacks/php-laravel/.github/workflows/dare-ci.yml +43 -43
- package/templates/stacks/php-laravel/README.md.hbs +36 -36
- package/templates/stacks/php-laravel/app/Http/Controllers/Api/AuthController.php +36 -36
- package/templates/stacks/php-laravel/app/Http/Controllers/Api/UsersController.php +33 -33
- package/templates/stacks/php-laravel/app/Http/Requests/CreateUserRequest.php +26 -26
- package/templates/stacks/php-laravel/app/Http/Requests/LoginRequest.php +34 -34
- package/templates/stacks/php-laravel/app/Llm/Contracts/LlmProvider.php +12 -12
- package/templates/stacks/php-laravel/app/Llm/Providers/DummyProvider.php +13 -13
- package/templates/stacks/php-laravel/app/Llm/Providers/OpenAiProvider.php +33 -33
- package/templates/stacks/php-laravel/app/Models/User.php +44 -44
- package/templates/stacks/php-laravel/app/Repositories/UsersRepository.php +32 -32
- package/templates/stacks/php-laravel/app/Services/AuthService.php +37 -37
- package/templates/stacks/php-laravel/app/Services/UsersService.php +57 -57
- package/templates/stacks/php-laravel/artisan +12 -12
- package/templates/stacks/php-laravel/bootstrap/app.php +29 -29
- package/templates/stacks/php-laravel/bootstrap/providers.php +5 -5
- package/templates/stacks/php-laravel/composer.json.hbs +58 -58
- package/templates/stacks/php-laravel/config/l5-swagger.php +41 -41
- package/templates/stacks/php-laravel/config/reverb.php +34 -34
- package/templates/stacks/php-laravel/config/sanctum.php +15 -15
- package/templates/stacks/php-laravel/database/migrations/2026_06_01_000001_create_users_table.php +27 -27
- package/templates/stacks/php-laravel/database/seeders/DatabaseSeeder.php +21 -21
- package/templates/stacks/php-laravel/gitignore +23 -23
- package/templates/stacks/php-laravel/llms.txt.hbs +53 -53
- package/templates/stacks/php-laravel/openapi.json.hbs +43 -43
- package/templates/stacks/php-laravel/phpstan.neon +9 -9
- package/templates/stacks/php-laravel/routes/api.php +13 -13
- package/templates/stacks/php-laravel/routes/channels.php +7 -7
- package/templates/stacks/php-laravel/tests/Feature/AuthTest.php +35 -35
- package/templates/stacks/php-laravel/tests/Feature/UsersTest.php +30 -30
- package/templates/stacks/php-laravel/tests/Pest.php +5 -5
- package/templates/stacks/python-fastapi/.dare/skills.yml +11 -11
- package/templates/stacks/python-fastapi/.env.example +21 -21
- package/templates/stacks/python-fastapi/.github/workflows/dare-ci.yml +43 -43
- package/templates/stacks/python-fastapi/README.md.j2 +35 -35
- package/templates/stacks/python-fastapi/alembic/env.py +46 -46
- package/templates/stacks/python-fastapi/alembic/script.py.mako +26 -26
- package/templates/stacks/python-fastapi/alembic/versions/0001_create_users.py.j2 +37 -37
- package/templates/stacks/python-fastapi/alembic.ini.j2 +39 -39
- package/templates/stacks/python-fastapi/app/core/config.py +24 -24
- package/templates/stacks/python-fastapi/app/core/security.py +34 -34
- package/templates/stacks/python-fastapi/app/db/session.py +22 -22
- package/templates/stacks/python-fastapi/app/main.py.j2 +36 -36
- package/templates/stacks/python-fastapi/app/models/__init__.py +3 -3
- package/templates/stacks/python-fastapi/app/models/user.py +30 -30
- package/templates/stacks/python-fastapi/app/repositories/user_repository.py +34 -34
- package/templates/stacks/python-fastapi/app/routers/auth.py +37 -37
- package/templates/stacks/python-fastapi/app/routers/users.py +46 -46
- package/templates/stacks/python-fastapi/app/schemas/user.py +56 -56
- package/templates/stacks/python-fastapi/app/services/auth_service.py +22 -22
- package/templates/stacks/python-fastapi/app/services/user_service.py +31 -31
- package/templates/stacks/python-fastapi/gitignore +12 -12
- package/templates/stacks/python-fastapi/llms.txt.j2 +53 -53
- package/templates/stacks/python-fastapi/openapi.json.j2 +43 -43
- package/templates/stacks/python-fastapi/pyproject.toml.j2 +45 -45
- package/templates/stacks/python-fastapi/tests/test_auth.py +22 -22
- package/templates/stacks/ruby-rails-8/.dare/skills.yml +50 -50
- package/templates/stacks/ruby-rails-8/.env.example +20 -20
- package/templates/stacks/ruby-rails-8/.github/workflows/dare-ci.yml +112 -112
- package/templates/stacks/ruby-rails-8/Gemfile.erb +61 -61
- package/templates/stacks/ruby-rails-8/app/channels/application_cable/channel.rb +11 -11
- package/templates/stacks/ruby-rails-8/app/channels/application_cable/connection.rb +34 -34
- package/templates/stacks/ruby-rails-8/app/channels/dare_updates_channel.rb +18 -18
- package/templates/stacks/ruby-rails-8/app/channels/user_updates_channel.rb +23 -23
- package/templates/stacks/ruby-rails-8/app/controllers/application_controller.rb +44 -44
- package/templates/stacks/ruby-rails-8/app/controllers/concerns/problem_details.rb +93 -93
- package/templates/stacks/ruby-rails-8/app/handlers/summarize_handler.rb +33 -33
- package/templates/stacks/ruby-rails-8/app/handlers/users_handler.rb +68 -68
- package/templates/stacks/ruby-rails-8/app/llm/cache/llm_cache.rb +44 -44
- package/templates/stacks/ruby-rails-8/app/llm/prompts/prompt_loader.rb +54 -54
- package/templates/stacks/ruby-rails-8/app/llm/prompts/summarize_v1.jinja2 +12 -12
- package/templates/stacks/ruby-rails-8/app/llm/providers/dummy_provider.rb +35 -35
- package/templates/stacks/ruby-rails-8/app/llm/providers/llm_provider.rb +67 -67
- package/templates/stacks/ruby-rails-8/app/llm/providers/openai_provider.rb +62 -62
- package/templates/stacks/ruby-rails-8/app/llm/rate_limit/token_bucket.rb +82 -82
- package/templates/stacks/ruby-rails-8/app/llm/validators/summarize_output_schema.json +21 -21
- package/templates/stacks/ruby-rails-8/app/llm/validators/validator.rb +52 -52
- package/templates/stacks/ruby-rails-8/app/models/user.rb +36 -36
- package/templates/stacks/ruby-rails-8/app/presenters/user_presenter.rb +48 -48
- package/templates/stacks/ruby-rails-8/app/repositories/document_repository.rb +57 -57
- package/templates/stacks/ruby-rails-8/app/repositories/user_repository.rb +73 -73
- package/templates/stacks/ruby-rails-8/app/services/create_user_service.rb +67 -67
- package/templates/stacks/ruby-rails-8/app/services/realtime_service.rb +53 -53
- package/templates/stacks/ruby-rails-8/app/services/summarize_document_service.rb +57 -57
- package/templates/stacks/ruby-rails-8/config/dare.yml +42 -42
- package/templates/stacks/ruby-rails-8/config/initializers/dare.rb +31 -31
- package/templates/stacks/ruby-rails-8/config/initializers/rack_attack.rb +64 -64
- package/templates/stacks/ruby-rails-8/config/initializers/rswag_api.rb +12 -12
- package/templates/stacks/ruby-rails-8/lib/tasks/dare.rake +159 -159
- package/templates/stacks/ruby-rails-8/llms.txt.erb +69 -69
- package/templates/stacks/ruby-rails-8/spec/api/summarize_spec.rb +56 -56
- package/templates/stacks/ruby-rails-8/spec/api/users_spec.rb +72 -72
- package/templates/stacks/ruby-rails-8/spec/channels/dare_updates_channel_spec.rb +61 -61
- package/templates/stacks/ruby-rails-8/spec/channels/user_updates_channel_spec.rb +56 -56
- package/templates/stacks/ruby-rails-8/spec/factories/users.rb +27 -27
- package/templates/stacks/ruby-rails-8/spec/handlers/users_handler_spec.rb +88 -88
- package/templates/stacks/ruby-rails-8/spec/rails_helper.rb +31 -31
- package/templates/stacks/ruby-rails-8/spec/services/create_user_service_spec.rb +88 -88
- package/templates/stacks/ruby-rails-8/spec/services/summarize_document_service_spec.rb +142 -142
- package/templates/stacks/ruby-rails-8/spec/swagger_helper.rb +73 -73
- package/templates/stacks/rust-axum/.dare/skills.yml +11 -11
- package/templates/stacks/rust-axum/.env.example +26 -26
- package/templates/stacks/rust-axum/.github/workflows/dare-ci.yml +40 -40
- package/templates/stacks/rust-axum/Cargo.toml.tera +53 -53
- package/templates/stacks/rust-axum/README.md.tera +37 -37
- package/templates/stacks/rust-axum/gitignore +5 -5
- package/templates/stacks/rust-axum/llms.txt.tera +54 -54
- package/templates/stacks/rust-axum/migrations/0001_create_users.sql +13 -13
- package/templates/stacks/rust-axum/openapi.json.tera +46 -46
- package/templates/stacks/rust-axum/src/config.rs +45 -45
- package/templates/stacks/rust-axum/src/errors.rs +48 -48
- package/templates/stacks/rust-axum/src/handlers/auth.rs +48 -48
- package/templates/stacks/rust-axum/src/handlers/mod.rs +3 -3
- package/templates/stacks/rust-axum/src/handlers/users.rs +81 -81
- package/templates/stacks/rust-axum/src/handlers/ws.rs +24 -24
- package/templates/stacks/rust-axum/src/lib.rs +19 -19
- package/templates/stacks/rust-axum/src/llm/mod.rs +1 -1
- package/templates/stacks/rust-axum/src/llm/provider.rs +48 -48
- package/templates/stacks/rust-axum/src/main.rs.tera +64 -64
- package/templates/stacks/rust-axum/src/middleware/auth.rs +20 -20
- package/templates/stacks/rust-axum/src/middleware/mod.rs +2 -2
- package/templates/stacks/rust-axum/src/middleware/rate_limit.rs +27 -27
- package/templates/stacks/rust-axum/src/models/mod.rs +1 -1
- package/templates/stacks/rust-axum/src/models/user.rs +13 -13
- package/templates/stacks/rust-axum/src/repositories/mod.rs +1 -1
- package/templates/stacks/rust-axum/src/repositories/user_repository.rs +62 -62
- package/templates/stacks/rust-axum/src/services/auth_service.rs +50 -50
- package/templates/stacks/rust-axum/src/services/mod.rs +2 -2
- package/templates/stacks/rust-axum/src/services/user_service.rs +53 -53
- package/templates/stacks/rust-axum/tests/integration_test.rs.tera +13 -13
- package/dist/commands/new.d.ts +0 -16
- package/dist/commands/new.d.ts.map +0 -1
- package/dist/commands/new.js +0 -104
- package/dist/commands/new.js.map +0 -1
|
@@ -1,262 +1,262 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Comunicação real-time (WebSocket, SSE) DARE-compliant — eventos tipados com JSON Schema, subscriptions autorizadas, reconexão com exponential backoff, e gerenciamento de subscriptions sem ghost listeners.
|
|
3
|
-
globs: **/realtime/**,**/ws/**,**/socket*.ts,**/socket*.py,**/socket*.rs,**/cable/**,**/channels/**
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Skill: Realtime DARE
|
|
8
|
-
|
|
9
|
-
Você é um especialista em comunicação real-time (WebSocket, SSE). Esta skill garante que toda integração real-time em projeto DARE seja **tipada, autorizada, reconectável e sem ghost listeners**.
|
|
10
|
-
|
|
11
|
-
## Arquitetura recomendada
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
┌─────────────────────────────────────────────────────────┐
|
|
15
|
-
│ Event Registry │
|
|
16
|
-
│ - Tipos de evento com schema JSON │
|
|
17
|
-
│ - Versionamento (.v1, .v2…) │
|
|
18
|
-
│ - Autorização declarada por evento │
|
|
19
|
-
└─────────────────────────────────────────────────────────┘
|
|
20
|
-
↓
|
|
21
|
-
┌─────────────────────────────────────────────────────────┐
|
|
22
|
-
│ Subscription Manager │
|
|
23
|
-
│ - Map<connection_id, Set<event_type>> │
|
|
24
|
-
│ - Cleanup garantido on disconnect │
|
|
25
|
-
└─────────────────────────────────────────────────────────┘
|
|
26
|
-
↓
|
|
27
|
-
┌─────────────────────────────────────────────────────────┐
|
|
28
|
-
│ Reconnect Strategy │
|
|
29
|
-
│ - Exponential backoff (1s, 2s, 4s, 8s, max 30s) │
|
|
30
|
-
│ - Jitter para evitar thundering herd │
|
|
31
|
-
│ - Resync de estado após reconectar │
|
|
32
|
-
└─────────────────────────────────────────────────────────┘
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Os 4 pilares
|
|
38
|
-
|
|
39
|
-
### 1. Schema validation de eventos
|
|
40
|
-
|
|
41
|
-
Todo evento WS/SSE tem schema JSON declarado:
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
// src/realtime/event_registry.ts
|
|
45
|
-
import { z } from 'zod';
|
|
46
|
-
|
|
47
|
-
export const EventRegistry = {
|
|
48
|
-
'user.created.v1': {
|
|
49
|
-
schema: z.object({
|
|
50
|
-
id: z.string().uuid(),
|
|
51
|
-
email: z.string().email(),
|
|
52
|
-
createdAt: z.string().datetime(),
|
|
53
|
-
}),
|
|
54
|
-
requires: 'admin',
|
|
55
|
-
},
|
|
56
|
-
'message.sent.v1': {
|
|
57
|
-
schema: z.object({
|
|
58
|
-
conversationId: z.string().uuid(),
|
|
59
|
-
senderId: z.string().uuid(),
|
|
60
|
-
body: z.string().max(2000),
|
|
61
|
-
sentAt: z.string().datetime(),
|
|
62
|
-
}),
|
|
63
|
-
requires: 'participant',
|
|
64
|
-
},
|
|
65
|
-
} as const;
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Server valida antes de emitir, client valida antes de processar. Evento inválido = log + drop.
|
|
69
|
-
|
|
70
|
-
### 2. Registro central de tipos
|
|
71
|
-
|
|
72
|
-
Um único arquivo `event_registry.ts/py/rs`. Adicionar evento passa por PR explícito. Versionamento via sufixo `.v1`, `.v2`.
|
|
73
|
-
|
|
74
|
-
### 3. Reconexão com exponential backoff
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
export class ReconnectStrategy {
|
|
78
|
-
private attempt = 0;
|
|
79
|
-
constructor(private base = 1000, private max = 30_000) {}
|
|
80
|
-
|
|
81
|
-
next(): number {
|
|
82
|
-
const delay = Math.min(this.base * 2 ** this.attempt, this.max);
|
|
83
|
-
const jitter = Math.random() * 1000;
|
|
84
|
-
this.attempt++;
|
|
85
|
-
return delay + jitter;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
reset() { this.attempt = 0; }
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Após reconectar, **resync de estado** — buscar eventos perdidos via REST ou pedir snapshot.
|
|
93
|
-
|
|
94
|
-
### 4. Subscription manager (zero ghost listeners)
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
export class SubscriptionManager {
|
|
98
|
-
private subs = new Map<string, Set<string>>();
|
|
99
|
-
|
|
100
|
-
subscribe(connId: string, event: string) {
|
|
101
|
-
if (!this.subs.has(connId)) this.subs.set(connId, new Set());
|
|
102
|
-
this.subs.get(connId)!.add(event);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
unsubscribe(connId: string, event: string) {
|
|
106
|
-
this.subs.get(connId)?.delete(event);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Cleanup SEMPRE on disconnect — sem exceção
|
|
110
|
-
onDisconnect(connId: string) {
|
|
111
|
-
this.subs.delete(connId);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
metrics() {
|
|
115
|
-
return { connections: this.subs.size, totalSubs: [...this.subs.values()].reduce((s, set) => s + set.size, 0) };
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
---
|
|
121
|
-
|
|
122
|
-
## Métricas (verificáveis em CI/runtime)
|
|
123
|
-
|
|
124
|
-
| ID | Métrica | Como medir |
|
|
125
|
-
|---|---|---|
|
|
126
|
-
| M-01 | 100% de event types com JSON Schema | grep no registry — todo evento tem `schema:` |
|
|
127
|
-
| M-02 | 100% de subscriptions autorizadas | grep por `authorize(` antes de `subscribe(` |
|
|
128
|
-
| M-03 | 0 ghost listeners após desconexão | métrica runtime `subs.size === 0` após disconnect |
|
|
129
|
-
| M-04 | Reconnect strategy configurada | grep por `ReconnectStrategy` ou backoff manual |
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## Antipatterns
|
|
134
|
-
|
|
135
|
-
| AP | Antipattern | Sinal | Correção |
|
|
136
|
-
|---|---|---|---|
|
|
137
|
-
| AP-01 | Evento sem schema | `socket.emit('foo', anything)` | Adicionar schema no registry |
|
|
138
|
-
| AP-02 | `socket.on(...)` sem cleanup | listener vive após disconnect | Usar SubscriptionManager |
|
|
139
|
-
| AP-03 | Reconexão sem backoff | reconecta imediatamente em loop | Exponential + jitter |
|
|
140
|
-
| AP-04 | Sem autorização de subscription | usuário ouve eventos cross-tenant | `authorize(user, event)` antes de `subscribe()` |
|
|
141
|
-
| AP-05 | Broadcast sem filtro | `io.emit()` para todos | Rooms/channels por tenant |
|
|
142
|
-
| AP-06 | Estado não recuperado | UI mostra dados stale | Resync via REST ou snapshot WS |
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## Stack recomendada
|
|
147
|
-
|
|
148
|
-
| Stack | WebSocket | SSE |
|
|
149
|
-
|---|---|---|
|
|
150
|
-
| Node | `socket.io`, `ws` | endpoint custom + `EventSource` no client |
|
|
151
|
-
| Rails | Action Cable + Solid Cable | Rack streaming |
|
|
152
|
-
| Rust/Axum | `tokio-tungstenite`, `axum::extract::ws` | `axum::response::sse::Sse` |
|
|
153
|
-
| FastAPI | `fastapi.WebSocket` | `sse-starlette` (`EventSourceResponse`) |
|
|
154
|
-
| Go | `gorilla/websocket`, `melody` | stdlib `http.Flusher` |
|
|
155
|
-
| NestJS | `@nestjs/websockets` (Socket.io ou ws) | endpoint custom |
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## Exemplo completo — Socket.io (Node)
|
|
160
|
-
|
|
161
|
-
```typescript
|
|
162
|
-
// Server
|
|
163
|
-
io.on('connection', (socket) => {
|
|
164
|
-
socket.on('subscribe', ({ eventType }) => {
|
|
165
|
-
const entry = EventRegistry[eventType];
|
|
166
|
-
if (!entry) return socket.emit('error', { code: 'UNKNOWN_EVENT' });
|
|
167
|
-
if (!authorize(socket.data.user, entry.requires)) {
|
|
168
|
-
return socket.emit('error', { code: 'FORBIDDEN' });
|
|
169
|
-
}
|
|
170
|
-
subMgr.subscribe(socket.id, eventType);
|
|
171
|
-
socket.join(`event:${eventType}`);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
socket.on('disconnect', () => {
|
|
175
|
-
subMgr.onDisconnect(socket.id); // cleanup SEMPRE
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Quando emitir um evento (de qualquer lugar)
|
|
180
|
-
export function emit<E extends keyof typeof EventRegistry>(eventType: E, payload: unknown) {
|
|
181
|
-
const entry = EventRegistry[eventType];
|
|
182
|
-
const valid = entry.schema.safeParse(payload);
|
|
183
|
-
if (!valid.success) { log.error('invalid event payload', valid.error); return; }
|
|
184
|
-
io.to(`event:${eventType}`).emit(eventType, valid.data);
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
// Client
|
|
190
|
-
const socket = io(url);
|
|
191
|
-
const strategy = new ReconnectStrategy();
|
|
192
|
-
|
|
193
|
-
socket.on('connect', () => {
|
|
194
|
-
strategy.reset();
|
|
195
|
-
resyncState();
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
socket.on('disconnect', () => {
|
|
199
|
-
setTimeout(() => socket.connect(), strategy.next());
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
socket.on('message.sent.v1', (payload) => {
|
|
203
|
-
const valid = EventRegistry['message.sent.v1'].schema.safeParse(payload);
|
|
204
|
-
if (!valid.success) return log.warn('invalid event received', valid.error);
|
|
205
|
-
handleMessage(valid.data);
|
|
206
|
-
});
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
---
|
|
210
|
-
|
|
211
|
-
## Aplicação por fase DARE
|
|
212
|
-
|
|
213
|
-
### Design
|
|
214
|
-
- Listar eventos WS/SSE necessários (formato `dominio.acao.vN`)
|
|
215
|
-
- Autorização por evento
|
|
216
|
-
- Estratégia de resync após reconect
|
|
217
|
-
|
|
218
|
-
### Blueprint
|
|
219
|
-
- Diagrama de event flow
|
|
220
|
-
- Stack escolhida (WS lib + cliente)
|
|
221
|
-
- Backoff configurado (base, max, jitter)
|
|
222
|
-
|
|
223
|
-
### Tasks
|
|
224
|
-
- Task: criar `event_registry.ts`
|
|
225
|
-
- Task: implementar `SubscriptionManager`
|
|
226
|
-
- Task: implementar `ReconnectStrategy`
|
|
227
|
-
- Task: configurar autorização por evento
|
|
228
|
-
- Task: instrumentar métrica de ghost listeners
|
|
229
|
-
|
|
230
|
-
### Execute
|
|
231
|
-
- Ralph Loop: grep falha se `socket.on` sem cleanup correspondente
|
|
232
|
-
- Métrica runtime: `subMgr.metrics()` em endpoint `/internal/realtime/stats`
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
## Boas práticas
|
|
237
|
-
|
|
238
|
-
1. **SSE para server→client unidirecional** — logs, métricas, dashboards
|
|
239
|
-
2. **WebSocket para bidirectional** — chat, colaboração ao vivo
|
|
240
|
-
3. **Heartbeat ping-pong** — detecta conexão zumbi (TCP OK, peer não responde)
|
|
241
|
-
4. **Backpressure** — se client lento, drop eventos antigos para evitar OOM
|
|
242
|
-
5. **Replay limitado** — guardar últimos N eventos por room (não histórico completo)
|
|
243
|
-
6. **Versionar eventos** — `.v1`, `.v2` permite migração gradual
|
|
244
|
-
7. **Logs estruturados** — emitir log por evento com tenant, user, eventType, success/fail
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
## Checklist final
|
|
249
|
-
|
|
250
|
-
- [ ] `event_registry.ts/py/rs` com todos os event types
|
|
251
|
-
- [ ] Cada evento tem schema JSON validado
|
|
252
|
-
- [ ] Cada evento declara `requires:` (autorização)
|
|
253
|
-
- [ ] `SubscriptionManager` com cleanup on disconnect
|
|
254
|
-
- [ ] `ReconnectStrategy` no client com exponential backoff + jitter
|
|
255
|
-
- [ ] Resync de estado pós-reconect (REST ou snapshot WS)
|
|
256
|
-
- [ ] Validação de payload no server antes de emitir
|
|
257
|
-
- [ ] Validação de payload no client antes de processar
|
|
258
|
-
- [ ] Métrica de ghost listeners em endpoint `/internal/realtime/stats`
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
Skill licenciada MIT — parte do DARE Method v3.
|
|
1
|
+
---
|
|
2
|
+
description: Comunicação real-time (WebSocket, SSE) DARE-compliant — eventos tipados com JSON Schema, subscriptions autorizadas, reconexão com exponential backoff, e gerenciamento de subscriptions sem ghost listeners.
|
|
3
|
+
globs: **/realtime/**,**/ws/**,**/socket*.ts,**/socket*.py,**/socket*.rs,**/cable/**,**/channels/**
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: Realtime DARE
|
|
8
|
+
|
|
9
|
+
Você é um especialista em comunicação real-time (WebSocket, SSE). Esta skill garante que toda integração real-time em projeto DARE seja **tipada, autorizada, reconectável e sem ghost listeners**.
|
|
10
|
+
|
|
11
|
+
## Arquitetura recomendada
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
┌─────────────────────────────────────────────────────────┐
|
|
15
|
+
│ Event Registry │
|
|
16
|
+
│ - Tipos de evento com schema JSON │
|
|
17
|
+
│ - Versionamento (.v1, .v2…) │
|
|
18
|
+
│ - Autorização declarada por evento │
|
|
19
|
+
└─────────────────────────────────────────────────────────┘
|
|
20
|
+
↓
|
|
21
|
+
┌─────────────────────────────────────────────────────────┐
|
|
22
|
+
│ Subscription Manager │
|
|
23
|
+
│ - Map<connection_id, Set<event_type>> │
|
|
24
|
+
│ - Cleanup garantido on disconnect │
|
|
25
|
+
└─────────────────────────────────────────────────────────┘
|
|
26
|
+
↓
|
|
27
|
+
┌─────────────────────────────────────────────────────────┐
|
|
28
|
+
│ Reconnect Strategy │
|
|
29
|
+
│ - Exponential backoff (1s, 2s, 4s, 8s, max 30s) │
|
|
30
|
+
│ - Jitter para evitar thundering herd │
|
|
31
|
+
│ - Resync de estado após reconectar │
|
|
32
|
+
└─────────────────────────────────────────────────────────┘
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Os 4 pilares
|
|
38
|
+
|
|
39
|
+
### 1. Schema validation de eventos
|
|
40
|
+
|
|
41
|
+
Todo evento WS/SSE tem schema JSON declarado:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
// src/realtime/event_registry.ts
|
|
45
|
+
import { z } from 'zod';
|
|
46
|
+
|
|
47
|
+
export const EventRegistry = {
|
|
48
|
+
'user.created.v1': {
|
|
49
|
+
schema: z.object({
|
|
50
|
+
id: z.string().uuid(),
|
|
51
|
+
email: z.string().email(),
|
|
52
|
+
createdAt: z.string().datetime(),
|
|
53
|
+
}),
|
|
54
|
+
requires: 'admin',
|
|
55
|
+
},
|
|
56
|
+
'message.sent.v1': {
|
|
57
|
+
schema: z.object({
|
|
58
|
+
conversationId: z.string().uuid(),
|
|
59
|
+
senderId: z.string().uuid(),
|
|
60
|
+
body: z.string().max(2000),
|
|
61
|
+
sentAt: z.string().datetime(),
|
|
62
|
+
}),
|
|
63
|
+
requires: 'participant',
|
|
64
|
+
},
|
|
65
|
+
} as const;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Server valida antes de emitir, client valida antes de processar. Evento inválido = log + drop.
|
|
69
|
+
|
|
70
|
+
### 2. Registro central de tipos
|
|
71
|
+
|
|
72
|
+
Um único arquivo `event_registry.ts/py/rs`. Adicionar evento passa por PR explícito. Versionamento via sufixo `.v1`, `.v2`.
|
|
73
|
+
|
|
74
|
+
### 3. Reconexão com exponential backoff
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
export class ReconnectStrategy {
|
|
78
|
+
private attempt = 0;
|
|
79
|
+
constructor(private base = 1000, private max = 30_000) {}
|
|
80
|
+
|
|
81
|
+
next(): number {
|
|
82
|
+
const delay = Math.min(this.base * 2 ** this.attempt, this.max);
|
|
83
|
+
const jitter = Math.random() * 1000;
|
|
84
|
+
this.attempt++;
|
|
85
|
+
return delay + jitter;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
reset() { this.attempt = 0; }
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Após reconectar, **resync de estado** — buscar eventos perdidos via REST ou pedir snapshot.
|
|
93
|
+
|
|
94
|
+
### 4. Subscription manager (zero ghost listeners)
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
export class SubscriptionManager {
|
|
98
|
+
private subs = new Map<string, Set<string>>();
|
|
99
|
+
|
|
100
|
+
subscribe(connId: string, event: string) {
|
|
101
|
+
if (!this.subs.has(connId)) this.subs.set(connId, new Set());
|
|
102
|
+
this.subs.get(connId)!.add(event);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
unsubscribe(connId: string, event: string) {
|
|
106
|
+
this.subs.get(connId)?.delete(event);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Cleanup SEMPRE on disconnect — sem exceção
|
|
110
|
+
onDisconnect(connId: string) {
|
|
111
|
+
this.subs.delete(connId);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
metrics() {
|
|
115
|
+
return { connections: this.subs.size, totalSubs: [...this.subs.values()].reduce((s, set) => s + set.size, 0) };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Métricas (verificáveis em CI/runtime)
|
|
123
|
+
|
|
124
|
+
| ID | Métrica | Como medir |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| M-01 | 100% de event types com JSON Schema | grep no registry — todo evento tem `schema:` |
|
|
127
|
+
| M-02 | 100% de subscriptions autorizadas | grep por `authorize(` antes de `subscribe(` |
|
|
128
|
+
| M-03 | 0 ghost listeners após desconexão | métrica runtime `subs.size === 0` após disconnect |
|
|
129
|
+
| M-04 | Reconnect strategy configurada | grep por `ReconnectStrategy` ou backoff manual |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Antipatterns
|
|
134
|
+
|
|
135
|
+
| AP | Antipattern | Sinal | Correção |
|
|
136
|
+
|---|---|---|---|
|
|
137
|
+
| AP-01 | Evento sem schema | `socket.emit('foo', anything)` | Adicionar schema no registry |
|
|
138
|
+
| AP-02 | `socket.on(...)` sem cleanup | listener vive após disconnect | Usar SubscriptionManager |
|
|
139
|
+
| AP-03 | Reconexão sem backoff | reconecta imediatamente em loop | Exponential + jitter |
|
|
140
|
+
| AP-04 | Sem autorização de subscription | usuário ouve eventos cross-tenant | `authorize(user, event)` antes de `subscribe()` |
|
|
141
|
+
| AP-05 | Broadcast sem filtro | `io.emit()` para todos | Rooms/channels por tenant |
|
|
142
|
+
| AP-06 | Estado não recuperado | UI mostra dados stale | Resync via REST ou snapshot WS |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Stack recomendada
|
|
147
|
+
|
|
148
|
+
| Stack | WebSocket | SSE |
|
|
149
|
+
|---|---|---|
|
|
150
|
+
| Node | `socket.io`, `ws` | endpoint custom + `EventSource` no client |
|
|
151
|
+
| Rails | Action Cable + Solid Cable | Rack streaming |
|
|
152
|
+
| Rust/Axum | `tokio-tungstenite`, `axum::extract::ws` | `axum::response::sse::Sse` |
|
|
153
|
+
| FastAPI | `fastapi.WebSocket` | `sse-starlette` (`EventSourceResponse`) |
|
|
154
|
+
| Go | `gorilla/websocket`, `melody` | stdlib `http.Flusher` |
|
|
155
|
+
| NestJS | `@nestjs/websockets` (Socket.io ou ws) | endpoint custom |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Exemplo completo — Socket.io (Node)
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Server
|
|
163
|
+
io.on('connection', (socket) => {
|
|
164
|
+
socket.on('subscribe', ({ eventType }) => {
|
|
165
|
+
const entry = EventRegistry[eventType];
|
|
166
|
+
if (!entry) return socket.emit('error', { code: 'UNKNOWN_EVENT' });
|
|
167
|
+
if (!authorize(socket.data.user, entry.requires)) {
|
|
168
|
+
return socket.emit('error', { code: 'FORBIDDEN' });
|
|
169
|
+
}
|
|
170
|
+
subMgr.subscribe(socket.id, eventType);
|
|
171
|
+
socket.join(`event:${eventType}`);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
socket.on('disconnect', () => {
|
|
175
|
+
subMgr.onDisconnect(socket.id); // cleanup SEMPRE
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Quando emitir um evento (de qualquer lugar)
|
|
180
|
+
export function emit<E extends keyof typeof EventRegistry>(eventType: E, payload: unknown) {
|
|
181
|
+
const entry = EventRegistry[eventType];
|
|
182
|
+
const valid = entry.schema.safeParse(payload);
|
|
183
|
+
if (!valid.success) { log.error('invalid event payload', valid.error); return; }
|
|
184
|
+
io.to(`event:${eventType}`).emit(eventType, valid.data);
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Client
|
|
190
|
+
const socket = io(url);
|
|
191
|
+
const strategy = new ReconnectStrategy();
|
|
192
|
+
|
|
193
|
+
socket.on('connect', () => {
|
|
194
|
+
strategy.reset();
|
|
195
|
+
resyncState();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
socket.on('disconnect', () => {
|
|
199
|
+
setTimeout(() => socket.connect(), strategy.next());
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
socket.on('message.sent.v1', (payload) => {
|
|
203
|
+
const valid = EventRegistry['message.sent.v1'].schema.safeParse(payload);
|
|
204
|
+
if (!valid.success) return log.warn('invalid event received', valid.error);
|
|
205
|
+
handleMessage(valid.data);
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Aplicação por fase DARE
|
|
212
|
+
|
|
213
|
+
### Design
|
|
214
|
+
- Listar eventos WS/SSE necessários (formato `dominio.acao.vN`)
|
|
215
|
+
- Autorização por evento
|
|
216
|
+
- Estratégia de resync após reconect
|
|
217
|
+
|
|
218
|
+
### Blueprint
|
|
219
|
+
- Diagrama de event flow
|
|
220
|
+
- Stack escolhida (WS lib + cliente)
|
|
221
|
+
- Backoff configurado (base, max, jitter)
|
|
222
|
+
|
|
223
|
+
### Tasks
|
|
224
|
+
- Task: criar `event_registry.ts`
|
|
225
|
+
- Task: implementar `SubscriptionManager`
|
|
226
|
+
- Task: implementar `ReconnectStrategy`
|
|
227
|
+
- Task: configurar autorização por evento
|
|
228
|
+
- Task: instrumentar métrica de ghost listeners
|
|
229
|
+
|
|
230
|
+
### Execute
|
|
231
|
+
- Ralph Loop: grep falha se `socket.on` sem cleanup correspondente
|
|
232
|
+
- Métrica runtime: `subMgr.metrics()` em endpoint `/internal/realtime/stats`
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Boas práticas
|
|
237
|
+
|
|
238
|
+
1. **SSE para server→client unidirecional** — logs, métricas, dashboards
|
|
239
|
+
2. **WebSocket para bidirectional** — chat, colaboração ao vivo
|
|
240
|
+
3. **Heartbeat ping-pong** — detecta conexão zumbi (TCP OK, peer não responde)
|
|
241
|
+
4. **Backpressure** — se client lento, drop eventos antigos para evitar OOM
|
|
242
|
+
5. **Replay limitado** — guardar últimos N eventos por room (não histórico completo)
|
|
243
|
+
6. **Versionar eventos** — `.v1`, `.v2` permite migração gradual
|
|
244
|
+
7. **Logs estruturados** — emitir log por evento com tenant, user, eventType, success/fail
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Checklist final
|
|
249
|
+
|
|
250
|
+
- [ ] `event_registry.ts/py/rs` com todos os event types
|
|
251
|
+
- [ ] Cada evento tem schema JSON validado
|
|
252
|
+
- [ ] Cada evento declara `requires:` (autorização)
|
|
253
|
+
- [ ] `SubscriptionManager` com cleanup on disconnect
|
|
254
|
+
- [ ] `ReconnectStrategy` no client com exponential backoff + jitter
|
|
255
|
+
- [ ] Resync de estado pós-reconect (REST ou snapshot WS)
|
|
256
|
+
- [ ] Validação de payload no server antes de emitir
|
|
257
|
+
- [ ] Validação de payload no client antes de processar
|
|
258
|
+
- [ ] Métrica de ghost listeners em endpoint `/internal/realtime/stats`
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
Skill licenciada MIT — parte do DARE Method v3.
|