Global product standards audit
This document records the pre-migration baseline for the ecosystem-wide product standards. It is intentionally evidence-based: an item is marked complete only when the shared implementation, affected callers, data migration, tests, and production verification all exist.
Scope and method
The audit covers the admin application, company dashboard, customer web application, customer Flutter application, driver Flutter application, shared packages, database migrations, APIs, notifications, documents, and public product surfaces.
Evidence was gathered from:
- repository-wide source scans excluding generated output and test doubles;
- schema, RLS, RPC, API, and shared-package inspection;
- a read-only authenticated production check of
/,/companies,/demos,/incidents,/tickets,/audit-log, and/adminsonadmin.shambus.com; - current official documentation for React Aria Components,
react-phone-number-input,phone_form_field, Google Identity Services,google_sign_in, and Supabase session handling.
The authenticated production pages rendered without captured console warnings or errors. That proves those routes currently load; it does not prove that their mutations, permissions, empty states, or all role combinations are correct.
Technical audit score
Web applications
| Dimension | Score | Verified baseline |
|---|---|---|
| Accessibility | 2/4 | Shared controls have labels and focus styling, but the shared Select is native, date controls lack complete grid/dialog semantics, and DateRangePicker nests a button inside a button. |
| Performance | 2/4 | Server pagination exists on some resources, but Routes fetches and filters the full tenant collection in a 911-line client page and there is no common large-dataset query contract. |
| Responsive design | 2/4 | Responsive variants exist, but many collection pages maintain separate card/table implementations and several filters use desktop-native controls. |
| Theming | 2/4 | ShamBus green and shared tokens exist, but app-local primitives, raw colors, custom SVGs, emoji icons, and duplicated constants still drift. |
| Implementation integrity | 1/4 | The ecosystem has strong individual features but no single collection-query, entity-reference, numeral, icon, or traveler-identity interface. |
| Total | 9/20 | Poor — shared seams require migration before page-level polish. |
Flutter applications (source and local browser audit; physical-device verification pending)
| Dimension | Score | Verified baseline |
|---|---|---|
| Accessibility | 2/4 | Material semantics are present in places, but emoji-rendered layout objects, inconsistent phone fields, and screen-local controls remain. |
| Performance | 2/4 | Feature separation and list builders exist, but image sizing/cache policy and low-end-device evidence are incomplete. |
| Appearance and theming | 2/4 | Cairo and shared green themes exist, but presentation constants and symbols are duplicated and not fully semantic. |
| Platform conformance | 3/4 | GoRouter, Material controls, sheets, bottom navigation, and native traveler Google authentication exist; physical-device OAuth and remaining web-shaped flows still need release evidence. |
| Adaptivity | 2/4 | Phone layouts are implemented, but tablet, multi-window, large-text, keyboard, and foldable evidence is incomplete. |
| Total | 11/20 | Acceptable baseline — significant native-product and device-verification work remains. |
Verified occurrence inventory
These counts are the original baseline that the migration guard must drive to zero. They exclude tests and generated build output and are retained for traceability rather than presented as the current state.
| Rule | Verified matches | Affected production files |
|---|---|---|
Native <select> | 31 | 15 |
| Native web date/time inputs | 25 | 15 |
| Emoji/symbol code points in product sources | 261 | 27 |
| Web formatting calls that do not force Latin digits | 48 | 21 |
| Locale-dependent Flutter number formatting | 21 | 14 |
| Raw web telephone inputs outside the shared field | 6 | 4 |
| Flutter phone entry surfaces without an international selector | 4 | 3 |
Current source-level migration evidence — 2026-08-22
pnpm lint:product-standardspassed across 1,078 production source files with zero violations for emoji, native web selects, native web date/time inputs, unsafe locale digits, direct Flutter locale formatters, raw Flutter phone fields, the retired phone package, or direct use of the third-party phone widget.packages/mobile_uinow owns the FlutterInternationalPhoneField. It usesphone_form_field10.0.18, the newest release compatible with the repository's Flutter 3.38.5 toolchain, with parser-backed validation, SVG country flags, searchable localized country selection, Syrian defaults, forced LTR input, and E.164-only output.- Customer mobile login, registration, booking for self, booking for another traveler, and separate WhatsApp-contact entry use the shared control. The duplicate raw widget, app-local normalizer, and
intl_phone_fielddependency were deleted. - Five shared phone-control widget tests, seven mobile-core formatter/normalizer tests, and seventy focused customer authentication/booking/input tests pass;
flutter analyzepasses for the customer app and the shared package. - The landing page, customer search page, Journey results filters, and customer mobile search now share one typed City → station/stop/airport identity. The web surfaces use the package-owned React Aria Combobox with grouped options; the obsolete mobile
/city-selectionimplementation was removed. Exact stop selections survive URLs and recent-search persistence, while old city-only history migrates safely. - Local evidence for the discovery slice: 54/54 focused web hierarchy tests passed before the landing migration, the landing/shared-combobox slice passes 9/9, focused mobile location/API/router tests pass 30/30, the mobile search/history slice passes 55/55, and customer mobile
flutter analyzeis clean. - The complete local Chromium route-flow gate now passes
180/180: all registered customer, dashboard, and admin routes plus28/28customer Flutter-web and14/14driver Flutter-web routes. Mobile checks wait for a real Flutter first frame rather than accepting the HTML bootstrap. The complete Flutter suites pass1461/1461customer and598/598driver tests, and both analyzers are clean. - This browser evidence covers route reachability and rejects unexpected page, console, document, and same-origin API failures. It does not prove every mutation, role combination, native plugin, physical-device behavior, production deployment, or complete manual visual review.
This is local source, test, and browser evidence. The standard remains below the production-release gate until Android/iOS device checks and the deployed role flows pass.
Native Select locations
packages/ui/src/select.tsxapps/admin/src/app/admins/page.tsxapps/admin/src/app/audit-log/page.tsxapps/admin/src/app/companies/page.tsxapps/admin/src/app/demos/page.tsxapps/admin/src/app/feature-flags/page.tsxapps/admin/src/app/incidents/page.tsxapps/admin/src/app/loyalty/page.tsxapps/admin/src/app/tickets/[id]/page.tsxapps/admin/src/app/tickets/page.tsxapps/admin/src/app/waitlist/page.tsxapps/customer/src/app/search/page.tsxapps/customer/src/app/support/new/page.tsxapps/dashboard/src/app/settings/page.tsxapps/dashboard/src/app/tickets/new/page.tsx
Native date/time locations
apps/admin/src/app/audit-log/page.tsxapps/admin/src/app/companies/page.tsxapps/admin/src/app/loyalty/page.tsxapps/customer/src/app/bookings/[id]/modify/page.tsxapps/customer/src/app/search/page.tsxapps/dashboard/src/app/bookings/page.tsxapps/dashboard/src/app/drivers/[id]/edit/page.tsxapps/dashboard/src/app/drivers/new/page.tsxapps/dashboard/src/app/office-booking/new/page.tsxapps/dashboard/src/app/office-booking/page.tsxapps/dashboard/src/app/payments/payment-ledger-panel.tsxapps/dashboard/src/app/reports/page.tsxapps/dashboard/src/app/trips/[id]/edit/page.tsxapps/dashboard/src/app/trips/new/trip-planner.tsxapps/dashboard/src/app/trips/trips-client.tsx
Emoji-bearing product sources
The concentration is not limited to decorative pages. It includes amenity metadata, country flags, seat maps, shared-message copy, email, WhatsApp copy, booking share text, OTP logs, demo access, and landing surfaces. The affected sources are:
packages/ui/src/country-selector.tsxpackages/shared/src/constants.dartpackages/shared/src/types.tsapps/mobile/customer/lib/core/services/share_service.dartapps/mobile/customer/lib/data/services/supabase_service.dartapps/mobile/customer/lib/features/booking/presentation/widgets/dynamic_seat_map.dartapps/admin/src/app/demos/page.tsxapps/admin/src/app/incidents/page.tsxapps/admin/src/components/landing/LandingPage.tsxapps/admin/src/constants.tsapps/admin/src/lib/constants.tsapps/admin/src/lib/services/email.service.tsapps/admin/src/lib/services/whatsapp.service.tsapps/dashboard/src/app/demo/access/page.tsxapps/dashboard/src/app/trips/[id]/seats/page.tsxapps/dashboard/src/components/landing/LandingPage.tsxapps/dashboard/src/constants.tsapps/dashboard/src/lib/constants.tsapps/dashboard/src/lib/services/email.service.tsapps/dashboard/src/lib/services/whatsapp.service.tsapps/customer/src/app/api/auth/customer/send-otp/route.tsapps/customer/src/app/api/auth/customer/verify-otp/route.tsapps/customer/src/components/booking/dynamic-seat-map.tsxapps/customer/src/constants.tsapps/customer/src/lib/constants.tsapps/customer/src/lib/services/email.service.tsapps/customer/src/lib/services/whatsapp.service.ts
Country flags must move from Unicode regional-indicator emojis to real SVG flag assets. Operational and amenity symbols must move to the platform icon registry. Notification copy must use structured headings and labels rather than emoji prefixes.
Findings by priority
P1 — The shared Select violates the global rule
packages/ui/src/select.tsx is a styled native <select>. Ten admin pages, two customer pages, and two dashboard pages also render native selects directly. The current interface cannot provide search, async results, multi-selection, grouped options, rich states, or consistent mobile overlays.
Required migration: replace the shared module with accessible Select, Combobox, and MultiSelect interfaces; migrate all callers; delete direct native implementations; add a source guard.
P1 — The date/time system is fragmented and has accessibility defects
Fifteen production files expose browser-native date/time controls. The shared date controls are hand-rolled and do not provide complete calendar-grid semantics, roving focus, locale-aware segments, or a responsive sheet presentation. DateRangePicker currently renders a clear button inside its trigger button, which is invalid nested interactivity and can cause hydration and keyboard problems.
Required migration: one date/time module with single date, range, date-time, time, presets, bounds, disabled dates, keyboard navigation, RTL/LTR, and a mobile dialog/sheet adapter.
P1 — Iconography is data drift, not only visual drift
There are 261 emoji/symbol matches across 27 production files. Amenity metadata stores emoji strings in both TypeScript and Dart, which makes the problem part of the shared data contract. Country flags are generated as emoji. Booking messages and notification templates use emoji as labels.
Required migration: stable icon keys in shared contracts, Lucide on web, Material/SF-compatible mapped icons in Flutter, SVG flags for countries, and text-only notification templates with optional channel-native structured media.
P1 — Latin digits are not guaranteed globally
Some web callers correctly use ar-SY-u-nu-latn, but at least 48 calls do not force the Latin numbering system. Fourteen Flutter files use locale-dependent number formatting, so Arabic UI can emit Arabic-Indic digits.
Required migration: central formatters for numbers, currency, dates, times, percentages, identifiers, and digit normalization. Arabic text locale and numbering system must be independent decisions. Inputs that accept digits must normalize Arabic-Indic and Eastern Arabic-Indic characters to Latin before validation.
P1 — Phone entry is only partially standardized
The web shared phone field already defaults to Syria, emits an E.164-shaped value, uses libphonenumber-js, and forces the control row to LTR. This is a strong foundation. It still uses emoji flags, and six product inputs bypass it. The Flutter app has no equivalent searchable international selector.
Required migration: keep the mature parsing library, replace flags with bundled SVG assets, migrate all web callers, add a native Flutter phone-field module, and enforce normalized E.164 values at request and database seams.
Current implementation: the web and Flutter shared controls now provide the common country-aware behavior, all known production callers have migrated, and source guards prevent direct alternatives. packages/mobile_core owns normalization and packages/mobile_ui owns native presentation. Device and production evidence is still pending, so this item is not yet release-verified.
P1 — Collection behavior is fragmented
Only one source file is named as a reusable filter component. The 911-line Routes page downloads a collection and filters it locally; its API accepts only is_active. Other resources independently parse combinations of status, date, search, page, and limit. Filter state is usually component state rather than a shareable URL, and sort semantics differ by route.
Required migration: a typed collection-query contract supporting search, filter groups, multi-sort, cursor/page pagination, URL serialization, saved views, authorization, and indexed server execution. UI pages consume the same FilterBar, filter-chip, sort, and saved-view modules.
P1 — The entity graph is implicit
Foreign keys exist for the core operational chain, but detail responses and screens do not expose a consistent related-record graph. Company, route, trip, bus, driver, booking, traveler/passenger, financial document, and payment references are composed differently by each page. Back navigation commonly loses list state.
Required migration: stable entity reference types, canonical detail paths, contextual breadcrumbs, related-record summaries, preserved return URLs, batched related counts, and explicit permission-aware links.
P1 — Default seat types are not guaranteed for every tenant
seat_type_definitions is already configurable and includes price modifiers, accessibility flags, color, active state, and sort order. The seed inserts four types only for a fixed demo company. There is no universal backfill plus new-company provisioning guarantee.
Required migration: an idempotent database provisioning function, a safe existing-company backfill, and a company-creation trigger/onboarding call. Defaults remain ordinary rows that companies can rename, disable, reorder, and extend.
P1 — The New Bus wizard is powerful but incomplete
The dashboard already has a four-stage wizard, reusable layout documents, templates, numbering schemes, deck support, a visual editor, WC/door/driver objects, validation, and preview. It should be preserved. The first stage only captures plate number, bus type, amenities, and active state; manufacturer, model, year, internal name, registration metadata, autosave, recovery, and complete review are absent.
Required migration: deepen the existing wizard rather than replace it with a simpler form. Add a versioned draft, per-step schema, unsaved-change protection, fuller vehicle metadata, amenity icon registry, capacity reconciliation, and mobile editing behavior.
P1 — Trip media is absent from the domain
No trip-image field or media relation exists in the production schema or trip contracts. Current route imagery is a deterministic illustrative fallback and cannot represent an operator-managed trip image.
Required migration: a trip-media relation with ownership, purpose, crop/focal metadata, variants, status, audit fields, storage policy, image-processing adapter, dashboard management, and read contracts for all customer surfaces.
P1 — Public company profiles are incomplete
Companies currently have name, logo, description, phone, email, website, address, city/governorate, verification state, and JSON settings. Cover media, short description, social links, policies, operating cities, services, gallery, public slug, publication state, and a customer profile route are absent.
Required migration: first-class company profile and media/policy relations, tenant-scoped editing, admin moderation, public read models, customer-facing profile pages, and links from trip cards/details.
P1 — Traveler Google authentication needs external release evidence
Traveler web now uses Google's official Identity Services button and a nonce-bound server exchange. Web and native mobile share the same verified-token, canonical-session, staff-isolation, account-linking, E.164 phone-completion, safe Passenger merge, and return-path contracts. Connected sign-in methods prevent removal of the last usable identity. These paths are implemented and locally tested.
Remaining release gates: create the real Web, Android, and iOS OAuth clients; register the Web JavaScript origins, sy.shambus.app, release/Play signing fingerprints, and iOS callback scheme; configure the production variables; then verify cancellation, account switching, expiry, network recovery, and deep-link return on physical devices. Google remains traveler-only and is not production-ready until these external configuration and device gates pass.
P1 — Mobile verification is incomplete
The customer app has localized navigation, booking, seats, tickets, notifications, offline behavior, one shared E.164 phone field, one paste/autofill-safe OTP field, and a maintained native Google adapter on Android/iOS. Compiled release and browser evidence exists; real-provider physical-device evidence, adaptive-tablet validation, and the broader mobile product pass remain unfinished. The driver app is covered by the same source standards guard even where no current phone field exists.
Required migration: shared Flutter presentation modules, native sheets and pickers, adaptive navigation, safe areas and keyboard insets, semantics, deep-link restoration, low-end image behavior, and device evidence for iOS and Android.
Current local evidence: every declared Flutter-web route reaches a real first frame in a fresh Chromium context (28/28 customer and 14/14 driver), with strict page, console, and HTTP checks. The route gate exposed and drove fixes for mobile CORS policy drift, legacy trip-search refreshes without route state, and unauthenticated chat failures. This narrows the remaining risk but does not close the native/device or production gates.
Target module seams
The migration must deepen existing shared packages rather than create app-local copies:
| Seam | Owner | Interface responsibility |
|---|---|---|
| Web interaction primitives | packages/ui | Select, Combobox, MultiSelect, date/time, phone, filters, data table, entity links, media upload, icons. |
| Formatting and normalization | packages/utils | Latin digits, dates/times, money, identifiers, E.164 normalization, URL-safe return paths. |
| Shared contracts | packages/types | Collection queries, entity references, related-record summaries, profiles, trip media, seat defaults, traveler auth methods. |
| Business behavior | packages/services | Server-side filtering, media processing, profile publication, traveler identity policy, saved views. |
| Persistence and authorization | infrastructure/supabase/migrations | Relations, constraints, RLS, indexes, provisioning functions, safe backfills. |
| Native presentation | packages/mobile_core + packages/mobile_ui | Platform-independent Latin/E.164 formatting plus shared Flutter controls, icon mapping, and deep-link return-state primitives. |
Migration gates
Each standard is complete only when all of these are true:
- The shared interface and its error modes are documented.
- Backend contracts, authorization, indexes, and migrations are in place where required.
- Existing data has an idempotent backfill and rollback-safe deployment path.
- All production callers use the shared interface; obsolete implementations are deleted.
- Unit, integration, database, E2E, accessibility, RTL/LTR, responsive, and permission tests pass.
- A mechanical source guard prevents native selects, native web date pickers, emoji product sources, unforced numeral formatting, raw Flutter phone fields, and direct third-party phone widgets from returning.
- Production is rebuilt, migrated, and verified with authenticated role flows before the standard is marked complete.
Positive foundations to preserve
@shambus/ui,@shambus/types,@shambus/utils, and@shambus/servicesalready provide the correct ownership direction.- Web and Flutter phone fields now use maintained parsing/validation packages, Syrian defaults, LTR isolation, and E.164 output behind shared product interfaces.
- Seat types and bus layout documents are already configurable domain records.
- The current New Bus flow contains a substantial visual layout editor and should be deepened, not discarded.
- Customer web and Flutter already have Arabic/English i18n architecture suitable for Turkish later.
- Multi-tenant RLS, company access checks, CSRF protection, notification delivery, and financial-document foundations already exist.
- Production admin baseline routes currently render without captured console errors.
This audit remains active until the source guard reaches zero and the production role matrix passes.