Finalproject alj - #293
Conversation
- Ficha del proyecto: Aida, Your Cleaning Coach - Descripción general: gamificación, shopping cart, IA adaptativa - Arquitectura técnica: AWS serverless, Lambda Layer, Clean Architecture - Modelo de datos: 9 tablas PostgreSQL con diagrama mermaid - Especificación API: endpoints principales en OpenAPI - Historias de usuario: 3 HU principales (onboarding, shopping cart, tolerancia a inactividad) - Tickets de trabajo: AID-52, AID-78, AID-96 documentados - Pull requests: 3 PRs principales (LIDR-academy#32, LIDR-academy#38, LIDR-academy#40) - Diseño UX: wireframes, paleta de colores, flujos - Instrucciones instalación: backend, web, mobile, infrastructure Información extraída de documentación del sistema: - DI-01-OVERVIEW.md: producto, funcionalidades, MVP scope - DI-02-ARQUITECTURA.md: arquitectura técnica, stacks CDK, Lambda catalog - DI-04-SCHEMA.md: modelo de datos, 9 tablas, constraints - DI-08-SEGURIDAD.md: security rules, OWASP compliance Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…esarrollo Registro de prompts clave utilizados en: 1. Descripción general del producto - Prompt 1: Propuesta de valor vs competencia - Prompt 2: Arquetipos de usuario y presets automáticos - Prompt 3: Matriz de gamificación sostenible 2. Arquitectura del sistema - Prompt 1: Decisiones técnicas (ADRs serverless) - Prompt 2: Diseño de 8 stacks CDK con dependencias - Prompt 3: Flujo de request de extremo a extremo 3. Modelo de datos - Prompt 1: Schema PostgreSQL (9 tablas) + decisiones - Prompt 2: Trade-offs de almacenamiento de tips IA 4. Especificación de API - Prompt 1: Contract de API (/v1, error envelope, CORS, rate limit) - Prompt 2: Diseño de Pydantic schemas v2 + validaciones 5. Historias de usuario - Prompt 1: User stories en formato Gherkin (BDD) 6. Tickets de trabajo - Prompt 1: Especificación detallada de AID-52 7. Pull requests - Prompt 1: Checklist de security + code review - Prompt 2: Generación de conventional commits Conclusión: Claude fue crítico en todas las fases (product, arch, backend, frontend, mobile, infrastructure, testing, code quality) para delivery de MVP completo, testeable y documentado en 8 semanas con 1 developer. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Prompts + respuestas completas de: 1. Descripción general del producto ✓ Propuesta de valor (4 capas diferenciadores vs Tody/Sweepy/Habitica/FlyLady) ✓ Arquetipos de usuario (5 segmentos con JSON de presets automáticos) ✓ Matriz de gamificación (XP formula, personajes, campañas estacionales) 2. Arquitectura del sistema ✓ ADRs con trade-offs (Database, Backend, API, Auth, IaC, IA) ✓ Decisión: PostgreSQL t4g.micro (/mes vs Aurora) ✓ Decisión: Lambda per endpoint + Layer (vs monolito/GraphQL) ✓ Decisión: HTTP API (/bin/zsh.40/M vs .50/M REST API) ✓ Decisión: CDK Python (testeable vs YAML CloudFormation) ✓ Decisión: Claude Haiku+Sonnet (caching 24h reduce costos 80%) 3. Especificación de API ✓ Error envelope estándar (error, error_code, request_id) ✓ Success response structure ✓ Rate limit 429 handling ✓ CORS allowlist (nunca * en production) 4. Pull requests & Code Review ✓ Security checklist detallado (secrets, SQL injection, IDOR, XSS) ✓ Code quality checklist (Clean Architecture, Pydantic, type hints, coverage) ✓ Ejemplo de PR review (PR LIDR-academy#32 con findings/suggestions) Todas las respuestas son: - Concretas (incluyen código, JSON, ejemplos) - Justificadas (por qué se eligió cada opción) - Reutilizables (templates para futuras PRs/decisions) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…referencias externas Changes: - README.md: estructura simplificada (0–7 secciones) * Elimina referencias a docs/DI-XX que no existen en el repo * Mantiene nomenclatura original de títulos/subtítulos * Contenido focusado en MVP (8 semanas, 1 developer) * Incluye: ficha, descripción, arquitectura, modelo de datos, API, HU, tickets, PRs - prompts.md: estructura simplificada (1–7 secciones) * Cada sección: máximo 3 prompts con respuesta (prompt + código/output) * Elimina referencias cruzadas a documentos inexistentes * Mantiene valor agregado de Claude en cada fase * Incluyé ejemplos concretos (JSON, Python, OpenAPI, Gherkin, conventional commits) Nomenclatura mantenida: - Ficha del proyecto (0.1–0.5) - Descripción general (1.1–1.4) - Arquitectura (2.1–2.6) - Modelo de datos (3.1–3.2) - API (4.1 endpoints principales) - Historias de usuario (5 × 3 HU) - Tickets (6 × 3 tickets) - Pull requests (7 × 3 PRs) Referencias eliminadas: - docs/DI-01-OVERVIEW.md - docs/DI-02-ARQUITECTURA.md - docs/DI-04-SCHEMA.md - docs/DI-08-SEGURIDAD.md - Cualquier reference a archivos dentro del proyecto que no existen Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Cambios: - README.md: estructura exacta de LIDR (0–7 secciones) * 0. Ficha del proyecto (0.1–0.5) * 1. Descripción general (1.1–1.4) * 2. Arquitectura del Sistema (2.1–2.6) * 3. Modelo de Datos (3.1–3.2) * 4. Especificación de la API * 5. Historias de Usuario * 6. Tickets de Trabajo * 7. Pull Requests - prompts.md: estructura exacta de LIDR (1–7 secciones) * Máximo 3 prompts por sección * Cada prompt con respuesta/código * Sin referencias cruzadas a archivos inexistentes * Ejemplos concretos (JSON, Python, YAML, Gherkin) Nomenclatura mantenida: - Títulos con formato **negrita** donde corresponde - Subtítulos claros y descriptivos - Contenido específico de Aida (no genérico) Referencias internas solo dentro del repo (ninguna a docs/DI-XX) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Cambios: - Estructura exacta de LIDR (0–7 secciones) - Nomenclatura de títulos/subtítulos según template - Contenido específico de Aida (no genérico) - Sin referencias externas a docs/DI-XX Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe PR replaces template sections in ChangesProject documentation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (1)
prompts.md (1)
21-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd language identifiers to all Markdown fences.
The documentation contains multiple unlabeled fenced blocks, triggering MD040 and reducing rendering/tooling quality.
prompts.md#L21-L21: label the prompt/response fences.readme.md#L174-L174: label the architecture diagram fence.readme.md#L222-L222: label the repository-tree fence.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@prompts.md` at line 21, Add language identifiers to every affected Markdown fence: label the prompt/response fences in prompts.md at lines 21-21, the architecture diagram fence in readme.md at lines 174-174, and the repository-tree fence in readme.md at lines 222-222, using identifiers appropriate to each block.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@prompts.md`:
- Around line 390-395: Update the 429 Too Many Requests response example to
include the required request_id field in its error envelope, while preserving
the existing rate-limit fields and structure.
- Around line 227-229: Update the documented COMPUTED cleanliness query to use
PostgreSQL’s scalar GREATEST function instead of MAX for clamping the calculated
value at zero, while preserving the existing days_since and decay_rate
expression.
- Around line 643-645: Update the logging guidance in the IDOR/token-validation
section so cognito_sub is not classified as “no PII”; either remove cognito_sub
from routine logs or explicitly document it as pseudonymous personal data with
retention, access, and redaction controls.
- Around line 385-388: Update the Rate limiting section in prompts.md to define
the schema fields needed by the documented implementation: add the timestamp
column used to track xp_events requests and the TIMESTAMPTZ expires_at column
used for cache TTL cleanup, or explicitly specify the dedicated usage and
expiration mechanism if those fields are not stored directly.
- Around line 289-292: Align the “Queries parametrizadas (SQLAlchemy ORM)” task
query with the documented schema by replacing the undefined tasks/space_id
references with the global task_catalog and its space_type field, or update the
documented schema to define the referenced tasks table and space_id column.
Ensure the resulting query uses schema-defined identifiers and preserves
filtering by required level and space context.
- Around line 352-356: Update CartCreateRequest.model_config to use Pydantic
v2’s extra='forbid' setting so unexpected fields are rejected, and add a
validation test confirming an unknown request field raises a validation error.
In `@readme.md`:
- Around line 353-447: Update the ER diagram to include the documented PRODUCTS
and AI_SUGGESTIONS_CACHE entities with their corresponding fields, and add any
documented relationships. Remove SPACES.cleanliness from the diagram because
cleanliness is computed dynamically rather than stored, keeping the diagram
consistent with the entity descriptions.
- Around line 305-313: Actualiza la sección “Logs” de la documentación para no
afirmar que los registros carecen de PII mientras incluyen el identificador
persistente cognito_sub. Elimina cognito_sub de los logs rutinarios o documenta
explícitamente su tratamiento como dato seudonimizado, junto con los controles
de retención y acceso requeridos; conserva request_id si corresponde.
---
Nitpick comments:
In `@prompts.md`:
- Line 21: Add language identifiers to every affected Markdown fence: label the
prompt/response fences in prompts.md at lines 21-21, the architecture diagram
fence in readme.md at lines 174-174, and the repository-tree fence in readme.md
at lines 222-222, using identifiers appropriate to each block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| Decisión cleanliness: COMPUTED en query | ||
| SELECT MAX(0, 100 - (days_since * decay_rate)) | ||
| Razón: Evita crons, siempre fresco |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
Use PostgreSQL’s scalar function GREATEST, not MAX.
MAX(0, ...) is aggregate syntax and will not implement this scalar clamp. As written, the documented cleanliness query is invalid.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@prompts.md` around lines 227 - 229, Update the documented COMPUTED
cleanliness query to use PostgreSQL’s scalar GREATEST function instead of MAX
for clamping the calculated value at zero, while preserving the existing
days_since and decay_rate expression.
| Queries parametrizadas (SQLAlchemy ORM): | ||
| - SELECT * FROM tasks WHERE required_level <= ? AND space_id = ? | ||
| - SELECT * FROM carts WHERE user_id = ? AND status = 'active' | ||
| - SELECT MAX(...) cleanliness FROM spaces WHERE user_id = ? (dinámico) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Align the query with the documented schema.
The schema defines a global task_catalog with space_type, but this query references a tasks table and space_id. Update either the schema or query; otherwise the documented operation cannot run.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@prompts.md` around lines 289 - 292, Align the “Queries parametrizadas
(SQLAlchemy ORM)” task query with the documented schema by replacing the
undefined tasks/space_id references with the global task_catalog and its
space_type field, or update the documented schema to define the referenced tasks
table and space_id column. Ensure the resulting query uses schema-defined
identifiers and preserves filtering by required level and space context.
| class CartCreateRequest(BaseModel): | ||
| items: list[CartItemInput] | ||
| suggested_by_ai: bool = False | ||
|
|
||
| model_config = ConfigDict(forbid='forbid') |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files matching prompts.md / py project files =="
git ls-files | rg '(^|/)(prompts\.md|pyproject\.toml|poetry\.lock|requirements.*\.txt|Pipfile|uv\.lock)$' || true
echo
echo "== relevant prompts.md lines =="
if [ -f prompts.md ]; then
nl -ba prompts.md | sed -n '330,370p'
fi
echo
echo "== pydantic declarations/config examples in code docs =="
rg -n "ConfigDict|forbid='forbid'|extra='forbid'|extra = |forbid" -S . || trueRepository: LIDR-academy/AI4Devs-finalproject
Length of output: 312
🌐 Web query:
Pydantic v2 ConfigDict extra='forbid' unknown fields documentation
💡 Result:
In Pydantic v2, setting extra='forbid' in the ConfigDict causes Pydantic to raise a ValidationError when extra (undefined) fields are provided during model initialization [1][2][3]. You can configure this behavior in two primary ways: 1. Using ConfigDict: Define the model_config attribute within your class using the ConfigDict class [1][2][4]. from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): x: int model_config = ConfigDict(extra='forbid') try: Model(x=1, y='a') except ValidationError as exc: print(exc) # Output: 1 validation error for Model # y # Extra inputs are not permitted [type=extra_forbidden, input_value='a', input_type=str] 2. Using Class Kwargs: You can also pass the configuration option directly as a keyword argument in the model definition [5][6]. from pydantic import BaseModel, ValidationError class Model(BaseModel, extra='forbid'): a: str try: Model(a='spam', b='oh no') except ValidationError as exc: print(exc) # Output: 1 validation error for Model # b # Extra inputs are not permitted [type=extra_forbidden, input_value='oh no', input_type=str] Additionally, you can override the configured extra behavior at runtime by passing the extra argument to validation methods like model_validate [2]: Model.model_validate({"x": 1, "y": 2}, extra="forbid") The default behavior for Pydantic models is extra='ignore' [1][3][6].
Citations:
- 1: https://pydantic.dev/docs/validation/2.11/api/pydantic/config/
- 2: https://pydantic.dev/docs/validation/latest/api/pydantic/config/
- 3: https://pydantic.dev/docs/validation/2.6/api/pydantic/config/
- 4: https://pydantic.dev/docs/validation/2.6/concepts/models/
- 5: https://pydantic.dev/docs/validation/2.6/concepts/config/
- 6: https://pydantic.dev/docs/validation/2.0/usage/model_config/
🌐 Web query:
Pydantic ConfigDict forbid key
💡 Result:
In Pydantic, you can prevent extra keys from being passed to a model by setting the extra configuration option to 'forbid' within the model's ConfigDict [1][2]. When this is enabled, Pydantic will raise a ValidationError if any extra data is provided during model initialization [1][3]. You can set this in your model configuration as follows: from pydantic import BaseModel, ConfigDict class MyModel(BaseModel): field1: str model_config = ConfigDict(extra='forbid') Additionally, you can override this configuration at runtime by passing extra='forbid' to validation methods such as model_validate [1][4]: MyModel.model_validate({"field1": "value", "extra_key": "data"}, extra="forbid") The available options for the extra configuration are: - 'ignore': Extra data is ignored (the default behavior) [1][2]. - 'forbid': Extra data is not permitted, and a ValidationError is raised [1][3]. - 'allow': Extra data is allowed and stored in the pydantic_extra attribute [1][2].
Citations:
- 1: https://pydantic.dev/docs/validation/latest/api/pydantic/config/
- 2: https://pydantic.dev/docs/validation/2.11/api/pydantic/config/
- 3: https://docs.pydantic.dev/2.1/usage/model_config/
- 4: https://pydantic.dev/docs/validation/dev/api/pydantic/config/
Use the Pydantic v2 extra='forbid' config key.
ConfigDict(forbid='forbid') is not the v2 unknown-field setting, so unexpected request fields can be accepted. Set model_config = ConfigDict(extra='forbid') and add a validation test that rejects an unexpected field.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@prompts.md` around lines 352 - 356, Update CartCreateRequest.model_config to
use Pydantic v2’s extra='forbid' setting so unexpected fields are rejected, and
add a validation test confirming an unknown request field raises a validation
error.
Source: MCP tools
| Rate limiting: | ||
| - API Gateway: throttling nativo (Throttle: 10000 requests/min) | ||
| - IA: track en DB (xp_events + timestamp), check before calling Claude | ||
| - Cache: expires_at TIMESTAMPTZ con trigger cleanup |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Document the fields required for rate limiting and TTL cleanup.
The implementation refers to an xp_events timestamp and cache expires_at, but neither field is defined in the documented schema. Add those columns or specify a dedicated usage/expiration mechanism before implementation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@prompts.md` around lines 385 - 388, Update the Rate limiting section in
prompts.md to define the schema fields needed by the documented implementation:
add the timestamp column used to track xp_events requests and the TIMESTAMPTZ
expires_at column used for cache TTL cleanup, or explicitly specify the
dedicated usage and expiration mechanism if those fields are not stored
directly.
| Response 429 Too Many Requests: | ||
| { | ||
| "error": "Rate limit exceeded", | ||
| "error_code": "RATE_LIMIT_EXCEEDED", | ||
| "retry_after_seconds": 3600 | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Include request_id in the 429 envelope.
The standard error contract requires request_id, but the rate-limit example omits it. Keep the 429 response structurally compatible with every other API error.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@prompts.md` around lines 390 - 395, Update the 429 Too Many Requests response
example to include the required request_id field in its error envelope, while
preserving the existing rate-limit fields and structure.
| ✓ IDOR: user_id del JWT (imposible forjar) | ||
| ✓ Token validation: event['requestContext']['authorizer']['jwt']['claims'] | ||
| ✓ Logging: cognito_sub only, no email/passwords |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not classify cognito_sub logs as “no PII” without a privacy policy.
This is a stable user identifier, not anonymous telemetry. Either remove it from routine logs or document it as pseudonymous personal data with retention, access, and redaction controls. (edpb.europa.eu)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@prompts.md` around lines 643 - 645, Update the logging guidance in the
IDOR/token-validation section so cognito_sub is not classified as “no PII”;
either remove cognito_sub from routine logs or explicitly document it as
pseudonymous personal data with retention, access, and redaction controls.
Source: MCP tools
| **Implementación:** | ||
| - **Autenticación:** Cognito JWT (email/password + Google) | ||
| - **Autorización:** Anti-IDOR (queries filtradas por user_id), admin vía grupo Cognito `aida-admins` | ||
| - **Secretos:** AWS Secrets Manager (DB credentials + API keys) | ||
| - **Red:** RDS en subnets privadas, Lambdas en VPC, NAT Gateway para salida controlada | ||
| - **Validación:** Pydantic v2 en frontend de cada Lambda | ||
| - **IA:** Input tratado como dato, no instrucción; caching de system prompt separado | ||
| - **Logs:** Sin PII (email/tokens), sí `cognito_sub` + `request_id` | ||
|
|
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Align the logging claim with the actual data being logged.
cognito_sub is a persistent user identifier, so “logs without PII” is too strong. Remove it from routine logs or document the required pseudonymous-data retention and access controls. (edpb.europa.eu)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@readme.md` around lines 305 - 313, Actualiza la sección “Logs” de la
documentación para no afirmar que los registros carecen de PII mientras incluyen
el identificador persistente cognito_sub. Elimina cognito_sub de los logs
rutinarios o documenta explícitamente su tratamiento como dato seudonimizado,
junto con los controles de retención y acceso requeridos; conserva request_id si
corresponde.
Source: MCP tools
| ```mermaid | ||
| erDiagram | ||
| USERS ||--o{ SPACES : has | ||
| USERS ||--o{ CARTS : has | ||
| USERS ||--|| USER_EQUIPMENT : has | ||
| USERS ||--o{ XP_EVENTS : generates | ||
| SPACES ||--o{ CART_ITEMS : contains | ||
| CARTS ||--o{ CART_ITEMS : contains | ||
| TASK_CATALOG ||--o{ CART_ITEMS : references | ||
|
|
||
| USERS { | ||
| UUID id PK | ||
| VARCHAR cognito_sub UK | ||
| VARCHAR email UK | ||
| VARCHAR name | ||
| VARCHAR archetype | ||
| VARCHAR character_type | ||
| INT character_level | ||
| INT total_xp | ||
| INT equipment_level | ||
| TIMESTAMPTZ last_active_at | ||
| BOOLEAN is_suspended | ||
| } | ||
|
|
||
| SPACES { | ||
| UUID id PK | ||
| UUID user_id FK | ||
| VARCHAR space_type | ||
| VARCHAR name | ||
| INT cleanliness | ||
| TIMESTAMPTZ last_cleaned_at | ||
| } | ||
|
|
||
| TASK_CATALOG { | ||
| UUID id PK | ||
| VARCHAR space_type | ||
| VARCHAR name | ||
| TEXT description | ||
| VARCHAR category | ||
| INT xp_reward | ||
| INT required_level | ||
| BOOLEAN is_active | ||
| } | ||
|
|
||
| CARTS { | ||
| UUID id PK | ||
| UUID user_id FK | ||
| VARCHAR status | ||
| TIMESTAMPTZ created_at | ||
| TIMESTAMPTZ completed_at | ||
| } | ||
|
|
||
| CART_ITEMS { | ||
| UUID id PK | ||
| UUID cart_id FK | ||
| UUID task_id FK | ||
| UUID space_id FK | ||
| BOOLEAN completed | ||
| } | ||
|
|
||
| USER_EQUIPMENT { | ||
| UUID id PK | ||
| UUID user_id FK | ||
| INT level | ||
| JSONB inventory | ||
| } | ||
|
|
||
| XP_EVENTS { | ||
| UUID id PK | ||
| UUID user_id FK | ||
| INT xp_amount | ||
| VARCHAR event_type | ||
| JSONB metadata | ||
| } | ||
| ``` | ||
|
|
||
| ### **3.2. Descripción de entidades principales:** | ||
|
|
||
| > Recuerda incluir el máximo detalle de cada entidad, como el nombre y tipo de cada atributo, descripción breve si procede, claves primarias y foráneas, relaciones y tipo de relación, restricciones (unique, not null…), etc. | ||
| **users:** Perfil del usuario, resultado del onboarding, gamificación. PKs UUID, cognito_sub UNIQUE, email UNIQUE, `is_suspended` para gestión admin, `last_active_at` para realismo conductual. | ||
|
|
||
| **spaces:** Espacios/ambientes del hogar del usuario. FK users con CASCADE. UNIQUE(user_id, space_type). `cleanliness` calculado dinámicamente en queries, nunca stored. | ||
|
|
||
| **task_catalog:** Catálogo global de tareas (admin-managed). Los usuarios de la app solo leen y seleccionan; nunca crean ni editan. Campos: name, description, space_type, category (basic/special/deep_clean), frequency_days, estimated_minutes, required_level, xp_reward, tips (JSONB), is_active. | ||
|
|
||
| **carts:** Carritos de limpieza (sesiones del usuario). Status: active, completed, abandoned. `suggested_by_ai` booleano. | ||
|
|
||
| **cart_items:** Tareas dentro de un carrito. FK carts CASCADE, task_id, space_id, completed bool. | ||
|
|
||
| **user_equipment:** Nivel de equipamiento (0–2) e inventario de productos (JSONB). | ||
|
|
||
| **xp_events:** Registro granular de XP (auditoría). event_type: task_completed, cart_completed, etc. Metadata en JSONB. | ||
|
|
||
| **products:** Catálogo de productos de limpieza (admin-managed). Nivel (0–2), categoría, descripción, is_active. | ||
|
|
||
| **ai_suggestions_cache:** Cache 24h de respuestas Claude. Clave: (user_id, suggestion_type, context_hash SHA-256). |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Synchronize the ER diagram with the documented schema.
The diagram omits PRODUCTS and AI_SUGGESTIONS_CACHE, despite both being documented entities, and shows SPACES.cleanliness as stored while the text says it is computed. Update the diagram and fields together to prevent conflicting implementation assumptions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@readme.md` around lines 353 - 447, Update the ER diagram to include the
documented PRODUCTS and AI_SUGGESTIONS_CACHE entities with their corresponding
fields, and add any documented relationships. Remove SPACES.cleanliness from the
diagram because cleanliness is computed dynamically rather than stored, keeping
the diagram consistent with the entity descriptions.
Final project Andrés Lagos Jara
Summary by CodeRabbit