Skip to content

Release v0.4.30: App Review access and Continue with Fleetbase - #162

Merged
roncodes merged 11 commits into
mainfrom
release/v0.4.30
Oct 27, 2026
Merged

roncodes merged 11 commits into
mainfrom
release/v0.4.30

Conversation

@roncodes

@roncodes roncodes commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Summary

Storefront signs customers in with a texted code. Apple and Google reviewers can't receive one, and Apple often rejects apps its reviewers can't sign in to. Until now the only workaround was server env (STOREFRONT_BYPASS_VERIFICATION_CODE with STOREFRONT_REVIEW_ACCOUNTS), which Fleetbase Cloud customers can't set (AppHelm Q-16).

This adds App Review access for stores and networks, built on core-api's new App Review access (fleetbase/core-api#323), which Navigator (fleetbase/fleetops#418) and future apps share:

  • Console. Turn it on in Storefront → Settings → App Review; for networks it's a section in the network's Settings. Copy the number, see the code once, create a new code (with a confirmation) or turn it off.

  • Number and code. Reviewers sign in with +1 202 555 0143, from the 555-0100–0199 range reserved for fiction, so core never texts it, plus a six-digit code. Core stores the code hashed. It is shown once and works only for the store or network that created it.

  • Flows. Sign-in, sign-up, adding the number at checkout, and account deletion all work without a text message. The review number gets 422 with a clear message where access is off, and is still not texted.

  • Orders. Orders placed by the review account get meta.app_review = true. The order panel shows an "App Review test order" alert and an "App Review order" badge, staff new-order SMS and email say so, and these orders are never auto-dispatched to a driver.

  • Self-hosted. The env review accounts still work as an instance-wide fallback, now for sign-up too, and are never sent a code.

  • Continue with Fleetbase (feat(oauth): storefront scopes for Continue with Fleetbase #163, merged into this branch). Apps holding an access token from core-api's OAuth provider (feat(oauth-server): Sign in with Fleetbase (OAuth 2.0 / OpenID Connect provider) core-api#324) get Storefront scopes, each needing an organization administrator's consent:

    Scope Endpoint What it does
    storefront:read GET /storefront/oauth/v1/storefronts Lists the token organization's stores and networks with their public store_/network_ keys. Nothing about customers, orders or payments
    storefront:app-key POST /storefront/oauth/v1/app-key Creates (or returns) one live API key per app for its Storefront app build, listed under Developers → API Keys
    storefront:review-access core's /oauth/v1/review-access/storefront-store|storefront-network/{id} Turns App Review access on or off

    The routes and scopes are only registered when core-api has the OAuth provider. This is how AppHelm connects a Cloud customer's storefront without pasting keys.

Implementation

  • AppReview::register() (in StorefrontServiceProvider::boot()) registers storefront-store (Store) and storefront-network (Network) with core, with the review number and permissions:
    • change: storefront manage-app-review store|network, a new schema action
    • read: storefront view store|network
  • Fleetbase\Storefront\Support\AppReview keeps what's Storefront's own: the shared review customer (one user, a customer contact per store), order marking, and the env keys. Code checks go through core.
  • CustomerController:
    • login-with-sms, request-creation-code, account-closure and request-phone-verification answer as if a code was sent, without sending anything.
    • verify-code, customers (create), confirm-account-closure and verify-phone-number accept the store's code.
    • verify-code creates the shared review account on its first sign-in.
    • Closing the review account removes only that store's customer.
    • Wrong-code lockouts for the review number are counted per store, so guessing at one store can't lock reviewers out of another.
  • Checkout marks meta.app_review. Storefront::autoDispatchOrder skips review orders.
  • Console: the Storefront::AppReviewAccess component (buttons only, so it doesn't mark the network settings form dirty) calls core's int/v1/review-access/storefront-store|storefront-network/{id}. A new settings.app-review page, a network settings section, Order::PanelAppReview, and a header badge.
  • composer.json requires core-api ^1.6.74, so CI can only pass once core-api v1.6.74, with #323, is tagged. This PR no longer adds a Storefront table: an earlier version of it had app_review_accesses and Storefront-only endpoints, and both are replaced by core's.

App Review API for the Console and AppHelm

PUT {api}/int/v1/review-access/storefront-store/{store public_id}   {"enabled": true}
→ {"review_access": {"type": "storefront-store", "enabled": true, "phone": "+12025550143", "phone_display": "+1 202 555 0143",
                     "has_code": true, "code_generated_at": "…", "enabled_at": "…", "code": "482913"}}
GET {api}/int/v1/review-access/storefront-store/{id}        (status, never the code)
PUT … {"regenerate_code": true}                              (new code; the old one stops working)

AppHelm uses the OAuth scope storefront:review-access above. From PHP: Fleetbase\Support\AppReview::update($store, true, $regenerate) and AppReview::status($store). An existing code can't be read back, so AppHelm should either ask the user for it or regenerate and keep the returned code.

CI

build and contract fail at Install dependencies: composer.json requires fleetbase/core-api ^1.6.74, and 1.6.74 isn't on Packagist yet (Packagist's latest is 1.6.73). Both will pass once fleetbase/core-api#322 (v1.6.74, with #323 and #324 merged in) is merged and tagged. Re-run the checks then. Nothing else in this PR fails.

Validation

  • PHP (full suite). Run with the core-api classes this checkout's server_vendor lacks (it has 1.6.69) loaded from release/v1.6.74, so feat(oauth): storefront scopes for Continue with Fleetbase #163's OAuth code runs against the real core: 1147 passed, 1 failed. The failure, "authenticated customer endpoints register devices and scope orders and places", fails the same way on untouched main locally and passes in CI on main.
  • AppReviewAccessTest (13 tests). The number is valid; access on (sign-in, no SMS); access off (refused, no SMS, code stops working); wrong code; another store's code; network access; env fallback; sign-up; account closure keeps the shared account; adding the number at checkout; order marking and no auto-dispatch; registration with core (number, permissions, company-scoped lookup); permission.
  • Not covered by tests. feat(oauth): storefront scopes for Continue with Fleetbase #163's OAuth controller and scopes have no Storefront tests. The token and scope checks they rely on are tested in core-api#324. They still need an end-to-end check on a running stack.
  • Ember. See the comment below.
  • Lint. php-cs-fixer on all changed PHP, including feat(oauth): storefront scopes for Continue with Fleetbase #163's files: clean. eslint, ember-template-lint, stylelint, prettier and fleetbase-intl-lint on the changed frontend files: clean.
  • Not done. A manual check in the Console. The local fleetbase-dev MySQL container was crash-looping.

Documentation Impact

docs/app-review.md covers store owners and developers, and the README env table is updated. fleetbase.io's Storefront docs need an "App Review access" page (needs-docs).

API Reference Impact

The public customer endpoints keep their shapes. For the review number they answer without sending a code, or with 422 when access is off. The Console endpoints are core's (int/v1/review-access/...).

Upgrading

  • Requires core-api v1.6.74 (App Review access and the OAuth provider). Run migrations: core adds review_accesses and the OAuth tables; Storefront adds none.
  • Grant storefront manage-app-review store / network to non-admin staff who should manage it.

… SMS

App Review access is a per-store and per-network setting: reviewers sign in with the fictional number +1 202 555 0143, which is never texted, and a six-digit code the owner creates in the Console (stored hashed, shown once, accepted only by the store that made it). Covers sign-in, sign-up, adding the number at checkout and account closure. Reviewers' orders get meta.app_review, are marked in the order panel and staff alerts, and are never auto-dispatched. The env review accounts stay as a self-hosted fallback. v0.4.30 release notes.
@roncodes roncodes added needs-docs Requires documentation updates needs-api-spec Requires API specification updates type:feature Feature or enhancement labels Oct 24, 2026
@codecov

codecov Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (69b3c20) to head (be542d3).

Additional details and impacted files
@@             Coverage Diff              @@
##                main      #162    +/-   ##
============================================
  Coverage     100.00%   100.00%            
- Complexity      3945      4014    +69     
============================================
  Files            224       229     +5     
  Lines          14018     14221   +203     
============================================
+ Hits           14018     14221   +203     
Flag Coverage Δ
backend 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The mechanism moves to core-api (fleetbase/core-api#323) so Navigator and future apps share it: stores and networks are registered with core as storefront-store and storefront-network, codes live in core's review_accesses table, and the Console calls core's int/v1/review-access endpoint. Storefront keeps the shared review customer, order marking and its env keys. The Storefront-only table, model, trait and routes are removed. Requires core-api ^1.6.74.
@roncodes roncodes changed the title Release v0.4.30: App Review access for app store reviewers Release v0.4.30: App Review access for app store reviewers (on core-api) Oct 24, 2026
@roncodes

Copy link
Copy Markdown
Member Author

Ember (ember test --filter app-review):

  • Before the move to core-api, the 3 new tests passed: the App Review settings component (on, code shown once, regenerate, off, network endpoint) and the order panel alert.
  • After the rework, the component only changed its endpoint and response key (int/v1/review-access/storefront-store|network/{id}, review_access), and the test was updated to match.
  • Two reruns after the rework couldn't start: headless Chrome failed to connect within 120s while other sessions' Ember runs were loading the machine. Please run pnpm test:ember --filter app-review once more, or rely on CI.

storefront:read lists the token's organization's stores and networks with
their public keys; storefront:app-key creates (or returns) one named API key
per app for its Storefront app build; storefront:review-access covers the
storefront-store and storefront-network types on core's review-access
endpoint.
feat(oauth): storefront scopes for Continue with Fleetbase
@roncodes roncodes mentioned this pull request Oct 25, 2026
4 of 6 tasks
@roncodes roncodes changed the title Release v0.4.30: App Review access for app store reviewers (on core-api) Release v0.4.30: App Review access and Continue with Fleetbase Oct 25, 2026
The customer app already sends Accept-Language on every request, but the
server ignored it, so API errors, push notifications, inbox items and SMS
codes stayed English for a customer using the app in Mongolian or Ukrainian.

SetStorefrontLocale (first in the storefront.api group) picks the closest
shipped language from Accept-Language, answers the request in it, restores
the previous locale afterwards, and stores it on the signed-in customer's
contact meta when it changed. Order notifications read that stored language
(CustomerLocale::for) and set it as the notification locale, so queued pushes
are written in it too. An order edit summary is English for the console and
driver, so non-English customers get the general "order was updated" line.

Customer API messages in the v1 controllers, SetStorefrontSession, the
validation rules and ReviewEligibility move to storefront::api, checkout,
customers and notifications translation files under server/resources/lang,
with en, mn and uk. English text is unchanged. Error codes and
gateway/passthrough messages stay as they are.

The Pest bootstrap gains a translator, __() and app()->getLocale()/setLocale().
From a native speaker's review: customer_not_found, no_customer_with_phone
and customer_user_not_found now add "Шинэ хэрэглэгчээр бүртгүүлнэ үү."
customer_not_found (update, find, delete) and customer_user_not_found (account
closure) are not sign-in errors, so telling the customer to register there
read wrongly. Only no_customer_with_phone (loginWithPhone) keeps the hint.
feat(i18n): answer storefront customers in their language
…review guards

The OAuth StorefrontController (#163) had no tests. Cover the store and
network listing (scoped to the token's organization) and the app key
(created once, reused after; expired, test and other-company keys are
never returned). Also cover the App Review notice in new-order SMS and
mail, and a customer whose account can't be loaded.

OAuthScopes no longer checks for core's OAuth provider: storefront
requires core-api ^1.6.74, which always has it.
@roncodes
roncodes merged commit af7d978 into main Oct 27, 2026
11 checks passed
@roncodes
roncodes deleted the release/v0.4.30 branch October 27, 2026 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-api-spec Requires API specification updates needs-docs Requires documentation updates type:feature Feature or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant