-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Epic: Country-Aware Scanner & Submission Pipeline
Product principle: Global capture, country-aware interpretation, routing, and review.
Scanning remains permissive. Submissions capture country context. Admin review surfaces mismatch signals. GS1 prefixes are hints, not truth.
Problem Statement
The scanner and submission pipeline currently operates in a country-blind fashion while the search/browse pipeline is correctly country-scoped. This inconsistency creates five concrete data-quality and moderation problems:
-
Ambiguous scan results.
api_record_scan()doesWHERE ean = TRIM(p_ean) LIMIT 1— noORDER BY, no country filter. If the same EAN exists in PL and DE, the result is nondeterministic. -
Country-blind submissions.
product_submissionshas nocountrycolumn. When a user in Germany submits a product, the admin reviewer has zero signal about which catalog it should enter. -
Global
has_pending_submissioncheck. The not-found screen checks globally for pending submissions. If a PL user submitted for EAN590..., a DE user scanning the same EAN sees "already submitted" — even though the DE catalog still needs it. -
Admin review without country context.
api_admin_get_submissions()returns submissions with zero country metadata. The admin cannot route submissions to the correct catalog. -
Scan history without context.
scan_historyrecords{ean, product_id, found}with no country context. Analytics cannot distinguish "scanned from DE region" vs "scanned from PL region."
Architecture Decision
Hybrid Model: Global capture + country-aware routing (Option 3 of 4 evaluated).
| Model | Verdict | Rationale |
|---|---|---|
| Strict region lock | ❌ Rejected | Too restrictive. Blocks legitimate cross-border product discovery. Goes against user's intent. |
| Fully global flat catalog | ❌ Rejected | Destroys country isolation (same EAN can have different formulations). Fails at 3+ countries. |
| Hybrid: global capture + country-aware routing | ✅ Chosen | Minimal change, high value. Preserves permissive scanning while adding context for routing and review. Works to 10 countries. |
| Canonical product + country overlay | ❌ Deferred | Over-engineered for 2 countries. product_links table already provides this capability at a basic level. Revisit at 4+ countries. |
Phased Implementation Plan
Phase 1 — Country Context Capture (no behavioral changes)
- schema(scanner): add scan_country to scan_history table #921 — schema: add
scan_countrytoscan_history - schema(scanner): add scan_country + suggested_country to product_submissions #922 — schema: add
scan_country+suggested_countrytoproduct_submissions - feat(scanner): pass user region through api_record_scan and api_submit_product #923 — feat: pass user region through
api_record_scan()andapi_submit_product() - feat(frontend): pass scan country from frontend scan/submit flow to RPCs #924 — feat: pass scan country from frontend scan/submit flow to RPCs
- feat(frontend): show country context in admin submission review UI #925 — feat: show country context in admin review UI
Phase 2 — Smart Lookup & Cross-Country Visibility
- feat(scanner): region-preferred product matching in api_record_scan #926 — feat: region-preferred product matching in
api_record_scan() - feat(frontend): cross-country product badge in scan result card #927 — feat: cross-country product badge in scan result card
- feat(scanner): GS1 prefix to country hint utility function #928 — feat: GS1 prefix → country hint utility function
- feat(scanner): country mismatch detection badges in admin review #929 — feat: country mismatch detection in admin review
Phase 3 — Submission Quality & Future Foundation
- feat(scanner): country-scoped pending submission uniqueness #930 — fix: country-scoped
has_pending_submissioncheck - feat(scanner): country-aware submission quality scoring #931 — feat: country context in submission quality scoring
- feat(scanner): cross-country scan and submission analytics views #932 — feat: cross-country scan analytics view
Scenarios Matrix
| # | Scenario | User sees | Stored | Admin sees | Flags |
|---|---|---|---|---|---|
| 1 | Region=DE, product in DE | Normal result card | scan_country=DE, product_id=DE | N/A | None |
| 2 | Region=DE, product in PL only | Result + "From Polish catalog" badge | scan_country=DE, product_id=PL | N/A | None |
| 3 | Region=DE, product in both | DE version (preferred) | scan_country=DE, product_id=DE | N/A | None |
| 4 | Region=DE, product only in PL | Result + "Polish catalog" badge | scan_country=DE, product_id=PL | N/A | None |
| 5 | Region=DE, product not found | Not-found + submit CTA (country=DE pre-filled) | scan_country=DE, found=false | suggested_country=DE, scan_country=DE | GS1 mismatch if applicable |
| 6 | Imported product | Same as 4 or 5 depending on catalog | User's region flows through | GS1 mismatch expected for imports | Info only |
| 7 | Same EAN, different formulation | Region-preferred match | Region-preferred product_id | "EAN exists in {other country}" | Admin decides: new entry or link |
| 8 | Wrong country submission | Form with country defaulted to region, editable | Whatever user selected | GS1 mismatch hint if applicable | Admin can override |
| 9 | Admin reviews mismatch | N/A | N/A | Visual warning badges for conflicts | Approve/override/reject |
Strategic Decisions
- Canonical product model: Defer until 4+ countries.
product_linksis sufficient for now. - Minimum safe first implementation: Phase 1 issues only — add country columns + pass through pipeline. No behavioral changes.
- Country override in submit form: Yes — default to user's region, allow editing.
- Scan history country: Store user's region at scan time, not physical location.
- GS1 prefix trust level: Hint only. Never block or auto-assign based on GS1.
has_pending_submissionscope: Country-scope it in Phase 3 — currently blocking cross-country submissions incorrectly.- Admin routing by country: Phase 2–3. For now, just show country context in the existing global queue.
Risks If We Do Nothing
- Growing DE catalog → more ambiguous scan matches. As DE reaches PL product count (~1,380), LIMIT 1 nondeterminism affects more users.
- Admin review errors. Without country context, admins will approve products into wrong catalogs.
- Blocked cross-country submissions. Global pending index prevents legitimate multi-country submissions for same EAN.
- Unusable scan analytics. Cannot distinguish scan-miss rates by country → cannot prioritize catalog gaps.
- Trust scoring false signals.
_score_submission_qualityawards points for EAN match against ANY country's product — inflates confidence for wrong-country submissions.
What to Defer
- Physical scan geolocation (never needed — region preference is sufficient)
- Canonical product graph / country overlay model (until 4+ countries)
- Auto-routing submissions to country-specific admin queues (until admin team grows)
- Cross-country product suggestion in not-found screen ("This product exists in PL — want to import it?" — nice but complex)
- Multi-language product name resolution in scan results (already partially handled by
resolve_language())