Appearance
Anonymous users can browse the catalogue, but scanning and adding cards or sealed products require the existing verified-email account journey. A reactive gate keeps camera, debug, bulk summary and add forms unmounted until the account is available; sign-out and failed/stale credential reads cannot unlock them. The explicit login action opens the existing sign-in/registration screens. New registration is not adopted locally before its existing password step succeeds.
The default ownership repository also refuses guest additions/restores. Existing local data is retained and normal account isolation remains unchanged. The scan dispatch rechecks the linked account instead of minting an anonymous identity.
API companion: backend #587, tracked by backend issue #586. All four scan routes, collection additions, idempotent mutations and restores require an active user token and email on the server. Operator/device tokens cannot bypass it. Missing/expired/revoked tokens retain 401; a valid anonymous account gets 403 email_account_required. The matched-route gate runs before upload processing, inference, quota charging and holding handlers; encoded URL spellings remain protected. Public catalogue, email verification and account/session recovery remain available.
Validation: app ESLint/TypeScript passed; Jest 3,027 passed, 11 skipped. API build and typecheck passed; API suite 1,600 passed, 21 skipped. Tests cover guest refusals, preserved local data, linked success, reactivity, stale read isolation, explicit login navigation and encoded scan routes. The Maestro guest journey is included but not run: Maestro is unavailable locally. No native dependency or configuration changes. The user approved the app's 15-file exception to retain tests and documentation.
Delivery: PRs target staging and remain open; no merge/deployment or migration. Deploy the app before API enforcement so old clients have a reachable prompt. No real user account, collection, quota or VPS data was modified. This change does not automatically combine local collections across accounts.