MotorSignal-App/docs/qa-2026-10-01/auth.md

47 lines
5.6 KiB
Markdown

# Authenticated isolated QA — 2026-10-01
## Environment and scope
Firebase CLI and the cached Firestore emulator were available. The repository's original `firebase.emulator.json` supports Firestore only; the QA configuration adds Auth. Both services bind to loopback: Auth `127.0.0.1:9099`, Firestore `127.0.0.1:8088`, project `demo-motorsignal-qa`. No production accounts, settings, entitlements, rules, or data were changed.
The active rules snapshot `auth.firestore.rules` is byte-identical to the repository `firestore.rules`, SHA-256 `A731D6319B56D2A13960FCBE621004D448AE611DC5C5657FAB25F0EFBE302EC6`. No rules weakening was used. Initial club/ride fixture seeding uses the Admin SDK solely against the explicitly configured local demo emulator. All listed scenario actions use signed-in client SDKs with the real rules enforced; these are automated backend checks, not browser or Flutter end-to-end results.
Six disposable accounts represent owner, admin, organizer (also a club admin), accepted/requesting participant, regular member, and outsider. Account identifiers are in `auth.results.json`. Passwords are supplied through `QA_DEMO_PASSWORD` and are not written to evidence. There is no personal account use.
## Executed results
- `auth.exercise.mjs`: **17/17 PASS**, rerun after service restart at approximately 2026-10-01 05:48 UTC.
- `auth.extra.mjs`: **7/7 PASS**. Uses separate `qa-extra-*` documents to avoid changing browser fixtures.
- Total unique SDK cases: **24 PASS, 0 FAIL**. Exact IDs and outcomes are in `auth.results.json` and `auth.extra-results.json`.
- Existing Firestore rules suite: **148/148 PASS**, `auth.rules-results.json`. This suite uses rules-unit-testing authenticated contexts and is a separate automated category, not real Auth sign-in coverage.
SDK actions verified registration/sign-out/sign-in, token refresh, sign-out access denial, public club discovery, request membership and administrator approval, personal and official club ride creation, regular-member official creation denial, outsider club-ride request denial, ride request/approval/rejection with cross-account reads, denied self-approval, open joining, accepted participant leaving, organizer removal with count/access updates, start/completion/cancellation, accepted live-presence write and peer read, nonparticipating admin presence denial, and presence denial after completion.
Negative-rule cases emit expected `PERMISSION_DENIED` messages, including evaluation-budget diagnostics. Their PASS means the attempted unauthorized operation was rejected; it does not establish which individual rule branch denied it. The positive counterparts completed successfully.
SDK sign-in and token refresh do not establish browser reload or mobile process-restart session persistence. See the browser owner's evidence for actual UI outcomes. No Flutter device interaction was performed by this worker.
## Reproduction
From repository root, set `XDG_CONFIG_HOME` to a disposable writable directory (the normal Firebase CLI preference directory was sandbox-inaccessible), then start:
```powershell
& firebase/emulator-tests/node_modules/.bin/firebase.cmd emulators:start --config docs/qa-2026-10-01/auth.firebase.json --project demo-motorsignal-qa --only auth,firestore
```
Wait for `All emulators ready`, set `QA_DEMO_PASSWORD` to a disposable password, and run `node docs/qa-2026-10-01/auth.exercise.mjs`, then `node docs/qa-2026-10-01/auth.extra.mjs`. The first script resets its own fixtures; do not run it while interactive testers rely on them.
The rules suite was run from `firebase/emulator-tests` with `FIRESTORE_EMULATOR_HOST=127.0.0.1:8088` using `vitest run --reporter=json --outputFile=../../docs/qa-2026-10-01/auth.rules-results.json`. It uses the distinct `motorsignal-emulator` namespace and clears its own fixture state.
A separate debug-only mobile entry exists at `tools/qa_auth_main.dart`. It uses the normal app/providers after local Firebase initialization, requires `R2_WORKER_URL=http://127.0.0.1:1`, and expects `adb reverse` for ports 9099/8088. The worker URL requirement prevents production sync/billing calls. Device build/install/runtime validation belongs to the exclusive device owner; the existence of this file does not prove mobile authentication works.
## Legitimate Pro entitlement blocker
Source inspection: `PlayBillingService` delivers purchases, `EntitlementCoordinator` submits them through `PurchaseVerificationService` to `/billing/verify-play-purchase`, and only verified entitlement unlocks CSV. The Worker verifier requires Google Play package configuration and Google service-account credentials. `FakeBillingService`, in-memory entitlement storage, and test-state constructors are mocks; they do not establish legitimate store entitlement.
No established isolated Play tester purchase/verified token or billing verification environment was found in the inspected setup. A Firebase emulator account/role alone does not grant Pro. Real Pro CSV UI validation remains blocked on an authorized Google Play test account with the configured product/test purchase and a verification environment that can validate it. No purchase or production entitlement change was attempted. Export-content automated coverage, if run by the parent, must be reported separately.
## Cleanup status
Browser owner completed. `auth.cleanup.mjs` ran at `2026-10-01T10:51:32.634Z`; Auth and Firestore cleanup endpoints both returned HTTP 200 (`auth.cleanup-results.json`). The Playwright browser closed, and local Next/Firebase emulator processes were stopped. Emulator state is transient and no longer serving. No production fixture persistence or change occurred.