adi_dev_workflow 1.1.1 → 1.2.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.
Files changed (111) hide show
  1. package/bin/index.js +8 -8
  2. package/frameworks/agents/qa-staff-engineer.md +311 -311
  3. package/frameworks/agents/qa-validation-expert.md +458 -458
  4. package/frameworks/agents/tech-review-conformance.md +200 -200
  5. package/frameworks/commands/ministack/README.md +2 -0
  6. package/frameworks/commands/ministack/code-review.md +2 -0
  7. package/frameworks/commands/ministack/generate-intent.md +2 -0
  8. package/frameworks/commands/ministack/generate-scope.md +2 -0
  9. package/frameworks/commands/ministack/generate-tasks.md +2 -0
  10. package/frameworks/commands/ministack/generate-tech-direction.md +2 -0
  11. package/frameworks/commands/ministack/run-ministack-tasks.md +3 -0
  12. package/frameworks/commands/ministack/run-ministack-withlinear.md +2 -0
  13. package/frameworks/commands/ministack/status.md +2 -0
  14. package/frameworks/commands/sdd/code-review.md +2 -0
  15. package/frameworks/commands/sdd/generate-prd.md +2 -0
  16. package/frameworks/commands/sdd/generate-task-plan.md +2 -0
  17. package/frameworks/commands/sdd/generate-tech-direction.md +2 -0
  18. package/frameworks/commands/sdd/generate-tech-spec.md +2 -0
  19. package/frameworks/commands/sdd/generate-tests.md +2 -0
  20. package/frameworks/commands/sdd/run_tasks.md +3 -0
  21. package/frameworks/commands/sdd/run_tasks_withlinear.md +2 -0
  22. package/frameworks/commands/sdd/status.md +2 -0
  23. package/frameworks/commands/sdd/validate-sdd.md +2 -0
  24. package/frameworks/commands/sync-tasks-to-linear.md +2 -0
  25. package/frameworks/commands/taskcard/generate-taskcard.md +2 -0
  26. package/frameworks/commands/taskcard/run-taskcard.md +2 -0
  27. package/frameworks/config/ai-framework-config.yaml +112 -0
  28. package/frameworks/skills/ministack-intent-expert/SKILL.md +2 -0
  29. package/frameworks/skills/ministack-scope-expert/SKILL.md +4 -0
  30. package/frameworks/skills/sdd-prd-expert/SKILL.md +2 -0
  31. package/frameworks/skills/sdd-task-plan-expert/SKILL.md +2 -0
  32. package/frameworks/skills/taskcard-expert/SKILL.md +4 -0
  33. package/package.json +28 -28
  34. package/src/cli.js +121 -121
  35. package/src/installer.js +155 -136
  36. package/src/transformer.js +86 -86
  37. package/frameworks/skills/ministack-tasks-expert/SKILL.md +0 -204
  38. package/frameworks/skills/ministack-tasks-expert/templates/task_plan_template.md +0 -78
  39. package/frameworks/skills/ministack-tasks-expert/templates/task_template.md +0 -103
  40. package/frameworks/skills/ministack-tech-direction-expert/SKILL.md +0 -230
  41. package/frameworks/skills/ministack-tech-direction-expert/evals/evals.json +0 -1
  42. package/frameworks/skills/ministack-tech-direction-expert/templates/tech_direction-template.md +0 -17
  43. package/frameworks/skills/prompt-engineer-expert/SKILL.md +0 -232
  44. package/frameworks/skills/prompt-engineer-expert/templates/prompt_template.md +0 -139
  45. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/benchmark.json +0 -99
  46. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/benchmark.md +0 -64
  47. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/eval_metadata.json +0 -12
  48. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/grading.json +0 -32
  49. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/outputs/response.md +0 -134
  50. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/outputs/transcript.md +0 -68
  51. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/timing.json +0 -5
  52. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/grading.json +0 -32
  53. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/outputs/response.md +0 -525
  54. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/outputs/transcript.md +0 -30
  55. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/timing.json +0 -5
  56. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/eval_metadata.json +0 -12
  57. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/grading.json +0 -32
  58. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/outputs/response.md +0 -1126
  59. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/outputs/transcript.md +0 -131
  60. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/timing.json +0 -5
  61. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/grading.json +0 -32
  62. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/outputs/response.md +0 -452
  63. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/outputs/transcript.md +0 -78
  64. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/timing.json +0 -5
  65. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/eval_metadata.json +0 -12
  66. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/grading.json +0 -32
  67. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/outputs/response.md +0 -101
  68. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/outputs/transcript.md +0 -133
  69. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/timing.json +0 -5
  70. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/grading.json +0 -32
  71. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/outputs/response.md +0 -248
  72. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/outputs/transcript.md +0 -49
  73. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/timing.json +0 -5
  74. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/review.html +0 -1325
  75. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/benchmark.json +0 -94
  76. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/benchmark.md +0 -67
  77. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/eval_metadata.json +0 -12
  78. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/grading.json +0 -32
  79. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/outputs/response.md +0 -117
  80. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/outputs/transcript.md +0 -91
  81. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/timing.json +0 -1
  82. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/grading.json +0 -32
  83. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/outputs/response.md +0 -694
  84. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/outputs/transcript.md +0 -45
  85. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/timing.json +0 -1
  86. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/eval_metadata.json +0 -12
  87. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/grading.json +0 -32
  88. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/outputs/response.md +0 -1087
  89. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/outputs/transcript.md +0 -124
  90. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/timing.json +0 -1
  91. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/grading.json +0 -32
  92. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/outputs/response.md +0 -458
  93. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/outputs/transcript.md +0 -84
  94. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/timing.json +0 -1
  95. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/eval_metadata.json +0 -12
  96. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/grading.json +0 -32
  97. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/outputs/response.md +0 -70
  98. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/outputs/transcript.md +0 -148
  99. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/timing.json +0 -1
  100. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/grading.json +0 -32
  101. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/outputs/response.md +0 -249
  102. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/outputs/transcript.md +0 -80
  103. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/timing.json +0 -1
  104. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/review.html +0 -1325
  105. package/frameworks/skills/sdd-tech-direction-expert/SKILL.md +0 -235
  106. package/frameworks/skills/sdd-tech-direction-expert/evals/evals.json +0 -1
  107. package/frameworks/skills/sdd-tech-direction-expert/templates/tech_direction-template.md +0 -23
  108. package/frameworks/skills/sdd-tech-spec-expert/SKILL.md +0 -317
  109. package/frameworks/skills/sdd-tech-spec-expert/evals/evals.json +0 -199
  110. package/frameworks/skills/sdd-tech-spec-expert/templates/spec_tech_template.md +0 -290
  111. package/frameworks/skills/sdd-tech-spec-expert/templates/tech_direction-template.md +0 -23
@@ -1,694 +0,0 @@
1
- # TASK PLAN — Modulo de Usuario v1
2
-
3
- ## Informacoes Gerais
4
-
5
- | Campo | Valor |
6
- |-------|-------|
7
- | **Feature** | Modulo de Usuario — Vakinha Burger |
8
- | **SPEC_TECH** | `docs/feature-user/v1/spec_tech.md` |
9
- | **Data** | 2026-03-08 |
10
- | **Branch** | `user-feature` |
11
- | **Total de Tasks** | 12 |
12
-
13
- ---
14
-
15
- ## Estrategia de Implementacao
16
-
17
- A implementacao segue a ordem do fluxo de dependencias do projeto: **Config -> Database -> Identity -> Repository -> Service -> Handler -> Interceptor -> Testes**. Cada task e independente o suficiente para ser validada isoladamente, mas deve ser implementada na ordem sequencial definida.
18
-
19
- **Convencao de prioridade:**
20
- - **P0** — Bloqueante para tasks seguintes
21
- - **P1** — Necessario para completar a feature
22
- - **P2** — Qualidade e testes complementares
23
-
24
- ---
25
-
26
- ## Tasks
27
-
28
- ### TASK 01 — Configuracao: Adicionar `jwt.expiration_hours`
29
-
30
- **Prioridade:** P0
31
- **Tipo:** Modificar arquivos existentes
32
-
33
- **Arquivos a modificar:**
34
- - `configs/config.yaml` — adicionar `expiration_hours: 24` dentro do bloco `jwt`
35
- - `internal/infra/config/config.go` — adicionar campo `JWTExpirationHours int` na struct `Config` e leitura via `v.GetInt("jwt.expiration_hours")`
36
-
37
- **Detalhes:**
38
- 1. Em `configs/config.yaml`, adicionar `expiration_hours: 24` sob a chave `jwt`
39
- 2. Em `config.go`, adicionar o campo `JWTExpirationHours int` na struct `Config`
40
- 3. No construtor `NewConfig`, adicionar `v.GetInt("jwt.expiration_hours")` para popular o campo
41
-
42
- **Criterio de conclusao:**
43
- - `Config` carrega `JWTExpirationHours` corretamente a partir do YAML
44
- - Valor padrao: 24
45
- - `make build` compila sem erro
46
-
47
- **Dependencias:** Nenhuma
48
-
49
- ---
50
-
51
- ### TASK 02 — Migration: Adicionar coluna `endereco` na tabela `usuarios`
52
-
53
- **Prioridade:** P0
54
- **Tipo:** Criar arquivo novo (se nao existir) ou validar existente
55
-
56
- **Arquivo:**
57
- - `internal/db/migrations/002_add_endereco_usuarios.sql`
58
-
59
- **Detalhes:**
60
- 1. Verificar se o arquivo ja existe (nota: conforme listagem do codebase, o arquivo `002_add_endereco_usuarios.sql` ja existe)
61
- 2. Validar que o conteudo corresponde ao especificado na SPEC_TECH secao 9.1:
62
- ```sql
63
- ALTER TABLE usuarios ADD COLUMN endereco TEXT NOT NULL DEFAULT '';
64
- ```
65
- 3. Se ja existir com conteudo correto, esta task esta concluida
66
-
67
- **Criterio de conclusao:**
68
- - Migration executa sem erro na inicializacao
69
- - Coluna `endereco` presente na tabela `usuarios` com default vazio
70
-
71
- **Dependencias:** Nenhuma
72
-
73
- ---
74
-
75
- ### TASK 03 — Proto: Atualizar `user.proto` com novos endpoints
76
-
77
- **Prioridade:** P0
78
- **Tipo:** Modificar arquivo existente
79
-
80
- **Arquivo a modificar:**
81
- - `api/proto/v1/user.proto` — substituicao total conforme SPEC_TECH secao 8.1
82
-
83
- **Detalhes:**
84
- 1. Atualizar mensagem `User` para incluir campo `address` (field 4)
85
- 2. Atualizar `CreateUserRequest` para incluir campo `address` (field 4)
86
- 3. Adicionar mensagens: `LoginRequest`, `LoginResponse`, `GetUserLoggedRequest`, `GetUserLoggedResponse`, `UpdateUserRequest` (com campos `optional`), `UpdateUserResponse`
87
- 4. Atualizar servico `UserService` com 4 RPCs: `CreateUser`, `Login`, `GetUserLogged`, `UpdateUser`
88
- 5. Remover `GetUser` (se existir) — substituido por `GetUserLogged`
89
- 6. Executar `make generate` para regenerar codigo
90
-
91
- **Criterio de conclusao:**
92
- - `make generate` executa sem erros
93
- - Codigo gerado em `gen/proto/v1/` reflete as novas mensagens e servico
94
- - `make lint` passa sem erros nos protobufs
95
-
96
- **Dependencias:** Nenhuma
97
-
98
- ---
99
-
100
- ### TASK 04 — SQLC: Atualizar queries de usuario
101
-
102
- **Prioridade:** P0
103
- **Tipo:** Modificar arquivo existente
104
-
105
- **Arquivo a modificar:**
106
- - `internal/db/queries/user.sql` — substituicao total conforme SPEC_TECH secao 9.2
107
-
108
- **Detalhes:**
109
- 1. Atualizar `CreateUser` para incluir `endereco`, `data_criacao`, `data_atualizacao` nos campos de INSERT
110
- 2. Manter `GetUserByID :one` — busca por ID
111
- 3. Adicionar `GetUserByEmail :one` — busca por email
112
- 4. Adicionar `UpdateUser :one` — update de `nome`, `email`, `senha_hash`, `endereco`, `data_atualizacao` com `RETURNING *`
113
- 5. Executar `make generate` para regenerar codigo SQLC
114
-
115
- **Criterio de conclusao:**
116
- - `make generate` executa sem erros
117
- - Codigo gerado em `internal/db/sqlc/` reflete as novas queries
118
- - Struct `CreateUserParams` inclui campo `Endereco`
119
-
120
- **Dependencias:** TASK 02 (migration deve existir para SQLC reconhecer a coluna)
121
-
122
- ---
123
-
124
- ### TASK 05 — Identity: Criar pacote `internal/pkg/identity`
125
-
126
- **Prioridade:** P0
127
- **Tipo:** Criar arquivo novo
128
-
129
- **Arquivo a criar:**
130
- - `internal/pkg/identity/identity.go`
131
-
132
- **Detalhes:**
133
- 1. Definir tipo `Claims` com `UserID string`, `Email string` e `jwt.RegisteredClaims`
134
- 2. Implementar `GenerateToken(userID, email, secret string, duration time.Duration) (string, time.Time, error)`
135
- - Assinatura HS256
136
- - Preencher `RegisteredClaims{ExpiresAt, IssuedAt}`
137
- 3. Implementar `ParseToken(tokenString, secret string) (*Claims, error)`
138
- - Validar algoritmo HS256 (rejeitar outros metodos de assinatura)
139
- 4. Implementar `WithUserID(ctx context.Context, userID string) context.Context`
140
- - Usar tipo `contextKey` unexportado: `type contextKey string`
141
- - Constante unexportada: `const userIDKey contextKey = "user_id"`
142
- 5. Implementar `UserIDFromContext(ctx context.Context) (string, bool)`
143
- 6. Adicionar dependencia `github.com/golang-jwt/jwt/v5` ao `go.mod`
144
-
145
- **Criterio de conclusao:**
146
- - Todas as 4 funcoes publicas implementadas conforme assinaturas da SPEC_TECH secao 10.1
147
- - `contextKey` e `userIDKey` sao unexportados
148
- - `CGO_ENABLED=1 go build ./internal/pkg/identity/...` compila sem erro
149
-
150
- **Dependencias:** Nenhuma
151
-
152
- ---
153
-
154
- ### TASK 06 — Repository: Estender `UserRepository`
155
-
156
- **Prioridade:** P0
157
- **Tipo:** Modificar arquivo existente
158
-
159
- **Arquivo a modificar:**
160
- - `internal/repository/user_repository.go`
161
-
162
- **Detalhes:**
163
- 1. Adicionar campo `Address string` ao struct `User`
164
- 2. Atualizar mapeamento no metodo `Create()`:
165
- - Incluir `Endereco` nos params SQLC
166
- - Incluir `Address: sqlcUser.Endereco` no mapeamento de retorno
167
- 3. Atualizar mapeamento no metodo `GetByID()`:
168
- - Incluir `Address: sqlcUser.Endereco` no mapeamento de retorno
169
- 4. Adicionar metodo `GetByEmail(ctx context.Context, email string) (*User, error)` a interface e implementacao:
170
- - Chamar `r.queries.GetUserByEmail(ctx, email)`
171
- - Mapear resultado SQLC -> dominio (incluindo `Address`)
172
- - Erro: `"falha ao buscar usuario por email: %w"`
173
- 5. Adicionar metodo `Update(ctx context.Context, user *User) (*User, error)` a interface e implementacao:
174
- - Mapear `*User` -> `sqlc.UpdateUserParams` (Nome, Email, SenhaHash, Endereco, DataAtualizacao, ID)
175
- - Mapear resultado SQLC -> dominio
176
- - Erro: `"falha ao atualizar usuario: %w"`
177
- 6. Mensagens de erro em portugues
178
-
179
- **Criterio de conclusao:**
180
- - Interface `UserRepository` tem 4 metodos: `Create`, `GetByID`, `GetByEmail`, `Update`
181
- - Todos os mapeamentos incluem `Address`/`Endereco`
182
- - `CGO_ENABLED=1 go build ./internal/repository/...` compila sem erro
183
-
184
- **Dependencias:** TASK 04 (queries SQLC geradas)
185
-
186
- ---
187
-
188
- ### TASK 07 — Service: Estender `UserService`
189
-
190
- **Prioridade:** P0
191
- **Tipo:** Modificar arquivo existente
192
-
193
- **Arquivo a modificar:**
194
- - `internal/service/user_service.go`
195
-
196
- **Detalhes:**
197
-
198
- **7.1 — Definir variaveis de erro (10 erros, mensagens em portugues):**
199
- ```go
200
- var (
201
- ErrInvalidName = errors.New("nome nao pode estar vazio")
202
- ErrInvalidEmail = errors.New("email invalido")
203
- ErrEmailAlreadyExists = errors.New("email ja cadastrado")
204
- ErrPasswordTooShort = errors.New("senha deve ter no minimo 8 caracteres")
205
- ErrAddressRequired = errors.New("endereco nao pode estar vazio")
206
- ErrInvalidCredentials = errors.New("credenciais invalidas")
207
- ErrUserNotFound = errors.New("usuario nao encontrado")
208
- ErrNoFieldsToUpdate = errors.New("ao menos um campo deve ser fornecido para atualizacao")
209
- ErrCurrentPasswordRequired = errors.New("senha atual e obrigatoria quando nova senha e informada")
210
- ErrCurrentPasswordWrong = errors.New("senha atual incorreta")
211
- )
212
- ```
213
-
214
- **7.2 — Definir novos tipos:**
215
- - Atualizar `CreateUserInput` — adicionar `Address string`
216
- - Criar `LoginResult{Token string, ExpiresAt time.Time, User *repository.User}`
217
- - Criar `UpdateUserInput{Name, Email, Address, NewPassword, CurrentPassword *string}`
218
-
219
- **7.3 — Atualizar construtor:**
220
- - `NewUserService(repo repository.UserRepository, cfg *config.Config, logger *zap.Logger) UserService`
221
- - Armazenar `cfg` e `logger` na struct `userService`
222
-
223
- **7.4 — Atualizar interface `UserService` com 4 metodos:**
224
- - `CreateUser(ctx context.Context, input CreateUserInput) (*repository.User, error)`
225
- - `Login(ctx context.Context, email, password string) (*LoginResult, error)`
226
- - `GetUserLogged(ctx context.Context, userID string) (*repository.User, error)`
227
- - `UpdateUser(ctx context.Context, userID string, input UpdateUserInput) (*repository.User, error)`
228
-
229
- **7.5 — Atualizar `CreateUser`:**
230
- - Validacoes em ordem: name vazio -> email formato (`net/mail.ParseAddress`) -> password len < 8 -> address vazio
231
- - Verificar email unico: `repo.GetByEmail(email)` — se encontrado: `ErrEmailAlreadyExists`
232
- - Hash: `bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)`
233
- - Persistir via `repo.Create` incluindo `Address`
234
- - Log Info: `"usuario criado com sucesso"` com `zap.String("user_id", ...)` e `zap.String("email", ...)`
235
-
236
- **7.6 — Implementar `Login`:**
237
- - `repo.GetByEmail(email)` — se nao existe: `ErrInvalidCredentials` + Log Warn
238
- - `bcrypt.CompareHashAndPassword(hash, password)` — se falha: `ErrInvalidCredentials` + Log Warn
239
- - `identity.GenerateToken(userID, email, cfg.JWTSecret, time.Duration(cfg.JWTExpirationHours)*time.Hour)`
240
- - Retornar `LoginResult` com `User.PasswordHash = ""`
241
- - Log Info: `"login bem-sucedido"`
242
-
243
- **7.7 — Implementar `GetUserLogged`:**
244
- - `repo.GetByID(userID)` — se erro: `ErrUserNotFound`
245
- - Limpar `user.PasswordHash = ""` antes de retornar
246
-
247
- **7.8 — Implementar `UpdateUser`:**
248
- - Validar ao menos 1 campo nao-nil -> `ErrNoFieldsToUpdate`
249
- - `repo.GetByID(userID)` -> obter usuario atual
250
- - Se `input.Email != nil`: `net/mail.ParseAddress` -> `ErrInvalidEmail`; `repo.GetByEmail` -> se existe e ID diferente: `ErrEmailAlreadyExists`
251
- - Se `input.NewPassword != nil`:
252
- - `len(*input.NewPassword) < 8` -> `ErrPasswordTooShort`
253
- - `input.CurrentPassword == nil` -> `ErrCurrentPasswordRequired`
254
- - `bcrypt.CompareHashAndPassword(currentUser.PasswordHash, *CurrentPassword)` -> `ErrCurrentPasswordWrong`
255
- - `bcrypt.GenerateFromPassword(*NewPassword, DefaultCost)`
256
- - Aplicar campos nao-nil sobre `currentUser`
257
- - `repo.Update(updatedUser)`
258
- - Limpar `PasswordHash` no retorno
259
- - Log Info com campos atualizados (nomes dos campos, nao valores)
260
-
261
- **Criterio de conclusao:**
262
- - Interface `UserService` com 4 metodos
263
- - 10 variaveis de erro definidas
264
- - Logging em portugues em todos os caminhos relevantes
265
- - Nenhuma senha, hash ou token logado
266
- - `CGO_ENABLED=1 go build ./internal/service/...` compila sem erro
267
-
268
- **Dependencias:** TASK 05 (identity), TASK 06 (repository), TASK 01 (config)
269
-
270
- ---
271
-
272
- ### TASK 08 — Handler: Estender `UserHandler` gRPC
273
-
274
- **Prioridade:** P0
275
- **Tipo:** Modificar arquivo existente
276
-
277
- **Arquivo a modificar:**
278
- - `internal/handler/grpc/user_handler.go`
279
-
280
- **Detalhes:**
281
-
282
- **8.1 — Atualizar `CreateUser`:**
283
- - Incluir `Address` no mapeamento request -> `CreateUserInput`
284
- - Resposta: `CreateUserResponse{id, name, email, created_at}` — sem `PasswordHash`
285
-
286
- **8.2 — Implementar `Login`:**
287
- - Mapear `LoginRequest{email, password}` para chamada `service.Login`
288
- - Resposta: `LoginResponse{token, expires_at, id, name, email}`
289
- - Formatar `expires_at` como string (RFC3339 ou similar)
290
-
291
- **8.3 — Implementar `GetUserLogged`:**
292
- - Extrair `userID` via `identity.UserIDFromContext(ctx)` — se ausente: `codes.Unauthenticated`
293
- - Chamar `service.GetUserLogged(ctx, userID)`
294
- - Resposta: `GetUserLoggedResponse{User{id, name, email, address, created_at, updated_at}}`
295
-
296
- **8.4 — Implementar `UpdateUser`:**
297
- - Extrair `userID` via `identity.UserIDFromContext(ctx)` — se ausente: `codes.Unauthenticated`
298
- - Construir `UpdateUserInput` com ponteiros (campos `optional` do proto -> `*string`)
299
- - Chamar `service.UpdateUser(ctx, userID, input)`
300
- - Resposta: `UpdateUserResponse{User{...}}`
301
-
302
- **8.5 — Remover `GetUser` (se existir) — substituido por `GetUserLogged`**
303
-
304
- **8.6 — Criar funcao auxiliar `domainUserToProto(user *repository.User) *pb.User`**
305
-
306
- **8.7 — Atualizar `mapServiceError` conforme SPEC_TECH secao 11.2:**
307
-
308
- | Erro de Service | gRPC Code |
309
- |----------------|-----------|
310
- | `ErrInvalidName`, `ErrInvalidEmail`, `ErrPasswordTooShort`, `ErrAddressRequired`, `ErrNoFieldsToUpdate`, `ErrCurrentPasswordRequired`, `ErrCurrentPasswordWrong` | `codes.InvalidArgument` |
311
- | `ErrEmailAlreadyExists` | `codes.AlreadyExists` |
312
- | `ErrInvalidCredentials` | `codes.Unauthenticated` |
313
- | `ErrUserNotFound` | `codes.NotFound` |
314
- | Demais erros | `codes.Internal` com mensagem `"erro interno do servidor"` |
315
-
316
- **Criterio de conclusao:**
317
- - Handler implementa os 4 RPCs do `UserServiceServer`
318
- - Mapeamento de erros completo
319
- - `PasswordHash` nunca exposto em nenhuma response
320
- - `user_id` extraido do contexto (nao de parametros) nos endpoints protegidos
321
- - `CGO_ENABLED=1 go build ./internal/handler/grpc/...` compila sem erro
322
-
323
- **Dependencias:** TASK 07 (service), TASK 05 (identity), TASK 03 (proto gerado)
324
-
325
- ---
326
-
327
- ### TASK 09 — Interceptor: Atualizar `AuthInterceptor`
328
-
329
- **Prioridade:** P0
330
- **Tipo:** Modificar arquivo existente
331
-
332
- **Arquivo a modificar:**
333
- - `internal/infra/grpc/interceptors/auth.go`
334
-
335
- **Detalhes:**
336
- 1. Adicionar `/proto.v1.UserService/Login` em `skipMethods` (junto com `CreateUser` que ja deve estar la)
337
- 2. Substituir parse manual do token por `identity.ParseToken(tokenString, cfg.JWTSecret)`
338
- 3. Apos validacao bem-sucedida: `ctx = identity.WithUserID(ctx, claims.UserID)`
339
- 4. Passar `ctx` atualizado ao `handler(ctx, req)`
340
-
341
- **Criterio de conclusao:**
342
- - `Login` e `CreateUser` sao rotas publicas (sem verificacao de token)
343
- - `GetUserLogged` e `UpdateUser` exigem token valido
344
- - `user_id` do JWT e injetado no contexto via `identity.WithUserID`
345
- - Token invalido/ausente retorna `codes.Unauthenticated`
346
- - `CGO_ENABLED=1 go build ./internal/infra/grpc/interceptors/...` compila sem erro
347
-
348
- **Dependencias:** TASK 05 (identity)
349
-
350
- ---
351
-
352
- ### TASK 10 — Testes Unitarios: Identity + Service + Handler + Interceptor
353
-
354
- **Prioridade:** P1
355
- **Tipo:** Criar + Modificar arquivos
356
-
357
- **Arquivos a criar:**
358
- - `internal/pkg/identity/identity_test.go`
359
- - `internal/infra/grpc/interceptors/auth_test.go`
360
-
361
- **Arquivos a modificar:**
362
- - `internal/service/user_service_test.go`
363
- - `internal/handler/grpc/user_handler_test.go`
364
-
365
- **Detalhes:**
366
-
367
- **10.1 — Identity tests (`identity_test.go`, 8 cenarios):**
368
-
369
- | Teste | Cenario |
370
- |-------|---------|
371
- | `TestGenerateToken_Success` | Token nao vazio, `expiresAt` no futuro |
372
- | `TestGenerateToken_TokenIsParseable` | `ParseToken(token, secret)` sem erro |
373
- | `TestGenerateToken_ClaimsContainCorrectData` | `claims.UserID` e `claims.Email` corretos |
374
- | `TestParseToken_WrongSecret` | Erro retornado |
375
- | `TestParseToken_ExpiredToken` | Erro retornado |
376
- | `TestParseToken_MalformedToken` | Erro retornado |
377
- | `TestContextRoundtrip_UserID` | `WithUserID` + `UserIDFromContext` retorna `"uuid-ctx", true` |
378
- | `TestUserIDFromContext_Missing` | Retorna `"", false` |
379
-
380
- **10.2 — Service tests — CreateUser (atualizar existentes + novos, ~9 cenarios):**
381
-
382
- | Teste | Cenario |
383
- |-------|---------|
384
- | `TestCreateUser_Success` | Atualizar para incluir `Address` |
385
- | `TestCreateUser_PasswordIsHashed` | Existente — manter |
386
- | `TestCreateUser_GeneratesValidUUID` | Existente — manter |
387
- | `TestCreateUser_ErrorEmptyName` | Atualizar se necessario |
388
- | `TestCreateUser_ErrorInvalidEmailFormat` | **Novo** — email invalido |
389
- | `TestCreateUser_ErrorPasswordTooShort_7Chars` | **Novo** — boundary 7 chars |
390
- | `TestCreateUser_PasswordExactly8Chars` | **Novo** — boundary 8 chars OK |
391
- | `TestCreateUser_ErrorEmptyAddress` | **Novo** — address vazio |
392
- | `TestCreateUser_ErrorRepositoryFailure` | Existente — manter |
393
-
394
- **10.3 — Service tests — Login (6 cenarios):**
395
-
396
- | Teste | Cenario |
397
- |-------|---------|
398
- | `TestLogin_Success` | `*LoginResult` com `Token` nao vazio, `ExpiresAt` no futuro |
399
- | `TestLogin_ResultDoesNotExposePasswordHash` | `result.User.PasswordHash == ""` |
400
- | `TestLogin_TokenExpiresAtRespectsConfig` | `result.ExpiresAt` ~= `now + JWTExpirationHours` (tolerancia 5s) |
401
- | `TestLogin_EmailNotFound_GenericError` | `ErrInvalidCredentials` |
402
- | `TestLogin_WrongPassword_GenericError` | `ErrInvalidCredentials` |
403
- | `TestLogin_ErrorRepositoryFailure` | Erro interno propagado |
404
-
405
- **10.4 — Service tests — GetUserLogged (3 cenarios):**
406
-
407
- | Teste | Cenario |
408
- |-------|---------|
409
- | `TestGetUserLogged_Success` | `*repository.User` com `PasswordHash:""` |
410
- | `TestGetUserLogged_UserNotFound` | `ErrUserNotFound` |
411
- | `TestGetUserLogged_RepositoryError` | Erro interno propagado |
412
-
413
- **10.5 — Service tests — UpdateUser (13 cenarios):**
414
-
415
- | Teste | Cenario |
416
- |-------|---------|
417
- | `TestUpdateUser_NameOnly` | Apenas nome atualizado |
418
- | `TestUpdateUser_EmailOnly` | Email atualizado |
419
- | `TestUpdateUser_AddressOnly` | Endereco atualizado |
420
- | `TestUpdateUser_PasswordChange_Success` | Novo hash diferente do anterior |
421
- | `TestUpdateUser_MultipleFields` | Varios campos aplicados |
422
- | `TestUpdateUser_NoFieldsToUpdate` | `ErrNoFieldsToUpdate` |
423
- | `TestUpdateUser_InvalidEmailFormat` | `ErrInvalidEmail` |
424
- | `TestUpdateUser_EmailAlreadyExists` | `ErrEmailAlreadyExists` |
425
- | `TestUpdateUser_CurrentPasswordMissing` | `ErrCurrentPasswordRequired` |
426
- | `TestUpdateUser_WrongCurrentPassword` | `ErrCurrentPasswordWrong` |
427
- | `TestUpdateUser_NewPasswordTooShort` | `ErrPasswordTooShort` |
428
- | `TestUpdateUser_UserNotFound` | `ErrUserNotFound` |
429
- | `TestUpdateUser_RepositoryFailure` | Erro interno propagado |
430
-
431
- **10.6 — Handler tests — CreateUser (8 cenarios):**
432
-
433
- | Teste | Cenario |
434
- |-------|---------|
435
- | `TestUserHandler_CreateUser_Success` | Response com `id`, `name`, `email`, `created_at` |
436
- | `TestUserHandler_CreateUser_ResponseDoesNotExposePasswordHash` | Sem hash na response |
437
- | `TestUserHandler_CreateUser_EmptyName` | `codes.InvalidArgument` |
438
- | `TestUserHandler_CreateUser_EmptyEmail` | `codes.InvalidArgument` |
439
- | `TestUserHandler_CreateUser_ShortPassword` | `codes.InvalidArgument` |
440
- | `TestUserHandler_CreateUser_EmptyAddress` | `codes.InvalidArgument` |
441
- | `TestUserHandler_CreateUser_DuplicateEmail` | `codes.AlreadyExists` |
442
- | `TestUserHandler_CreateUser_InternalError` | `codes.Internal` |
443
-
444
- **10.7 — Handler tests — Login (3 cenarios):**
445
-
446
- | Teste | Cenario |
447
- |-------|---------|
448
- | `TestUserHandler_Login_Success` | Response com `token`, `expires_at`, `id`, `name`, `email` |
449
- | `TestUserHandler_Login_InvalidCredentials` | `codes.Unauthenticated` |
450
- | `TestUserHandler_Login_InternalError` | `codes.Internal` |
451
-
452
- **10.8 — Handler tests — GetUserLogged (3 cenarios):**
453
-
454
- | Teste | Cenario |
455
- |-------|---------|
456
- | `TestUserHandler_GetUserLogged_Success` | Response com dados completos via JWT |
457
- | `TestUserHandler_GetUserLogged_MissingUserID` | `codes.Unauthenticated` |
458
- | `TestUserHandler_GetUserLogged_NotFound` | `codes.NotFound` |
459
-
460
- **10.9 — Handler tests — UpdateUser (10 cenarios):**
461
-
462
- | Teste | Cenario |
463
- |-------|---------|
464
- | `TestUserHandler_UpdateUser_NameOnly` | Response com `name` atualizado |
465
- | `TestUserHandler_UpdateUser_EmailOnly` | Response com email atualizado |
466
- | `TestUserHandler_UpdateUser_PasswordChange` | Response com sucesso |
467
- | `TestUserHandler_UpdateUser_MultipleFields` | Todos os campos atualizados |
468
- | `TestUserHandler_UpdateUser_NoFields` | `codes.InvalidArgument` |
469
- | `TestUserHandler_UpdateUser_EmailAlreadyExists` | `codes.AlreadyExists` |
470
- | `TestUserHandler_UpdateUser_CurrentPasswordMissing` | `codes.InvalidArgument` |
471
- | `TestUserHandler_UpdateUser_WrongCurrentPassword` | `codes.InvalidArgument` |
472
- | `TestUserHandler_UpdateUser_NewPasswordTooShort` | `codes.InvalidArgument` |
473
- | `TestUserHandler_UpdateUser_UserNotFound` | `codes.NotFound` |
474
-
475
- **10.10 — Interceptor tests (`auth_test.go`, 3 cenarios):**
476
-
477
- | Teste | Cenario |
478
- |-------|---------|
479
- | `TestAuthInterceptor_ValidToken_InjectsUserID` | Handler recebe ctx com `identity.UserIDFromContext(ctx) == "uuid-123"` |
480
- | `TestAuthInterceptor_SkipsLogin` | `/Login` e `/CreateUser` nao exigem token (table-driven) |
481
- | `TestAuthInterceptor_ProtectedMethodsRequireAuth` | `GetUserLogged` e `UpdateUser` sem token retornam `Unauthenticated` (table-driven) |
482
-
483
- **10.11 — Atualizar mocks:**
484
- - `MockUserService` — adicionar `Login`, `GetUserLogged`, `UpdateUser`
485
- - `MockUserRepository` — adicionar `GetByEmail`, `Update`
486
-
487
- **Criterio de conclusao:**
488
- - `CGO_ENABLED=1 go test ./internal/pkg/identity/... -v` — todos passam
489
- - `CGO_ENABLED=1 go test ./internal/service/... -v` — todos passam
490
- - `CGO_ENABLED=1 go test ./internal/handler/grpc/... -v` — todos passam
491
- - `CGO_ENABLED=1 go test ./internal/infra/grpc/interceptors/... -v` — todos passam
492
-
493
- **Dependencias:** TASK 05-09
494
-
495
- ---
496
-
497
- ### TASK 11 — Testes de Integracao: Repository + Migration
498
-
499
- **Prioridade:** P1
500
- **Tipo:** Criar arquivo novo
501
-
502
- **Arquivo a criar:**
503
- - `internal/repository/user_repository_integration_test.go`
504
-
505
- **Detalhes:**
506
-
507
- **11.1 — Setup:**
508
- ```go
509
- func setupTestDB(t *testing.T) *sql.DB {
510
- t.Helper()
511
- db, err := database.NewDatabase(&config.Config{DatabasePath: filepath.Join(t.TempDir(), "test.db")})
512
- require.NoError(t, err)
513
- t.Cleanup(func() { db.Close() })
514
- return db
515
- }
516
- ```
517
-
518
- **11.2 — Cenarios de Repository (12 testes):**
519
-
520
- | Teste | Cenario |
521
- |-------|---------|
522
- | `TestUserRepository_Create_Success` | Todos os campos persistidos incluindo `Address` |
523
- | `TestUserRepository_CreateAndGetByID` | Dados identicos ao inserido |
524
- | `TestUserRepository_GetByEmail` | Retorna user correto com `Address` |
525
- | `TestUserRepository_Create_DuplicateEmail` | Erro contendo `"UNIQUE constraint failed"` |
526
- | `TestUserRepository_GetByID_NotFound` | Erro contendo `"nao encontrado"` |
527
- | `TestUserRepository_GetByEmail_NotFound` | Erro contendo `"nao encontrado"` |
528
- | `TestUserRepository_Update_NameOnly` | `Name == "Novo Nome"`, outros inalterados |
529
- | `TestUserRepository_Update_Email` | `Email == "novo@x.com"` |
530
- | `TestUserRepository_Update_PasswordHash` | `PasswordHash == novoHash` |
531
- | `TestUserRepository_Update_Address` | `Address == "Nova Rua, 99"` |
532
- | `TestUserRepository_Update_UpdatedAtChanges` | `UpdatedAt` posterior ao `CreatedAt` |
533
- | `TestUserRepository_Create_GeneratesValidUUID` | `uuid.Parse(result.ID)` sem erro |
534
-
535
- **11.3 — Testes de migracao (em `internal/infra/database/sqlite_test.go`):**
536
-
537
- | Teste | Cenario |
538
- |-------|---------|
539
- | `TestRunMigrations_TableSchema_IncludesEndereco` | `PRAGMA table_info(usuarios)` lista `endereco` com tipo `TEXT` |
540
- | `TestRunMigrations_EnderecocolumnDefaultEmpty` | INSERT sem `endereco` -> SELECT retorna `""` |
541
- | `TestRunMigrations_IdempotentWithEndereco` | Segunda `NewDatabase` nao retorna erro |
542
-
543
- **Criterio de conclusao:**
544
- - `CGO_ENABLED=1 go test ./internal/repository/... -v` — todos passam
545
- - Testes usam banco em diretorio temporario (sem efeitos colaterais)
546
-
547
- **Dependencias:** TASK 02, 04, 06
548
-
549
- ---
550
-
551
- ### TASK 12 — Testes E2E: Fluxos completos
552
-
553
- **Prioridade:** P2
554
- **Tipo:** Criar arquivo novo
555
-
556
- **Arquivo a criar:**
557
- - `internal/e2e/user_e2e_test.go`
558
-
559
- **Detalhes:**
560
-
561
- **12.1 — Setup:**
562
- - `setupE2EServer(t)` — servidor gRPC em porta efemera (`:0`)
563
- - Banco SQLite em `t.TempDir()`
564
- - Config, DB, Repo, Service, Handler, gRPC Server montados manualmente ou via FX
565
- - Retorna `pb.UserServiceClient` + funcao de cleanup
566
-
567
- **12.2 — Cenarios (5 fluxos E2E):**
568
-
569
- | Teste | Fluxo |
570
- |-------|-------|
571
- | `TestE2E_CreateUser_FullFlow` | `CreateUser` com dados validos -> verificar response: UUID valido, `name`, `email`, `created_at` presentes, sem token (RN-6) |
572
- | `TestE2E_LoginAndGetUserLogged_FullFlow` | `CreateUser` -> `Login` -> verificar token nao vazio -> `GetUserLogged` com Bearer token -> verificar dados completos (`id`, `name`, `email`, `address`) |
573
- | `TestE2E_UpdateUser_PartialUpdate` | `CreateUser` -> `Login` -> `UpdateUser{name: "Novo Nome"}` com Bearer -> `GetUserLogged` -> confirmar `name` atualizado, demais inalterados |
574
- | `TestE2E_ProtectedRoutes_RequireAuth` | `GetUserLogged` sem token -> `codes.Unauthenticated`; `UpdateUser` sem token -> `codes.Unauthenticated`; `CreateUser` e `Login` funcionam sem token |
575
- | `TestE2E_UpdateUser_PasswordChangeAndReauth` | `CreateUser` -> `Login` (senha original) -> `UpdateUser{new_password, current_password}` -> `Login` nova senha -> sucesso; `Login` senha antiga -> `codes.Unauthenticated` |
576
-
577
- **Criterio de conclusao:**
578
- - `CGO_ENABLED=1 go test ./internal/e2e/... -v` — todos passam
579
- - Testes isolados (banco temporario, porta efemera)
580
-
581
- **Dependencias:** TASK 01-09 (implementacao completa)
582
-
583
- ---
584
-
585
- ## Ordem de Execucao
586
-
587
- ```
588
- Fase 1 — Fundacao (paralelas):
589
- TASK 01 (Config)
590
- TASK 02 (Migration)
591
- TASK 03 (Proto + make generate)
592
- TASK 05 (Identity)
593
-
594
- Fase 2 — Dados:
595
- TASK 04 (SQLC queries + make generate) [depende: TASK 02]
596
-
597
- Fase 3 — Camadas de negocio:
598
- TASK 06 (Repository) [depende: TASK 04]
599
- TASK 09 (Interceptor) [depende: TASK 05]
600
-
601
- Fase 4 — Logica e apresentacao:
602
- TASK 07 (Service) [depende: TASK 01, 05, 06]
603
- TASK 08 (Handler) [depende: TASK 03, 05, 07]
604
-
605
- Fase 5 — Testes:
606
- TASK 10 (Unitarios) [depende: TASK 05-09]
607
- TASK 11 (Integracao) [depende: TASK 02, 04, 06]
608
- TASK 12 (E2E) [depende: TASK 01-09]
609
- ```
610
-
611
- ---
612
-
613
- ## Comandos de Validacao
614
-
615
- | Fase | Comando |
616
- |------|---------|
617
- | Apos TASK 01 | `make build` |
618
- | Apos TASK 03 | `make generate && make lint` |
619
- | Apos TASK 04 | `make generate` |
620
- | Apos TASK 05 | `CGO_ENABLED=1 go build ./internal/pkg/identity/...` |
621
- | Apos TASK 06 | `CGO_ENABLED=1 go build ./internal/repository/...` |
622
- | Apos TASK 07 | `CGO_ENABLED=1 go build ./internal/service/...` |
623
- | Apos TASK 08 | `CGO_ENABLED=1 go build ./internal/handler/grpc/...` |
624
- | Apos TASK 09 | `CGO_ENABLED=1 go build ./internal/infra/grpc/interceptors/...` |
625
- | Apos TASK 10 | `CGO_ENABLED=1 go test ./internal/pkg/identity/... ./internal/service/... ./internal/handler/grpc/... ./internal/infra/grpc/interceptors/... -v` |
626
- | Apos TASK 11 | `CGO_ENABLED=1 go test ./internal/repository/... -v` |
627
- | Apos TASK 12 | `CGO_ENABLED=1 go test ./internal/e2e/... -v` |
628
- | **Validacao final** | `make build && CGO_ENABLED=1 go test ./... -v` |
629
-
630
- ---
631
-
632
- ## Rastreabilidade SPEC_TECH -> Tasks
633
-
634
- | Secao SPEC_TECH | Task(s) |
635
- |-----------------|---------|
636
- | 4.1 Tabela usuarios | TASK 02 |
637
- | 4.2 Modelos Go | TASK 06, 07 |
638
- | 4.3 JWT Claims | TASK 05 |
639
- | 5.2 US-01 CreateUser | TASK 03, 04, 06, 07, 08 |
640
- | 5.3 US-02 Login | TASK 03, 05, 07, 08 |
641
- | 5.4 US-03 GetUserLogged | TASK 03, 05, 07, 08, 09 |
642
- | 5.5 US-04 UpdateUser | TASK 03, 04, 07, 08, 09 |
643
- | 6 Regras de Negocio (RN-1 a RN-12) | TASK 07 |
644
- | 8 API Proto | TASK 03 |
645
- | 9 Persistencia | TASK 02, 04 |
646
- | 10.1 Identity | TASK 05 |
647
- | 10.2 Interceptor | TASK 09 |
648
- | 10.3 bcrypt | TASK 07 |
649
- | 11 Tratamento de Erros | TASK 07, 08 |
650
- | 12 Configuracao | TASK 01 |
651
- | 13 Logging | TASK 07 |
652
- | 14.1 Testes Unitarios | TASK 10 |
653
- | 14.2 Testes Integracao | TASK 11 |
654
- | 14.3 Testes E2E | TASK 12 |
655
-
656
- ---
657
-
658
- ## Rastreabilidade Criterios de Aceite -> Tasks
659
-
660
- | CA | Tasks de Implementacao | Task de Teste |
661
- |----|----------------------|---------------|
662
- | CA-01 (Cadastro com sucesso) | TASK 03, 04, 06, 07, 08 | TASK 10, 11, 12 |
663
- | CA-02 (Email unico) | TASK 06, 07, 08 | TASK 10, 11, 12 |
664
- | CA-03 (Formato email) | TASK 07, 08 | TASK 10 |
665
- | CA-04 (Senha >= 8) | TASK 07, 08 | TASK 10 |
666
- | CA-05 (Nome obrigatorio) | TASK 07, 08 | TASK 10 |
667
- | CA-06 (Endereco obrigatorio) | TASK 07, 08 | TASK 10 |
668
- | CA-07 (Sem auto-login) | TASK 07, 08 | TASK 10, 12 |
669
- | CA-08 (Login retorna token) | TASK 05, 07, 08 | TASK 10, 12 |
670
- | CA-09 (Erro generico auth) | TASK 07, 08 | TASK 10, 12 |
671
- | CA-10 (Consultar dados) | TASK 07, 08, 09 | TASK 10, 11, 12 |
672
- | CA-11 (Rotas protegidas) | TASK 09 | TASK 10, 12 |
673
- | CA-12 (Atualizacao parcial) | TASK 07, 08 | TASK 10, 11, 12 |
674
- | CA-13 (Email unico update) | TASK 07, 08 | TASK 10 |
675
- | CA-14 (Confirmar senha atual) | TASK 07, 08 | TASK 10, 12 |
676
- | CA-15 (Nova senha >= 8) | TASK 07, 08 | TASK 10 |
677
- | CA-16 (Nenhum campo) | TASK 07, 08 | TASK 10 |
678
-
679
- ---
680
-
681
- ## Resumo
682
-
683
- | Metrica | Valor |
684
- |---------|-------|
685
- | Total de tasks | 12 |
686
- | Tasks P0 (bloqueantes) | 9 |
687
- | Tasks P1 (necessarias) | 2 |
688
- | Tasks P2 (complementares) | 1 |
689
- | Arquivos a criar | 4 (`identity.go`, `identity_test.go`, `auth_test.go`, `user_e2e_test.go`, `user_repository_integration_test.go`) |
690
- | Arquivos a modificar | 7 (`config.yaml`, `config.go`, `user.proto`, `user.sql`, `user_repository.go`, `user_service.go`, `user_handler.go`, `auth.go`, `user_service_test.go`, `user_handler_test.go`) |
691
- | Arquivos gerados (nao tocar) | `gen/proto/v1/`, `internal/db/sqlc/` |
692
- | User Stories cobertas | US-01, US-02, US-03, US-04 |
693
- | Criterios de Aceite cobertos | CA-01 a CA-16 |
694
- | Regras de Negocio cobertas | RN-1 a RN-12 |