Implement UUIDv7 recipe ids and soft delete - #1277
Conversation
Addressed in commit |
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
f8d072c to
d9a78bf
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The UUIDv7 + soft-delete implementation is cohesive across layers and is backed by updated unit/integration/frontend tests, with only a minor test-serialization consistency nit noted.
Pull request overview
This PR implements application-generated UUIDv7 identifiers for recipe-related entities and Menu users, and switches recipe deletion to a soft-delete model with an owner-only restore endpoint. It reshapes the EF Core schema (including a filtered uniqueness index for titles) and wires the new restore/undo flow through the backend API, repositories/services, integration/unit tests, and the Vue/Quasar frontend.
Changes:
- Convert
Recipe,RecipeIngredient,RecipeStep, andMenuUseridentifiers (PKs/FKs) fromintidentity to UUIDv7Guid, withValueGeneratedNever()and app-side ID generation. - Add recipe soft delete via
DeletedAtUtc, a global EF query filter, a filtered unique index for(OwnerUserId, Title), andPOST /api/recipe/{recipeId}/restore. - Update frontend delete UX to show a Quasar Notify “Undo” action that calls restore and invalidates recipe queries; update backend + frontend tests accordingly.
File summaries
| File | Description |
|---|---|
| ui/menu-website/src/services/recipe-service.ts | Adds restore mutation hook and updates cache invalidation to use UUID ids. |
| ui/menu-website/src/services/recipe-api.ts | Adds typed API call for POST /api/recipe/{recipeId}/restore. |
| ui/menu-website/src/pages/RecipeList.test.ts | Updates recipe-api mock to include restoreRecipe. |
| ui/menu-website/src/pages/RecipeDetail.vue | Adds Quasar Notify delete/undo flow and restore handler. |
| ui/menu-website/src/pages/RecipeDetail.test.ts | Registers Quasar Notify plugin in tests and adds undo test coverage. |
| ui/menu-website/src/pages/EditRecipe.test.ts | Updates recipe-api mock to include restoreRecipe. |
| ui/menu-website/src/main.ts | Registers Quasar Notify plugin for app-wide notifications. |
| ui/menu-website/src/components/organisms/recipe/recipe-form.test.ts | Updates recipe-api mock to include restoreRecipe. |
| docs/specs/recipe-soft-delete.md | Documents current “never purge” retention policy for soft-deleted recipes. |
| backend/MenuDB/Migrations/MenuDbContextModelSnapshot.cs | Updates snapshot for UUID keys, DeletedAtUtc, filtered index, and query filter. |
| backend/MenuDB/Migrations/20260906190329_ConvertRecipeEntityIdsToUuidV7AndSoftDelete.Designer.cs | Adds migration designer model reflecting UUID keys + soft delete changes. |
| backend/MenuDB/Migrations/20260906190329_ConvertRecipeEntityIdsToUuidV7AndSoftDelete.cs | Adds guarded migration that drops/recreates empty entity tables with UUID keys + soft delete. |
| backend/MenuDB/Data/RecipeStepEntity.cs | Switches step PK/FK types to Guid. |
| backend/MenuDB/Data/RecipeIngredientEntity.cs | Switches ingredient PK/FK types to Guid. |
| backend/MenuDB/Data/RecipeEntity.cs | Switches recipe PK/FK types to Guid and adds DeletedAtUtc. |
| backend/MenuDB/Data/MenuUserEntity.cs | Switches menu user PK type to Guid. |
| backend/MenuDB/Configuration/RecipeStepEntityConfiguration.cs | Changes step key generation to application-generated (ValueGeneratedNever). |
| backend/MenuDB/Configuration/RecipeIngredientEntityConfiguration.cs | Changes ingredient key generation to application-generated (ValueGeneratedNever). |
| backend/MenuDB/Configuration/RecipeEntityConfiguration.cs | Changes recipe key generation + adds query filter + filtered uniqueness index. |
| backend/MenuDB/Configuration/MenuUserEntityConfiguration.cs | Changes menu user key generation to application-generated (ValueGeneratedNever). |
| backend/MenuDB.Tests/RecipeStepEntityConfigurationTests.cs | Adds test asserting step key is Guid and not store-generated. |
| backend/MenuDB.Tests/RecipeIngredientEntityConfigurationTests.cs | Adds tests for ingredient key types and key generation. |
| backend/MenuDB.Tests/RecipeEntityConfigurationTests.cs | Adds tests for recipe key generation, query filter, and filtered index. |
| backend/MenuDB.Tests/MenuUserEntityConfigurationTests.cs | Adds test asserting menu user key is Guid and not store-generated. |
| backend/MenuApi/ValueObjects/Recipe.cs | Updates RecipeId Vogen type to wrap Guid. |
| backend/MenuApi/ValueObjects/MenuUserId.cs | Updates MenuUserId Vogen type to wrap Guid. |
| backend/MenuApi/Services/RecipeService.cs | Adds service method to restore a recipe (owner-checked). |
| backend/MenuApi/Services/IRecipeService.cs | Adds RestoreRecipeAsync to the service contract. |
| backend/MenuApi/Repositories/RecipeStepRepository.cs | Generates UUIDv7 step ids on upsert. |
| backend/MenuApi/Repositories/RecipeRepository.cs | Generates UUIDv7 recipe/ingredient ids; implements soft delete + restore + include-deleted read. |
| backend/MenuApi/Repositories/MenuUserRepository.cs | Generates UUIDv7 menu user ids on insert. |
| backend/MenuApi/Repositories/IRecipeRepository.cs | Adds restore and include-deleted repository APIs. |
| backend/MenuApi/Recipes/RecipeApi.cs | Adds POST {recipeId}/restore endpoint and response metadata. |
| backend/MenuApi.Tests/Services/RecipeServiceTests.cs | Adds unit tests for restore behavior (success/not found/forbidden). |
| backend/MenuApi.Tests/Services/MenuUserServiceTests.cs | Updates tests to use Guid-based MenuUserId. |
| backend/MenuApi.Tests/Repositories/RecipeRepositoryTests.cs | Adds tests for UUIDv7 generation and query filter behavior; updates Guid-based ids. |
| backend/MenuApi.Tests/Controllers/RecipeApiTests.cs | Adds controller tests for restore endpoint and updates Guid-based ids. |
| backend/MenuApi.Integration.Tests/ValidationIntegrationTests.cs | Updates validation tests to use GUID ids in routes and JSON parsing. |
| backend/MenuApi.Integration.Tests/UserProvisioningIntegrationTests.cs | Updates user id expectations and response model to Guid. |
| backend/MenuApi.Integration.Tests/RecipeWithIngredientsIntegrationTests.cs | Updates recipe id handling from int to Guid. |
| backend/MenuApi.Integration.Tests/RecipeReadAuthorizationIntegrationTests.cs | Updates recipe id handling from int to Guid. |
| backend/MenuApi.Integration.Tests/RecipeIntegrationTests.cs | Updates recipe id handling and list DTO id type to Guid. |
| backend/MenuApi.Integration.Tests/RecipeDeleteIntegrationTests.cs | Updates delete tests for soft-delete semantics and adds restore/duplicate-title scenarios. |
| backend/MenuApi.Integration.Tests/RecipeCreateUpdateIntegrationTests.cs | Updates recipe id parsing and not-found route to GUID. |
| backend/MenuApi.Integration.Tests/Factory/TestDatabaseSeeder.cs | Updates seeded ids to UUIDv7 and adds helpers for counts + soft delete. |
| .sonarcloud.properties | Excludes EF migration scaffolding from SonarCloud CPD duplication checks. |
Review details
Files not reviewed (1)
- backend/MenuDB/Migrations/20260906190329_ConvertRecipeEntityIdsToUuidV7AndSoftDelete.Designer.cs: Generated file
- Files reviewed: 45/46 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d9a78bf58c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Co-authored-by: Codex <codex@openai.com>
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6e3b4fe6fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".



Summary
Implements UUIDv7 entity identifiers and soft deletion for recipes in one coordinated change.
Closes #1215
Closes #1216
Changes
DeletedAtUtc, a global active-recipe query filter, filtered title uniqueness, and owner-only restore atPOST /api/recipe/{recipeId}/restore.Verification
dotnet build MenuApi.sln --configuration Release --no-restore— passed, 0 warnings/errors.dotnet test MenuApi.Tests --configuration Release --no-restore— 154 passed.dotnet test MenuDB.Tests --configuration Release --no-restore— 16 passed.pnpm test:unit— 156 passed.pnpm test:storybook— 93 passed.pnpm build— passed.pnpm lint— passed with 0 errors and 19 existing warnings.