Tasks completed: 2/2 - Define common OIDC and secure store contracts - Add JVM and Wasm actuals SUMMARY: .planning/phases/02-authentication-foundation/02-03-SUMMARY.md
243 lines
16 KiB
Markdown
243 lines
16 KiB
Markdown
# Requirements: Recipe
|
||
|
||
**Defined:** 2026-04-24
|
||
**Core Value:** "My week is planned." I pick recipes, the calendar fills up, and I know what we're eating.
|
||
|
||
## v1 Requirements
|
||
|
||
### Authentication & identity
|
||
|
||
- [x] **AUTH-01**: User can sign in via the self-hosted Authentik instance using OIDC (authorization code flow with PKCE)
|
||
- [x] **AUTH-02**: Client stores access + refresh tokens securely (iOS Keychain / Android EncryptedSharedPreferences)
|
||
- [x] **AUTH-03**: Ktor server validates incoming access tokens via Authentik's JWKS endpoint (issuer, audience, expiry, signature, clock skew leeway)
|
||
- [x] **AUTH-04**: User session persists across app launches without re-authentication (token refresh handled transparently)
|
||
- [x] **AUTH-05**: User can sign out, which revokes local tokens and returns to the login screen
|
||
- [x] **AUTH-06**: Users are JIT-provisioned in the server database on first successful login (by OIDC `sub` claim)
|
||
|
||
### Household sharing
|
||
|
||
- [ ] **HSHD-01**: On first login, user is prompted to create a new household or join an existing one via invite code
|
||
- [ ] **HSHD-02**: User can create a new household and become its first member
|
||
- [ ] **HSHD-03**: User can generate an invite code for their household (short-lived, single-use)
|
||
- [ ] **HSHD-04**: Another user can redeem an invite code to join the household
|
||
- [ ] **HSHD-05**: All household members see the same plan, pantry, and shopping list
|
||
- [ ] **HSHD-06**: Server-side tenancy is enforced: every household-scoped query filters by `household_id` derived from the authenticated principal, never from the request body
|
||
- [ ] **HSHD-07**: Client queries for household data filter locally by active `household_id` (defense in depth)
|
||
|
||
### Recipes — browse & detail
|
||
|
||
- [ ] **RCPE-01**: User can view a grid of the household's recipe catalog
|
||
- [ ] **RCPE-02**: User can filter recipes by meal slot (śniadanie / drugie śniadanie / obiad / przekąska / kolacja)
|
||
- [ ] **RCPE-03**: User can filter recipes by tag (e.g., "szybkie", "wegetariańskie", "wysokobiałkowe")
|
||
- [ ] **RCPE-04**: User can filter recipes by cooking time range (minutes)
|
||
- [ ] **RCPE-05**: User can search recipes by title or tag text
|
||
- [ ] **RCPE-06**: User can open a recipe detail view showing ingredients (with amounts + units), steps, nutrition per serving, and cooking time
|
||
- [ ] **RCPE-07**: Recipe detail shows ingredient alternatives (substitutions) where defined in the catalog
|
||
- [ ] **RCPE-08**: Recipe catalog is seeded via server-side SQL fixtures or admin CLI (no in-app authoring in v1)
|
||
|
||
### Meal planner (hero feature)
|
||
|
||
- [ ] **PLAN-01**: User can view a calendar showing planned meals per day
|
||
- [ ] **PLAN-02**: User can navigate between days/weeks/months in the calendar
|
||
- [ ] **PLAN-03**: User can add a recipe to any of the 5 slots on any day (śniadanie, drugie śniadanie, obiad, przekąska, kolacja)
|
||
- [ ] **PLAN-04**: User can remove a meal entry from a slot
|
||
- [ ] **PLAN-05**: User can replace a meal entry by picking a different recipe
|
||
- [ ] **PLAN-06**: User can adjust servings on a meal entry (1–12)
|
||
- [ ] **PLAN-07**: User can substitute an ingredient in a meal entry with one of the defined alternatives
|
||
- [ ] **PLAN-08**: User can exclude an ingredient from a meal entry (won't appear in shopping/pantry calculations)
|
||
- [ ] **PLAN-09**: User can add an extra ingredient to a meal entry (amount + unit from the ingredient catalog)
|
||
- [ ] **PLAN-10**: User can override the amount of an ingredient in a meal entry
|
||
- [ ] **PLAN-11**: User can select a specific product (pack size) for a given ingredient in a meal entry
|
||
- [ ] **PLAN-12**: User can mark a meal slot as skipped for a day
|
||
- [ ] **PLAN-13**: User sees daily nutrition totals (kcal, protein, fat, carbs) aggregated from all planned meals that day, respecting customizations
|
||
- [ ] **PLAN-14**: Meal entries have stable UUID identity (never composite keys like `date + slot`) to survive concurrent edits
|
||
|
||
### Pantry
|
||
|
||
- [ ] **PNTR-01**: User can view pantry inventory grouped by ingredient category (pieczywo, nabiał, mięso i ryby, warzywa, owoce, suche, przyprawy, inne)
|
||
- [ ] **PNTR-02**: User can manually add or update the quantity of an ingredient in the pantry (using its pantry unit: g, ml, szt.)
|
||
- [ ] **PNTR-03**: User sees which ingredients fall short over a user-selected planning horizon (e.g., next 7 days) based on the plan minus current pantry
|
||
- [ ] **PNTR-04**: User can filter pantry view by category
|
||
- [ ] **PNTR-05**: User can filter pantry view by shortfall status (needed / sufficient / not in plan)
|
||
|
||
### Shopping list
|
||
|
||
- [ ] **SHOP-01**: User can select a date range from the plan to generate a shopping list
|
||
- [ ] **SHOP-02**: Shopping list aggregates all ingredient needs across selected days minus current pantry quantities
|
||
- [ ] **SHOP-03**: Shopping list groups items by ingredient category for efficient in-store navigation
|
||
- [ ] **SHOP-04**: User can mark an item as bought during a shopping session; the item is removed from active needs and added to pantry in its pantry unit
|
||
- [ ] **SHOP-05**: User can undo a recently marked-bought item within the same session
|
||
- [ ] **SHOP-06**: Session log persists across app restarts until the user explicitly clears it
|
||
|
||
### Offline + sync
|
||
|
||
- [ ] **SYNC-01**: Client reads all household data from local SQLDelight without requiring network
|
||
- [ ] **SYNC-02**: Client writes all household data locally first (optimistic UI), then queues the change for sync
|
||
- [ ] **SYNC-03**: Server assigns `updated_at` (server time, monotonic) on every accepted write; clients never trust their own device clock for sync ordering
|
||
- [ ] **SYNC-04**: Client pulls household changes via `GET /sync/pull?since=...` using a lexicographic `(updated_at, id)` cursor to survive same-millisecond writes
|
||
- [ ] **SYNC-05**: Client pushes pending writes via `POST /sync/push` (batched); accepted writes come back with server-assigned `updated_at`
|
||
- [ ] **SYNC-06**: Deletes are soft deletes (`deleted_at` column); synced as state changes, not as "delete ops"
|
||
- [ ] **SYNC-07**: Sync runs on: app foreground, pull-to-refresh, debounced 2s after every local write, and polls every 20–30s while foreground
|
||
- [ ] **SYNC-08**: Sync failures (network error, 5xx) retry with exponential backoff and do not block the UI
|
||
- [ ] **SYNC-09**: Sync engine is implemented as a single Koin singleton owning the outbox queue and pull cursor — features never issue HTTP writes directly
|
||
- [ ] **SYNC-10**: When two household members edit the same row, the server-assigned later write wins; no silent data loss because writes use UUID identity, not natural keys
|
||
|
||
### UI foundation (polish + glass aesthetic)
|
||
|
||
- [ ] **UI-01**: All user-facing strings are externalized as Compose resources (i18n-ready), even though v1 ships Polish only
|
||
- [ ] **UI-02**: App ships with Polish-language copy throughout
|
||
- [ ] **UI-03**: Bottom tab navigation with 4 tabs: Przepisy / Planer / Spiżarnia / Zakupy, each preserving its own back stack independently
|
||
- [ ] **UI-04**: Tab bar and nav bar use Haze-based glass/blur effects (Liquid Glass approximation)
|
||
- [ ] **UI-05**: App supports light and dark color schemes with translucent surfaces working in both
|
||
- [ ] **UI-06**: UI is iOS-idiomatic within Compose constraints (safe areas, swipe-back gesture where applicable, keyboard avoidance)
|
||
- [ ] **UI-07**: Visual hierarchy is less cramped than the mockup — deliberate spacing, calmer typography, readable at arm's length
|
||
- [ ] **UI-08**: Locale-aware date formatting for display (days, months, weekday names in Polish); sync wire-format stays UTC ISO-8601
|
||
- [ ] **UI-09**: App starts cleanly on first launch (no blank flash) and shows appropriate empty states when catalog / plan / pantry / shopping are empty
|
||
|
||
### Infrastructure & build
|
||
|
||
- [x] **INFRA-01**: Gradle version catalog at `gradle/libs.versions.toml` is the single source of truth for library versions
|
||
- [x] **INFRA-02**: `build-logic/` convention plugins centralize Kotlin/Compose/test configuration across modules
|
||
- [x] **INFRA-03**: iOS Kotlin/Native binary options set from day 1: `kotlin.native.binary.objcDisposeOnMain=false`, `gc=cms`
|
||
- [ ] **INFRA-04**: Server Docker image builds and deploys to user's homelab alongside Authentik
|
||
- [ ] **INFRA-05**: Flyway migrations run automatically on server startup in a known order
|
||
- [x] **INFRA-06**: `shared/commonMain` contains only domain models + API DTOs — no UI, no HTTP, no DB code
|
||
- [ ] **INFRA-07**: App is distributed to partner via TestFlight (iOS) for initial dogfooding
|
||
|
||
## v2 Requirements
|
||
|
||
Explicitly acknowledged but deferred. Not in the v1 roadmap.
|
||
|
||
### In-app recipe authoring
|
||
|
||
- **AUTHR-01**: User can create a new recipe with ingredients, steps, nutrition, allowed slots, tags
|
||
- **AUTHR-02**: User can edit an existing recipe
|
||
- **AUTHR-03**: User can archive/delete a recipe they created
|
||
|
||
### Nutrition goal tracking
|
||
|
||
- **NUTR-01**: User can set daily macro targets (kcal, protein, fat, carbs)
|
||
- **NUTR-02**: Planner shows deficit/surplus vs. targets per day
|
||
- **NUTR-03**: User can view weekly nutrition trends
|
||
|
||
### Additional platforms
|
||
|
||
- **PLAT-01**: Android app distributed to household members (APK or Play Store)
|
||
- **PLAT-02**: Web (Compose for Wasm) as a PWA replacement for the current mockup
|
||
- **PLAT-03**: English localization (full copy pass)
|
||
|
||
### Sync hardening
|
||
|
||
- **SYNC2-01**: Server-sent events (SSE) for near-realtime sync instead of polling
|
||
- **SYNC2-02**: Per-table upgrade path from LWW to operation-log sync if concurrent-edit data loss becomes observable
|
||
|
||
### iOS Liquid Glass fidelity
|
||
|
||
- **LG2-01**: Native SwiftUI interop for tab bar and nav bar (real iOS 26 Liquid Glass material) if Compose approximation proves inadequate on real hardware
|
||
|
||
## Out of Scope
|
||
|
||
Explicitly excluded. Documented to prevent scope creep.
|
||
|
||
| Feature | Reason |
|
||
|---------|--------|
|
||
| Social features (comments, ratings, public profiles, feeds) | Private household app, not a community product |
|
||
| Recipe sharing between households | Households are isolated in v1; recipe marketplace is not the point |
|
||
| Meal-plan marketplace / paid plans | Personal-use product |
|
||
| Grocery-delivery integrations (Instacart, Carrefour Online, etc.) | Polish-market + small scope; integration cost not justified |
|
||
| Barcode scanning / receipt OCR for pantry updates | Manual entry is fine for a 2-person household |
|
||
| AI-generated recipes | Curated catalog is the value |
|
||
| Apple Sign-in as a first-class button | Authentik OIDC is user's IdP, not a third-party social login |
|
||
| Port of mockup's vanilla-JS visual design | Visual rebuild around Liquid-Glass language; mockup is functional spec only |
|
||
| Port of mockup's ~80 ingredients + ~30 recipes as seed data | User explicitly chose to re-curate catalog fresh |
|
||
| Device-clock-based sync timestamps | Silent data loss under drift; server-assigned timestamps mandatory |
|
||
| True iOS 26 Liquid Glass native material in v1 | Requires SwiftUI interop; Compose approximation is v1 scope |
|
||
|
||
## Traceability
|
||
|
||
Populated during roadmap creation. Each v1 requirement maps to exactly one phase.
|
||
|
||
| Requirement | Phase | Status |
|
||
|-------------|-------|--------|
|
||
| AUTH-01 | Phase 2: Authentication Foundation | Complete |
|
||
| AUTH-02 | Phase 2: Authentication Foundation | Complete |
|
||
| AUTH-03 | Phase 2: Authentication Foundation | Pending |
|
||
| AUTH-04 | Phase 2: Authentication Foundation | Complete |
|
||
| AUTH-05 | Phase 2: Authentication Foundation | Complete |
|
||
| AUTH-06 | Phase 2: Authentication Foundation | Pending |
|
||
| HSHD-01 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| HSHD-02 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| HSHD-03 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| HSHD-04 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| HSHD-05 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| HSHD-06 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| HSHD-07 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| RCPE-01 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| RCPE-02 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| RCPE-03 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| RCPE-04 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| RCPE-05 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| RCPE-06 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| RCPE-07 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| RCPE-08 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| PLAN-01 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PLAN-02 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PLAN-03 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PLAN-04 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PLAN-05 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PLAN-06 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PLAN-07 | Phase 7: Meal Planner — Customization & Nutrition | Pending |
|
||
| PLAN-08 | Phase 7: Meal Planner — Customization & Nutrition | Pending |
|
||
| PLAN-09 | Phase 7: Meal Planner — Customization & Nutrition | Pending |
|
||
| PLAN-10 | Phase 7: Meal Planner — Customization & Nutrition | Pending |
|
||
| PLAN-11 | Phase 7: Meal Planner — Customization & Nutrition | Pending |
|
||
| PLAN-12 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PLAN-13 | Phase 7: Meal Planner — Customization & Nutrition | Pending |
|
||
| PLAN-14 | Phase 6: Meal Planner — Core Write Path | Pending |
|
||
| PNTR-01 | Phase 8: Pantry | Pending |
|
||
| PNTR-02 | Phase 8: Pantry | Pending |
|
||
| PNTR-03 | Phase 8: Pantry | Pending |
|
||
| PNTR-04 | Phase 8: Pantry | Pending |
|
||
| PNTR-05 | Phase 8: Pantry | Pending |
|
||
| SHOP-01 | Phase 9: Shopping List & Session Log | Pending |
|
||
| SHOP-02 | Phase 9: Shopping List & Session Log | Pending |
|
||
| SHOP-03 | Phase 9: Shopping List & Session Log | Pending |
|
||
| SHOP-04 | Phase 9: Shopping List & Session Log | Pending |
|
||
| SHOP-05 | Phase 9: Shopping List & Session Log | Pending |
|
||
| SHOP-06 | Phase 9: Shopping List & Session Log | Pending |
|
||
| SYNC-01 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-02 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-03 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-04 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-05 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-06 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-07 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-08 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-09 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| SYNC-10 | Phase 4: Sync Engine Skeleton | Pending |
|
||
| UI-01 | Phase 11: Localization & iOS Deployment | Pending |
|
||
| UI-02 | Phase 11: Localization & iOS Deployment | Pending |
|
||
| UI-03 | Phase 10: UI Chrome & Haze Liquid-Glass Polish | Pending |
|
||
| UI-04 | Phase 10: UI Chrome & Haze Liquid-Glass Polish | Pending |
|
||
| UI-05 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| UI-06 | Phase 10: UI Chrome & Haze Liquid-Glass Polish | Pending |
|
||
| UI-07 | Phase 10: UI Chrome & Haze Liquid-Glass Polish | Pending |
|
||
| UI-08 | Phase 5: Recipe Catalog (Read Path) | Pending |
|
||
| UI-09 | Phase 10: UI Chrome & Haze Liquid-Glass Polish | Pending |
|
||
| INFRA-01 | Phase 1: Project Infrastructure & Module Wiring | Complete |
|
||
| INFRA-02 | Phase 1: Project Infrastructure & Module Wiring | Complete |
|
||
| INFRA-03 | Phase 1: Project Infrastructure & Module Wiring | Complete |
|
||
| INFRA-04 | Phase 11: Localization & iOS Deployment | Pending |
|
||
| INFRA-05 | Phase 3: Households, Membership & Server Data Foundation | Pending |
|
||
| INFRA-06 | Phase 1: Project Infrastructure & Module Wiring | Complete |
|
||
| INFRA-07 | Phase 11: Localization & iOS Deployment | Pending |
|
||
|
||
**Coverage:**
|
||
- v1 requirements: **72 total** (AUTH=6, HSHD=7, RCPE=8, PLAN=14, PNTR=5, SHOP=6, SYNC=10, UI=9, INFRA=7)
|
||
- Mapped to phases: **72**
|
||
- Unmapped: **0**
|
||
|
||
---
|
||
*Requirements defined: 2026-04-24*
|
||
*Last updated: 2026-04-23 after roadmap creation*
|