πŸ§ͺ Almighty Dollar β€” Pair Test Plan

Live pair-programming QA for the Christian-business directory with tithe tracking: guest browsing, accounts & listings, connect β†’ sale pipeline, org verification & payouts, and security probes. Two testers β€” the agent (AD Dev) and Mike β€” execute the same steps with different accounts and data, compare results, and file GitHub issues for every mismatch.

Protocol Environments & data A Β· Guest browse B Β· Accounts & listings C Β· Connect β†’ sale D Β· Org verify & payout E Β· Security & cross-env Results & issue log

How this session works

  1. Agent executes a step in a real browser, posts screenshots to the Discord thread, and states pass/fail.
  2. Mike repeats the same step with his own accounts and data, posting his screenshots to the thread.
  3. Compare. Same result β†’ check the box in the log. Different result β†’ both re-run once, then file an issue.
  4. File a GitHub issue for every wanted change (see conventions below) and link it in the log row.
  5. Move to the next step. Flows are ordered so data created earlier feeds later flows: B registers the org + business, C connects customer β†’ owner pipeline β†’ sale, D verifies and pays out that sale, E probes the walls around all of it.

Issue conventions

Evidence conventions

Environments & test data

ThingValue
Production web (read-only this session)almightydollar.us β€” verified HTTP 200 + SPA loads 2026-09-27 (www too). Convex client baked into the bundle: useful-antelope-558.convex.cloud (verified in the deployed JS, not from docs).
Staging Convex (all writes)upbeat-giraffe-329.convex.cloud β€” the backend the journey scripts already seed and test against (e.g. Faithful Electric Co. seeded 2026-09-24).
Staging webRun locally against staging: cd ~/Repos/almightydollar-app && npm install && EXPO_PUBLIC_CONVEX_URL=https://upbeat-giraffe-329.convex.cloud npm run web β†’ http://localhost:8081. Agent keeps one dev server running for the session; Mike uses the deployed prod site for his read-only checks and the agent's local server for staging writes.
RuleEvery write (signups, connects, sales, verifications) happens on staging. Prod gets read-only browsing only (Flow A1–A4), so no test rows land in production data.
Password reset / ResendOnly fires if RESEND_API_KEY is set on the staging Convex deployment; if unset the reset token is still created but no email is sent (code path warns and skips). B5 records which.

Test data markers

Staging is a shared backend: journeys and earlier tests already have rows there. Never edit or delete rows you didn't create this session; if a step shows someone else's data, screenshot it and move on.

Flow A Β· Guest β€” browse the directory (no account)

Persona: a church member discovering local businesses. Read-only: A1–A4 on production, A5 on staging (agent's local server). Produces: nothing β€” this flow is pure observation, and it's the baseline everything else is compared against.

A1BothOpen https://almightydollar.us fresh (hard reload), desktop.
Expected: dark theme by default, home renders with stats and content (not a blank page β€” the old org-list pagination bug would show exactly that), no unresolved tokens, no console errors. Mike also tries https://www.almightydollar.us.
A2AgentDirectory tab: how many businesses list, do category / location / org filters actually filter, does search match and miss correctly. MikeSame on prod, plus filter by a category that has zero matches and one with many.
Expected: filters narrow the list live; empty result shows an empty state, not a spinner or crash.
A3BothOrganizations tab: open one org's public page, then run the same search from two different org pages if search is available there.
Expected: org page shows name, community impact numbers, member businesses; no other org's data bleeds in. With ~29k orgs imported, check the list stays responsive (searchable/paginated picker shipped in PR #18 β€” verify it actually feels fine).
A4AgentOpen a business detail page as a guest. Try every action: Connect, review, anything else visible. MikeSame on your phone's browser at almightydollar.us.
Expected: gated actions prompt sign-in instead of failing silently; guest sees full public info but cannot write anything.
A5AgentSwitch to the staging dev server (localhost:8081) and repeat A1 + A2 there β€” this proves the local↔staging setup works before accounts get created in Flow B.
Expected: same app against staging data (Faithful Electric Co. and other journey rows may appear β€” that's the marker that you're on staging, not prod). If localhost:8081 shows prod data or errors, stop and fix the env wiring first β€” every later step depends on this.

Flow B Β· Accounts & listings β€” sign up, register org, register business

Persona: three signups in one flow β€” customer, org admin, business owner. Feed data: none. Produces: the accounts and listings that Flows C and D use. Run on staging only.

B1AgentSign up as a customer: pairtest.b1.agent@example.com, any password β‰₯ minimum, role lands as customer by default. MikeSame with you+pairtestB1@…, and also try registering with an email that's already in the system (your own, twice).
Expected: account created, logged in, lands on Home as customer. Duplicate email gets a clear rejection, not a second account and not a crash.
B2AgentRegister an organization: PairTest B2 Agent Community Church, pairtest.b2.agent@example.com, tithe 15%. MikeSame with PairTest B2 Mike Community Church and tithe 12%.
Expected: org created; registrant is auto-promoted to org_admin (role auto-assignment on registration); tithe % saved as entered (15 / 12) and shown on the org dashboard.
B3AgentRegister a business: PairTest B3 Agent Services, pairtest.b3.agent@example.com, affiliated with your own B2 org (org picker on the register form). MikeSame with PairTest B3 Mike Services affiliated with your B2 org β€” and note whether the picker makes you pick one org or supports several.
Expected: business created, registrant is the business_owner; business appears in the directory immediately; the org affiliation links back to your B2 org (this is what makes the C5 tithe flow to the right org).
B4BothDirectory: find your own B3 business by search and by category filter. Open its detail page.
Expected: business listed with the category and org chosen at registration; detail page shows the owner's org affiliation.
B5AgentAuth edges: log out, log back in with a wrong password, then use "Forgot password" for your B1 email. MikeDo the same with yours and tell the thread whether a reset email actually arrived (and in what folder).
Expected: wrong password rejected with a clear message. Reset flow creates a token; whether email arrives depends on RESEND_API_KEY on staging (see env table) β€” record which happened. If no email arrives, the token still exists server-side: that's the documented behavior, note it.

Flow C Β· Connect β†’ pipeline β†’ sale (customer + business owner)

Persona: customer connects, owner works the lead and records the sale. Feed data: B1 (customer), B3 (business + owner). Produces: a closed connection and a pending_verification sale that Flow D verifies. Run on staging.

C1AgentAs the B1 customer, open your B3 business and tap Connect. The org picker should appear β€” choose your own B2 org (15%). MikeSame with yours (12%). Then connect a second time to the same business and watch what happens.
Expected: connection created with status pending and your chosen org. Second connect: either blocked with a clear message or allowed as a duplicate β€” record which; behavior is currently undocumented.
C2AgentLog in as the B3 owner (separate browser profile or incognito so both sessions stay live). Business Dashboard: find the C1 lead β€” customer name, contact info, chosen org visible? MikeSame with yours.
Expected: lead appears on the owner dashboard with the customer's name + phone/email and the org they picked. Owner sees the lead even while the customer's session is still open elsewhere (that's why dual profiles).
C3AgentAdvance the lead: pending β†’ contacted β†’ quoted, one tap each, watching the customer side between taps (customer's My Connections). MikeSame; also try advancing a step backwards (quoted β†’ contacted) if the UI allows it.
Expected: customer's connection card reflects each status change live. Backwards transitions: whatever the UI does, record it β€” the backend only documents forward taps.
C4BothCancel path: as the customer, connect to your partner tester's B3 business too (agent connects to Mike's, Mike connects to agent's), then cancel that pending request from My Connections.
Expected: cancel works while pending; the owner's dashboard drops or flags the cancelled lead; cancelled connection cannot be advanced by the owner afterwards.
C5AgentAs owner, Record Sale on the C3 connection: $250. MikeRecord $120 on yours.
Expected: tithe auto-computed from the org % β€” agent $37.50 (250 Γ— 15%), Mike $14.40 (120 Γ— 12%). Wrong number here means the % didn't propagate from B2. Sale status pending_verification, connection flips to closed.
C6AgentValidation sweep as owner: record a sale with amount 0, then a negative amount, then non-numeric garbage. MikeTry a huge amount (e.g. 999999999999) and a decimal like 10.555 β€” watch the rounding.
Expected: observe and record everything. Input validation here is likely thin; this step decides the wanted behavior for the issue rather than confirming a documented one.

Flow D Β· Org admin β€” verify tithe, payout, impact rollup

Persona: the church admin confirming real money arrived. Feed data: the B2 org admin account and the C5 sale. Produces: a verified + paid tithe, updated impact totals. Run on staging.

D1AgentLog in as the B2 org admin (third browser profile). Org Dashboard: check the zero-state before the sale shows, then confirm the C5 sale appears as awaiting verification. MikeSame with yours.
Expected: dashboard shows the sale with amount, tithe amount ($37.50 / $14.40), org % (15 / 12), status pending_verification. Nothing is auto-verified β€” verification is a human tap.
D2BothVerify the tithe.
Expected: status β†’ verified (verifiedAt set); the amount moves into the org's pending-payout total; customer's Tithing History now shows the verified tithe.
D3BothMark the payout Received.
Expected: status β†’ paid_to_org (paidAt set); org totals move from pending payout to paid out. This is the honor-system leg β€” no money moves, the app only records that it did.
D4AgentCheck every rollup surface: the B2 org's public page, the customer's Profile tithe impact, the owner's sales list. MikeSame for yours, logged out (public view only).
Expected: public org page shows total sales, total tithing, paid out and your business as a member; customer profile shows the cumulative tithe impact; all three surfaces agree on the numbers.
D5AgentCross-checks: as the customer, leave a review on the B3 business after the closed connection (verified-purchase path), and confirm the review shows with its badge. MikeSame; also check whether a review from an account that didn't connect gets the verified badge (it shouldn't).
Expected: post-connection review shows verified-purchase badge; unconnected review doesn't.

Flow E Β· Security & cross-env probes (agent-led)

Persona: an adversarial user poking at the walls. Mike observes and re-runs the UI-only ones. These steps are expected to fail safely β€” a success is a critical finding.

E1AgentSession-token reuse: copy your customer's session token out of browser storage (DevTools β†’ Local Storage), paste it into a fresh browser profile, and load the app β€” then as the org admin, try the same with the customer's token.
Expected: token reuse in another browser restores the same session (bearer-token auth β€” that's how it's built, 30-day tokens). What must not happen: the customer token unlocking owner or admin actions. Every role-gated action checked with the wrong token is a critical finding.
E2AgentWrong-role probes as plain customer (B1 account): try to advance your own connection's lead status, record a sale, verify a tithe, mark a payout β€” via any UI surface that renders for you.
Expected: every owner/admin action rejected server-side, not just hidden in the UI. A success means role checks are client-only β€” critical finding.
E3Agentorganizations:bulkImport gate: confirm from the code path (convex/organizations.ts) that only platform admin role passes, and try to reach it with a non-admin session from the app.
Expected: non-admins get "Only platform admins can bulk import organizations." β€” the fix from the roadmap shipped; this step proves it live.
E4AgentCross-env wiring pin: confirm prod (almightydollar.us bundle) points at useful-antelope-558 and staging writes never touched it β€” re-check the prod org directory before/after the session for pairtest rows. MikeSpot-check prod once more at session end: search the directory for "PairTest".
Expected: zero pairtest rows on prod at any point. Any pairtest data on prod is a session failure β€” file it immediately.
E5AgentSession expiry edge: edit the session record's expiry on staging (or wait for a naturally expired token if one exists from old journey runs) and confirm the app logs the user out cleanly instead of erroring.
Expected: expired token β†’ clean redirect to sign-in, no stack trace, no half-rendered screen.

Results & issue log

Fill in during the session. "Match" = agent and Mike saw the same behavior. Every ⚠/βœ– row needs an issue link.

StepAgentMikeMatchIssueNotes
A1prod, read-only
A2
A329k orgs responsiveness
A4guest gates
A5staging wiring gate for B–E
B1
B215% vs 12% on purpose
B3
B4
B5Resend key gate
C1duplicate-connect undocumented
C2
C3backwards transition undocumented
C4cross-pair cancel
C5$37.50 / $14.40 expected
C60/negative/huge/rounding
D1
D2
D3honor-system leg
D4rollup agreement
D5verified-purchase badge
E1token reuse / role walls
E2server-side role checks
E3bulkImport gate (fixed?)
E4prod stays clean
E5expired session

Suggested rounds

Session cleanup