Requirements¶
Where this document sits¶
In our scoping flow, work moves from Conditions of Satisfaction, to requirements, to a structured backlog, to the choice of a delivery model, and finally to the documents that carry the project forward. This Requirements document is the bridge between the Conditions of Satisfaction, which state what success looks like, and the engineering backlog. It restates, in one management-readable place, what the platform must do for each person who uses it: the personas, the functional requirements expressed as user stories, and the end-to-end journeys those requirements compose into.
It is a faithful copy of the engineering analysis kept under version control in
development/analysis/stories.md and
development/analysis/journeys.md, with acceptance
behaviour in development/analysis/bdd.md. Those remain
the source of truth that the build is traced against. The domain rules and vocabulary behind
the requirements live in Domain, and their implementation
structure is explained in the Architecture reference.
| Status | Baselined: reflects the platform as built |
| Scope basis | Conditions of Satisfaction #5; no gamification |
| Prioritization | MoSCoW: Must / Should / Could |
Reading guide¶
The functional requirements (Part A) are the testable units of work; the journeys (Part B) show how they string together into the experience each persona actually lives. Build order is incremental: requirements in Epics 1->2->3->4 form the thin end-to-end slice (anonymous scan -> optional account -> personal verdict -> fridge); Epics 5 and 6 add the privacy guarantees and the brand side; Epics 7 and 8 extend the consumer experience (shopping list, history and compare) that ships on top of the slice.
Personas¶
- Anonymous Shopper: anyone in a supermarket who scans a product. No account, no friction. Tracked only by a pseudonymous, invisible Visitor ID.
- Sara, Account Holder. 24, goes to the gym, follows a high-protein diet, lactose intolerant. Wants to know in seconds, at the shelf, "is this right for me?", and to stop throwing food away.
- Marco, Brand Manager. Works at a mid-sized food brand. Needs proof that consumers engage with his products' QR codes. Sees only anonymized aggregates, never an individual.
Part A: Functional requirements¶
Requirements at a glance¶
| ID | Requirement | Persona | Priority |
|---|---|---|---|
| 1.1 | Scan a product code | Anonymous Shopper | Must |
| 1.2 | See the digital label | Anonymous Shopper | Must |
| 1.3 | See the product's journey | Anonymous Shopper | Should |
| 1.4 | See the sustainability score | Anonymous Shopper | Should |
| 1.5 | Handle unknown products gracefully | Anonymous Shopper | Must |
| 1.6 | Handle partial data gracefully | Anonymous Shopper | Must |
| 2.1 | Create an account (optional) | Anonymous Shopper | Must |
| 2.2 | Give explicit consent for health data | Sara | Must |
| 2.3 | Set allergies and conditions | Sara | Must |
| 2.4 | Set dietary preferences and goal | Sara | Must |
| 2.5 | Delete profile or account | Sara | Must |
| 3.1 | Get a personal verdict on scan | Sara | Must |
| 3.2 | Get safety alerts | Sara | Must |
| 3.3 | See how the product fits a goal | Sara | Must |
| 3.4 | Anonymous users see what they're missing | Anonymous Shopper | Should |
| 4.1 | Add a scanned product to the Fridge | Sara | Must |
| 4.2 | See the Fridge by freshness | Sara | Must |
| 4.3 | Be warned before food expires | Sara | Should |
| 4.4 | Remove or mark items | Sara | Must |
| 4.5 | See waste at a glance | Sara | Could |
| 5.1 | Understand what data goes where | Sara | Must |
| 5.2 | Health data stays personal | Sara | Must |
| 5.3 | Keep activity across sign-up | Anonymous Shopper | Must |
| 6.1 | Log in and see my products | Marco | Must |
| 6.2 | See scan counts | Marco | Must |
| 6.3 | See anonymized engagement | Marco | Should |
| 6.4 | Onboard a product | Marco | Should |
| 7.1 | Add a product to the Shopping List | Sara | Must |
| 7.2 | Manage the Shopping List | Sara | Must |
| 7.3 | Re-buy what left the Fridge | Sara | Should |
| 7.4 | Re-stock the Fridge from a purchase | Sara | Should |
| 8.1 | Revisit my scan history | Anonymous Shopper | Should |
| 8.2 | Compare recent scans | Anonymous Shopper | Could |
| 8.3 | Use the app in my language | Anonymous Shopper | Should |
Epic 1: Scan a product (works for everyone, no login)¶
1.1: Scan a product code (Must) As an Anonymous Shopper, I want to scan the code on a package with my phone, so that I instantly see what the product is.
- Given a GS1 Digital Link QR code, when I scan it, then I see the product name, brand, image and basic information in under 3 seconds.
- A plain retail barcode (EAN / UPC / GTIN) is also accepted, so products without a Digital Link still resolve.
- A GS1 Digital Link opens the product directly from the phone's native camera, no app install; the in-app scanner is a shortcut to the same resolver.
- The code (GTIN, lot, expiry) is decoded on the device before any network call.
- Works without creating an account or logging in.
1.2: See the digital label (Must) As an Anonymous Shopper, I want to see the ingredients, allergens and nutrition values of the scanned product, so that I don't have to read tiny print on the package.
- Ingredients, the allergen list and the nutrition table (energy, fat, sugar, protein, salt) are shown clearly.
- Allergens are visually highlighted, not buried in text.
- Where the label was assembled from a community source rather than the brand, that provenance is reflected honestly (the data is shown but flagged as unverified).
1.3: See where the product comes from (Should) As an Anonymous Shopper, I want to see the product's journey (origin -> processing -> distribution), so that I can trust what I'm buying.
- The journey is shown as an ordered list of steps, each with place and date.
1.4: See the sustainability score (Should) As an Anonymous Shopper, I want a simple 0–100 eco score with a short explanation, so that I can compare products on sustainability at a glance.
- One overall score, expandable into the five pillars (CO₂, recyclability, animal welfare, local sourcing, packaging).
1.5: Handle unknown products gracefully (Must) As an Anonymous Shopper, I want a clear message when a scanned product isn't in the system yet, so that I'm not confused by an error screen.
- A "We don't know this product yet" screen, with a one-tap option to report or request it, never a raw error.
1.6: Handle partial data gracefully (Must) As an Anonymous Shopper, I want to still see the available information when part of the data can't be loaded, so that one failure doesn't make the whole scan useless.
- If a data source fails (e.g. eco score), the rest of the passport still renders, with a small "temporarily unavailable" note on the affected section only.
Epic 2: My profile and goals (optional account, consent-gated)¶
2.1: Create an account (optional) (Must) As an Anonymous Shopper, I want to create an account in under a minute, so that I can unlock personalization, but only if I choose to.
- Scanning never requires an account; the app invites me, it never forces me.
- Sign-up asks only the minimum (email + password or equivalent).
- Authentication is delegated to the platform's identity provider, the app stores no passwords of its own.
2.2: Give explicit consent for health data (Must) As Sara, I want to explicitly agree before entering any health information, so that I stay in control of my sensitive data.
- The health profile cannot be created without an explicit opt-in (checkbox + timestamp + policy version recorded in an append-only consent ledger).
- Declining saves nothing.
2.3: Set my allergies and conditions (Must) As Sara, I want to select my allergies (e.g. dairy, gluten, nuts) and conditions (e.g. diabetes, lactose intolerance) from a clear list, so that scans can warn me about products that are risky for me.
- The standard EU allergen list is selectable with one tap each; the conditions list likewise.
- I can edit these at any time.
2.4: Set my dietary preferences and goal (Must) As Sara, I want to set my diet (e.g. vegan, high-protein, low-sodium) and my current goal (e.g. build muscle, lose weight, eat more sustainably), so that the app can judge products against what I am trying to achieve.
- One primary goal at a time, changeable anytime.
2.5: Delete my profile or account (Must) As Sara, I want to delete my health profile, or my whole account, at any time, so that my right to erasure is respected.
- Two distinct, clearly labelled actions: delete the health profile only (the account remains usable) or delete the whole account.
- Deletion is complete, immediate and confirmed; no retention tricks or multi-step dissuasion.
Epic 3: "Does this fit me?" (the core moment)¶
3.1: Get a personal verdict on scan (Must) As Sara, I want every scan to open with a simple personal verdict, Good for you / Be careful / Avoid, so that I get my answer in the first 3 seconds, not after reading a data sheet.
- The verdict appears at the top of the scan result, before any other detail.
- Tapping it reveals the reasons.
- When the underlying label is incomplete and the product cannot be assessed, the verdict is shown as Unknown, it is never silently rendered as Good.
3.2: Get safety alerts (Must) As Sara, I want a prominent red alert when a product contains something I'm allergic to, so that I never buy it by mistake.
- An allergen match produces a high-severity alert, impossible to miss (colour + icon + text).
- Condition conflicts (e.g. diabetes ↔ high sugar) and diet conflicts (e.g. vegan ↔ milk) produce medium-severity warnings with a one-line reason.
3.3: See how the product fits my goal (Must) As Sara, I want to see whether this product supports my current goal (e.g. "high in protein, fits your muscle-building goal"), so that staying adherent to my plan becomes effortless.
- One or two plain-language lines connecting the product's nutrition to my stated goal. Simple language, no jargon.
3.4: Anonymous users see what they're missing (Should) As an Anonymous Shopper, I want to see that a personal verdict exists ("Create a profile to see if this fits you"), so that I understand the value of an account without being nagged.
- Shown once per scan result, dismissible, never blocking the product information.
Epic 4: My Fridge (own it, use it, don't waste it)¶
4.1: Add a scanned product to my Fridge (Must) As Sara, I want to save a scanned product to my Fridge with one tap, so that the app knows what I have at home.
- The same physical item cannot be added twice; multiple items with the same GTIN are allowed.
- The expiry date decoded from the scanned code (lot/expiry) is stored with the item.
4.2: See my Fridge by freshness (Must) As Sara, I want to see my Fridge sorted by what expires first, with clear fresh / expiring / expired states, so that I use food before it goes bad.
- Expiring (≤5 days) and expired items are visually distinct and shown first.
- Freshness is derived from the expiry date at view time, never a stale stored flag.
4.3: Be warned before food expires (Should) As Sara, I want a notification when something in my Fridge is about to expire, so that I can use it instead of throwing it away.
- One reminder when an item crosses the "expiring" threshold; no spam.
4.4: Remove or mark items (Must) As Sara, I want to remove items from my Fridge when I've used or discarded them, so that the list stays true.
- Every removal is classified, "used" vs "thrown away", so my waste can be tracked honestly. There is no neutral delete.
4.5: See my waste at a glance (Could) As Sara, I want a simple monthly summary ("you used 14 items, 2 expired"), so that I can see myself wasting less over time.
- Plain numbers, no points, no badges.
Epic 5: Trust & privacy (cross-cutting)¶
5.1: Understand what data goes where (Must) As Sara, I want a short, plain-language privacy summary at onboarding, so that I know brands only ever see anonymous aggregates, never me.
- One screen, readable in 30 seconds, written in simple everyday language.
5.2: My health data stays personal (Must) As Sara, I want my allergies, conditions and goals never to be visible to brands or other users in any identifiable form, so that I can be honest in my profile.
- Brand dashboard queries can only return counts and aggregates; no individual-level health data crosses the privacy wall.
5.3: Keep my activity when I sign up (Must) As an Anonymous Shopper, I want my pre-account activity preserved when I create an account, so that signing up costs me nothing.
- The pseudonymous Visitor ID assigned at the first scan is linked to the new account, not replaced; earlier activity is preserved without retroactively de-anonymizing it.
Epic 6: Brand dashboard (deliberately simple)¶
6.1: Log in and see my products (Must) As Marco, I want to log in and see the list of my brand's products on the platform, so that I know what's live.
- I only ever see my own brand's products and numbers, never another brand's, anywhere in the dashboard.
6.2: See scan counts (Must) As Marco, I want to see how many times each of my products was scanned (total and over time), so that I have proof consumers actually engage with the QR code.
- A simple table plus one trend line per product. No beautification.
6.3: See anonymized engagement (Should) As Marco, I want aggregate engagement signals (e.g. % of scans saved to a Fridge, % of scanners with accounts), so that I can judge depth of interest, not just volume.
- All numbers are aggregates with a minimum group size; nothing traceable to a person.
6.4: Onboard a product (Should) As Marco, I want to submit my product's data (label, origin, sustainability info) through a simple form or file upload, so that my products appear correctly in consumer scans.
- Manual upload is acceptable for the MVP; no integration required.
Epic 7: My Shopping List (the mirror of the Fridge)¶
The Shopping List tracks what the consumer wants to buy, as the Fridge tracks what they own. It is server-owned and registered-only, but, unlike the health profile, it is not health data and is therefore not consent-gated.
7.1: Add a product to my Shopping List (Must) As Sara, I want to add a real product to my Shopping List, by searching for it or from a scan result, so that I remember to buy it.
- Every item is product-linked: it carries a real GTIN with a trusted name/brand/image snapshot. There are no free-text entries.
- Adding a product already on the list increases its quantity instead of creating a duplicate line.
7.2: See and manage my Shopping List (Must) As Sara, I want to see my list, adjust quantities and tick items off, so that the list reflects what I still need.
- Each item shows its product snapshot and quantity; quantity is bounded to a sensible range.
- I can mark an item as bought or removed; both are final.
7.3: Re-buy what left my Fridge (Should) As Sara, I want to be offered "add to shopping list?" when I use up or discard a Fridge item, so that re-buying staples is one tap.
- The prompt appears on Fridge removal and only acts when I confirm, nothing is added silently.
7.4: Re-stock my Fridge from a purchase (Should) As Sara, I want to be offered "add to fridge?" when I mark a list item as bought, so that my Fridge stays in sync with my shopping.
- The prompt appears on purchase and only acts when I confirm; it uses the product's GTIN, so no re-scan is needed.
Epic 8: Revisit and compare (find products again)¶
8.1: Revisit my scan history (Should) As an Anonymous Shopper, I want a searchable history of everything I've scanned, so that I can find a product again without re-scanning it.
- A dedicated History page lists scanned products newest-first, searchable by name or brand.
- Available without an account; it is a device-local convenience cache, not the authoritative server record.
8.2: Compare recent scans (Could) As an Anonymous Shopper, I want to compare two or three recently scanned products side by side, so that I can choose between them.
- Field-level differences (e.g. eco score, sugar) are highlighted.
- Compare reuses cached scan snapshots and never replaces the deterministic personal verdict.
8.3: Use the app in my language (Should) As an Anonymous Shopper, I want the interface in my own language, so that the product information and verdicts are easy to read.
- The interface is available in English, Italian, Spanish and French.
- Verdict and alert reason codes are localized at the presentation layer; no localized text is carried in domain data or events.
Non-functional requirements (cross-cutting)¶
These constrain how the functional requirements are met and are enforced architecturally. They are summarized here for the management reader; the authoritative form lives in the ASRs, which hold the quality attributes and their scenarios, and the Architecture reference.
- Anonymous-first. Every scan path works with no account; an account only ever adds capability.
- Speed at the shelf. A scan resolves to a readable passport in under 3 seconds.
- Graceful degradation. A failing external data source degrades one passport section, never the whole scan; the verdict degrades to Unknown, never a silent Good.
- Privacy wall. Per-scan and per-visitor facts stay on the consumer side; only minimum-group-size aggregates reach the brand side.
- Brand isolation. Every brand-owned record is tenant-scoped; a brand user never sees another brand's data.
- Delegated authentication. No passwords, sessions or tokens are hand-rolled; identity is owned by the platform's identity provider.
- Mobile-first, multi-language. The interface is designed for one-thumb phone use and ships in English, Italian, Spanish and French.
Explicitly out of scope for this MVP¶
- Reward points, lottery tickets, referrals and prize draws, cut after advisory feedback; value must come from the product itself.
- Reviews and community features, revisit after traction.
- Automated brand data integrations, manual onboarding only.
- A cross-device, server-side scan history, the current history is device-local.
- Open-Food-Facts-wide product search for the Shopping List, only the local catalog is searched today.
- Native app-store releases, if a mobile web app reaches users faster.
Part B: User journeys¶
Each journey traces one persona through a complete flow and is mapped to the requirements it realizes (IDs in parentheses). Journeys 1–4 follow the thin end-to-end slice; Journeys 5 and 6 cover privacy and the brand side; Journeys 7 and 8 cover the shopping list and the revisit/compare experience.
Journey 1: First scan, no account (Anonymous Shopper)¶
Context: standing at a supermarket shelf, holding a product, phone in hand. No app installed, no account. This is the moment the platform earns or loses the user.
Goal: know what this product is, what's in it, and whether to trust it, in seconds.
Shelf -> Scan code -> Product Passport
├── Digital label (ingredients, allergens, nutrition)
├── Journey (origin -> processing -> distribution)
├── Eco score (0–100, expandable)
└── "Create a profile to see if this fits you" (dismissible)
- The shopper points the phone camera at the GS1 Digital Link QR on the package, no app download. A plain retail barcode (EAN / UPC) is accepted too. (1.1)
- The code (GTIN, lot, expiry) is decoded on the phone before any network call. (1.1)
- The Product Passport opens: product name, brand and image render in under 3 seconds. (1.1)
- The shopper checks the digital label: ingredients, highlighted allergens, nutrition table. (1.2)
- Optionally they expand the journey (1.3) and the eco score (1.4).
- A single dismissible line notes that a personal verdict exists for account holders. (3.4)
Exit points: satisfied (close), curious (-> Journey 2), or comparing (-> Journey 8).
Failure paths: unknown product -> a clear report screen (1.5); partial data -> the affected section shows "temporarily unavailable", the rest renders (1.6).
Journey 2: From anonymous to Sara (sign-up and health profile)¶
Context: the shopper has scanned a few products and wants the personal verdict. Sign-up is invited, never forced.
Goal: unlock personalization in under a minute, consenting knowingly along the way.
"Create a profile" -> Sign-up (email + password)
-> Privacy summary (30 seconds, plain language)
-> Health personalization? ──no──-> Done (app fully usable)
│ yes
Explicit consent (opt-in recorded)
-> Allergies & conditions -> Diet & goal -> Done
- The shopper taps "Create a profile". (2.1)
- Sign-up asks only email + password; authentication is handled by the identity provider. (2.1)
- The pseudonymous Visitor ID from earlier scans is linked to the new account, no pre-account activity is lost. (5.3)
- A one-screen privacy summary explains that brands only ever see anonymous aggregates. (5.1)
- Health personalization is explicitly optional: decline saves nothing; accept records an opt-in (checkbox + timestamp + policy version). (2.2)
- Sara selects allergies and conditions from the standard EU list. (2.3)
- She sets her diet and one primary goal. (2.4)
Exit point: a complete (or deliberately minimal) profile, editable at any time.
Journey 3: "Does this fit me?" (Sara's personalized scan)¶
Context: Sara, logged in with her health profile, picks up a yogurt at the shelf, the core moment of the product.
Goal: a personal answer, is this right for me?, in the first 3 seconds.
Scan code -> Verdict banner (Good for you / Be careful / Avoid / Unknown)
├── tap -> reasons (allergen, condition, diet, goal)
└── below: full Product Passport (as in Journey 1)
- Sara scans the code as in Journey 1.
- The result opens with the verdict on top, before any other detail (3.1): Avoid for an allergen match (red, impossible to miss) (3.2); Be careful for a condition or diet conflict with a one-line reason (3.2); Good for you with a goal-fit line (3.3); Unknown when the label is too incomplete to assess, never a silent Good (3.1).
- Tapping the verdict reveals reasons; scrolling shows the same full passport.
- Sara decides at the shelf.
Exit points: bought it (-> Journey 4) (4.1); want it later (-> Journey 7) (7.1); put it back (scan the next).
Journey 4: My Fridge (from purchase to "nothing wasted")¶
Context: Sara is home with her shopping. Days pass between the steps, the only flow that spans weeks.
Goal: use what she owns before it expires, and see her waste shrink.
Scan result -> "Add to Fridge" (expiry from code stored)
⋮ days pass ⋮
Notification: "expires in 5 days" -> open Fridge (sorted by freshness)
-> use it -> mark "used" -> item removed -> "Re-buy?" (Journey 7)
-> too late -> mark "thrown away" -> counted honestly -> "Re-buy?" (Journey 7)
⋮ end of month ⋮
Summary: "you used 14 items, 2 expired"
- Sara taps "Add to Fridge"; the decoded expiry is stored with the physical item, which cannot be added twice (multiple items may share a GTIN). (4.1)
- The Fridge sorts by soonest expiry, with fresh / expiring (≤5 days) / expired visually distinct. (4.2)
- One notification fires when an item crosses the expiring threshold. (4.3)
- She removes items marking "used" vs "thrown away" (4.4), and may be offered "add to shopping list?" to re-buy a staple (7.3).
- At month end she sees plain numbers. (4.5)
Exit point: a Fridge that reflects reality, and a monthly number she wants to lower.
Journey 5: Walking away (consent revocation and erasure)¶
Context: Sara no longer wants her health data on the platform, or wants to leave entirely. This journey must be as short as sign-up.
Goal: exercise her right to erasure with one clear action.
Settings -> Delete health profile -> confirm -> profile gone, account remains
└-> Delete account -> confirm -> everything gone
- From settings, Sara chooses to delete the health profile only or the whole account. (2.5)
- One action, one confirmation; no retention tricks.
- Deletion is complete, immediate and confirmed.
- If only the profile was deleted, the app keeps working, back to the anonymous-style experience, with an account; her Shopping List (not health data) is unaffected.
Exit point: trust preserved, the existence of this painless path is what makes Journey 2 feel safe. (5.2)
Journey 6: Proof of engagement (Marco at the brand dashboard)¶
Context: Marco needs to justify the QR investment internally, from his desk.
Goal: walk into a meeting with evidence that consumers actually scan.
Login -> My products (what's live)
-> per-product scan counts (table + trend line)
-> engagement aggregates (% saved to Fridge, % with accounts)
Onboard a new product -> form / file upload -> appears in consumer scans
- Marco logs in and sees his brand's products. (6.1)
- For each, total scans and a trend over time, a table and one trend line. (6.2)
- Aggregate engagement signals (% saved to a Fridge, % with accounts), every number an aggregate above a minimum group size. (6.3, 5.2)
- A new product is submitted via form or file upload. (6.4)
Exit point: a screenshot-able dashboard, and zero access to any individual consumer.
Journey 7: My Shopping List (re-buy and re-stock loops)¶
Context: Sara plans her shopping the way she manages her fridge. The Shopping List is the mirror of the Fridge, what she wants versus what she owns, and the two talk to each other only when she says so.
Goal: keep a reliable list of real products and close the loop between buying and owning.
Add to list (search a product, or from a scan, or "re-buy" from the Fridge)
-> Shopping List (product snapshots + quantities)
-> mark "bought" -> "Add to fridge?" -> Fridge (Journey 4)
-> mark "removed" -> dropped without buying
- Sara adds a product, by catalog search, from a scan (Journey 3), or via the "re-buy?" prompt on a Fridge removal (Journey 4). Every entry is a real product with a trusted snapshot; no free-text notes. (7.1)
- Re-adding something already on the list bumps its quantity. (7.1)
- She adjusts quantities and marks each item as bought or removed. (7.2)
- On bought, she is offered "add to fridge?", one confirmation re-stocks by GTIN, no re-scan. (7.4)
Exit points: re-stocked (-> Journey 4), or a clean list. The fridge ↔ list loops are client-orchestrated prompts, explicit confirmations, never a silent sync.
Journey 8: Revisiting and comparing (Anonymous Shopper)¶
Context: the shopper scanned several products and wants to find one again, or choose between two, without re-scanning in the aisle.
Goal: get back to a product, or decide between candidates, in a couple of taps.
History (searchable, newest first) ── find a product ──-> Product Passport (Journey 1)
Recent scans -> Compare (2–3 products side by side, differences highlighted)
- From the History tab, the shopper searches by product name or brand and reopens any product, no account needed. (8.1)
- From recent scans, they pick two or three products and open Compare, which highlights field-level differences such as eco score and sugar. (8.2)
- Throughout, the interface is in the shopper's language (English, Italian, Spanish or French). (8.3)
Exit point: the shopper finds or chooses a product and continues into a normal passport view (Journey 1), or, signed in, a personal verdict (Journey 3).
How the journeys connect¶
The thin slice to build first is the vertical path 1 -> 2 -> 3 -> 4. Journeys 5 and 6 guard trust and monetize the slice; Journeys 7 and 8 extend the consumer experience, the Shopping List closes the re-buy / re-stock loops with the Fridge, while History and Compare make scanned products easy to find again.