@dewtech/dare-cli 2.17.0 → 3.0.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/README.md +98 -3
- package/dist/__tests__/confidence.test.d.ts +2 -0
- package/dist/__tests__/confidence.test.d.ts.map +1 -0
- package/dist/__tests__/confidence.test.js +73 -0
- package/dist/__tests__/confidence.test.js.map +1 -0
- package/dist/__tests__/datamodel.test.d.ts +2 -0
- package/dist/__tests__/datamodel.test.d.ts.map +1 -0
- package/dist/__tests__/datamodel.test.js +131 -0
- package/dist/__tests__/datamodel.test.js.map +1 -0
- package/dist/__tests__/dna-detector.test.d.ts +2 -0
- package/dist/__tests__/dna-detector.test.d.ts.map +1 -0
- package/dist/__tests__/dna-detector.test.js +97 -0
- package/dist/__tests__/dna-detector.test.js.map +1 -0
- package/dist/__tests__/dna-facts.test.d.ts +2 -0
- package/dist/__tests__/dna-facts.test.d.ts.map +1 -0
- package/dist/__tests__/dna-facts.test.js +44 -0
- package/dist/__tests__/dna-facts.test.js.map +1 -0
- package/dist/__tests__/graph-renderer.test.d.ts +2 -0
- package/dist/__tests__/graph-renderer.test.d.ts.map +1 -0
- package/dist/__tests__/graph-renderer.test.js +85 -0
- package/dist/__tests__/graph-renderer.test.js.map +1 -0
- package/dist/__tests__/migration.test.d.ts +2 -0
- package/dist/__tests__/migration.test.d.ts.map +1 -0
- package/dist/__tests__/migration.test.js +77 -0
- package/dist/__tests__/migration.test.js.map +1 -0
- package/dist/__tests__/module-detector.test.d.ts +2 -0
- package/dist/__tests__/module-detector.test.d.ts.map +1 -0
- package/dist/__tests__/module-detector.test.js +83 -0
- package/dist/__tests__/module-detector.test.js.map +1 -0
- package/dist/__tests__/refine.test.js +49 -49
- package/dist/__tests__/reverse-facts.test.d.ts +2 -0
- package/dist/__tests__/reverse-facts.test.d.ts.map +1 -0
- package/dist/__tests__/reverse-facts.test.js +78 -0
- package/dist/__tests__/reverse-facts.test.js.map +1 -0
- package/dist/__tests__/review.test.js +38 -38
- package/dist/__tests__/validate.test.js +65 -65
- package/dist/bin/dare.js +32 -3
- package/dist/bin/dare.js.map +1 -1
- package/dist/commands/blueprint.js +122 -122
- package/dist/commands/dag.d.ts.map +1 -1
- package/dist/commands/dag.js +43 -79
- package/dist/commands/dag.js.map +1 -1
- package/dist/commands/dna.d.ts +3 -0
- package/dist/commands/dna.d.ts.map +1 -0
- package/dist/commands/dna.js +69 -0
- package/dist/commands/dna.js.map +1 -0
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +101 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/new.d.ts +16 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +103 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/reverse.d.ts +3 -0
- package/dist/commands/reverse.d.ts.map +1 -0
- package/dist/commands/reverse.js +201 -0
- package/dist/commands/reverse.js.map +1 -0
- package/dist/commands/welcome.d.ts +14 -0
- package/dist/commands/welcome.d.ts.map +1 -0
- package/dist/commands/welcome.js +29 -0
- package/dist/commands/welcome.js.map +1 -0
- package/dist/skills/commands/add.d.ts +23 -0
- package/dist/skills/commands/add.d.ts.map +1 -0
- package/dist/skills/commands/add.js +206 -0
- package/dist/skills/commands/add.js.map +1 -0
- package/dist/skills/commands/info.d.ts +14 -0
- package/dist/skills/commands/info.d.ts.map +1 -0
- package/dist/skills/commands/info.js +99 -0
- package/dist/skills/commands/info.js.map +1 -0
- package/dist/skills/commands/list.d.ts +19 -0
- package/dist/skills/commands/list.d.ts.map +1 -0
- package/dist/skills/commands/list.js +163 -0
- package/dist/skills/commands/list.js.map +1 -0
- package/dist/skills/commands/publish.d.ts +56 -0
- package/dist/skills/commands/publish.d.ts.map +1 -0
- package/dist/skills/commands/publish.js +272 -0
- package/dist/skills/commands/publish.js.map +1 -0
- package/dist/skills/commands/remove.d.ts +19 -0
- package/dist/skills/commands/remove.d.ts.map +1 -0
- package/dist/skills/commands/remove.js +96 -0
- package/dist/skills/commands/remove.js.map +1 -0
- package/dist/skills/commands/update.d.ts +31 -0
- package/dist/skills/commands/update.d.ts.map +1 -0
- package/dist/skills/commands/update.js +132 -0
- package/dist/skills/commands/update.js.map +1 -0
- package/dist/skills/index.d.ts +22 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +33 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/manifest.d.ts +54 -0
- package/dist/skills/manifest.d.ts.map +1 -0
- package/dist/skills/manifest.js +162 -0
- package/dist/skills/manifest.js.map +1 -0
- package/dist/skills/registry-local.d.ts +67 -0
- package/dist/skills/registry-local.d.ts.map +1 -0
- package/dist/skills/registry-local.js +130 -0
- package/dist/skills/registry-local.js.map +1 -0
- package/dist/skills/registry-mock.json +109 -0
- package/dist/skills/registry-remote.d.ts +110 -0
- package/dist/skills/registry-remote.d.ts.map +1 -0
- package/dist/skills/registry-remote.js +246 -0
- package/dist/skills/registry-remote.js.map +1 -0
- package/dist/skills/registry.d.ts +49 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +94 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/tests/manifest.spec.d.ts +8 -0
- package/dist/skills/tests/manifest.spec.d.ts.map +1 -0
- package/dist/skills/tests/manifest.spec.js +176 -0
- package/dist/skills/tests/manifest.spec.js.map +1 -0
- package/dist/skills/tests/publish.spec.d.ts +12 -0
- package/dist/skills/tests/publish.spec.d.ts.map +1 -0
- package/dist/skills/tests/publish.spec.js +276 -0
- package/dist/skills/tests/publish.spec.js.map +1 -0
- package/dist/skills/tests/registry-local.spec.d.ts +8 -0
- package/dist/skills/tests/registry-local.spec.d.ts.map +1 -0
- package/dist/skills/tests/registry-local.spec.js +231 -0
- package/dist/skills/tests/registry-local.spec.js.map +1 -0
- package/dist/skills/tests/registry.spec.d.ts +7 -0
- package/dist/skills/tests/registry.spec.d.ts.map +1 -0
- package/dist/skills/tests/registry.spec.js +58 -0
- package/dist/skills/tests/registry.spec.js.map +1 -0
- package/dist/skills/tests/remote-registry.spec.d.ts +9 -0
- package/dist/skills/tests/remote-registry.spec.d.ts.map +1 -0
- package/dist/skills/tests/remote-registry.spec.js +357 -0
- package/dist/skills/tests/remote-registry.spec.js.map +1 -0
- package/dist/skills/tests/update.spec.d.ts +9 -0
- package/dist/skills/tests/update.spec.d.ts.map +1 -0
- package/dist/skills/tests/update.spec.js +166 -0
- package/dist/skills/tests/update.spec.js.map +1 -0
- package/dist/utils/banner.d.ts +28 -0
- package/dist/utils/banner.d.ts.map +1 -0
- package/dist/utils/banner.js +77 -0
- package/dist/utils/banner.js.map +1 -0
- package/dist/utils/banner.spec.d.ts +5 -0
- package/dist/utils/banner.spec.d.ts.map +1 -0
- package/dist/utils/banner.spec.js +253 -0
- package/dist/utils/banner.spec.js.map +1 -0
- package/dist/utils/confidence.d.ts +41 -0
- package/dist/utils/confidence.d.ts.map +1 -0
- package/dist/utils/confidence.js +101 -0
- package/dist/utils/confidence.js.map +1 -0
- package/dist/utils/datamodel.d.ts +41 -0
- package/dist/utils/datamodel.d.ts.map +1 -0
- package/dist/utils/datamodel.js +535 -0
- package/dist/utils/datamodel.js.map +1 -0
- package/dist/utils/dna-detector.d.ts +61 -0
- package/dist/utils/dna-detector.d.ts.map +1 -0
- package/dist/utils/dna-detector.js +354 -0
- package/dist/utils/dna-detector.js.map +1 -0
- package/dist/utils/dna-facts.d.ts +13 -0
- package/dist/utils/dna-facts.d.ts.map +1 -0
- package/dist/utils/dna-facts.js +109 -0
- package/dist/utils/dna-facts.js.map +1 -0
- package/dist/utils/excalidraw-renderer.d.ts +11 -71
- package/dist/utils/excalidraw-renderer.d.ts.map +1 -1
- package/dist/utils/excalidraw-renderer.js +29 -162
- package/dist/utils/excalidraw-renderer.js.map +1 -1
- package/dist/utils/graph-renderer.d.ts +115 -0
- package/dist/utils/graph-renderer.d.ts.map +1 -0
- package/dist/utils/graph-renderer.js +216 -0
- package/dist/utils/graph-renderer.js.map +1 -0
- package/dist/utils/migration.d.ts +64 -0
- package/dist/utils/migration.d.ts.map +1 -0
- package/dist/utils/migration.js +183 -0
- package/dist/utils/migration.js.map +1 -0
- package/dist/utils/module-detector.d.ts +46 -0
- package/dist/utils/module-detector.d.ts.map +1 -0
- package/dist/utils/module-detector.js +348 -0
- package/dist/utils/module-detector.js.map +1 -0
- package/dist/utils/project-generator.js +252 -252
- package/dist/utils/reverse-facts.d.ts +50 -0
- package/dist/utils/reverse-facts.d.ts.map +1 -0
- package/dist/utils/reverse-facts.js +291 -0
- package/dist/utils/reverse-facts.js.map +1 -0
- package/dist/utils/stack-bootstrap.js +371 -371
- package/package.json +8 -3
- package/templates/DARE-dag-example.yaml +280 -280
- package/templates/UPDATE-MANIFEST.json +48 -48
- 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 -0
- package/templates/ide/antigravity/.agents/skills/dare-dag-build/SKILL.md +154 -0
- package/templates/ide/antigravity/.agents/skills/dare-dag-run/SKILL.md +130 -0
- package/templates/ide/antigravity/.agents/skills/dare-dag-runner/SKILL.md +203 -203
- package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +63 -0
- package/templates/ide/antigravity/.agents/skills/dare-docker/SKILL.md +315 -0
- package/templates/ide/antigravity/.agents/skills/dare-frontend-design/SKILL.md +192 -0
- package/templates/ide/antigravity/.agents/skills/dare-laravel-api/SKILL.md +337 -0
- package/templates/ide/antigravity/.agents/skills/dare-layered-design/SKILL.md +166 -0
- package/templates/ide/antigravity/.agents/skills/dare-llm-integration/SKILL.md +217 -0
- package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +61 -0
- package/templates/ide/antigravity/.agents/skills/dare-quality-telemetry/SKILL.md +187 -0
- package/templates/ide/antigravity/.agents/skills/dare-realtime/SKILL.md +217 -0
- package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +114 -114
- package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +108 -0
- package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +111 -111
- package/templates/ide/antigravity/.agents/skills/dare-rust-leptos/SKILL.md +263 -0
- package/templates/ide/antigravity/.agents/skills/dare-rust-workspace/SKILL.md +275 -275
- package/templates/ide/antigravity/.agents/skills/dare-security/SKILL.md +274 -0
- package/templates/ide/antigravity/.agents/skills/dare-tasks/SKILL.md +265 -265
- package/templates/ide/antigravity/.agents/skills/dare-telemetry/SKILL.md +188 -0
- package/templates/ide/antigravity/.agents/skills/skill-fastapi-api/SKILL.md +343 -0
- package/templates/ide/antigravity/.agents/skills/skill-go-gin-api/SKILL.md +377 -0
- package/templates/ide/antigravity/.agents/skills/skill-mcp-server/SKILL.md +382 -0
- package/templates/ide/antigravity/.agents/skills/skill-nestjs-api/SKILL.md +326 -0
- package/templates/ide/antigravity/.agents/skills/skill-rails-api/SKILL.md +393 -0
- 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/claude/.claude/commands/dare-ax.md +131 -0
- package/templates/ide/claude/.claude/commands/dare-blueprint.md +134 -134
- package/templates/ide/claude/.claude/commands/dare-bugfix-design.md +119 -0
- 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 -0
- package/templates/ide/claude/.claude/commands/dare-dag-viz.md +197 -197
- package/templates/ide/claude/.claude/commands/dare-design.md +69 -69
- package/templates/ide/claude/.claude/commands/dare-dna.md +75 -0
- package/templates/ide/claude/.claude/commands/dare-docker.md +207 -0
- package/templates/ide/claude/.claude/commands/dare-execute.md +152 -152
- package/templates/ide/claude/.claude/commands/dare-feature-design.md +147 -0
- package/templates/ide/claude/.claude/commands/dare-frontend-design.md +149 -0
- package/templates/ide/claude/.claude/commands/dare-laravel-api.md +211 -0
- package/templates/ide/claude/.claude/commands/dare-layered-design.md +124 -0
- package/templates/ide/claude/.claude/commands/dare-llm-integration.md +148 -0
- package/templates/ide/claude/.claude/commands/dare-migrate.md +72 -0
- package/templates/ide/claude/.claude/commands/dare-quality-telemetry.md +166 -0
- package/templates/ide/claude/.claude/commands/dare-realtime.md +159 -0
- package/templates/ide/claude/.claude/commands/dare-refine.md +145 -145
- package/templates/ide/claude/.claude/commands/dare-reverse.md +139 -0
- 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-tasks.md +70 -70
- package/templates/ide/claude/.claude/commands/dare-telemetry.md +132 -0
- package/templates/ide/claude/.claude/commands/skill-fastapi-api.md +205 -0
- package/templates/ide/claude/.claude/commands/skill-go-gin-api.md +232 -0
- package/templates/ide/claude/.claude/commands/skill-mcp-server.md +228 -0
- package/templates/ide/claude/.claude/commands/skill-nestjs-api.md +210 -0
- package/templates/ide/claude/.claude/commands/skill-rails-api.md +236 -0
- 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/cursor/.cursor/commands/dag-viz.md +139 -0
- package/templates/ide/cursor/.cursor/commands/generate-blueprint.md +86 -86
- package/templates/ide/cursor/.cursor/commands/generate-design.md +35 -35
- package/templates/ide/cursor/.cursor/commands/generate-tasks.md +184 -184
- package/templates/ide/cursor/.cursor/commands/refine-task.md +107 -107
- package/templates/ide/cursor/.cursor/commands/review-task.md +91 -91
- package/templates/ide/cursor/.cursor/commands/run-dag.md +110 -110
- package/templates/ide/cursor/.cursor/rules/skill-ax.mdc +263 -0
- package/templates/ide/cursor/.cursor/rules/skill-dag-build.mdc +173 -0
- package/templates/ide/cursor/.cursor/rules/skill-dag-run.mdc +134 -0
- package/templates/ide/cursor/.cursor/rules/skill-dag-runner.mdc +221 -221
- package/templates/ide/cursor/.cursor/rules/skill-dna.mdc +63 -0
- package/templates/ide/cursor/.cursor/rules/skill-fastapi-api.mdc +352 -0
- package/templates/ide/cursor/.cursor/rules/skill-frontend-design.mdc +244 -0
- package/templates/ide/cursor/.cursor/rules/skill-go-gin-api.mdc +371 -0
- package/templates/ide/cursor/.cursor/rules/skill-layered-design.mdc +266 -0
- package/templates/ide/cursor/.cursor/rules/skill-llm-integration.mdc +295 -0
- package/templates/ide/cursor/.cursor/rules/skill-mcp-server.mdc +367 -0
- package/templates/ide/cursor/.cursor/rules/skill-migrate.mdc +58 -0
- package/templates/ide/cursor/.cursor/rules/skill-nestjs-api.mdc +346 -0
- package/templates/ide/cursor/.cursor/rules/skill-quality-telemetry.mdc +248 -0
- package/templates/ide/cursor/.cursor/rules/skill-rails-api.mdc +400 -0
- package/templates/ide/cursor/.cursor/rules/skill-realtime.mdc +262 -0
- package/templates/ide/cursor/.cursor/rules/skill-reverse.mdc +107 -0
- package/templates/ide/cursor/.cursor/rules/skill-rust-leptos.mdc +281 -0
- 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/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/shared/docker-compose.yml +41 -41
- package/dist/__tests__/dag-runner/adapters.test.d.ts +0 -2
- package/dist/__tests__/dag-runner/adapters.test.d.ts.map +0 -1
- package/dist/__tests__/dag-runner/adapters.test.js +0 -134
- package/dist/__tests__/dag-runner/adapters.test.js.map +0 -1
- package/dist/dag-runner/adapters/antigravity.d.ts +0 -6
- package/dist/dag-runner/adapters/antigravity.d.ts.map +0 -1
- package/dist/dag-runner/adapters/antigravity.js +0 -54
- package/dist/dag-runner/adapters/antigravity.js.map +0 -1
- package/dist/dag-runner/adapters/claude.d.ts +0 -6
- package/dist/dag-runner/adapters/claude.d.ts.map +0 -1
- package/dist/dag-runner/adapters/claude.js +0 -48
- package/dist/dag-runner/adapters/claude.js.map +0 -1
- package/dist/dag-runner/adapters/cursor.d.ts +0 -6
- package/dist/dag-runner/adapters/cursor.d.ts.map +0 -1
- package/dist/dag-runner/adapters/cursor.js +0 -58
- package/dist/dag-runner/adapters/cursor.js.map +0 -1
- package/dist/dag-runner/adapters/index.d.ts +0 -46
- package/dist/dag-runner/adapters/index.d.ts.map +0 -1
- package/dist/dag-runner/adapters/index.js +0 -55
- package/dist/dag-runner/adapters/index.js.map +0 -1
- package/dist/dag-runner/utils/timeout.d.ts +0 -27
- package/dist/dag-runner/utils/timeout.d.ts.map +0 -1
- package/dist/dag-runner/utils/timeout.js +0 -55
- package/dist/dag-runner/utils/timeout.js.map +0 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# /dare-telemetry
|
|
2
|
+
|
|
3
|
+
Rastreia tokens e modelos de IA usados em cada etapa do Método DARE. Atualiza `DARE/TELEMETRY.md` com modelo, tokens, tempo e tentativas (Ralph Loop) por comando.
|
|
4
|
+
|
|
5
|
+
## Como usar
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/dare-telemetry # gera relatório completo
|
|
9
|
+
/dare-telemetry append <comando> # adiciona entrada do último comando
|
|
10
|
+
/dare-telemetry report # gera resumo + custo estimado
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Diferença com `/dare-quality-telemetry`
|
|
14
|
+
|
|
15
|
+
- **`/dare-telemetry`** — uso de IA (modelos, tokens, tempo)
|
|
16
|
+
- **`/dare-quality-telemetry`** — métricas de qualidade das skills (M-01 a M-04)
|
|
17
|
+
|
|
18
|
+
## Modelos rastreáveis
|
|
19
|
+
|
|
20
|
+
| Modelo | Provider | Melhor para |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| Claude Opus 4.7 | Anthropic | Design, blueprint, security review |
|
|
23
|
+
| Claude Sonnet 4.5 | Anthropic | Execução de tasks |
|
|
24
|
+
| GPT-4 Turbo | OpenAI | Tarefas gerais |
|
|
25
|
+
| Gemini 2.0 Flash | Google | Tasks simples, batch |
|
|
26
|
+
| Ollama (local) | Self-hosted | Dados sensíveis |
|
|
27
|
+
|
|
28
|
+
## Estrutura `DARE/TELEMETRY.md`
|
|
29
|
+
|
|
30
|
+
```markdown
|
|
31
|
+
# Telemetria do Projeto
|
|
32
|
+
|
|
33
|
+
## Resumo Executivo
|
|
34
|
+
- Projeto: [Nome]
|
|
35
|
+
- Tokens totais: 147,909 in / 38,250 out
|
|
36
|
+
- Modelos: Opus 4.7, Sonnet 4.5
|
|
37
|
+
- Tempo total: ~31 min
|
|
38
|
+
- Custo estimado: $2.63
|
|
39
|
+
|
|
40
|
+
## Detalhamento por Etapa
|
|
41
|
+
|
|
42
|
+
### 1. Design
|
|
43
|
+
- Timestamp, Modelo, Tokens in/out, Tempo, Comando, Resultado
|
|
44
|
+
|
|
45
|
+
### 2. Blueprint
|
|
46
|
+
- (idem)
|
|
47
|
+
|
|
48
|
+
### 3. Tasks
|
|
49
|
+
- (idem) + número de tasks geradas
|
|
50
|
+
|
|
51
|
+
### 4. Execute Tasks
|
|
52
|
+
Por task:
|
|
53
|
+
- task-001 — Migration
|
|
54
|
+
- Modelo, Tokens, Tempo
|
|
55
|
+
- Tentativas Ralph Loop: 1
|
|
56
|
+
- Status: ✓
|
|
57
|
+
|
|
58
|
+
## Análise
|
|
59
|
+
|
|
60
|
+
| Etapa | Tokens in/out | % | Tempo |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
|
|
63
|
+
## Custo estimado
|
|
64
|
+
|
|
65
|
+
| Modelo | In | Out | $/M in | $/M out | Total |
|
|
66
|
+
|---|---|---|---|---|---|
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## O que fazer
|
|
70
|
+
|
|
71
|
+
### Passo 1: Após cada comando DARE
|
|
72
|
+
|
|
73
|
+
Adicione entrada com:
|
|
74
|
+
- Timestamp (`date -u +%FT%TZ`)
|
|
75
|
+
- Modelo do agente
|
|
76
|
+
- Tokens estimados in/out (pegar do output se disponível, perguntar se não)
|
|
77
|
+
- Tempo de execução
|
|
78
|
+
- Comando exato executado
|
|
79
|
+
- Resultado (arquivo gerado, número de tasks, etc.)
|
|
80
|
+
- Observações qualitativas
|
|
81
|
+
|
|
82
|
+
### Passo 2: Para `/dare-execute` de cada task
|
|
83
|
+
|
|
84
|
+
Rastreie especialmente:
|
|
85
|
+
- **Tentativas no Ralph Loop** — se >2, task precisa refinamento do spec
|
|
86
|
+
- Status (Sucesso/Falha)
|
|
87
|
+
|
|
88
|
+
### Passo 3: Recompilar análise
|
|
89
|
+
|
|
90
|
+
A cada 5 tasks ou release, atualize a seção Análise com totais.
|
|
91
|
+
|
|
92
|
+
### Passo 4: Custo
|
|
93
|
+
|
|
94
|
+
Use tabela de preços oficial (varia por modelo). Tokens in vs out têm preços diferentes — não some os dois.
|
|
95
|
+
|
|
96
|
+
## Otimizações recomendadas
|
|
97
|
+
|
|
98
|
+
1. **Modelo certo para tarefa**:
|
|
99
|
+
- Opus → design/blueprint/security
|
|
100
|
+
- Sonnet → execução
|
|
101
|
+
- Gemini Flash → tasks simples / batch
|
|
102
|
+
2. **Reutilizar contexto** — múltiplas tasks na mesma sessão economiza re-leitura
|
|
103
|
+
3. **Revisar Blueprint antes de Tasks** — evita re-geração
|
|
104
|
+
4. **Ralph Loop alto = spec ruim** — se task precisa >2 tentativas, refine BLUEPRINT.md
|
|
105
|
+
|
|
106
|
+
## Antipatterns
|
|
107
|
+
|
|
108
|
+
| AP | Antipattern | Por quê |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| AP-01 | Não rastrear telemetria | Sem dados para otimizar |
|
|
111
|
+
| AP-02 | Usar Opus para tasks triviais | Desperdício |
|
|
112
|
+
| AP-03 | Ignorar Ralph Loop alto | Specs ruins acumulam |
|
|
113
|
+
| AP-04 | Não auditar modelo (compliance) | Risco regulatório |
|
|
114
|
+
|
|
115
|
+
## Capturando tokens no Claude Code
|
|
116
|
+
|
|
117
|
+
- `/cost` exibe tokens da sessão atual
|
|
118
|
+
- Modelo aparece no rodapé do terminal
|
|
119
|
+
- Em CI, use `--debug` ou `--telemetry-output` se disponível
|
|
120
|
+
|
|
121
|
+
## Saída esperada
|
|
122
|
+
|
|
123
|
+
Markdown completo do `DARE/TELEMETRY.md` atualizado, com:
|
|
124
|
+
- Nova entrada do último comando
|
|
125
|
+
- Análise agregada refrescada
|
|
126
|
+
- Custo total recalculado
|
|
127
|
+
|
|
128
|
+
$ARGUMENTS
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
Skill MIT — parte do DARE Method.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# /skill-fastapi-api
|
|
2
|
+
|
|
3
|
+
Padrões DARE para APIs REST em Python + FastAPI + Pydantic v2 + SQLAlchemy 2.0 async. Routers, dependency injection, schemas Pydantic, OAuth2+JWT, slowapi rate limit, pytest+httpx, OpenAPI auto-gerado.
|
|
4
|
+
|
|
5
|
+
## Como usar
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/skill-fastapi-api # audita projeto FastAPI
|
|
9
|
+
/skill-fastapi-api scaffold users # gera router + service + repo + schemas
|
|
10
|
+
/skill-fastapi-api migrate-validation # extrai validação manual para Pydantic
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Stack canônica
|
|
14
|
+
|
|
15
|
+
- Python 3.11+ com type hints obrigatórios
|
|
16
|
+
- FastAPI 0.115+ (async/await)
|
|
17
|
+
- Pydantic v2
|
|
18
|
+
- SQLAlchemy 2.0 async + asyncpg
|
|
19
|
+
- alembic (migrations)
|
|
20
|
+
- passlib + argon2
|
|
21
|
+
- python-jose ou PyJWT
|
|
22
|
+
- slowapi (rate limit)
|
|
23
|
+
- pytest + pytest-asyncio + httpx
|
|
24
|
+
- ruff + mypy
|
|
25
|
+
|
|
26
|
+
## Estrutura
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
app/
|
|
30
|
+
├── main.py
|
|
31
|
+
├── core/{config.py, security.py}
|
|
32
|
+
├── api/{deps.py, v1/{users.py, auth.py}}
|
|
33
|
+
├── services/
|
|
34
|
+
├── repositories/
|
|
35
|
+
├── models/ ← SQLAlchemy ORM
|
|
36
|
+
├── schemas/ ← Pydantic DTOs
|
|
37
|
+
└── tests/
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Router (Handler)
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
@router.post("/users", response_model=UserOut, status_code=201)
|
|
44
|
+
async def create_user(
|
|
45
|
+
payload: UserCreate,
|
|
46
|
+
service: RegisterUser = Depends(),
|
|
47
|
+
_current: User = Depends(get_current_user),
|
|
48
|
+
):
|
|
49
|
+
try:
|
|
50
|
+
return await service.execute(payload)
|
|
51
|
+
except UserAlreadyExistsError:
|
|
52
|
+
raise HTTPException(409, "User already exists")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Schemas (Pydantic v2)
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
class UserCreate(BaseModel):
|
|
59
|
+
email: EmailStr
|
|
60
|
+
name: str = Field(min_length=1, max_length=255)
|
|
61
|
+
password: str = Field(min_length=12)
|
|
62
|
+
|
|
63
|
+
class UserOut(BaseModel):
|
|
64
|
+
id: int
|
|
65
|
+
email: EmailStr
|
|
66
|
+
name: str
|
|
67
|
+
created_at: datetime
|
|
68
|
+
model_config = {"from_attributes": True}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Service
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
class RegisterUser:
|
|
75
|
+
def __init__(self, repo: UsersRepository = Depends()):
|
|
76
|
+
self.repo = repo
|
|
77
|
+
|
|
78
|
+
async def execute(self, payload: UserCreate) -> User:
|
|
79
|
+
if await self.repo.exists_by_email(payload.email):
|
|
80
|
+
raise UserAlreadyExistsError()
|
|
81
|
+
return await self.repo.create(
|
|
82
|
+
email=payload.email,
|
|
83
|
+
name=payload.name,
|
|
84
|
+
password_hash=hash_password(payload.password),
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Repository (SQLAlchemy 2.0)
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
class UsersRepository:
|
|
92
|
+
def __init__(self, db: AsyncSession = Depends(get_db)):
|
|
93
|
+
self.db = db
|
|
94
|
+
|
|
95
|
+
async def exists_by_email(self, email: str) -> bool:
|
|
96
|
+
result = await self.db.execute(select(User.id).where(User.email == email))
|
|
97
|
+
return result.scalar_one_or_none() is not None
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Auth (OAuth2 + JWT)
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from passlib.hash import argon2
|
|
104
|
+
from jose import jwt
|
|
105
|
+
|
|
106
|
+
def hash_password(p: str) -> str: return argon2.hash(p)
|
|
107
|
+
def verify_password(p: str, h: str) -> bool: return argon2.verify(p, h)
|
|
108
|
+
|
|
109
|
+
def create_access_token(sub: str) -> str:
|
|
110
|
+
expire = datetime.utcnow() + timedelta(minutes=15)
|
|
111
|
+
return jwt.encode({"sub": sub, "exp": expire}, settings.JWT_SECRET, algorithm="HS256")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Rate limit (slowapi)
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from slowapi import Limiter
|
|
118
|
+
from slowapi.util import get_remote_address
|
|
119
|
+
|
|
120
|
+
limiter = Limiter(key_func=get_remote_address)
|
|
121
|
+
app.state.limiter = limiter
|
|
122
|
+
app.add_middleware(SlowAPIMiddleware)
|
|
123
|
+
|
|
124
|
+
@router.post("/login")
|
|
125
|
+
@limiter.limit("5/15minute")
|
|
126
|
+
async def login(request: Request, ...):
|
|
127
|
+
...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Settings
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
class Settings(BaseSettings):
|
|
134
|
+
DATABASE_URL: str
|
|
135
|
+
JWT_SECRET: str
|
|
136
|
+
model_config = SettingsConfigDict(env_file=".env")
|
|
137
|
+
|
|
138
|
+
settings = Settings()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Testes
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
@pytest.mark.asyncio
|
|
145
|
+
async def test_create_user(client: AsyncClient, admin_token: str):
|
|
146
|
+
res = await client.post("/v1/users",
|
|
147
|
+
json={"email": "jane@example.com", "name": "Jane", "password": "longsecret123"},
|
|
148
|
+
headers={"Authorization": f"Bearer {admin_token}"})
|
|
149
|
+
assert res.status_code == 201
|
|
150
|
+
|
|
151
|
+
@pytest.mark.asyncio
|
|
152
|
+
async def test_duplicate_email(client, admin_token):
|
|
153
|
+
await client.post("/v1/users", json={...}, headers={...})
|
|
154
|
+
res = await client.post("/v1/users", json={...}, headers={...})
|
|
155
|
+
assert res.status_code == 409
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Antipatterns
|
|
159
|
+
|
|
160
|
+
| AP | Antipattern | Correção |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| AP-01 | SQLAlchemy no router | Repository via Depends |
|
|
163
|
+
| AP-02 | Validação manual | Pydantic schema |
|
|
164
|
+
| AP-03 | Lógica no router | Service |
|
|
165
|
+
| AP-04 | `return user` sem response_model | `response_model=UserOut` |
|
|
166
|
+
| AP-05 | Secret hardcoded | pydantic-settings + .env |
|
|
167
|
+
| AP-06 | Login sem rate limit | `@limiter.limit("5/15minute")` |
|
|
168
|
+
| AP-07 | Senha em response | `response_model=UserOut` sem password |
|
|
169
|
+
| AP-08 | Sem `from_attributes=True` | adicionar no model_config |
|
|
170
|
+
|
|
171
|
+
## Segurança (com `/dare-security`)
|
|
172
|
+
|
|
173
|
+
- Argon2 via passlib
|
|
174
|
+
- JWT HS256 (`JWT_SECRET ≥ 32 bytes`) ou RS256
|
|
175
|
+
- Headers middleware (HSTS, X-Frame-Options)
|
|
176
|
+
- CORS específico
|
|
177
|
+
- Rate limit em login + APIs públicas
|
|
178
|
+
|
|
179
|
+
## CI
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
ruff check .
|
|
183
|
+
ruff format --check .
|
|
184
|
+
mypy app
|
|
185
|
+
pytest --cov=app --cov-fail-under=80
|
|
186
|
+
pip-audit
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## O que fazer
|
|
190
|
+
|
|
191
|
+
1. Audit:
|
|
192
|
+
```bash
|
|
193
|
+
grep -rn "db\.execute" app/api/
|
|
194
|
+
grep -rn "request\.json()" app/api/
|
|
195
|
+
```
|
|
196
|
+
2. `request.json()` → Pydantic schema
|
|
197
|
+
3. Lógica em router > 5 linhas → Service
|
|
198
|
+
4. SQLAlchemy em router → Repository
|
|
199
|
+
5. Configurar `slowapi`, settings via env, OpenAPI customizado
|
|
200
|
+
|
|
201
|
+
$ARGUMENTS
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
Skill MIT — parte do DARE Method.
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# /skill-go-gin-api
|
|
2
|
+
|
|
3
|
+
Padrões DARE para APIs REST em Go + Gin (ou stdlib net/http) + sqlc + PostgreSQL. Handlers, services, repositories, middleware, validador, JWT, rate limit, swag OpenAPI.
|
|
4
|
+
|
|
5
|
+
## Como usar
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/skill-go-gin-api # audita projeto Go
|
|
9
|
+
/skill-go-gin-api scaffold users # gera handler + service + repo + sqlc query
|
|
10
|
+
/skill-go-gin-api migrate-validation # extrai json.Unmarshal manual para binding tags
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Stack canônica
|
|
14
|
+
|
|
15
|
+
- Go 1.22+ (slog, errors.Is/As, generics)
|
|
16
|
+
- Gin (preferido) ou stdlib net/http
|
|
17
|
+
- sqlc (queries seguras geradas de SQL)
|
|
18
|
+
- pgx v5
|
|
19
|
+
- go-playground/validator (via Gin binding tags)
|
|
20
|
+
- golang-jwt/jwt v5
|
|
21
|
+
- swaggo/swag (OpenAPI)
|
|
22
|
+
- testify + httptest
|
|
23
|
+
- golangci-lint + govulncheck
|
|
24
|
+
|
|
25
|
+
## Estrutura
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
cmd/server/main.go
|
|
29
|
+
internal/
|
|
30
|
+
├── handlers/ ← Handler
|
|
31
|
+
├── services/ ← Service
|
|
32
|
+
├── repositories/ ← Repository (sqlc)
|
|
33
|
+
├── domain/ ← Models + erros sentinela
|
|
34
|
+
├── middleware/
|
|
35
|
+
└── config/
|
|
36
|
+
db/
|
|
37
|
+
├── migrations/ ← golang-migrate
|
|
38
|
+
└── queries/ ← .sql para sqlc
|
|
39
|
+
sqlc.yaml
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Handler
|
|
43
|
+
|
|
44
|
+
```go
|
|
45
|
+
// @Summary Create user
|
|
46
|
+
// @Router /users [post]
|
|
47
|
+
func (h *UserHandler) Create(c *gin.Context) {
|
|
48
|
+
var dto CreateUserDTO
|
|
49
|
+
if err := c.ShouldBindJSON(&dto); err != nil {
|
|
50
|
+
c.JSON(400, gin.H{"error": err.Error()})
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
user, err := h.register.Execute(c.Request.Context(), dto.ToService())
|
|
54
|
+
if err != nil {
|
|
55
|
+
if errors.Is(err, domain.ErrUserAlreadyExists) {
|
|
56
|
+
c.JSON(409, gin.H{"error": "USER_EXISTS"})
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
c.JSON(500, gin.H{"error": "INTERNAL"})
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
c.JSON(201, ToUserResponse(user))
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## DTO
|
|
67
|
+
|
|
68
|
+
```go
|
|
69
|
+
type CreateUserDTO struct {
|
|
70
|
+
Email string `json:"email" binding:"required,email"`
|
|
71
|
+
Name string `json:"name" binding:"required,min=1,max=255"`
|
|
72
|
+
Password string `json:"password" binding:"required,min=12"`
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Service
|
|
77
|
+
|
|
78
|
+
```go
|
|
79
|
+
type RegisterUser struct {
|
|
80
|
+
repo *repositories.UserRepository
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func (s *RegisterUser) Execute(ctx context.Context, in RegisterUserInput) (*domain.User, error) {
|
|
84
|
+
exists, err := s.repo.ExistsByEmail(ctx, in.Email)
|
|
85
|
+
if err != nil { return nil, err }
|
|
86
|
+
if exists { return nil, domain.ErrUserAlreadyExists }
|
|
87
|
+
return s.repo.Create(ctx, repositories.CreateUserParams{
|
|
88
|
+
Email: in.Email,
|
|
89
|
+
Name: in.Name,
|
|
90
|
+
PasswordHash: hashPassword(in.Password),
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Repository (sqlc)
|
|
96
|
+
|
|
97
|
+
```sql
|
|
98
|
+
-- db/queries/users.sql
|
|
99
|
+
-- name: ExistsUserByEmail :one
|
|
100
|
+
SELECT EXISTS(SELECT 1 FROM users WHERE email = $1);
|
|
101
|
+
|
|
102
|
+
-- name: CreateUser :one
|
|
103
|
+
INSERT INTO users (email, name, password_hash) VALUES ($1, $2, $3)
|
|
104
|
+
RETURNING id, email, name, created_at;
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```go
|
|
108
|
+
type UserRepository struct { q *sqlc.Queries }
|
|
109
|
+
func (r *UserRepository) ExistsByEmail(ctx context.Context, email string) (bool, error) {
|
|
110
|
+
return r.q.ExistsUserByEmail(ctx, email)
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Domain (erros sentinela)
|
|
115
|
+
|
|
116
|
+
```go
|
|
117
|
+
var (
|
|
118
|
+
ErrUserAlreadyExists = errors.New("user already exists")
|
|
119
|
+
ErrUserNotFound = errors.New("user not found")
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Middleware (JWT)
|
|
124
|
+
|
|
125
|
+
```go
|
|
126
|
+
func AuthRequired(secret []byte) gin.HandlerFunc {
|
|
127
|
+
return func(c *gin.Context) {
|
|
128
|
+
tokenStr := strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
|
|
129
|
+
token, err := jwt.Parse(tokenStr, func(t *jwt.Token) (any, error) { return secret, nil })
|
|
130
|
+
if err != nil || !token.Valid {
|
|
131
|
+
c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
c.Set("user_id", token.Claims.(jwt.MapClaims)["sub"])
|
|
135
|
+
c.Next()
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Rate limit
|
|
141
|
+
|
|
142
|
+
```go
|
|
143
|
+
import "github.com/gin-contrib/limit"
|
|
144
|
+
router.Use(limit.MaxAllowed(20))
|
|
145
|
+
login := router.Group("/auth").Use(myRateLimiter("5/15m"))
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## OpenAPI (swag)
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
swag init -g cmd/server/main.go -o docs
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```go
|
|
155
|
+
import _ "myapp/docs"
|
|
156
|
+
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
|
157
|
+
router.GET("/openapi.json", func(c *gin.Context) { c.File("docs/swagger.json") })
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Testes
|
|
161
|
+
|
|
162
|
+
```go
|
|
163
|
+
// Service unit
|
|
164
|
+
func TestCreateUser(t *testing.T) {
|
|
165
|
+
repo := &mocks.UserRepository{}
|
|
166
|
+
repo.On("ExistsByEmail", mock.Anything, "jane@example.com").Return(false, nil)
|
|
167
|
+
repo.On("Create", mock.Anything, mock.Anything).Return(&domain.User{ID: 1}, nil)
|
|
168
|
+
svc := services.NewRegisterUser(repo)
|
|
169
|
+
user, err := svc.Execute(ctx, ...)
|
|
170
|
+
require.NoError(t, err)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Handler via httptest
|
|
174
|
+
func TestUserHandlerCreate(t *testing.T) {
|
|
175
|
+
r := gin.New()
|
|
176
|
+
r.POST("/users", h.Create)
|
|
177
|
+
w := httptest.NewRecorder()
|
|
178
|
+
req := httptest.NewRequest("POST", "/users", strings.NewReader(`{...}`))
|
|
179
|
+
r.ServeHTTP(w, req)
|
|
180
|
+
assert.Equal(t, 201, w.Code)
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Antipatterns
|
|
185
|
+
|
|
186
|
+
| AP | Antipattern | Correção |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| AP-01 | `database/sql` no handler | Repository + sqlc |
|
|
189
|
+
| AP-02 | Validação manual | `binding:` tags |
|
|
190
|
+
| AP-03 | Lógica no handler | Service |
|
|
191
|
+
| AP-04 | Retornar `db.User` direto | DTO `UserResponse` |
|
|
192
|
+
| AP-05 | Secret hardcoded | `os.Getenv` ou viper |
|
|
193
|
+
| AP-06 | Sem rate limit em login | middleware |
|
|
194
|
+
| AP-07 | `panic` em handler | recovery middleware |
|
|
195
|
+
| AP-08 | Context não propagado | sempre `ctx context.Context` |
|
|
196
|
+
| AP-09 | SQL com `fmt.Sprintf` | sqlc / parametrizado |
|
|
197
|
+
| AP-10 | `errors.New` espalhado | sentinela em domain/errors.go |
|
|
198
|
+
|
|
199
|
+
## Segurança (com `/dare-security`)
|
|
200
|
+
|
|
201
|
+
- Argon2 (`golang.org/x/crypto/argon2`)
|
|
202
|
+
- JWT HS256 com secret ≥32 bytes, ou RS256
|
|
203
|
+
- `gin-contrib/cors` com origens específicas
|
|
204
|
+
- Rate limit em login
|
|
205
|
+
|
|
206
|
+
## CI
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
go vet ./...
|
|
210
|
+
golangci-lint run
|
|
211
|
+
go test ./... -race -cover
|
|
212
|
+
govulncheck ./...
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## O que fazer
|
|
216
|
+
|
|
217
|
+
1. Audit:
|
|
218
|
+
```bash
|
|
219
|
+
grep -rn "database/sql" internal/handlers/
|
|
220
|
+
grep -rn "json.Unmarshal" internal/handlers/
|
|
221
|
+
grep -rn "fmt.Sprintf.*SELECT" internal/
|
|
222
|
+
```
|
|
223
|
+
2. `json.Unmarshal` → struct com `binding:`
|
|
224
|
+
3. Lógica em handler > 5 linhas → Service
|
|
225
|
+
4. SQL em handler → sqlc query + Repository
|
|
226
|
+
5. Configurar middleware auth + rate limit + swag
|
|
227
|
+
|
|
228
|
+
$ARGUMENTS
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
Skill MIT — parte do DARE Method.
|