adi_dev_workflow 1.1.1 → 1.3.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/bin/index.js +8 -8
- package/frameworks/agents/qa-staff-engineer.md +311 -311
- package/frameworks/agents/qa-validation-expert.md +458 -458
- package/frameworks/agents/tech-review-conformance.md +200 -200
- package/frameworks/commands/ministack/README.md +2 -0
- package/frameworks/commands/ministack/code-review.md +2 -0
- package/frameworks/commands/ministack/generate-intent.md +2 -0
- package/frameworks/commands/ministack/generate-scope.md +2 -0
- package/frameworks/commands/ministack/generate-tasks.md +2 -0
- package/frameworks/commands/ministack/generate-tech-direction.md +2 -0
- package/frameworks/commands/ministack/run-ministack-tasks.md +3 -0
- package/frameworks/commands/ministack/run-ministack-withlinear.md +2 -0
- package/frameworks/commands/ministack/status.md +2 -0
- package/frameworks/commands/sdd/code-review.md +2 -0
- package/frameworks/commands/sdd/generate-prd.md +2 -0
- package/frameworks/commands/sdd/generate-task-plan.md +2 -0
- package/frameworks/commands/sdd/generate-tech-direction.md +2 -0
- package/frameworks/commands/sdd/generate-tech-spec.md +2 -0
- package/frameworks/commands/sdd/generate-tests.md +2 -0
- package/frameworks/commands/sdd/run_tasks.md +3 -0
- package/frameworks/commands/sdd/run_tasks_withlinear.md +2 -0
- package/frameworks/commands/sdd/status.md +2 -0
- package/frameworks/commands/sdd/validate-sdd.md +2 -0
- package/frameworks/commands/sync-tasks-to-linear.md +2 -0
- package/frameworks/commands/taskcard/generate-taskcard.md +2 -0
- package/frameworks/commands/taskcard/run-taskcard.md +2 -0
- package/frameworks/config/ai-framework-config.yaml +112 -0
- package/frameworks/skills/ministack-tasks-expert/SKILL.md +204 -204
- package/frameworks/skills/ministack-tasks-expert/templates/task_plan_template.md +78 -78
- package/frameworks/skills/ministack-tasks-expert/templates/task_template.md +103 -103
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/benchmark.json +99 -99
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/benchmark.md +64 -64
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/eval_metadata.json +12 -12
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/outputs/response.md +134 -134
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/outputs/transcript.md +68 -68
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/timing.json +5 -5
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/outputs/response.md +525 -525
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/outputs/transcript.md +30 -30
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/timing.json +5 -5
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/eval_metadata.json +12 -12
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/outputs/response.md +1126 -1126
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/outputs/transcript.md +131 -131
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/timing.json +5 -5
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/outputs/response.md +452 -452
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/outputs/transcript.md +78 -78
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/timing.json +5 -5
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/eval_metadata.json +12 -12
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/outputs/response.md +101 -101
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/outputs/transcript.md +133 -133
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/timing.json +5 -5
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/outputs/response.md +248 -248
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/outputs/transcript.md +49 -49
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/timing.json +5 -5
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/review.html +1325 -1325
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/benchmark.json +94 -94
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/benchmark.md +67 -67
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/eval_metadata.json +12 -12
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/outputs/response.md +117 -117
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/outputs/transcript.md +91 -91
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/timing.json +1 -1
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/outputs/response.md +694 -694
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/outputs/transcript.md +45 -45
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/timing.json +1 -1
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/eval_metadata.json +12 -12
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/outputs/response.md +1087 -1087
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/outputs/transcript.md +124 -124
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/timing.json +1 -1
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/outputs/response.md +458 -458
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/outputs/transcript.md +84 -84
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/timing.json +1 -1
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/eval_metadata.json +12 -12
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/outputs/response.md +70 -70
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/outputs/transcript.md +148 -148
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/timing.json +1 -1
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/grading.json +32 -32
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/outputs/response.md +249 -249
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/outputs/transcript.md +80 -80
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/timing.json +1 -1
- package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/review.html +1325 -1325
- package/frameworks/skills/sdd-tech-spec-expert/SKILL.md +317 -317
- package/frameworks/skills/sdd-tech-spec-expert/evals/evals.json +199 -199
- package/frameworks/skills/sdd-tech-spec-expert/templates/spec_tech_template.md +290 -290
- package/frameworks/skills/sdd-tech-spec-expert/templates/tech_direction-template.md +23 -23
- package/package.json +28 -28
- package/src/cli.js +121 -121
- package/src/installer.js +155 -136
- package/src/transformer.js +86 -86
|
@@ -1,458 +1,458 @@
|
|
|
1
|
-
# TASK PLAN — Adicionar Telefone ao Usuario v1
|
|
2
|
-
|
|
3
|
-
## 1. Identificacao
|
|
4
|
-
|
|
5
|
-
| Campo | Valor |
|
|
6
|
-
|-------|-------|
|
|
7
|
-
| **Feature** | Adicionar Telefone ao Modulo de Usuario |
|
|
8
|
-
| **Versao** | v1 |
|
|
9
|
-
| **Data** | 2026-03-08 |
|
|
10
|
-
| **SPEC_TECH** | docs/feature-telefone-usuario/v1/spec_tech.md |
|
|
11
|
-
| **Total de Tasks** | 7 |
|
|
12
|
-
| **Estimativa Total** | ~2h |
|
|
13
|
-
|
|
14
|
-
## 2. Resumo
|
|
15
|
-
|
|
16
|
-
Adicionar campo opcional `telefone` a tabela `usuarios` e expor via gRPC em CreateUser, UpdateUser, GetUserLogged e na mensagem User. Inclui migracao de banco, atualizacao de queries SQLC, repository, service (com validacao), handler gRPC e proto.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 3. Tasks
|
|
21
|
-
|
|
22
|
-
### TASK-1: Criar migracao de banco de dados
|
|
23
|
-
|
|
24
|
-
**Camada:** Database
|
|
25
|
-
**Arquivo a criar:**
|
|
26
|
-
- `internal/db/migrations/003_add_telefone_usuarios.sql`
|
|
27
|
-
|
|
28
|
-
**Descricao:**
|
|
29
|
-
Criar nova migracao para adicionar a coluna `telefone` (TEXT, opcional/nullable) a tabela `usuarios`.
|
|
30
|
-
|
|
31
|
-
**Conteudo:**
|
|
32
|
-
```sql
|
|
33
|
-
ALTER TABLE usuarios ADD COLUMN telefone TEXT;
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
**Observacoes:**
|
|
37
|
-
- A coluna e opcional (sem NOT NULL), conforme SPEC_TECH
|
|
38
|
-
- Seguir o padrao de numeracao sequencial (proxima e 003)
|
|
39
|
-
- NAO editar migracoes existentes (001, 002)
|
|
40
|
-
- Sem migracao down pois o SQLite nao suporta DROP COLUMN de forma nativa em versoes antigas
|
|
41
|
-
|
|
42
|
-
**Criterio de aceite:**
|
|
43
|
-
- Arquivo `003_add_telefone_usuarios.sql` criado
|
|
44
|
-
- Migracao executa sem erro na inicializacao da aplicacao
|
|
45
|
-
- Coluna `telefone` existe na tabela `usuarios` apos boot
|
|
46
|
-
|
|
47
|
-
**Dependencias:** Nenhuma
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
### TASK-2: Atualizar queries SQLC
|
|
52
|
-
|
|
53
|
-
**Camada:** SQLC Queries
|
|
54
|
-
**Arquivo a editar:**
|
|
55
|
-
- `internal/db/sqlc/queries/user.sql`
|
|
56
|
-
|
|
57
|
-
**Descricao:**
|
|
58
|
-
Atualizar as queries `CreateUser` e `UpdateUser` para incluir a coluna `telefone`.
|
|
59
|
-
|
|
60
|
-
**Alteracoes:**
|
|
61
|
-
|
|
62
|
-
Na query `CreateUser`, adicionar `telefone` na lista de colunas e valores:
|
|
63
|
-
```sql
|
|
64
|
-
-- name: CreateUser :one
|
|
65
|
-
INSERT INTO usuarios (id, nome, email, senha_hash, endereco, telefone, data_criacao, data_atualizacao)
|
|
66
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
67
|
-
RETURNING *;
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Na query `UpdateUser`, adicionar `telefone` no SET:
|
|
71
|
-
```sql
|
|
72
|
-
-- name: UpdateUser :one
|
|
73
|
-
UPDATE usuarios
|
|
74
|
-
SET nome = ?,
|
|
75
|
-
email = ?,
|
|
76
|
-
senha_hash = ?,
|
|
77
|
-
endereco = ?,
|
|
78
|
-
telefone = ?,
|
|
79
|
-
data_atualizacao = ?
|
|
80
|
-
WHERE id = ?
|
|
81
|
-
RETURNING *;
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
**Observacoes:**
|
|
85
|
-
- As queries `GetUserByID` e `GetUserByEmail` usam `SELECT *`, entao ja retornarao o campo `telefone` automaticamente
|
|
86
|
-
- Apos editar, executar `make sqlc` para regenerar codigo em `internal/db/sqlc/`
|
|
87
|
-
|
|
88
|
-
**Criterio de aceite:**
|
|
89
|
-
- Queries atualizadas com coluna `telefone`
|
|
90
|
-
- `make sqlc` executa sem erros
|
|
91
|
-
- Codigo gerado em `internal/db/sqlc/` reflete o novo campo `Telefone`
|
|
92
|
-
|
|
93
|
-
**Dependencias:** TASK-1
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
### TASK-3: Atualizar Repository
|
|
98
|
-
|
|
99
|
-
**Camada:** Repository
|
|
100
|
-
**Arquivo a editar:**
|
|
101
|
-
- `internal/repository/user_repository.go`
|
|
102
|
-
|
|
103
|
-
**Descricao:**
|
|
104
|
-
Adicionar campo `Phone` ao modelo `User` e atualizar mapeamentos entre SQLC e dominio.
|
|
105
|
-
|
|
106
|
-
**Alteracoes:**
|
|
107
|
-
|
|
108
|
-
1. Adicionar campo `Phone` na struct `User`:
|
|
109
|
-
```go
|
|
110
|
-
type User struct {
|
|
111
|
-
ID string
|
|
112
|
-
Name string
|
|
113
|
-
Email string
|
|
114
|
-
PasswordHash string
|
|
115
|
-
Address string
|
|
116
|
-
Phone string // novo campo
|
|
117
|
-
CreatedAt time.Time
|
|
118
|
-
UpdatedAt time.Time
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
2. Atualizar metodo `Create` para mapear `Phone` -> `Telefone` nos params SQLC:
|
|
123
|
-
```go
|
|
124
|
-
params := sqlc.CreateUserParams{
|
|
125
|
-
ID: user.ID,
|
|
126
|
-
Nome: user.Name,
|
|
127
|
-
Email: user.Email,
|
|
128
|
-
SenhaHash: user.PasswordHash,
|
|
129
|
-
Endereco: user.Address,
|
|
130
|
-
Telefone: sql.NullString{String: user.Phone, Valid: user.Phone != ""},
|
|
131
|
-
DataCriacao: user.CreatedAt,
|
|
132
|
-
DataAtualizacao: user.UpdatedAt,
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
3. Atualizar metodo `Update` da mesma forma, adicionando `Telefone` nos params.
|
|
137
|
-
|
|
138
|
-
4. Atualizar funcao `toUser` para mapear `Telefone` -> `Phone`:
|
|
139
|
-
```go
|
|
140
|
-
func toUser(u sqlc.Usuario) *User {
|
|
141
|
-
return &User{
|
|
142
|
-
ID: u.ID,
|
|
143
|
-
Name: u.Nome,
|
|
144
|
-
Email: u.Email,
|
|
145
|
-
PasswordHash: u.SenhaHash,
|
|
146
|
-
Address: u.Endereco,
|
|
147
|
-
Phone: u.Telefone.String, // NullString -> string
|
|
148
|
-
CreatedAt: u.DataCriacao,
|
|
149
|
-
UpdatedAt: u.DataAtualizacao,
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
**Observacoes:**
|
|
155
|
-
- O tipo SQLC gerado para `telefone` sera `sql.NullString` pois a coluna e nullable
|
|
156
|
-
- Verificar o tipo exato apos `make sqlc` e ajustar o mapeamento se necessario
|
|
157
|
-
|
|
158
|
-
**Criterio de aceite:**
|
|
159
|
-
- Struct `User` possui campo `Phone string`
|
|
160
|
-
- Create e Update mapeiam `Phone` corretamente para `Telefone` do SQLC
|
|
161
|
-
- `toUser` mapeia `Telefone` de volta para `Phone`
|
|
162
|
-
- Compilacao sem erros
|
|
163
|
-
|
|
164
|
-
**Dependencias:** TASK-2
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
### TASK-4: Atualizar Service
|
|
169
|
-
|
|
170
|
-
**Camada:** Service
|
|
171
|
-
**Arquivo a editar:**
|
|
172
|
-
- `internal/service/user_service.go`
|
|
173
|
-
|
|
174
|
-
**Descricao:**
|
|
175
|
-
Adicionar campo `Phone` nos inputs e incluir validacao de tamanho (10-15 caracteres quando informado).
|
|
176
|
-
|
|
177
|
-
**Alteracoes:**
|
|
178
|
-
|
|
179
|
-
1. Adicionar nova variavel de erro:
|
|
180
|
-
```go
|
|
181
|
-
ErrInvalidPhone = errors.New("telefone deve ter entre 10 e 15 caracteres")
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
2. Adicionar campo `Phone` em `CreateUserInput`:
|
|
185
|
-
```go
|
|
186
|
-
type CreateUserInput struct {
|
|
187
|
-
Name string
|
|
188
|
-
Email string
|
|
189
|
-
Password string
|
|
190
|
-
Address string
|
|
191
|
-
Phone string // novo, opcional
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
3. Adicionar campo `Phone` em `UpdateUserInput`:
|
|
196
|
-
```go
|
|
197
|
-
type UpdateUserInput struct {
|
|
198
|
-
Name *string
|
|
199
|
-
Email *string
|
|
200
|
-
Address *string
|
|
201
|
-
Phone *string // novo, opcional
|
|
202
|
-
NewPassword *string
|
|
203
|
-
CurrentPassword *string
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
4. Em `CreateUser`, adicionar validacao antes de criar o usuario:
|
|
208
|
-
```go
|
|
209
|
-
if input.Phone != "" {
|
|
210
|
-
if len(input.Phone) < 10 || len(input.Phone) > 15 {
|
|
211
|
-
return nil, ErrInvalidPhone
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
E incluir `Phone: input.Phone` ao criar `repository.User`.
|
|
216
|
-
|
|
217
|
-
5. Em `UpdateUser`:
|
|
218
|
-
- Adicionar `input.Phone` na verificacao de "nenhum campo" (linha 171)
|
|
219
|
-
- Adicionar bloco para processar phone:
|
|
220
|
-
```go
|
|
221
|
-
if input.Phone != nil {
|
|
222
|
-
if *input.Phone != "" && (len(*input.Phone) < 10 || len(*input.Phone) > 15) {
|
|
223
|
-
return nil, ErrInvalidPhone
|
|
224
|
-
}
|
|
225
|
-
currentUser.Phone = *input.Phone
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
**Criterio de aceite:**
|
|
230
|
-
- `CreateUserInput` e `UpdateUserInput` possuem campo Phone
|
|
231
|
-
- Validacao de telefone (10-15 chars) funciona para CreateUser e UpdateUser
|
|
232
|
-
- Telefone vazio e aceito (campo opcional)
|
|
233
|
-
- `ErrInvalidPhone` definido e exportado
|
|
234
|
-
|
|
235
|
-
**Dependencias:** TASK-3
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
### TASK-5: Atualizar Proto (user.proto)
|
|
240
|
-
|
|
241
|
-
**Camada:** Proto/gRPC
|
|
242
|
-
**Arquivo a editar:**
|
|
243
|
-
- `api/proto/v1/user.proto`
|
|
244
|
-
|
|
245
|
-
**Descricao:**
|
|
246
|
-
Adicionar campo `phone` nas mensagens proto relevantes.
|
|
247
|
-
|
|
248
|
-
**Alteracoes:**
|
|
249
|
-
|
|
250
|
-
1. Mensagem `User` — adicionar campo `phone` (field number 7):
|
|
251
|
-
```proto
|
|
252
|
-
message User {
|
|
253
|
-
string id = 1;
|
|
254
|
-
string name = 2;
|
|
255
|
-
string email = 3;
|
|
256
|
-
string address = 4;
|
|
257
|
-
string created_at = 5;
|
|
258
|
-
string updated_at = 6;
|
|
259
|
-
string phone = 7;
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
2. Mensagem `CreateUserRequest` — adicionar campo `phone` (field number 5):
|
|
264
|
-
```proto
|
|
265
|
-
message CreateUserRequest {
|
|
266
|
-
string name = 1;
|
|
267
|
-
string email = 2;
|
|
268
|
-
string password = 3;
|
|
269
|
-
string address = 4;
|
|
270
|
-
string phone = 5;
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
3. Mensagem `UpdateUserRequest` — adicionar campo `phone` (field number 6):
|
|
275
|
-
```proto
|
|
276
|
-
message UpdateUserRequest {
|
|
277
|
-
optional string name = 1;
|
|
278
|
-
optional string email = 2;
|
|
279
|
-
optional string address = 3;
|
|
280
|
-
optional string new_password = 4;
|
|
281
|
-
optional string current_password = 5;
|
|
282
|
-
optional string phone = 6;
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
**Observacoes:**
|
|
287
|
-
- Apos editar, executar `make proto` (ou `buf generate`) para regenerar codigo em `gen/`
|
|
288
|
-
- NAO editar arquivos em `gen/` manualmente
|
|
289
|
-
- `CreateUserResponse` e `LoginResponse` NAO precisam do campo phone (seguem o formato atual que retorna campos selecionados)
|
|
290
|
-
|
|
291
|
-
**Criterio de aceite:**
|
|
292
|
-
- `user.proto` atualizado com campo `phone` nas 3 mensagens
|
|
293
|
-
- `make proto` executa sem erros
|
|
294
|
-
- Codigo gerado em `gen/` reflete os novos campos
|
|
295
|
-
|
|
296
|
-
**Dependencias:** Nenhuma (pode ser feita em paralelo com TASK-1 a TASK-4)
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
### TASK-6: Atualizar Handler gRPC
|
|
301
|
-
|
|
302
|
-
**Camada:** Handler
|
|
303
|
-
**Arquivo a editar:**
|
|
304
|
-
- `internal/handler/grpc/user_handler.go`
|
|
305
|
-
|
|
306
|
-
**Descricao:**
|
|
307
|
-
Atualizar os handlers para passar o campo `phone` entre proto e service, e incluir na conversao dominio->proto.
|
|
308
|
-
|
|
309
|
-
**Alteracoes:**
|
|
310
|
-
|
|
311
|
-
1. Em `CreateUser`, adicionar `Phone` ao input:
|
|
312
|
-
```go
|
|
313
|
-
user, err := h.userService.CreateUser(ctx, service.CreateUserInput{
|
|
314
|
-
Name: req.GetName(),
|
|
315
|
-
Email: req.GetEmail(),
|
|
316
|
-
Password: req.GetPassword(),
|
|
317
|
-
Address: req.GetAddress(),
|
|
318
|
-
Phone: req.GetPhone(),
|
|
319
|
-
})
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
2. Em `UpdateUser`, adicionar bloco para phone:
|
|
323
|
-
```go
|
|
324
|
-
if req.Phone != nil {
|
|
325
|
-
input.Phone = req.Phone
|
|
326
|
-
}
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
3. Em `domainUserToProto`, adicionar mapeamento de `Phone`:
|
|
330
|
-
```go
|
|
331
|
-
func domainUserToProto(user *repository.User) *pb.User {
|
|
332
|
-
return &pb.User{
|
|
333
|
-
Id: user.ID,
|
|
334
|
-
Name: user.Name,
|
|
335
|
-
Email: user.Email,
|
|
336
|
-
Address: user.Address,
|
|
337
|
-
Phone: user.Phone,
|
|
338
|
-
CreatedAt: user.CreatedAt.Format(time.RFC3339),
|
|
339
|
-
UpdatedAt: user.UpdatedAt.Format(time.RFC3339),
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
4. Em `mapServiceError`, adicionar mapeamento para `ErrInvalidPhone`:
|
|
345
|
-
```go
|
|
346
|
-
case errors.Is(err, service.ErrInvalidPhone):
|
|
347
|
-
return status.Errorf(codes.InvalidArgument, "%v", err)
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
**Criterio de aceite:**
|
|
351
|
-
- CreateUser passa `Phone` do request para o service
|
|
352
|
-
- UpdateUser passa `Phone` do request para o service
|
|
353
|
-
- `domainUserToProto` inclui `Phone`
|
|
354
|
-
- `mapServiceError` trata `ErrInvalidPhone`
|
|
355
|
-
- Compilacao sem erros
|
|
356
|
-
|
|
357
|
-
**Dependencias:** TASK-4, TASK-5
|
|
358
|
-
|
|
359
|
-
---
|
|
360
|
-
|
|
361
|
-
### TASK-7: Atualizar Testes
|
|
362
|
-
|
|
363
|
-
**Camada:** Testes
|
|
364
|
-
**Arquivos a editar:**
|
|
365
|
-
- `internal/service/user_service_test.go`
|
|
366
|
-
- `internal/handler/grpc/user_handler_test.go`
|
|
367
|
-
|
|
368
|
-
**Descricao:**
|
|
369
|
-
Adicionar testes para o novo campo `phone` e atualizar testes existentes que precisam refletir a presenca do campo.
|
|
370
|
-
|
|
371
|
-
**Alteracoes em `user_service_test.go`:**
|
|
372
|
-
|
|
373
|
-
1. Adicionar teste `TestCreateUser_WithPhone_Success` — cria usuario com telefone valido
|
|
374
|
-
2. Adicionar teste `TestCreateUser_PhoneTooShort` — telefone com menos de 10 caracteres deve retornar `ErrInvalidPhone`
|
|
375
|
-
3. Adicionar teste `TestCreateUser_PhoneTooLong` — telefone com mais de 15 caracteres deve retornar `ErrInvalidPhone`
|
|
376
|
-
4. Adicionar teste `TestCreateUser_PhoneEmpty_Success` — telefone vazio e aceito (opcional)
|
|
377
|
-
5. Adicionar teste `TestUpdateUser_PhoneOnly` — atualiza somente telefone
|
|
378
|
-
6. Adicionar teste `TestUpdateUser_PhoneInvalid` — telefone invalido no update retorna `ErrInvalidPhone`
|
|
379
|
-
7. Adicionar caso `"telefone invalido"` na table-driven `TestCreateUser_ValidationTableDriven`
|
|
380
|
-
|
|
381
|
-
**Alteracoes em `user_handler_test.go`:**
|
|
382
|
-
|
|
383
|
-
1. Adicionar teste `TestUserHandler_CreateUser_WithPhone` — verifica passagem do phone do proto para o service
|
|
384
|
-
2. Adicionar teste `TestUserHandler_UpdateUser_PhoneOnly` — verifica atualizacao de phone
|
|
385
|
-
3. Atualizar `TestDomainUserToProto` para incluir e validar campo `Phone`
|
|
386
|
-
4. Adicionar `ErrInvalidPhone` ao `TestMapServiceError_AllErrors` com codigo `InvalidArgument`
|
|
387
|
-
5. Atualizar testes existentes que criam `repository.User` para incluir campo `Phone` onde relevante (evitar warnings de campos faltantes)
|
|
388
|
-
|
|
389
|
-
**Criterio de aceite:**
|
|
390
|
-
- Todos os testes novos passam
|
|
391
|
-
- Testes existentes continuam passando
|
|
392
|
-
- Cobertura de: phone valido, phone vazio (opcional), phone curto demais, phone longo demais
|
|
393
|
-
- `make test` passa sem erros
|
|
394
|
-
|
|
395
|
-
**Dependencias:** TASK-4, TASK-6
|
|
396
|
-
|
|
397
|
-
---
|
|
398
|
-
|
|
399
|
-
## 4. Ordem de Execucao
|
|
400
|
-
|
|
401
|
-
```
|
|
402
|
-
TASK-1 (migracao) ──> TASK-2 (sqlc queries) ──> TASK-3 (repository) ──> TASK-4 (service) ──┐
|
|
403
|
-
├──> TASK-6 (handler) ──> TASK-7 (testes)
|
|
404
|
-
TASK-5 (proto) ─────────────────────────────────────────────────────────────────────────────┘
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
**Caminho critico:** TASK-1 -> TASK-2 -> TASK-3 -> TASK-4 -> TASK-6 -> TASK-7
|
|
408
|
-
|
|
409
|
-
**Paralelismo possivel:** TASK-5 pode ser executada em paralelo com TASK-1 a TASK-4.
|
|
410
|
-
|
|
411
|
-
---
|
|
412
|
-
|
|
413
|
-
## 5. Comandos de Geracao/Verificacao
|
|
414
|
-
|
|
415
|
-
Apos as alteracoes, executar na seguinte ordem:
|
|
416
|
-
|
|
417
|
-
```bash
|
|
418
|
-
# 1. Gerar codigo proto (apos TASK-5)
|
|
419
|
-
make proto
|
|
420
|
-
|
|
421
|
-
# 2. Gerar codigo SQLC (apos TASK-2)
|
|
422
|
-
make sqlc
|
|
423
|
-
|
|
424
|
-
# 3. Compilar para verificar erros
|
|
425
|
-
make build
|
|
426
|
-
|
|
427
|
-
# 4. Rodar todos os testes
|
|
428
|
-
make test
|
|
429
|
-
|
|
430
|
-
# 5. Lint dos protobufs
|
|
431
|
-
make lint
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
---
|
|
435
|
-
|
|
436
|
-
## 6. Arquivos Impactados (Resumo)
|
|
437
|
-
|
|
438
|
-
| Arquivo | Acao |
|
|
439
|
-
|---------|------|
|
|
440
|
-
| `internal/db/migrations/003_add_telefone_usuarios.sql` | Criar |
|
|
441
|
-
| `internal/db/sqlc/queries/user.sql` | Editar |
|
|
442
|
-
| `internal/db/sqlc/` (gerado) | Regenerar via `make sqlc` |
|
|
443
|
-
| `api/proto/v1/user.proto` | Editar |
|
|
444
|
-
| `gen/proto/v1/` (gerado) | Regenerar via `make proto` |
|
|
445
|
-
| `internal/repository/user_repository.go` | Editar |
|
|
446
|
-
| `internal/service/user_service.go` | Editar |
|
|
447
|
-
| `internal/handler/grpc/user_handler.go` | Editar |
|
|
448
|
-
| `internal/service/user_service_test.go` | Editar |
|
|
449
|
-
| `internal/handler/grpc/user_handler_test.go` | Editar |
|
|
450
|
-
|
|
451
|
-
---
|
|
452
|
-
|
|
453
|
-
## 7. Riscos e Observacoes
|
|
454
|
-
|
|
455
|
-
1. **Tipo SQLC para coluna nullable:** A coluna `telefone` e nullable (sem NOT NULL), entao o SQLC gerara `sql.NullString`. O mapeamento no repository precisa tratar isso corretamente (NullString <-> string).
|
|
456
|
-
2. **Migracao automatica:** A migracao executa no boot da aplicacao. Verificar que o numero sequencial 003 esta correto e nao conflita com outras migracoes em desenvolvimento.
|
|
457
|
-
3. **Compatibilidade retroativa do proto:** Adicionar campos com novos field numbers (7, 5, 6) e retrocompativel com clientes existentes. Clientes antigos simplesmente ignorarao o campo `phone`.
|
|
458
|
-
4. **Testes de integracao:** O arquivo `internal/e2e/user_e2e_test.go` pode precisar de atualizacao, mas nao foi incluido no escopo da SPEC_TECH. Avaliar se e necessario.
|
|
1
|
+
# TASK PLAN — Adicionar Telefone ao Usuario v1
|
|
2
|
+
|
|
3
|
+
## 1. Identificacao
|
|
4
|
+
|
|
5
|
+
| Campo | Valor |
|
|
6
|
+
|-------|-------|
|
|
7
|
+
| **Feature** | Adicionar Telefone ao Modulo de Usuario |
|
|
8
|
+
| **Versao** | v1 |
|
|
9
|
+
| **Data** | 2026-03-08 |
|
|
10
|
+
| **SPEC_TECH** | docs/feature-telefone-usuario/v1/spec_tech.md |
|
|
11
|
+
| **Total de Tasks** | 7 |
|
|
12
|
+
| **Estimativa Total** | ~2h |
|
|
13
|
+
|
|
14
|
+
## 2. Resumo
|
|
15
|
+
|
|
16
|
+
Adicionar campo opcional `telefone` a tabela `usuarios` e expor via gRPC em CreateUser, UpdateUser, GetUserLogged e na mensagem User. Inclui migracao de banco, atualizacao de queries SQLC, repository, service (com validacao), handler gRPC e proto.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 3. Tasks
|
|
21
|
+
|
|
22
|
+
### TASK-1: Criar migracao de banco de dados
|
|
23
|
+
|
|
24
|
+
**Camada:** Database
|
|
25
|
+
**Arquivo a criar:**
|
|
26
|
+
- `internal/db/migrations/003_add_telefone_usuarios.sql`
|
|
27
|
+
|
|
28
|
+
**Descricao:**
|
|
29
|
+
Criar nova migracao para adicionar a coluna `telefone` (TEXT, opcional/nullable) a tabela `usuarios`.
|
|
30
|
+
|
|
31
|
+
**Conteudo:**
|
|
32
|
+
```sql
|
|
33
|
+
ALTER TABLE usuarios ADD COLUMN telefone TEXT;
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Observacoes:**
|
|
37
|
+
- A coluna e opcional (sem NOT NULL), conforme SPEC_TECH
|
|
38
|
+
- Seguir o padrao de numeracao sequencial (proxima e 003)
|
|
39
|
+
- NAO editar migracoes existentes (001, 002)
|
|
40
|
+
- Sem migracao down pois o SQLite nao suporta DROP COLUMN de forma nativa em versoes antigas
|
|
41
|
+
|
|
42
|
+
**Criterio de aceite:**
|
|
43
|
+
- Arquivo `003_add_telefone_usuarios.sql` criado
|
|
44
|
+
- Migracao executa sem erro na inicializacao da aplicacao
|
|
45
|
+
- Coluna `telefone` existe na tabela `usuarios` apos boot
|
|
46
|
+
|
|
47
|
+
**Dependencias:** Nenhuma
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### TASK-2: Atualizar queries SQLC
|
|
52
|
+
|
|
53
|
+
**Camada:** SQLC Queries
|
|
54
|
+
**Arquivo a editar:**
|
|
55
|
+
- `internal/db/sqlc/queries/user.sql`
|
|
56
|
+
|
|
57
|
+
**Descricao:**
|
|
58
|
+
Atualizar as queries `CreateUser` e `UpdateUser` para incluir a coluna `telefone`.
|
|
59
|
+
|
|
60
|
+
**Alteracoes:**
|
|
61
|
+
|
|
62
|
+
Na query `CreateUser`, adicionar `telefone` na lista de colunas e valores:
|
|
63
|
+
```sql
|
|
64
|
+
-- name: CreateUser :one
|
|
65
|
+
INSERT INTO usuarios (id, nome, email, senha_hash, endereco, telefone, data_criacao, data_atualizacao)
|
|
66
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
67
|
+
RETURNING *;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Na query `UpdateUser`, adicionar `telefone` no SET:
|
|
71
|
+
```sql
|
|
72
|
+
-- name: UpdateUser :one
|
|
73
|
+
UPDATE usuarios
|
|
74
|
+
SET nome = ?,
|
|
75
|
+
email = ?,
|
|
76
|
+
senha_hash = ?,
|
|
77
|
+
endereco = ?,
|
|
78
|
+
telefone = ?,
|
|
79
|
+
data_atualizacao = ?
|
|
80
|
+
WHERE id = ?
|
|
81
|
+
RETURNING *;
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Observacoes:**
|
|
85
|
+
- As queries `GetUserByID` e `GetUserByEmail` usam `SELECT *`, entao ja retornarao o campo `telefone` automaticamente
|
|
86
|
+
- Apos editar, executar `make sqlc` para regenerar codigo em `internal/db/sqlc/`
|
|
87
|
+
|
|
88
|
+
**Criterio de aceite:**
|
|
89
|
+
- Queries atualizadas com coluna `telefone`
|
|
90
|
+
- `make sqlc` executa sem erros
|
|
91
|
+
- Codigo gerado em `internal/db/sqlc/` reflete o novo campo `Telefone`
|
|
92
|
+
|
|
93
|
+
**Dependencias:** TASK-1
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### TASK-3: Atualizar Repository
|
|
98
|
+
|
|
99
|
+
**Camada:** Repository
|
|
100
|
+
**Arquivo a editar:**
|
|
101
|
+
- `internal/repository/user_repository.go`
|
|
102
|
+
|
|
103
|
+
**Descricao:**
|
|
104
|
+
Adicionar campo `Phone` ao modelo `User` e atualizar mapeamentos entre SQLC e dominio.
|
|
105
|
+
|
|
106
|
+
**Alteracoes:**
|
|
107
|
+
|
|
108
|
+
1. Adicionar campo `Phone` na struct `User`:
|
|
109
|
+
```go
|
|
110
|
+
type User struct {
|
|
111
|
+
ID string
|
|
112
|
+
Name string
|
|
113
|
+
Email string
|
|
114
|
+
PasswordHash string
|
|
115
|
+
Address string
|
|
116
|
+
Phone string // novo campo
|
|
117
|
+
CreatedAt time.Time
|
|
118
|
+
UpdatedAt time.Time
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
2. Atualizar metodo `Create` para mapear `Phone` -> `Telefone` nos params SQLC:
|
|
123
|
+
```go
|
|
124
|
+
params := sqlc.CreateUserParams{
|
|
125
|
+
ID: user.ID,
|
|
126
|
+
Nome: user.Name,
|
|
127
|
+
Email: user.Email,
|
|
128
|
+
SenhaHash: user.PasswordHash,
|
|
129
|
+
Endereco: user.Address,
|
|
130
|
+
Telefone: sql.NullString{String: user.Phone, Valid: user.Phone != ""},
|
|
131
|
+
DataCriacao: user.CreatedAt,
|
|
132
|
+
DataAtualizacao: user.UpdatedAt,
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
3. Atualizar metodo `Update` da mesma forma, adicionando `Telefone` nos params.
|
|
137
|
+
|
|
138
|
+
4. Atualizar funcao `toUser` para mapear `Telefone` -> `Phone`:
|
|
139
|
+
```go
|
|
140
|
+
func toUser(u sqlc.Usuario) *User {
|
|
141
|
+
return &User{
|
|
142
|
+
ID: u.ID,
|
|
143
|
+
Name: u.Nome,
|
|
144
|
+
Email: u.Email,
|
|
145
|
+
PasswordHash: u.SenhaHash,
|
|
146
|
+
Address: u.Endereco,
|
|
147
|
+
Phone: u.Telefone.String, // NullString -> string
|
|
148
|
+
CreatedAt: u.DataCriacao,
|
|
149
|
+
UpdatedAt: u.DataAtualizacao,
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Observacoes:**
|
|
155
|
+
- O tipo SQLC gerado para `telefone` sera `sql.NullString` pois a coluna e nullable
|
|
156
|
+
- Verificar o tipo exato apos `make sqlc` e ajustar o mapeamento se necessario
|
|
157
|
+
|
|
158
|
+
**Criterio de aceite:**
|
|
159
|
+
- Struct `User` possui campo `Phone string`
|
|
160
|
+
- Create e Update mapeiam `Phone` corretamente para `Telefone` do SQLC
|
|
161
|
+
- `toUser` mapeia `Telefone` de volta para `Phone`
|
|
162
|
+
- Compilacao sem erros
|
|
163
|
+
|
|
164
|
+
**Dependencias:** TASK-2
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### TASK-4: Atualizar Service
|
|
169
|
+
|
|
170
|
+
**Camada:** Service
|
|
171
|
+
**Arquivo a editar:**
|
|
172
|
+
- `internal/service/user_service.go`
|
|
173
|
+
|
|
174
|
+
**Descricao:**
|
|
175
|
+
Adicionar campo `Phone` nos inputs e incluir validacao de tamanho (10-15 caracteres quando informado).
|
|
176
|
+
|
|
177
|
+
**Alteracoes:**
|
|
178
|
+
|
|
179
|
+
1. Adicionar nova variavel de erro:
|
|
180
|
+
```go
|
|
181
|
+
ErrInvalidPhone = errors.New("telefone deve ter entre 10 e 15 caracteres")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
2. Adicionar campo `Phone` em `CreateUserInput`:
|
|
185
|
+
```go
|
|
186
|
+
type CreateUserInput struct {
|
|
187
|
+
Name string
|
|
188
|
+
Email string
|
|
189
|
+
Password string
|
|
190
|
+
Address string
|
|
191
|
+
Phone string // novo, opcional
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
3. Adicionar campo `Phone` em `UpdateUserInput`:
|
|
196
|
+
```go
|
|
197
|
+
type UpdateUserInput struct {
|
|
198
|
+
Name *string
|
|
199
|
+
Email *string
|
|
200
|
+
Address *string
|
|
201
|
+
Phone *string // novo, opcional
|
|
202
|
+
NewPassword *string
|
|
203
|
+
CurrentPassword *string
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
4. Em `CreateUser`, adicionar validacao antes de criar o usuario:
|
|
208
|
+
```go
|
|
209
|
+
if input.Phone != "" {
|
|
210
|
+
if len(input.Phone) < 10 || len(input.Phone) > 15 {
|
|
211
|
+
return nil, ErrInvalidPhone
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
E incluir `Phone: input.Phone` ao criar `repository.User`.
|
|
216
|
+
|
|
217
|
+
5. Em `UpdateUser`:
|
|
218
|
+
- Adicionar `input.Phone` na verificacao de "nenhum campo" (linha 171)
|
|
219
|
+
- Adicionar bloco para processar phone:
|
|
220
|
+
```go
|
|
221
|
+
if input.Phone != nil {
|
|
222
|
+
if *input.Phone != "" && (len(*input.Phone) < 10 || len(*input.Phone) > 15) {
|
|
223
|
+
return nil, ErrInvalidPhone
|
|
224
|
+
}
|
|
225
|
+
currentUser.Phone = *input.Phone
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Criterio de aceite:**
|
|
230
|
+
- `CreateUserInput` e `UpdateUserInput` possuem campo Phone
|
|
231
|
+
- Validacao de telefone (10-15 chars) funciona para CreateUser e UpdateUser
|
|
232
|
+
- Telefone vazio e aceito (campo opcional)
|
|
233
|
+
- `ErrInvalidPhone` definido e exportado
|
|
234
|
+
|
|
235
|
+
**Dependencias:** TASK-3
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### TASK-5: Atualizar Proto (user.proto)
|
|
240
|
+
|
|
241
|
+
**Camada:** Proto/gRPC
|
|
242
|
+
**Arquivo a editar:**
|
|
243
|
+
- `api/proto/v1/user.proto`
|
|
244
|
+
|
|
245
|
+
**Descricao:**
|
|
246
|
+
Adicionar campo `phone` nas mensagens proto relevantes.
|
|
247
|
+
|
|
248
|
+
**Alteracoes:**
|
|
249
|
+
|
|
250
|
+
1. Mensagem `User` — adicionar campo `phone` (field number 7):
|
|
251
|
+
```proto
|
|
252
|
+
message User {
|
|
253
|
+
string id = 1;
|
|
254
|
+
string name = 2;
|
|
255
|
+
string email = 3;
|
|
256
|
+
string address = 4;
|
|
257
|
+
string created_at = 5;
|
|
258
|
+
string updated_at = 6;
|
|
259
|
+
string phone = 7;
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
2. Mensagem `CreateUserRequest` — adicionar campo `phone` (field number 5):
|
|
264
|
+
```proto
|
|
265
|
+
message CreateUserRequest {
|
|
266
|
+
string name = 1;
|
|
267
|
+
string email = 2;
|
|
268
|
+
string password = 3;
|
|
269
|
+
string address = 4;
|
|
270
|
+
string phone = 5;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
3. Mensagem `UpdateUserRequest` — adicionar campo `phone` (field number 6):
|
|
275
|
+
```proto
|
|
276
|
+
message UpdateUserRequest {
|
|
277
|
+
optional string name = 1;
|
|
278
|
+
optional string email = 2;
|
|
279
|
+
optional string address = 3;
|
|
280
|
+
optional string new_password = 4;
|
|
281
|
+
optional string current_password = 5;
|
|
282
|
+
optional string phone = 6;
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Observacoes:**
|
|
287
|
+
- Apos editar, executar `make proto` (ou `buf generate`) para regenerar codigo em `gen/`
|
|
288
|
+
- NAO editar arquivos em `gen/` manualmente
|
|
289
|
+
- `CreateUserResponse` e `LoginResponse` NAO precisam do campo phone (seguem o formato atual que retorna campos selecionados)
|
|
290
|
+
|
|
291
|
+
**Criterio de aceite:**
|
|
292
|
+
- `user.proto` atualizado com campo `phone` nas 3 mensagens
|
|
293
|
+
- `make proto` executa sem erros
|
|
294
|
+
- Codigo gerado em `gen/` reflete os novos campos
|
|
295
|
+
|
|
296
|
+
**Dependencias:** Nenhuma (pode ser feita em paralelo com TASK-1 a TASK-4)
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### TASK-6: Atualizar Handler gRPC
|
|
301
|
+
|
|
302
|
+
**Camada:** Handler
|
|
303
|
+
**Arquivo a editar:**
|
|
304
|
+
- `internal/handler/grpc/user_handler.go`
|
|
305
|
+
|
|
306
|
+
**Descricao:**
|
|
307
|
+
Atualizar os handlers para passar o campo `phone` entre proto e service, e incluir na conversao dominio->proto.
|
|
308
|
+
|
|
309
|
+
**Alteracoes:**
|
|
310
|
+
|
|
311
|
+
1. Em `CreateUser`, adicionar `Phone` ao input:
|
|
312
|
+
```go
|
|
313
|
+
user, err := h.userService.CreateUser(ctx, service.CreateUserInput{
|
|
314
|
+
Name: req.GetName(),
|
|
315
|
+
Email: req.GetEmail(),
|
|
316
|
+
Password: req.GetPassword(),
|
|
317
|
+
Address: req.GetAddress(),
|
|
318
|
+
Phone: req.GetPhone(),
|
|
319
|
+
})
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
2. Em `UpdateUser`, adicionar bloco para phone:
|
|
323
|
+
```go
|
|
324
|
+
if req.Phone != nil {
|
|
325
|
+
input.Phone = req.Phone
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
3. Em `domainUserToProto`, adicionar mapeamento de `Phone`:
|
|
330
|
+
```go
|
|
331
|
+
func domainUserToProto(user *repository.User) *pb.User {
|
|
332
|
+
return &pb.User{
|
|
333
|
+
Id: user.ID,
|
|
334
|
+
Name: user.Name,
|
|
335
|
+
Email: user.Email,
|
|
336
|
+
Address: user.Address,
|
|
337
|
+
Phone: user.Phone,
|
|
338
|
+
CreatedAt: user.CreatedAt.Format(time.RFC3339),
|
|
339
|
+
UpdatedAt: user.UpdatedAt.Format(time.RFC3339),
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
4. Em `mapServiceError`, adicionar mapeamento para `ErrInvalidPhone`:
|
|
345
|
+
```go
|
|
346
|
+
case errors.Is(err, service.ErrInvalidPhone):
|
|
347
|
+
return status.Errorf(codes.InvalidArgument, "%v", err)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Criterio de aceite:**
|
|
351
|
+
- CreateUser passa `Phone` do request para o service
|
|
352
|
+
- UpdateUser passa `Phone` do request para o service
|
|
353
|
+
- `domainUserToProto` inclui `Phone`
|
|
354
|
+
- `mapServiceError` trata `ErrInvalidPhone`
|
|
355
|
+
- Compilacao sem erros
|
|
356
|
+
|
|
357
|
+
**Dependencias:** TASK-4, TASK-5
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
### TASK-7: Atualizar Testes
|
|
362
|
+
|
|
363
|
+
**Camada:** Testes
|
|
364
|
+
**Arquivos a editar:**
|
|
365
|
+
- `internal/service/user_service_test.go`
|
|
366
|
+
- `internal/handler/grpc/user_handler_test.go`
|
|
367
|
+
|
|
368
|
+
**Descricao:**
|
|
369
|
+
Adicionar testes para o novo campo `phone` e atualizar testes existentes que precisam refletir a presenca do campo.
|
|
370
|
+
|
|
371
|
+
**Alteracoes em `user_service_test.go`:**
|
|
372
|
+
|
|
373
|
+
1. Adicionar teste `TestCreateUser_WithPhone_Success` — cria usuario com telefone valido
|
|
374
|
+
2. Adicionar teste `TestCreateUser_PhoneTooShort` — telefone com menos de 10 caracteres deve retornar `ErrInvalidPhone`
|
|
375
|
+
3. Adicionar teste `TestCreateUser_PhoneTooLong` — telefone com mais de 15 caracteres deve retornar `ErrInvalidPhone`
|
|
376
|
+
4. Adicionar teste `TestCreateUser_PhoneEmpty_Success` — telefone vazio e aceito (opcional)
|
|
377
|
+
5. Adicionar teste `TestUpdateUser_PhoneOnly` — atualiza somente telefone
|
|
378
|
+
6. Adicionar teste `TestUpdateUser_PhoneInvalid` — telefone invalido no update retorna `ErrInvalidPhone`
|
|
379
|
+
7. Adicionar caso `"telefone invalido"` na table-driven `TestCreateUser_ValidationTableDriven`
|
|
380
|
+
|
|
381
|
+
**Alteracoes em `user_handler_test.go`:**
|
|
382
|
+
|
|
383
|
+
1. Adicionar teste `TestUserHandler_CreateUser_WithPhone` — verifica passagem do phone do proto para o service
|
|
384
|
+
2. Adicionar teste `TestUserHandler_UpdateUser_PhoneOnly` — verifica atualizacao de phone
|
|
385
|
+
3. Atualizar `TestDomainUserToProto` para incluir e validar campo `Phone`
|
|
386
|
+
4. Adicionar `ErrInvalidPhone` ao `TestMapServiceError_AllErrors` com codigo `InvalidArgument`
|
|
387
|
+
5. Atualizar testes existentes que criam `repository.User` para incluir campo `Phone` onde relevante (evitar warnings de campos faltantes)
|
|
388
|
+
|
|
389
|
+
**Criterio de aceite:**
|
|
390
|
+
- Todos os testes novos passam
|
|
391
|
+
- Testes existentes continuam passando
|
|
392
|
+
- Cobertura de: phone valido, phone vazio (opcional), phone curto demais, phone longo demais
|
|
393
|
+
- `make test` passa sem erros
|
|
394
|
+
|
|
395
|
+
**Dependencias:** TASK-4, TASK-6
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## 4. Ordem de Execucao
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
TASK-1 (migracao) ──> TASK-2 (sqlc queries) ──> TASK-3 (repository) ──> TASK-4 (service) ──┐
|
|
403
|
+
├──> TASK-6 (handler) ──> TASK-7 (testes)
|
|
404
|
+
TASK-5 (proto) ─────────────────────────────────────────────────────────────────────────────┘
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**Caminho critico:** TASK-1 -> TASK-2 -> TASK-3 -> TASK-4 -> TASK-6 -> TASK-7
|
|
408
|
+
|
|
409
|
+
**Paralelismo possivel:** TASK-5 pode ser executada em paralelo com TASK-1 a TASK-4.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## 5. Comandos de Geracao/Verificacao
|
|
414
|
+
|
|
415
|
+
Apos as alteracoes, executar na seguinte ordem:
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
# 1. Gerar codigo proto (apos TASK-5)
|
|
419
|
+
make proto
|
|
420
|
+
|
|
421
|
+
# 2. Gerar codigo SQLC (apos TASK-2)
|
|
422
|
+
make sqlc
|
|
423
|
+
|
|
424
|
+
# 3. Compilar para verificar erros
|
|
425
|
+
make build
|
|
426
|
+
|
|
427
|
+
# 4. Rodar todos os testes
|
|
428
|
+
make test
|
|
429
|
+
|
|
430
|
+
# 5. Lint dos protobufs
|
|
431
|
+
make lint
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## 6. Arquivos Impactados (Resumo)
|
|
437
|
+
|
|
438
|
+
| Arquivo | Acao |
|
|
439
|
+
|---------|------|
|
|
440
|
+
| `internal/db/migrations/003_add_telefone_usuarios.sql` | Criar |
|
|
441
|
+
| `internal/db/sqlc/queries/user.sql` | Editar |
|
|
442
|
+
| `internal/db/sqlc/` (gerado) | Regenerar via `make sqlc` |
|
|
443
|
+
| `api/proto/v1/user.proto` | Editar |
|
|
444
|
+
| `gen/proto/v1/` (gerado) | Regenerar via `make proto` |
|
|
445
|
+
| `internal/repository/user_repository.go` | Editar |
|
|
446
|
+
| `internal/service/user_service.go` | Editar |
|
|
447
|
+
| `internal/handler/grpc/user_handler.go` | Editar |
|
|
448
|
+
| `internal/service/user_service_test.go` | Editar |
|
|
449
|
+
| `internal/handler/grpc/user_handler_test.go` | Editar |
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## 7. Riscos e Observacoes
|
|
454
|
+
|
|
455
|
+
1. **Tipo SQLC para coluna nullable:** A coluna `telefone` e nullable (sem NOT NULL), entao o SQLC gerara `sql.NullString`. O mapeamento no repository precisa tratar isso corretamente (NullString <-> string).
|
|
456
|
+
2. **Migracao automatica:** A migracao executa no boot da aplicacao. Verificar que o numero sequencial 003 esta correto e nao conflita com outras migracoes em desenvolvimento.
|
|
457
|
+
3. **Compatibilidade retroativa do proto:** Adicionar campos com novos field numbers (7, 5, 6) e retrocompativel com clientes existentes. Clientes antigos simplesmente ignorarao o campo `phone`.
|
|
458
|
+
4. **Testes de integracao:** O arquivo `internal/e2e/user_e2e_test.go` pode precisar de atualizacao, mas nao foi incluido no escopo da SPEC_TECH. Avaliar se e necessario.
|