x
This commit is contained in:
1 parent
70877882b0
commit
ce2f4cf0c8
93 files changed
+4200
-67
No files matched your search
@@ -0,0 +1,58 @@
|
||||
# BRIEFING — 2026-06-29T21:35:55Z
|
||||
|
||||
## Mission
|
||||
Review the backend and DB changes implemented in M2 for correctness, robustness, type-safety, and schema conformance.
|
||||
|
||||
## 🔒 My Identity
|
||||
- Archetype: Reviewer & Critic
|
||||
- Roles: reviewer, critic
|
||||
- Working directory: /home/ti/git/homaroma/.agents/reviewer_m2_2_v2
|
||||
- Original parent: 8e727cf6-d863-41ec-9bd2-f8dead86db2a
|
||||
- Milestone: Milestone 2: Backend & DB
|
||||
- Instance: Reviewer 2 (v2)
|
||||
|
||||
## 🔒 Key Constraints
|
||||
- Review-only — do NOT modify implementation code
|
||||
- Network restriction: CODE_ONLY (no external URLs, curl/wget, etc.)
|
||||
- Only write files inside my own folder (/home/ti/git/homaroma/.agents/reviewer_m2_2_v2)
|
||||
|
||||
## Current Parent
|
||||
- Conversation ID: 8e727cf6-d863-41ec-9bd2-f8dead86db2a
|
||||
- Updated: 2026-06-29T21:35:55Z
|
||||
|
||||
## Review Scope
|
||||
- **Files to review**:
|
||||
- `apps/backend/prisma/schema.prisma`
|
||||
- `packages/types/index.ts`
|
||||
- `apps/backend/src/routes/menus.ts`
|
||||
- `apps/mcp-server/menu-tools.ts`
|
||||
- `apps/mcp-server/menu-toolkit.ts`
|
||||
- **Interface contracts**: API endpoints, Prisma schema definitions, database structures, TypeScript definitions.
|
||||
- **Review criteria**: correctness, robustness, type-safety, schema conformance, TypeBox validation, database transaction mapping.
|
||||
|
||||
## Key Decisions Made
|
||||
- Performed detailed review of all target M2 files.
|
||||
- Completed typescript check and ran backend E2E api verification tests.
|
||||
- Issued verdict: FAIL (Requires changes).
|
||||
|
||||
## Artifact Index
|
||||
- /home/ti/git/homaroma/.agents/reviewer_m2_2_v2/review.md — Final review report containing findings and FAIL verdict.
|
||||
|
||||
## Review Checklist
|
||||
- **Items reviewed**:
|
||||
- Prisma schema (`apps/backend/prisma/schema.prisma`) — Checked (Cascade deletes ok, schema definitions match)
|
||||
- Shared types (`packages/types/index.ts`) — Checked (Missing `isActive` in Menu type interface)
|
||||
- Backend routes (`apps/backend/src/routes/menus.ts`) — Checked (Found transaction atomicity, unmapped fields, missing validation schema, missing import extensions, return mismatch)
|
||||
- MCP Server tools (`menu-tools.ts` & `menu-toolkit.ts`) — Checked (Found translation spreading bug)
|
||||
- **Verdict**: FAIL (Requires Changes)
|
||||
- **Unverified claims**: Frontend layout integration (out of scope for Backend Milestone).
|
||||
|
||||
## Attack Surface
|
||||
- **Hypotheses tested**:
|
||||
- Transaction atomicity in PUT: Proved non-atomic due to parent `prisma` updates before transaction.
|
||||
- Type-safety compilation under NodeNext: Proved relative import compilation errors due to missing `.js` extensions.
|
||||
- Translation array merging: Proved spreading array of translation objects corrupts the label/title shape.
|
||||
- **Vulnerabilities found**:
|
||||
- Database inconsistent state on partial transaction failure.
|
||||
- Insecure PATCH route lacking TypeBox schema validation.
|
||||
- **Untested angles**: Persistent snapshot store (uses in-memory map which resets on server restart).
|
||||
@@ -0,0 +1,13 @@
|
||||
## 2026-06-29T11:49:03Z
|
||||
|
||||
You are Reviewer 2 (v2) for Milestone 2: Backend & DB.
|
||||
Your working directory is /home/ti/git/homaroma/.agents/reviewer_m2_2_v2.
|
||||
Please review the changes implemented by the Worker in M2 for correctness, robustness, type-safety, and schema conformance:
|
||||
- Prisma schema (`apps/backend/prisma/schema.prisma`)
|
||||
- Shared types (`packages/types/index.ts`)
|
||||
- Backend routes (`apps/backend/src/routes/menus.ts`)
|
||||
- MCP Server tools (`apps/mcp-server/menu-tools.ts` and `apps/mcp-server/menu-toolkit.ts`)
|
||||
|
||||
Look for potential bugs, unmapped fields in transactions, Elysia TypeBox schema mismatches, and TypeScript type-safety issues.
|
||||
Write your findings and review verdict (PASS/FAIL) in `/home/ti/git/homaroma/.agents/reviewer_m2_2_v2/review.md`.
|
||||
Once finished, send a message back with your verdict and a summary.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Handoff Report — Milestone 2: Backend & DB Review (Reviewer 2 - v2)
|
||||
|
||||
This handoff report summarizes the findings of Reviewer 2 (v2) for Milestone 2.
|
||||
|
||||
## 1. Observation
|
||||
The following file observations and logs were recorded:
|
||||
* **Non-Atomic PUT Updates**: In `apps/backend/src/routes/menus.ts`, the Menu record is updated/created outside the database transaction block (lines 97-101), while MenuItems are created/deleted/updated inside the transaction (lines 103-153).
|
||||
* **Missing POST Fields**: In `apps/backend/src/routes/menus.ts` (lines 32-73), the `POST /menus` endpoint's validation schema and DB query do not include or map the `payload` and `isActive` fields.
|
||||
* **Missing validation on PATCH**: In `apps/backend/src/routes/menus.ts` (lines 183-228), the `PATCH /items/:id/translations` endpoint does not pass a TypeBox validation schema to Elysia.
|
||||
* **Relative Import Failures**: `apps/backend/src/routes/menus.ts` (lines 2-3) uses:
|
||||
```typescript
|
||||
import prisma from "../lib/prisma";
|
||||
import { adminOnly } from "../middleware/auth";
|
||||
```
|
||||
This causes typescript compilation errors under the `NodeNext` ECMAScript Module Resolution, yielding `error TS2835: Relative import paths need explicit file extensions...`.
|
||||
* **GET Mock/Status Mismatch**: In `apps/backend/src/routes/menus.ts` (lines 26-28), `GET /menus/:name` returns a mock object without an `id` field and 200 OK status when the menu is not found:
|
||||
```typescript
|
||||
return { name, items: [], payload: null, rootImage: null, isActive: false };
|
||||
```
|
||||
* **Missing Type Property**: In `packages/types/index.ts` (lines 205-211), the `Menu` interface lacks the `isActive` property.
|
||||
* **Translation Corrupting Merging**: In `apps/mcp-server/menu-tools.ts` (line 284), translations are merged using `{ ...nextNode.translations }`. If `translations` is an array (e.g. `[{ langCode: "th", label: "..." }]`), it creates index keys (`{ "0": ... }`) in the translatable object.
|
||||
|
||||
## 2. Logic Chain
|
||||
* If a PUT request experiences a database failure during transaction execution (such as `MenuItem` insertion failure), the preceding `Menu` update/creation has already committed on the standard `prisma` client. Therefore, the rollback is partial and database consistency is violated.
|
||||
* Under `NodeNext` resolution, relative paths must include extensions. Thus, `import` statements without `.js` break the production build compilation.
|
||||
* Spreading an array inside an object converts the array elements into index properties. If `translations` is an array of objects, `{ ...nextNode.translations }` yields `{ "0": { langCode: "th", label: "..." } }`, which corrupts the structure and causes storefront translation retrieval failures.
|
||||
* Returning a 200 status with an `id`-less mock object for non-existent resources breaks frontend type assumptions and impedes 404 error handling in the client.
|
||||
|
||||
## 3. Caveats
|
||||
* The review was restricted to the backend and MCP server layers. Frontend UI components and layouts (in `apps/website` and `apps/spa`) were not inspected.
|
||||
|
||||
## 4. Conclusion
|
||||
The M2 backend changes do not fully meet correctness, robustness, type-safety, and schema conformance criteria. The verdict is **FAIL**. Major fixes are required for transaction safety, import compliance, TypeBox route validation, and translation merging logic.
|
||||
|
||||
## 5. Verification Method
|
||||
* **Type Safety Verification**:
|
||||
Run `bunx tsc -p apps/backend/tsconfig.json --noEmit` from the root directory and ensure no errors are reported in the menu routes.
|
||||
* **API Behavior Verification**:
|
||||
Start the backend and run the challenger script:
|
||||
`bun apps/backend/test_menu_api_challenger.ts`
|
||||
Confirm that duplicate name checks and atomic PUT operations are correct.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Progress Heartbeat
|
||||
|
||||
Last visited: 2026-06-29T21:35:45Z
|
||||
|
||||
## Status
|
||||
- Analyzed the Prisma schema, shared types, menus route, and MCP server tools.
|
||||
- Performed backend compile and ran API verification tests.
|
||||
- Identified multiple issues:
|
||||
1. Transaction integrity issue (Menu updated outside transaction in PUT).
|
||||
2. Unmapped fields `payload` and `isActive` in POST route.
|
||||
3. Missing TypeBox schema validation in PATCH route.
|
||||
4. Type-safety compilation errors (missing `.js` extensions under NodeNext).
|
||||
5. Missing `isActive` in shared Menu type interface.
|
||||
6. Return type mismatch in GET /:name when menu is not found (missing `id` and returns 200 instead of 404).
|
||||
7. Translation array spreading bug in `applyMenuAddNode`.
|
||||
- Preparing the final review report `review.md`.
|
||||
@@ -0,0 +1,128 @@
|
||||
# Review Report — Milestone 2: Backend & DB (Reviewer 2 - v2)
|
||||
|
||||
## Review Summary
|
||||
|
||||
**Verdict**: **FAIL** (Requires Changes)
|
||||
|
||||
*The implementation contains multiple critical and major issues regarding transaction atomicity, type safety, unmapped fields, missing validation schemas, and logical data structure corruption in the translation handling of the MCP tool.*
|
||||
|
||||
---
|
||||
|
||||
## Findings
|
||||
|
||||
### 1. [Critical] Transaction Integrity Violation in PUT Route
|
||||
- **What**: In `PUT /menus/:name`, the parent `Menu` record is created or updated using the standard `prisma` client *before and outside* the `prisma.$transaction` block where `MenuItem` and `MenuItemTranslation` records are modified.
|
||||
- **Where**: `apps/backend/src/routes/menus.ts` (Lines 97-101, 103-153)
|
||||
- **Why**: If a database error, unique constraint violation, or connection drop occurs inside the transaction block, the transaction will roll back all modifications to menu items. However, the changes to the `Menu` record (such as update to `payload`, `isActive`, or `rootImage`) will *not* roll back. This violates the ACID properties of the database and can lead to corrupt menu states.
|
||||
- **Suggestion**: Perform the `prisma.menu.findUnique`, `prisma.menu.create`, and `prisma.menu.update` calls inside the transaction callback, executing them on the `tx` transaction client.
|
||||
|
||||
### 2. [Major] Unmapped Fields in POST Route
|
||||
- **What**: `POST /menus` ignores the `payload` and `isActive` fields, preventing menus from being fully configured on creation.
|
||||
- **Where**: `apps/backend/src/routes/menus.ts` (Lines 32-73)
|
||||
- **Why**: The Prisma schema defines `payload` (Json) and `isActive` (Boolean) on the `Menu` model. However, the POST endpoint's TypeBox schema and database mapping omit these fields, preventing users from initializing menu structures or changing active status via POST.
|
||||
- **Suggestion**: Add `payload` and `isActive` to the TypeBox body schema and pass them to the `prisma.menu.create` data parameter.
|
||||
|
||||
### 3. [Major] Missing TypeBox Validation Schema on PATCH Endpoint
|
||||
- **What**: The `.patch("/items/:id/translations")` route completely lacks an Elysia TypeBox validation schema.
|
||||
- **Where**: `apps/backend/src/routes/menus.ts` (Lines 183-228)
|
||||
- **Why**: Bypassing schema validation leaves the endpoint open to arbitrary payloads. The request body is manually parsed after casting to `any` (`const payload = body as any`), violating the project standard of strict TypeBox validation.
|
||||
- **Suggestion**: Pass a TypeBox schema option defining the expected structure of `params` (validating `id` as a number) and `body`.
|
||||
|
||||
### 4. [Major] Relative Import Path Compilation Errors under NodeNext Resolution
|
||||
- **What**: Relative import paths are missing explicit `.js` file extensions.
|
||||
- **Where**: `apps/backend/src/routes/menus.ts` (Lines 2-3)
|
||||
- **Why**: Under ECMAScript Module Resolution (`NodeNext`/`Node16` configured in `tsconfig.json`), TypeScript strictly requires file extensions on relative imports. Without them, the project fails to compile, throwing `TS2835: Relative import paths need explicit file extensions...`.
|
||||
- **Suggestion**: Append `.js` extensions:
|
||||
```typescript
|
||||
import prisma from "../lib/prisma.js";
|
||||
import { adminOnly } from "../middleware/auth.js";
|
||||
```
|
||||
|
||||
### 5. [Major] Return Type and Status Mismatch for Non-Existent Menu
|
||||
- **What**: `GET /menus/:name` returns a mock object without an `id` field and a `200` OK status when a menu is not found.
|
||||
- **Where**: `apps/backend/src/routes/menus.ts` (Lines 16-30)
|
||||
- **Why**: The shared `Menu` interface in `packages/types/index.ts` requires `id: number`. Returning a mock object like `{ name, items: [], payload: null, rootImage: null, isActive: false }` lacks an `id` and violates type conformance. Returning `200` OK instead of `404 Not Found` also hides resource non-existence from the client.
|
||||
- **Suggestion**: Set `set.status = 404` and return a structured error message like `{ error: "Menu not found" }` when a menu is missing.
|
||||
|
||||
### 6. [Minor] Shared Types Menu Interface is Missing `isActive`
|
||||
- **What**: The shared `Menu` interface does not include `isActive`.
|
||||
- **Where**: `packages/types/index.ts` (Lines 205-211)
|
||||
- **Why**: The database model defines `isActive Boolean @default(true)`. Missing it in the TypeScript declaration causes compilation or type-safety issues for consumers.
|
||||
- **Suggestion**: Add `isActive: boolean` to the `Menu` interface.
|
||||
|
||||
### 7. [Major] Translation Array Spreading Bug in MCP Tools
|
||||
- **What**: The `applyMenuAddNode` helper spreads `nextNode.translations` directly into an object, even if it is an array.
|
||||
- **Where**: `apps/mcp-server/menu-tools.ts` (Lines 272-300)
|
||||
- **Why**: `validateMenuNodeData` permits `translations` to be an array or object. If a list of translations is passed as an array (e.g. `[{ langCode: "th", label: "..." }]`), spreading it creates index-based keys (like `{ "0": { langCode: "th", label: "..." } }`) instead of language code keys. This corrupts the translatable object structure in the database.
|
||||
- **Suggestion**: Convert the array to a key-value dictionary (e.g., `{ th: "..." }`) before merging.
|
||||
|
||||
### 8. [Minor] Bypassing Type Safety with `tx: any`
|
||||
- **What**: The database transaction client is cast to `any`.
|
||||
- **Where**: `apps/backend/src/routes/menus.ts` (Line 103)
|
||||
- **Why**: Disabling type safety within the transaction block makes it easy to introduce undetected runtime errors during schema changes.
|
||||
- **Suggestion**: Remove the `any` cast and type the transaction client properly.
|
||||
|
||||
---
|
||||
|
||||
## Verified Claims
|
||||
|
||||
- **Claim**: Menu API supports rootImage, columnImage, and hoverImage storage and retrieval → Verified via running `apps/backend/test_menu_api_challenger.ts` → **PASS** (retrieved values match input payloads exactly).
|
||||
- **Claim**: Elysia routes perform validation checks on rootImage, columnImage, and order fields → Verified via running `test_menu_api_challenger.ts` → **PASS** (correctly throws 422 Unprocessable Entity for invalid types).
|
||||
- **Claim**: Database schema correctly defines relation cascades → Verified via inspecting `schema.prisma` → **PASS** (cascades on delete of menus and menu items are present).
|
||||
|
||||
---
|
||||
|
||||
## Coverage Gaps
|
||||
|
||||
- **PATCH Endpoint Validation**: The `PATCH /menus/items/:id/translations` route has no validation schema. (Risk level: **Medium**; Recommendation: Add TypeBox validation).
|
||||
- **POST Endpoint Mapping**: Missing `payload` and `isActive` fields on `POST /menus`. (Risk level: **Medium**; Recommendation: Map missing fields).
|
||||
|
||||
---
|
||||
|
||||
## Unverified Items
|
||||
|
||||
- **Frontend Integration**: Layout rendering and responsive constraints on frontend components. (Reason: Outside the scope of M2 Backend & DB review).
|
||||
|
||||
---
|
||||
|
||||
## Challenge Summary
|
||||
|
||||
**Overall risk assessment**: **HIGH**
|
||||
|
||||
*The combination of split transaction blocks (non-atomic updates) and logical bugs in translation array handling risks database state corruption that could crash storefront rendering of the Mega Menu.*
|
||||
|
||||
---
|
||||
|
||||
## Challenges
|
||||
|
||||
### 1. Non-Atomic Menu Updates
|
||||
- **Assumption challenged**: PUT operations are atomic because they use `prisma.$transaction`.
|
||||
- **Attack scenario**: A client PUTs an update to a menu payload. The Menu record is updated successfully, but a database error occurs during the subsequent MenuItem updates inside the transaction. The transaction rolls back, but the Menu changes remain committed.
|
||||
- **Blast radius**: The Menu model metadata changes but its associated items do not, leaving the menu structure broken.
|
||||
- **Mitigation**: Move the Menu creation/update query inside the transaction callback.
|
||||
|
||||
### 2. Translation Array Spreading Corruption
|
||||
- **Assumption challenged**: Node translations are always plain objects.
|
||||
- **Attack scenario**: A client calls `add_menu_node` with translations as an array. The tool spreads it, creating index keys.
|
||||
- **Blast radius**: Corrupted database payload crashes storefront translation lookup.
|
||||
- **Mitigation**: Detect array types and convert to dictionary.
|
||||
|
||||
### 3. Duplicate Menu 500 Leak
|
||||
- **Assumption challenged**: Database uniqueness constraints are handled gracefully.
|
||||
- **Attack scenario**: Creating a menu with an existing name throws P2002.
|
||||
- **Blast radius**: The API crashes with `500 Internal Server Error` instead of `409 Conflict`, leaking DB constraints in the log.
|
||||
- **Mitigation**: Intercept P2002 and return `409`.
|
||||
|
||||
---
|
||||
|
||||
## Stress Test Results
|
||||
|
||||
- **Duplicate Name POST** → Expect `400/409` → Got `500` → **FAIL**
|
||||
- **PUT Transaction Failure** → Expect Rollback of all changes → Got partial update of Menu → **FAIL**
|
||||
- **Array Translation on Node Add** → Expect `{ th: "..." }` → Got `{ "0": { langCode: "th", ... } }` → **FAIL**
|
||||
|
||||
---
|
||||
|
||||
## Unchallenged Areas
|
||||
|
||||
- **Menu Snapshot Storage**: Snapshot storage uses in-memory map which works fine but does not persist across server restarts (implied constraint for local tool execution).
|
||||
Reference in new issue
Block a user