maestro-bundle 1.3.1 → 1.5.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 +19 -6
- package/package.json +1 -1
- package/src/cli.mjs +12 -1
- package/templates/bundle-ai-agents/AGENTS.md +6 -0
- package/templates/bundle-ai-agents/PRD_TEMPLATE.md +161 -0
- package/templates/bundle-ai-agents/skills/agent-orchestration/SKILL.md +107 -41
- package/templates/bundle-ai-agents/skills/agent-orchestration/references/graph-patterns.md +50 -0
- package/templates/bundle-ai-agents/skills/agent-orchestration/references/routing-strategies.md +47 -0
- package/templates/bundle-ai-agents/skills/api-design/SKILL.md +125 -16
- package/templates/bundle-ai-agents/skills/api-design/references/pydantic-patterns.md +72 -0
- package/templates/bundle-ai-agents/skills/api-design/references/rest-conventions.md +51 -0
- package/templates/bundle-ai-agents/skills/clean-architecture/SKILL.md +113 -21
- package/templates/bundle-ai-agents/skills/clean-architecture/references/dependency-injection.md +60 -0
- package/templates/bundle-ai-agents/skills/clean-architecture/references/layer-rules.md +56 -0
- package/templates/bundle-ai-agents/skills/context-engineering/SKILL.md +104 -36
- package/templates/bundle-ai-agents/skills/context-engineering/references/compression-techniques.md +76 -0
- package/templates/bundle-ai-agents/skills/context-engineering/references/context-budget-calculator.md +45 -0
- package/templates/bundle-ai-agents/skills/database-modeling/SKILL.md +146 -19
- package/templates/bundle-ai-agents/skills/database-modeling/references/index-strategies.md +48 -0
- package/templates/bundle-ai-agents/skills/database-modeling/references/naming-conventions.md +27 -0
- package/templates/bundle-ai-agents/skills/docker-containerization/SKILL.md +124 -15
- package/templates/bundle-ai-agents/skills/docker-containerization/references/compose-patterns.md +97 -0
- package/templates/bundle-ai-agents/skills/docker-containerization/references/dockerfile-checklist.md +37 -0
- package/templates/bundle-ai-agents/skills/eval-testing/SKILL.md +113 -25
- package/templates/bundle-ai-agents/skills/eval-testing/references/eval-types.md +52 -0
- package/templates/bundle-ai-agents/skills/eval-testing/references/golden-dataset-template.md +59 -0
- package/templates/bundle-ai-agents/skills/memory-management/SKILL.md +112 -28
- package/templates/bundle-ai-agents/skills/memory-management/references/memory-tiers.md +41 -0
- package/templates/bundle-ai-agents/skills/memory-management/references/namespace-conventions.md +41 -0
- package/templates/bundle-ai-agents/skills/prompt-engineering/SKILL.md +139 -47
- package/templates/bundle-ai-agents/skills/prompt-engineering/references/anti-patterns.md +59 -0
- package/templates/bundle-ai-agents/skills/prompt-engineering/references/prompt-templates.md +75 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/SKILL.md +104 -27
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/chunking-strategies.md +27 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/embedding-models.md +31 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/rag-evaluation.md +39 -0
- package/templates/bundle-ai-agents/skills/testing-strategy/SKILL.md +127 -18
- package/templates/bundle-ai-agents/skills/testing-strategy/references/fixture-patterns.md +81 -0
- package/templates/bundle-ai-agents/skills/testing-strategy/references/naming-conventions.md +69 -0
- package/templates/bundle-base/skills/branch-strategy/SKILL.md +134 -21
- package/templates/bundle-base/skills/branch-strategy/references/branch-rules.md +40 -0
- package/templates/bundle-base/skills/code-review/SKILL.md +123 -38
- package/templates/bundle-base/skills/code-review/references/review-checklist.md +45 -0
- package/templates/bundle-base/skills/commit-pattern/SKILL.md +98 -39
- package/templates/bundle-base/skills/commit-pattern/references/conventional-commits.md +40 -0
- package/templates/bundle-data-pipeline/AGENTS.md +6 -0
- package/templates/bundle-data-pipeline/PRD_TEMPLATE.md +161 -0
- package/templates/bundle-data-pipeline/skills/data-preprocessing/SKILL.md +110 -19
- package/templates/bundle-data-pipeline/skills/data-preprocessing/references/pandas-cheatsheet.md +63 -0
- package/templates/bundle-data-pipeline/skills/data-preprocessing/references/pandera-schemas.md +44 -0
- package/templates/bundle-data-pipeline/skills/docker-containerization/SKILL.md +132 -16
- package/templates/bundle-data-pipeline/skills/docker-containerization/references/compose-patterns.md +82 -0
- package/templates/bundle-data-pipeline/skills/docker-containerization/references/dockerfile-best-practices.md +57 -0
- package/templates/bundle-data-pipeline/skills/feature-engineering/SKILL.md +143 -45
- package/templates/bundle-data-pipeline/skills/feature-engineering/references/encoding-guide.md +41 -0
- package/templates/bundle-data-pipeline/skills/feature-engineering/references/scaling-guide.md +38 -0
- package/templates/bundle-data-pipeline/skills/mlops-pipeline/SKILL.md +156 -37
- package/templates/bundle-data-pipeline/skills/mlops-pipeline/references/mlflow-commands.md +69 -0
- package/templates/bundle-data-pipeline/skills/model-training/SKILL.md +152 -33
- package/templates/bundle-data-pipeline/skills/model-training/references/evaluation-metrics.md +52 -0
- package/templates/bundle-data-pipeline/skills/model-training/references/model-selection-guide.md +41 -0
- package/templates/bundle-data-pipeline/skills/rag-pipeline/SKILL.md +127 -39
- package/templates/bundle-data-pipeline/skills/rag-pipeline/references/chunking-strategies.md +51 -0
- package/templates/bundle-data-pipeline/skills/rag-pipeline/references/embedding-models.md +49 -0
- package/templates/bundle-frontend-spa/AGENTS.md +6 -0
- package/templates/bundle-frontend-spa/PRD_TEMPLATE.md +161 -0
- package/templates/bundle-frontend-spa/skills/authentication/SKILL.md +196 -13
- package/templates/bundle-frontend-spa/skills/authentication/references/jwt-security.md +41 -0
- package/templates/bundle-frontend-spa/skills/component-design/SKILL.md +191 -41
- package/templates/bundle-frontend-spa/skills/component-design/references/accessibility-checklist.md +41 -0
- package/templates/bundle-frontend-spa/skills/component-design/references/tailwind-patterns.md +65 -0
- package/templates/bundle-frontend-spa/skills/e2e-testing/SKILL.md +241 -79
- package/templates/bundle-frontend-spa/skills/e2e-testing/references/playwright-selectors.md +66 -0
- package/templates/bundle-frontend-spa/skills/e2e-testing/references/test-patterns.md +82 -0
- package/templates/bundle-frontend-spa/skills/integration-api/SKILL.md +221 -31
- package/templates/bundle-frontend-spa/skills/integration-api/references/api-patterns.md +81 -0
- package/templates/bundle-frontend-spa/skills/react-patterns/SKILL.md +195 -70
- package/templates/bundle-frontend-spa/skills/react-patterns/references/component-checklist.md +22 -0
- package/templates/bundle-frontend-spa/skills/react-patterns/references/hook-patterns.md +63 -0
- package/templates/bundle-frontend-spa/skills/responsive-layout/SKILL.md +162 -22
- package/templates/bundle-frontend-spa/skills/responsive-layout/references/breakpoint-guide.md +63 -0
- package/templates/bundle-frontend-spa/skills/state-management/SKILL.md +158 -30
- package/templates/bundle-frontend-spa/skills/state-management/references/react-query-config.md +64 -0
- package/templates/bundle-frontend-spa/skills/state-management/references/state-patterns.md +78 -0
- package/templates/bundle-jhipster-microservices/AGENTS.md +6 -0
- package/templates/bundle-jhipster-microservices/PRD_TEMPLATE.md +161 -0
- package/templates/bundle-jhipster-microservices/skills/ci-cd-pipeline/SKILL.md +135 -45
- package/templates/bundle-jhipster-microservices/skills/ci-cd-pipeline/references/gitlab-ci-templates.md +93 -0
- package/templates/bundle-jhipster-microservices/skills/clean-architecture/SKILL.md +87 -21
- package/templates/bundle-jhipster-microservices/skills/clean-architecture/references/layer-rules.md +78 -0
- package/templates/bundle-jhipster-microservices/skills/ddd-tactical/SKILL.md +94 -25
- package/templates/bundle-jhipster-microservices/skills/ddd-tactical/references/ddd-patterns.md +48 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/SKILL.md +63 -21
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/references/angular-microservices.md +40 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/references/angular-structure.md +59 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-docker-k8s/SKILL.md +125 -91
- package/templates/bundle-jhipster-microservices/skills/jhipster-docker-k8s/references/docker-k8s-commands.md +68 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/SKILL.md +72 -20
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/references/cross-service-entities.md +36 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/references/jdl-types.md +56 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-gateway/SKILL.md +80 -8
- package/templates/bundle-jhipster-microservices/skills/jhipster-gateway/references/gateway-config.md +43 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-kafka/SKILL.md +115 -22
- package/templates/bundle-jhipster-microservices/skills/jhipster-kafka/references/kafka-events.md +39 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-registry/SKILL.md +92 -23
- package/templates/bundle-jhipster-microservices/skills/jhipster-registry/references/consul-config.md +61 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-service/SKILL.md +81 -18
- package/templates/bundle-jhipster-microservices/skills/jhipster-service/references/service-patterns.md +40 -0
- package/templates/bundle-jhipster-microservices/skills/testing-strategy/SKILL.md +101 -20
- package/templates/bundle-jhipster-microservices/skills/testing-strategy/references/test-naming.md +55 -0
- package/templates/bundle-jhipster-monorepo/AGENTS.md +6 -0
- package/templates/bundle-jhipster-monorepo/PRD_TEMPLATE.md +161 -0
- package/templates/bundle-jhipster-monorepo/skills/clean-architecture/SKILL.md +87 -21
- package/templates/bundle-jhipster-monorepo/skills/clean-architecture/references/layer-rules.md +78 -0
- package/templates/bundle-jhipster-monorepo/skills/ddd-tactical/SKILL.md +94 -25
- package/templates/bundle-jhipster-monorepo/skills/ddd-tactical/references/ddd-patterns.md +48 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-angular/SKILL.md +99 -52
- package/templates/bundle-jhipster-monorepo/skills/jhipster-angular/references/angular-structure.md +59 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-entities/SKILL.md +89 -36
- package/templates/bundle-jhipster-monorepo/skills/jhipster-entities/references/jdl-types.md +56 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-liquibase/SKILL.md +123 -23
- package/templates/bundle-jhipster-monorepo/skills/jhipster-liquibase/references/liquibase-operations.md +95 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-security/SKILL.md +106 -19
- package/templates/bundle-jhipster-monorepo/skills/jhipster-security/references/security-checklist.md +47 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-spring/SKILL.md +84 -16
- package/templates/bundle-jhipster-monorepo/skills/jhipster-spring/references/spring-layers.md +41 -0
- package/templates/bundle-jhipster-monorepo/skills/testing-strategy/SKILL.md +101 -20
- package/templates/bundle-jhipster-monorepo/skills/testing-strategy/references/test-naming.md +55 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Embedding Models Comparison
|
|
2
|
+
|
|
3
|
+
## OpenAI Models
|
|
4
|
+
|
|
5
|
+
| Model | Dimensions | Max Tokens | Best For |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| text-embedding-3-large | 3072 (or custom) | 8191 | Highest quality, production |
|
|
8
|
+
| text-embedding-3-small | 1536 | 8191 | Cost-effective, good quality |
|
|
9
|
+
| text-embedding-ada-002 | 1536 | 8191 | Legacy, still widely used |
|
|
10
|
+
|
|
11
|
+
## Usage with LangChain
|
|
12
|
+
```python
|
|
13
|
+
from langchain_openai import OpenAIEmbeddings
|
|
14
|
+
|
|
15
|
+
# Default (text-embedding-3-large with reduced dimensions)
|
|
16
|
+
embeddings = OpenAIEmbeddings(model="text-embedding-3-large", dimensions=1536)
|
|
17
|
+
|
|
18
|
+
# Full dimensions for maximum quality
|
|
19
|
+
embeddings = OpenAIEmbeddings(model="text-embedding-3-large", dimensions=3072)
|
|
20
|
+
|
|
21
|
+
# Cost-effective option
|
|
22
|
+
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Open Source Alternatives
|
|
26
|
+
```python
|
|
27
|
+
from langchain_community.embeddings import HuggingFaceEmbeddings
|
|
28
|
+
|
|
29
|
+
# All-MiniLM (fast, lightweight)
|
|
30
|
+
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
|
|
31
|
+
|
|
32
|
+
# BGE (high quality, multilingual)
|
|
33
|
+
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-large-en-v1.5")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Dimensionality and pgvector
|
|
37
|
+
When creating the pgvector extension and table:
|
|
38
|
+
```sql
|
|
39
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
40
|
+
|
|
41
|
+
-- Match dimensions to your embedding model
|
|
42
|
+
CREATE TABLE embeddings (
|
|
43
|
+
id SERIAL PRIMARY KEY,
|
|
44
|
+
content TEXT,
|
|
45
|
+
embedding vector(1536) -- adjust to match model dimensions
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
CREATE INDEX ON embeddings USING ivfflat (embedding vector_cosine_ops);
|
|
49
|
+
```
|
|
@@ -14,6 +14,12 @@ Este projeto usa **GitHub Spec Kit** para governança. Antes de implementar qual
|
|
|
14
14
|
|
|
15
15
|
Nunca pular direto para código. Spec primeiro, código depois.
|
|
16
16
|
|
|
17
|
+
## Product Requirements Document
|
|
18
|
+
|
|
19
|
+
O arquivo `PRD.md` na raiz do projeto contém os requisitos do produto definidos pelo analista/dev. Consulte-o para entender O QUE construir, as user stories, critérios de aceite, modelo de dados e API specification. Este AGENTS.md define COMO o agente deve trabalhar; o PRD define O QUE deve ser construído.
|
|
20
|
+
|
|
21
|
+
- `PRD.md` — Requisitos do produto, user stories, API spec, modelo de dados
|
|
22
|
+
|
|
17
23
|
## References
|
|
18
24
|
|
|
19
25
|
Documentos de referência que o agente deve consultar quando necessário:
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Product Requirements Document (PRD)
|
|
2
|
+
|
|
3
|
+
> Este documento define os requisitos do produto. Deve ser preenchido pelo analista de requisitos e/ou pelo dev antes de iniciar o desenvolvimento. O agente AI usa este documento como contexto para entender O QUE construir.
|
|
4
|
+
|
|
5
|
+
## 1. Resumo Executivo
|
|
6
|
+
|
|
7
|
+
<!-- Descreva em 2-3 frases o que é o produto e qual problema resolve -->
|
|
8
|
+
|
|
9
|
+
## 2. Usuários Alvo
|
|
10
|
+
|
|
11
|
+
<!-- Quem vai usar o sistema? Descreva as personas -->
|
|
12
|
+
|
|
13
|
+
### Persona 1: [Nome]
|
|
14
|
+
- **Perfil:**
|
|
15
|
+
- **Objetivos:**
|
|
16
|
+
- **Dores:**
|
|
17
|
+
|
|
18
|
+
## 3. Escopo do MVP
|
|
19
|
+
|
|
20
|
+
### Incluído no MVP
|
|
21
|
+
- [ ] Feature 1
|
|
22
|
+
- [ ] Feature 2
|
|
23
|
+
- [ ] Feature 3
|
|
24
|
+
|
|
25
|
+
### Fora do MVP (futuro)
|
|
26
|
+
- [ ] Feature futura 1
|
|
27
|
+
- [ ] Feature futura 2
|
|
28
|
+
|
|
29
|
+
## 4. User Stories
|
|
30
|
+
|
|
31
|
+
### US01: [Título]
|
|
32
|
+
**Como** [persona], **quero** [ação], **para** [benefício].
|
|
33
|
+
|
|
34
|
+
**Critérios de aceite:**
|
|
35
|
+
- [ ] CA1:
|
|
36
|
+
- [ ] CA2:
|
|
37
|
+
|
|
38
|
+
### US02: [Título]
|
|
39
|
+
**Como** [persona], **quero** [ação], **para** [benefício].
|
|
40
|
+
|
|
41
|
+
**Critérios de aceite:**
|
|
42
|
+
- [ ] CA1:
|
|
43
|
+
- [ ] CA2:
|
|
44
|
+
|
|
45
|
+
## 5. Arquitetura de Alto Nível
|
|
46
|
+
|
|
47
|
+
<!-- Diagrama em Mermaid ou ASCII mostrando os componentes principais -->
|
|
48
|
+
|
|
49
|
+
```mermaid
|
|
50
|
+
graph LR
|
|
51
|
+
A[Frontend] --> B[API]
|
|
52
|
+
B --> C[Database]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Estrutura de Diretórios
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
project/
|
|
59
|
+
├── src/
|
|
60
|
+
├── tests/
|
|
61
|
+
└── ...
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 6. Features Detalhadas
|
|
65
|
+
|
|
66
|
+
### Feature 1: [Nome]
|
|
67
|
+
- **Descrição:**
|
|
68
|
+
- **Regras de negócio:**
|
|
69
|
+
-
|
|
70
|
+
- **Inputs:**
|
|
71
|
+
- **Outputs:**
|
|
72
|
+
- **Edge cases:**
|
|
73
|
+
-
|
|
74
|
+
|
|
75
|
+
### Feature 2: [Nome]
|
|
76
|
+
- **Descrição:**
|
|
77
|
+
- **Regras de negócio:**
|
|
78
|
+
-
|
|
79
|
+
|
|
80
|
+
## 7. Stack Tecnológica
|
|
81
|
+
|
|
82
|
+
| Componente | Tecnologia | Justificativa |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| Backend | | |
|
|
85
|
+
| Frontend | | |
|
|
86
|
+
| Banco de dados | | |
|
|
87
|
+
| Cache | | |
|
|
88
|
+
| Deploy | | |
|
|
89
|
+
|
|
90
|
+
## 8. API Specification
|
|
91
|
+
|
|
92
|
+
### Endpoints
|
|
93
|
+
|
|
94
|
+
#### `GET /api/v1/resource`
|
|
95
|
+
- **Descrição:**
|
|
96
|
+
- **Response:** `200 OK`
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"items": [],
|
|
100
|
+
"total": 0,
|
|
101
|
+
"page": 1,
|
|
102
|
+
"size": 20
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### `POST /api/v1/resource`
|
|
107
|
+
- **Descrição:**
|
|
108
|
+
- **Body:**
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"field": "value"
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
- **Response:** `201 Created`
|
|
115
|
+
|
|
116
|
+
## 9. Modelo de Dados
|
|
117
|
+
|
|
118
|
+
```sql
|
|
119
|
+
CREATE TABLE example (
|
|
120
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
121
|
+
name VARCHAR(100) NOT NULL,
|
|
122
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
123
|
+
);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 10. Requisitos Não-Funcionais
|
|
127
|
+
|
|
128
|
+
| Requisito | Alvo | Prioridade |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| Performance | Response time < 500ms | Alta |
|
|
131
|
+
| Disponibilidade | 99.9% uptime | Média |
|
|
132
|
+
| Segurança | OWASP Top 10 | Alta |
|
|
133
|
+
| Escalabilidade | Até X usuários simultâneos | Média |
|
|
134
|
+
|
|
135
|
+
## 11. Fases de Implementação
|
|
136
|
+
|
|
137
|
+
### Fase 1: Foundation
|
|
138
|
+
- [ ] Setup do projeto
|
|
139
|
+
- [ ] Modelo de dados
|
|
140
|
+
- [ ] Endpoints básicos
|
|
141
|
+
|
|
142
|
+
### Fase 2: Core Features
|
|
143
|
+
- [ ] Feature 1 completa
|
|
144
|
+
- [ ] Feature 2 completa
|
|
145
|
+
|
|
146
|
+
### Fase 3: Polish
|
|
147
|
+
- [ ] Testes E2E
|
|
148
|
+
- [ ] Performance
|
|
149
|
+
- [ ] Documentação
|
|
150
|
+
|
|
151
|
+
## 12. Riscos e Mitigações
|
|
152
|
+
|
|
153
|
+
| Risco | Impacto | Probabilidade | Mitigação |
|
|
154
|
+
|---|---|---|---|
|
|
155
|
+
| | | | |
|
|
156
|
+
|
|
157
|
+
## 13. Critérios de Sucesso
|
|
158
|
+
|
|
159
|
+
- [ ] Critério 1
|
|
160
|
+
- [ ] Critério 2
|
|
161
|
+
- [ ] Critério 3
|
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: authentication
|
|
3
|
-
description:
|
|
3
|
+
description: Implement JWT authentication with login, refresh tokens, route protection, and Axios interceptors for both frontend and backend. Use when you need to add login, JWT auth, protected routes, or token refresh to an application.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Maestro
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Authentication
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Implement complete JWT authentication flow covering backend token generation, frontend auth state, Axios interceptors, and protected routes.
|
|
9
11
|
|
|
12
|
+
## When to Use
|
|
13
|
+
- User needs to implement login/logout functionality
|
|
14
|
+
- User wants to protect routes requiring authentication
|
|
15
|
+
- User needs JWT token generation and validation (backend)
|
|
16
|
+
- User wants to add automatic token refresh
|
|
17
|
+
- User needs to set up Axios interceptors for auth headers
|
|
18
|
+
|
|
19
|
+
## Available Operations
|
|
20
|
+
1. Create JWT token generation and validation (FastAPI backend)
|
|
21
|
+
2. Build login/logout flow with Zustand auth store
|
|
22
|
+
3. Set up Axios interceptors for automatic Bearer token headers
|
|
23
|
+
4. Implement protected route wrappers
|
|
24
|
+
5. Add refresh token rotation
|
|
25
|
+
|
|
26
|
+
## Multi-Step Workflow
|
|
27
|
+
|
|
28
|
+
### Step 1: Install Backend Dependencies
|
|
29
|
+
```bash
|
|
30
|
+
pip install fastapi python-jose[cryptography] passlib[bcrypt] python-multipart
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Step 2: Create JWT Token Utilities (Backend)
|
|
10
34
|
```python
|
|
35
|
+
# src/auth/jwt.py
|
|
36
|
+
import os
|
|
37
|
+
from datetime import datetime, timedelta
|
|
38
|
+
from jose import jwt, JWTError
|
|
11
39
|
from fastapi import Depends, HTTPException, status
|
|
12
40
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
13
|
-
from jose import jwt, JWTError
|
|
14
|
-
from datetime import datetime, timedelta
|
|
15
41
|
|
|
16
42
|
security = HTTPBearer()
|
|
17
43
|
SECRET_KEY = os.environ["JWT_SECRET"]
|
|
@@ -23,7 +49,7 @@ def create_access_token(user_id: str) -> str:
|
|
|
23
49
|
payload = {
|
|
24
50
|
"sub": user_id,
|
|
25
51
|
"exp": datetime.utcnow() + ACCESS_TOKEN_EXPIRE,
|
|
26
|
-
"type": "access"
|
|
52
|
+
"type": "access",
|
|
27
53
|
}
|
|
28
54
|
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
|
|
29
55
|
|
|
@@ -31,11 +57,13 @@ def create_refresh_token(user_id: str) -> str:
|
|
|
31
57
|
payload = {
|
|
32
58
|
"sub": user_id,
|
|
33
59
|
"exp": datetime.utcnow() + REFRESH_TOKEN_EXPIRE,
|
|
34
|
-
"type": "refresh"
|
|
60
|
+
"type": "refresh",
|
|
35
61
|
}
|
|
36
62
|
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
|
|
37
63
|
|
|
38
|
-
async def get_current_user(
|
|
64
|
+
async def get_current_user(
|
|
65
|
+
credentials: HTTPAuthorizationCredentials = Depends(security),
|
|
66
|
+
) -> User:
|
|
39
67
|
try:
|
|
40
68
|
payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM])
|
|
41
69
|
if payload.get("type") != "access":
|
|
@@ -46,22 +74,68 @@ async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(s
|
|
|
46
74
|
return user
|
|
47
75
|
except JWTError:
|
|
48
76
|
raise HTTPException(status_code=401, detail="Invalid token")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Step 3: Create Auth Endpoints (Backend)
|
|
80
|
+
```python
|
|
81
|
+
# src/auth/routes.py
|
|
82
|
+
from fastapi import APIRouter, HTTPException
|
|
83
|
+
|
|
84
|
+
router = APIRouter(prefix="/auth", tags=["auth"])
|
|
85
|
+
|
|
86
|
+
@router.post("/login")
|
|
87
|
+
async def login(data: LoginRequest):
|
|
88
|
+
user = await user_repo.find_by_email(data.email)
|
|
89
|
+
if not user or not verify_password(data.password, user.hashed_password):
|
|
90
|
+
raise HTTPException(status_code=401, detail="Invalid credentials")
|
|
91
|
+
return {
|
|
92
|
+
"access_token": create_access_token(str(user.id)),
|
|
93
|
+
"refresh_token": create_refresh_token(str(user.id)),
|
|
94
|
+
"user": UserResponse.from_entity(user),
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@router.post("/refresh")
|
|
98
|
+
async def refresh(data: RefreshRequest):
|
|
99
|
+
try:
|
|
100
|
+
payload = jwt.decode(data.refresh_token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
101
|
+
if payload.get("type") != "refresh":
|
|
102
|
+
raise HTTPException(status_code=401, detail="Invalid token type")
|
|
103
|
+
return {"access_token": create_access_token(payload["sub"])}
|
|
104
|
+
except JWTError:
|
|
105
|
+
raise HTTPException(status_code=401, detail="Invalid refresh token")
|
|
49
106
|
|
|
50
|
-
# Endpoint protegido
|
|
51
107
|
@router.get("/me")
|
|
52
108
|
async def get_me(user: User = Depends(get_current_user)):
|
|
53
109
|
return UserResponse.from_entity(user)
|
|
54
110
|
```
|
|
55
111
|
|
|
56
|
-
|
|
112
|
+
Test the backend:
|
|
113
|
+
```bash
|
|
114
|
+
# Start the API server
|
|
115
|
+
uvicorn src.main:app --reload --port 8000
|
|
57
116
|
|
|
117
|
+
# Test login
|
|
118
|
+
curl -X POST http://localhost:8000/auth/login -H "Content-Type: application/json" -d '{"email": "admin@example.com", "password": "admin123"}'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Step 4: Install Frontend Dependencies
|
|
122
|
+
```bash
|
|
123
|
+
npm install axios zustand
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Step 5: Create Auth Store (Frontend)
|
|
58
127
|
```tsx
|
|
128
|
+
// src/stores/useAuthStore.ts
|
|
129
|
+
import { create } from 'zustand';
|
|
130
|
+
import { authApi } from '@/services/authApi';
|
|
131
|
+
|
|
59
132
|
interface AuthState {
|
|
60
133
|
token: string | null;
|
|
61
134
|
user: User | null;
|
|
135
|
+
isAuthenticated: boolean;
|
|
62
136
|
login: (email: string, password: string) => Promise<void>;
|
|
63
137
|
logout: () => void;
|
|
64
|
-
|
|
138
|
+
setToken: (token: string) => void;
|
|
65
139
|
}
|
|
66
140
|
|
|
67
141
|
export const useAuthStore = create<AuthState>((set) => ({
|
|
@@ -70,21 +144,130 @@ export const useAuthStore = create<AuthState>((set) => ({
|
|
|
70
144
|
isAuthenticated: !!localStorage.getItem('token'),
|
|
71
145
|
|
|
72
146
|
login: async (email, password) => {
|
|
73
|
-
const { access_token, user } = await authApi.login(email, password);
|
|
147
|
+
const { access_token, refresh_token, user } = await authApi.login(email, password);
|
|
74
148
|
localStorage.setItem('token', access_token);
|
|
149
|
+
localStorage.setItem('refresh_token', refresh_token);
|
|
75
150
|
set({ token: access_token, user, isAuthenticated: true });
|
|
76
151
|
},
|
|
77
152
|
|
|
78
153
|
logout: () => {
|
|
79
154
|
localStorage.removeItem('token');
|
|
155
|
+
localStorage.removeItem('refresh_token');
|
|
80
156
|
set({ token: null, user: null, isAuthenticated: false });
|
|
81
157
|
},
|
|
158
|
+
|
|
159
|
+
setToken: (token) => {
|
|
160
|
+
localStorage.setItem('token', token);
|
|
161
|
+
set({ token });
|
|
162
|
+
},
|
|
82
163
|
}));
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Step 6: Set Up Axios Interceptors
|
|
167
|
+
```tsx
|
|
168
|
+
// src/lib/api.ts
|
|
169
|
+
import axios from 'axios';
|
|
170
|
+
import { useAuthStore } from '@/stores/useAuthStore';
|
|
83
171
|
|
|
84
|
-
|
|
172
|
+
export const api = axios.create({
|
|
173
|
+
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:8000/api/v1',
|
|
174
|
+
timeout: 10000,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Add auth header to every request
|
|
85
178
|
api.interceptors.request.use((config) => {
|
|
86
179
|
const token = localStorage.getItem('token');
|
|
87
|
-
if (token)
|
|
180
|
+
if (token) {
|
|
181
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
182
|
+
}
|
|
88
183
|
return config;
|
|
89
184
|
});
|
|
185
|
+
|
|
186
|
+
// Handle 401 responses: try refresh, then logout
|
|
187
|
+
api.interceptors.response.use(
|
|
188
|
+
(response) => response.data,
|
|
189
|
+
async (error) => {
|
|
190
|
+
if (error.response?.status === 401) {
|
|
191
|
+
const refreshToken = localStorage.getItem('refresh_token');
|
|
192
|
+
if (refreshToken && !error.config._retry) {
|
|
193
|
+
error.config._retry = true;
|
|
194
|
+
try {
|
|
195
|
+
const { access_token } = await authApi.refresh(refreshToken);
|
|
196
|
+
useAuthStore.getState().setToken(access_token);
|
|
197
|
+
error.config.headers.Authorization = `Bearer ${access_token}`;
|
|
198
|
+
return api(error.config);
|
|
199
|
+
} catch {
|
|
200
|
+
useAuthStore.getState().logout();
|
|
201
|
+
window.location.href = '/login';
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
useAuthStore.getState().logout();
|
|
205
|
+
window.location.href = '/login';
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return Promise.reject(error.response?.data || error);
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Step 7: Create Protected Route Wrapper
|
|
214
|
+
```tsx
|
|
215
|
+
// src/components/ProtectedRoute.tsx
|
|
216
|
+
import { Navigate } from 'react-router-dom';
|
|
217
|
+
import { useAuthStore } from '@/stores/useAuthStore';
|
|
218
|
+
|
|
219
|
+
export function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
|
220
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
221
|
+
|
|
222
|
+
if (!isAuthenticated) {
|
|
223
|
+
return <Navigate to="/login" replace />;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return <>{children}</>;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Usage in router:
|
|
230
|
+
// <Route path="/dashboard" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
|
|
90
231
|
```
|
|
232
|
+
|
|
233
|
+
### Step 8: Verify the Auth Flow
|
|
234
|
+
```bash
|
|
235
|
+
npm run dev
|
|
236
|
+
# 1. Navigate to /login
|
|
237
|
+
# 2. Enter credentials and submit
|
|
238
|
+
# 3. Verify redirect to /dashboard
|
|
239
|
+
# 4. Verify protected routes redirect to /login when not authenticated
|
|
240
|
+
# 5. Verify token is in localStorage
|
|
241
|
+
# 6. Verify API calls include Authorization header (check Network tab)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Resources
|
|
245
|
+
- `references/jwt-security.md` - JWT security best practices and common vulnerabilities
|
|
246
|
+
|
|
247
|
+
## Examples
|
|
248
|
+
### Example 1: Add Login to an Existing App
|
|
249
|
+
User asks: "Add authentication to our React app with a login page"
|
|
250
|
+
Response approach:
|
|
251
|
+
1. Create backend auth endpoints (login, refresh, me)
|
|
252
|
+
2. Create useAuthStore with Zustand
|
|
253
|
+
3. Set up Axios interceptors for token management
|
|
254
|
+
4. Create LoginPage component with form
|
|
255
|
+
5. Wrap routes in ProtectedRoute
|
|
256
|
+
6. Test the full flow end-to-end
|
|
257
|
+
|
|
258
|
+
### Example 2: Fix Token Expiry Issues
|
|
259
|
+
User asks: "Users keep getting logged out, how do I add token refresh?"
|
|
260
|
+
Response approach:
|
|
261
|
+
1. Add refresh token endpoint to backend
|
|
262
|
+
2. Store refresh token in localStorage alongside access token
|
|
263
|
+
3. Add 401 interceptor that tries refresh before logging out
|
|
264
|
+
4. Set retry flag to prevent infinite refresh loops
|
|
265
|
+
5. Test by setting short access token expiry and verifying refresh works
|
|
266
|
+
|
|
267
|
+
## Notes
|
|
268
|
+
- Never store tokens in cookies without httpOnly + secure + sameSite flags
|
|
269
|
+
- Set a reasonable access token expiry (1 hour) and longer refresh token (7 days)
|
|
270
|
+
- Always validate token type ("access" vs "refresh") server-side
|
|
271
|
+
- Use environment variables for JWT_SECRET, never hardcode
|
|
272
|
+
- Implement rate limiting on login endpoints to prevent brute force
|
|
273
|
+
- Clear all stored tokens on logout
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# JWT Security Best Practices
|
|
2
|
+
|
|
3
|
+
## Token Storage
|
|
4
|
+
| Method | Security | XSS Risk | CSRF Risk |
|
|
5
|
+
|---|---|---|---|
|
|
6
|
+
| localStorage | Low | High | None |
|
|
7
|
+
| httpOnly Cookie | High | None | Medium |
|
|
8
|
+
| In-memory (variable) | Highest | None | None |
|
|
9
|
+
|
|
10
|
+
Recommendation: Use httpOnly cookies for production, localStorage for development/SPAs.
|
|
11
|
+
|
|
12
|
+
## Token Expiry
|
|
13
|
+
| Token Type | Recommended Expiry |
|
|
14
|
+
|---|---|
|
|
15
|
+
| Access Token | 15 min - 1 hour |
|
|
16
|
+
| Refresh Token | 7 - 30 days |
|
|
17
|
+
|
|
18
|
+
## Security Checklist
|
|
19
|
+
- [ ] Use strong secret key (256+ bits): `openssl rand -hex 32`
|
|
20
|
+
- [ ] Set algorithm explicitly (HS256 or RS256), never "none"
|
|
21
|
+
- [ ] Validate token type (access vs refresh) on every endpoint
|
|
22
|
+
- [ ] Implement refresh token rotation (new refresh token on each use)
|
|
23
|
+
- [ ] Rate limit login endpoint (5 attempts per minute)
|
|
24
|
+
- [ ] Log failed login attempts
|
|
25
|
+
- [ ] Clear all tokens on logout (both client and server)
|
|
26
|
+
- [ ] Use HTTPS in production
|
|
27
|
+
|
|
28
|
+
## Common Vulnerabilities
|
|
29
|
+
1. **Algorithm confusion**: Always specify algorithm in `jwt.decode()`, never accept from token
|
|
30
|
+
2. **Missing expiry check**: Always include `exp` claim
|
|
31
|
+
3. **Token reuse after logout**: Maintain a blocklist or use short-lived tokens
|
|
32
|
+
4. **Refresh without rotation**: Rotate refresh tokens to limit damage from stolen tokens
|
|
33
|
+
|
|
34
|
+
## Generating a Secure Secret
|
|
35
|
+
```bash
|
|
36
|
+
# Generate a 256-bit hex secret
|
|
37
|
+
openssl rand -hex 32
|
|
38
|
+
|
|
39
|
+
# Or with Python
|
|
40
|
+
python -c "import secrets; print(secrets.token_hex(32))"
|
|
41
|
+
```
|