Public Access
fix: address adversarial review blockers
All §1 consensus blockers and §2 high-risk gaps resolved: Schema fixes: - Remove RecipeIngredient join table, use JSONB for ingredients - Add family_member table for per-voter approval tracking - Add all ENUMs for status fields (no loose VARCHAR) - Add CHECK constraints (household_size, rating 1-5, day_of_week) - Add name_lower for case-insensitive ingredient matching - Add grocery_item → ingredient FK - Fix day_of_week to ISO-8601 (1=Monday, 7=Sunday) - Remove calorie_target (nutrition is non-goal) Approval flow redesign: - Email link → confirmation page (GET), not auto-approve - Actual vote is POST from confirmation page - Per-voter tokens (single-use, 72h TTL) - Record which member voted Auth model: - VPN-only for admin endpoints - Session-based for family web UI Docker hardening: - Remove direct port exposure for backend/frontend - nginx is sole entrypoint - Add docker-compose.dev.yml for local dev Skeleton fixes: - Add missing Pantry.tsx page - Add missing index.html (Vite entrypoint) - Add package-lock.json - Fix SQLAlchemy 2 text() for raw SQL - Remove create_all from startup (use migrations) - Configure Alembic properly Docs updates: - Update Lucky URL to luckysupermarkets.com - Add WCAG 2.1 AA accessibility target - Update family profile with correct mushroom preferences - Add external dependencies list to SPEC Verification: - docker compose config: PASS - docker compose build backend: PASS - docker compose build frontend: PASS - backend import: PASS - alembic context: PASS
This commit is contained in:
+75
-21
@@ -31,7 +31,7 @@ Current meal kit services (Blue Apron → EveryPlate → HungryRoot → Sunbaske
|
||||
### Primary Goals
|
||||
1. **Weekly Meal Planning**: Automatically generate a 7-day meal plan each week
|
||||
2. **Grocery Integration**: Scrape Lucky California weekly ads and product catalog for sales/in-season items
|
||||
3. **Family Approval Workflow**: Send email to both adults with meal proposal, image, and details; one denial swaps the meal
|
||||
3. **Family Approval Workflow**: Send email to adults with meal proposal, image, and details; one denial swaps the meal
|
||||
4. **Shopping List Generation**: Create weekly shopping list grouped by Lucky California aisles, highlighting sales
|
||||
5. **Pantry Integration**: Allow users to specify items they have at home to incorporate into meal suggestions
|
||||
6. **Web UI**: Modern interface for non-technical family members to interact with meals, feedback, and recipes
|
||||
@@ -81,15 +81,21 @@ Current meal kit services (Blue Apron → EveryPlate → HungryRoot → Sunbaske
|
||||
- Calorie, budget, and health conscious eating
|
||||
- Food should be tasty but not overly expensive
|
||||
|
||||
### Family Members
|
||||
| Member | Role | Mushroom Preference |
|
||||
|--------|------|-------------------|
|
||||
| Adult 1 | Adult | Does NOT like mushrooms |
|
||||
| Adult 2 | Adult | Likes mushrooms |
|
||||
| Child 1 | Child | Does NOT like mushrooms |
|
||||
| Child 2 | Child | OK with mushrooms |
|
||||
|
||||
### Dietary Constraints
|
||||
- One adult likes mushrooms
|
||||
- One child is OK with mushrooms
|
||||
- Two adults and one child do NOT like mushrooms
|
||||
- 3 of 4 family members do NOT like mushrooms
|
||||
- No allergies
|
||||
|
||||
### Preference Signals
|
||||
- "Never suggest this ingredient" flags
|
||||
- Per-meal ratings (1-5 stars)
|
||||
- "Never suggest this ingredient" flags (per family, not per member)
|
||||
- Per-meal ratings (1-5 stars, per member)
|
||||
- Denial reasons (too expensive, looks boring, contains disliked ingredient, etc.)
|
||||
- Home pantry items to incorporate
|
||||
|
||||
@@ -105,31 +111,53 @@ Current meal kit services (Blue Apron → EveryPlate → HungryRoot → Sunbaske
|
||||
- Variety requirements (avoid sauce/ingredient repetition)
|
||||
- Home pantry items to use
|
||||
|
||||
2. Email sent to both adults containing:
|
||||
2. Email sent to all adult family members containing:
|
||||
- All 7 meals listed with images
|
||||
- Each meal has: Approve / Deny buttons (via email links or web UI)
|
||||
- Denial requires a reason selection or free-text
|
||||
- Each meal has: "View & Vote" link to web approval page
|
||||
- Email does NOT auto-approve on link click
|
||||
|
||||
3. Approval handling:
|
||||
- If both approve OR no response → meal confirmed
|
||||
- If either denies → meal swapped with alternative suggestion
|
||||
- Denied meals logged for learning
|
||||
3. Approval page flow (Web UI):
|
||||
- Adult clicks email link → lands on confirmation page
|
||||
- Page shows meal details, image, ingredients, estimated cost
|
||||
- Adult clicks "Approve" or "Deny"
|
||||
- Denial requires selecting a reason
|
||||
- Vote is recorded per-member (not per-household)
|
||||
|
||||
4. After approval deadline:
|
||||
4. Approval handling:
|
||||
- If majority of adults approve → meal confirmed
|
||||
- If any adult denies → meal swapped with alternative suggestion
|
||||
- Denial reason is recorded for learning
|
||||
- Explicit deadline: 48 hours from email send
|
||||
- After deadline: meals with insufficient responses auto-expire and are excluded
|
||||
|
||||
5. After approval period:
|
||||
- Final meal plan locked
|
||||
- Shopping list generated
|
||||
- Recipes made available in web UI
|
||||
|
||||
### Approval Token Security
|
||||
- Each email contains a unique, single-use token per family member
|
||||
- Tokens expire after 72 hours
|
||||
- Tokens can only be used once (marked USED after voting)
|
||||
- Email links lead to a confirmation page; actual vote is a POST
|
||||
|
||||
---
|
||||
|
||||
## 8. Technical Constraints
|
||||
|
||||
### Self-Hosting Requirements
|
||||
- Must run on local infrastructure (homelab, NUC, Synology, etc.)
|
||||
- Remote access via reverse proxy (Caddy or nginx)
|
||||
- No external cloud services except SendGrid for email
|
||||
- Remote access via reverse proxy with VPN or TLS
|
||||
- Primary access: local network only (VPN required for remote)
|
||||
|
||||
### Authentication & Authorization
|
||||
- **Admin endpoints** (`/api/admin/*`): VPN-only access
|
||||
- **Family web UI**: Session-based authentication (simple username/password)
|
||||
- **Email approval links**: Token-based, single-use, time-limited
|
||||
- No JWT; no OAuth
|
||||
|
||||
### Lucky California Integration
|
||||
- **URL**: https://luckysupermarkets.com (verified)
|
||||
- Primary: Scrape weekly ad and product catalog
|
||||
- Store scraped data locally
|
||||
- Respect robots.txt and rate limiting
|
||||
@@ -139,15 +167,41 @@ Current meal kit services (Blue Apron → EveryPlate → HungryRoot → Sunbaske
|
||||
- SendGrid for transactional email
|
||||
- HTML email templates with meal images
|
||||
- Plain text fallback for email clients that block images
|
||||
- Accessible: includes alt text for images, works with screen readers
|
||||
|
||||
### External Dependencies
|
||||
| Service | Purpose | Required |
|
||||
|---------|---------|----------|
|
||||
| SendGrid | Transactional email | Yes |
|
||||
| luckysupermarkets.com | Grocery scraping | Yes |
|
||||
| Recipe websites | Recipe images | Yes |
|
||||
| AI Image API (optional) | Fallback image generation | No |
|
||||
|
||||
---
|
||||
|
||||
## 9. Data Retention
|
||||
## 9. Accessibility (WCAG 2.1 AA)
|
||||
|
||||
### Web UI
|
||||
- All interactive elements keyboard accessible
|
||||
- Color contrast ratio ≥ 4.5:1 for normal text
|
||||
- Form inputs have visible labels
|
||||
- Error messages are descriptive and associated with inputs
|
||||
- Skip navigation links provided
|
||||
|
||||
### Email
|
||||
- HTML emails include meaningful alt text for all images
|
||||
- Plain text version provided as fallback
|
||||
- Links are descriptive (not "click here")
|
||||
- Font sizes are readable (minimum 14px equivalent)
|
||||
|
||||
---
|
||||
|
||||
## 10. Data Retention
|
||||
|
||||
### Stored Data
|
||||
- All recipes (scraped and manually added)
|
||||
- Meal plans (weekly history)
|
||||
- Approval/denial history with reasons
|
||||
- Per-member votes and denial history
|
||||
- Feedback (ratings, flags, pantry items)
|
||||
- Scraped grocery data (weekly refresh)
|
||||
|
||||
@@ -158,17 +212,17 @@ Current meal kit services (Blue Apron → EveryPlate → HungryRoot → Sunbaske
|
||||
|
||||
---
|
||||
|
||||
## 10. Success Metrics
|
||||
## 11. Success Metrics
|
||||
|
||||
1. **Adoption**: Family consistently uses the system weekly
|
||||
2. **Meal variety**: No more than 2 meals/week share the same sauce or primary protein
|
||||
3. **Cost efficiency**: Average cost per serving within 150% of equivalent grocery-store meal
|
||||
4. **Approval rate**: >80% of proposed meals approved without changes
|
||||
4. **Explicit approval rate**: >80% of proposed meals receive explicit approval (not silence)
|
||||
5. **Learning**: After 4 weeks, system should not propose previously denied meals
|
||||
|
||||
---
|
||||
|
||||
## 11. Future Considerations
|
||||
## 12. Future Considerations
|
||||
|
||||
- Twilio WhatsApp integration for wife who prefers messaging
|
||||
- Direct Lucky California online ordering
|
||||
|
||||
Reference in New Issue
Block a user