Skip to content

Merchant Venue Association in Provisioning - Manual Test Plan โ€‹

FieldValue
Branch / PRfeat/autopilot-merchant-venue (session PR #792)
Issue#793 (builds on #786 venue creation, #790 application review)
Environmentadmin portal (dev) -> auth-api Cloud Run (dev); writes merchants, venues, adminActions in lantern-app-dev
Build flags / confignone; requires VITE_AUTH_API_URL + VITE_VENUE_API_URL set in the admin build
Build (commit)fill after deploy
TesterMechelle (+ agent live run below)
Datefill on run

Summary โ€‹

#ScenarioResultNotes
1Create merchant, then associate a venue in the same flow[ ] pass [ ] fail [ ] blockedhappy path
2Approve application, associate venue, end-to-end[ ] pass [ ] fail [ ] blockedend-to-end
3Skip venue association (optional step)[ ] pass [ ] fail [ ] blockedregression
4Venue already claimed by another merchant is surfaced, non-blocking[ ] pass [ ] fail [ ] blockedguardrail
5Associating the same venue twice is idempotent[ ] pass [ ] fail [ ] blocked
6Non-admin cannot associate[ ] pass [ ] fail [ ] blockedguardrail
7Data + audit verification[ ] pass [ ] fail [ ] blockeddata
8Offer create is unblocked after association[ ] pass [ ] fail [ ] blockedthe payoff

Server layers already verified (pre-existing) โ€‹

The POST /auth/admin/merchants/:merchantId/venues endpoint (associateVenueWithMerchant) already exists, is transaction-wrapped, and returns MERCHANT_NOT_FOUND / VENUE_NOT_FOUND (404), VENUE_ALREADY_CLAIMED (409), ALREADY_ASSOCIATED (200), ASSOCIATED (201 + adminActions entry). This change is the admin-UI wiring that calls it inside the provisioning flow, so the scenarios below are the browser + data + integration layers of the new flow.

Setup / preconditions โ€‹

  • Sign in to the dev admin portal as an admin (Agent Probe for the agent run).
  • At least one unclaimed venue exists in dev venues (create one via Merchants/Platform -> Venues -> Add venue, #786, if needed). Note its name + id.
  • Use a throwaway email for provisioning: creating a merchant is a real account (Auth user + optional invite email).
  • Data lives in lantern-app-dev: merchants, venues, adminActions, users, merchant_applications.

Scenarios โ€‹

1. Create merchant, then associate a venue in the same flow (happy path) โ€‹

  • Steps: Merchants -> All Merchants -> Create. Fill email/business/contact, uncheck "Send email invite", Create Merchant. On the venue step, search the unclaimed venue by name, associate it, continue to detail.
  • Expected: Merchant is created; the venue step appears with the new merchant's id; after associating, the merchant detail shows the venue in its venues list.
  • Verify (data): merchants/{id}.venueIds contains the venue id; venues/{id}.merchantId == {merchantId}.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:   (merchantId + venueId)
Follow-up:

2. Approve an application, associate a venue, end-to-end โ€‹

  • Steps: Merchants -> Applications -> Review & create on a pending application -> confirm prefilled fields -> Create Merchant -> associate a venue on the venue step -> continue.
  • Expected: Account provisioned, application flips to approved and links merchantId/userId, venue associated, detail shows the venue.
  • Verify (data): application status: approved + merchantId; merchants/{id}.venueIds has the venue; adminActions has both reviewMerchantApplication and associateVenue.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:
Follow-up:

3. Skip venue association (the step is optional) โ€‹

  • Steps: Create a merchant. Note the venue step's hint that offers are blocked without a venue, then choose "Skip for now".
  • Expected: The venue step shows the "without a venue, every offer is blocked" hint; choosing "Skip for now" lands on merchant detail with no venue linked and no error.
  • Verify (data): merchants/{id}.venueIds is empty/absent.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:
Follow-up:

4. Venue already claimed by another merchant is surfaced, non-blocking โ€‹

  • Steps: Provision merchant A and associate venue V. Provision merchant B and try to associate the same venue V.
  • Expected: A clear "already associated with another merchant" message (409 VENUE_ALREADY_CLAIMED); merchant B is still created; the admin can pick a different venue or skip. The whole flow does NOT read as a failed create.
  • Verify (data): venues/V.merchantId still points at A; B has no venue.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:
Follow-up:

5. Associating the same venue twice is idempotent โ€‹

  • Steps: Associate venue V to merchant A, then attempt to associate V to A again.
  • Expected: No error, no duplicate; 200 alreadyAssociated: true. venueIds has V exactly once.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:
Follow-up:

6. Non-admin cannot associate (guardrail) โ€‹

  • Steps: As a signed-in non-admin (or no auth), call POST /auth/admin/merchants/<id>/venues on the dev auth-api (curl / devtools).
  • Expected: 403 FORBIDDEN (non-admin) or 401 (no auth); no state change.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:
Follow-up:

7. Data + audit verification โ€‹

  • Steps: After scenario 1 or 2, inspect Firestore.
  • Expected / Verify: merchants/{id}.venueIds includes the venue; venues/{id}.merchantId equals the merchant id; venues/{id}.updatedAt bumped; adminActions has an associateVenue doc with performedBy = your uid.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:
Follow-up:

8. Offer create is unblocked after association (the payoff) โ€‹

  • Steps: As the newly-provisioned + venue-associated merchant (or an admin acting on their behalf), attempt to create an offer.
  • Expected: Offer create no longer returns 400 VENUE_NOT_ASSOCIATED; it proceeds (subject to the normal offer validation).
  • Verify: the offer create request succeeds / advances past the venue-association gate.
Result:    [ ] pass   [ ] fail   [ ] blocked
Actual:
Evidence:
Follow-up:

Agent live run โ€‹

To be filled by the agent browser pass (local admin stack -> local/branch auth-api -> dev Firebase, Agent Probe admin, App Check bypassed locally). Record what the run actually showed or the specific blocker here.

Notes โ€‹

  • The associate endpoint is transactional and pre-existing; the risk in this change is entirely in the admin-UI flow (state handling after create, non-blocking error surface, the optional-skip path).
  • If the alpha venue does not yet exist, create it first via the #786 venue form; this flow associates an existing venue, it does not create one inline (kept out of scope to stay focused).

Built with VitePress