Files
recipe/.planning/REQUIREMENTS.md

16 KiB
Raw Blame History

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

  • AUTH-01: User can sign in via the self-hosted Authentik instance using OIDC (authorization code flow with PKCE)
  • AUTH-02: Client stores access + refresh tokens securely (iOS Keychain / Android EncryptedSharedPreferences)
  • AUTH-03: Ktor server validates incoming access tokens via Authentik's JWKS endpoint (issuer, audience, expiry, signature, clock skew leeway)
  • AUTH-04: User session persists across app launches without re-authentication (token refresh handled transparently)
  • AUTH-05: User can sign out, which revokes local tokens and returns to the login screen
  • 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 (112)
  • 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 2030s 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

  • INFRA-01: Gradle version catalog at gradle/libs.versions.toml is the single source of truth for library versions
  • INFRA-02: build-logic/ convention plugins centralize Kotlin/Compose/test configuration across modules
  • 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
  • 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 Pending
AUTH-02 Phase 2: Authentication Foundation Pending
AUTH-03 Phase 2: Authentication Foundation Pending
AUTH-04 Phase 2: Authentication Foundation Pending
AUTH-05 Phase 2: Authentication Foundation Pending
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