Key Flows

These sequence diagrams describe current orchestration, cross-checked against the public and internal contracts in 'services//openapi.yaml'. OpenAPI defines interfaces; the service implementation defines call order, timeout and fallback behavior.

The diagrams show the accepted consumer flows. The separate event-driven analytics path is documented in Event Sourcing: the measurement pipeline aggregates Kafka facts and Brand Analytics serves the resulting read model.

1. Anonymous Scan

sequenceDiagram actor Consumer participant Web as Consumer Web App participant Gateway as API Gateway participant Passport as passport-service participant Catalog as Producer Registry / OFF Cache participant Journey as Journey Source participant Recipes as Recipe Source participant Broker as Kafka Consumer->>Web: Scan GS1 Digital Link Web->>Web: Decode GTIN<br/>(or preserve Digital Link qualifiers) Web->>Gateway: POST /api/v1/scans Gateway->>Passport: Create anonymous scan with Visitor ID Passport->>Catalog: Resolve producer projection or OFF cache Passport->>Passport: Save ScanRecord Passport-->>Broker: ProductScanned Passport->>Journey: Resolve journey by GTIN and optional lot Journey-->>Passport: Loaded or unavailable Passport->>Recipes: Find recipe suggestions Recipes-->>Passport: Loaded or unavailable Passport-->>Gateway: Complete ResolvedPassport<br/>with per-section states Gateway-->>Web: Base passport + unauthenticated verdict<br/>+ journey/recipe states Web-->>Consumer: Show result

The in-memory producer registry or persistent Open Food Facts community cache supplies the base product. Producer synchronization is independent of scans. Verdict, Journey and Recipes are resolved synchronously and sequentially before the response; a failed optional dependency changes only its section state. The current implementation does not return pending sections or require client polling.

When the consumer uses a camera app instead of the in-app scanner, the flow starts at the Resolver route instead: the browser opens GET /01/{gtin}/…; the gateway has passport-service parse the path and create the same scan, then redirects the browser to the result page. Processing from Resolve producer projection or OFF cache onward is identical.

2. Personalized Scan

sequenceDiagram actor Consumer participant Web as Consumer Web App participant Gateway as API Gateway participant Passport as passport-service participant Personalization as personalization-service participant ProfileDB as Personalization DB participant Rules as Configured Rule Provider participant Journey as Journey Source participant Recipes as Recipe Source participant Broker as Kafka Consumer->>Web: Scan GS1 Digital Link Web->>Gateway: POST /api/v1/scans with bearer token Gateway->>Passport: Create scan with Account reference Passport->>Passport: Resolve catalog entry and save ScanRecord Passport->>Personalization: POST /internal/v1/verdicts<br/>Account ref + Digital Label Personalization->>ProfileDB: Load HealthProfile Personalization->>Rules: Load versioned rule set Personalization->>Personalization: Compute Verdict and goal-fit Personalization-->>Broker: VerdictComputed Personalization-->>Passport: Verdict Passport->>Journey: Resolve Journey Journey-->>Passport: Loaded or unavailable Passport->>Recipes: Resolve Recipes Recipes-->>Passport: Loaded or unavailable Passport-->>Broker: ProductScanned Passport-->>Gateway: ResolvedPassport + Verdict Gateway-->>Web: Scan result Web-->>Consumer: Show Verdict first

The Health Profile remains inside personalization-service; Passport receives only the computed Verdict. Journey and Recipe failures remain section-local, and a Personalization timeout returns a verdict_unavailable section rather than failing the scan.

3. Add to Fridge

sequenceDiagram actor Consumer participant Web as Consumer Web App participant Gateway as API Gateway participant Fridge as fridge-service participant Passport as passport-service participant FridgeStore as Fridge Event Store participant Broker as Kafka Consumer->>Web: Add scanned item to Fridge Web->>Gateway: POST /api/v1/me/fridge/items<br/>{ scanId } Gateway->>Fridge: Add item for authenticated Account Fridge->>Passport: GET /internal/v1/scans/{scanId}/item Passport-->>Fridge: Trusted ScannedItem + passport snapshot Fridge->>Fridge: Check physical-item uniqueness Fridge->>FridgeStore: Append ItemAddedToFridge Fridge-->>Broker: ItemAddedToFridge Fridge-->>Gateway: Created FridgeItem Gateway-->>Web: 201 Created Web-->>Consumer: Show item in Fridge

Only scanId comes from the client. The Fridge obtains trusted GTIN, serial, expiry and display data from passport-service.