← All tests

Random Bugs #2 and #3 STAGING

Two items from Narong's "Random Bugs (Unrelated to Development Phase)" page. Both were verified to still reproduce on live staging before any code was written — the previous sweep found 3 of 5 ❌ marks were already stale, so these were checked first. Neither was stale. No migration.

#2 — "A member invited through NIX Cafe can see both products (NIX POS & NIX OS when NIX OS is activated for the user)."

#3 — "Remove Odoo Integration Indicators (dashboard)."

#2 — the Launchpad advertised doors that don't open

The Launchpad rendered one card per tenant subscription, never consulting the user's entitlement. Both product apps already reject non-entitled users server-side — nix-cafe's auth() and Outdoor's ensureBridgeForTenantUser each require an explicit nix_user_product_roles row for non-owners — so this was never an access hole. It was the portal offering a member a product that would bounce them.

The fix needed no new data: /tenant/auth/me already returns the correct per-user productRoles (owners get an implicit role on every active product; everyone else gets their explicit rows, filtered to active subscriptions). The grid simply wasn't using it.

Two follow-ons came out of the same reasoning. The inactive-subscriptions list was the one other place a non-entitled product still appeared, so it's now owner-only — owners keep the billing signal, members don't see NIX OS listed as "cancelled". And a member with no assignments used to land on "Your tenant doesn't have any active product subscriptions — contact NIX Sales", which is the wrong destination for what is an access problem their own admin fixes; that case now has its own copy.

member launchpad, one card
After. posuser@lumiere-coffee.com — a real cafe-only member over real SSO. One card. Before the fix this same account saw an Outdoor Sales card too.
owner launchpad, two cards
The control. The owner of the same tenant still sees both products — the fix hides what you can't open, not what you can.
no-access empty state
The newly reachable empty state: a member with no product assignments is pointed at their own administrator rather than at NIX Sales.

#3 — Odoo indicators removed

The amber "Odoo is not linked" banner is gone, and the component is deleted. Narong's note said "(dashboard)", but the banner was one shared component rendered on four pages — Dashboard, Settings, Reports and Reports > Order Analysis — so removing it from only the screen he happened to screenshot would have left the identical banner on three others. 35 deletions, no additions.

Worth stating plainly: this was the only in-app signal that Odoo sync had stopped. After this change a Pro merchant whose link breaks sees nothing in the merchant app — the remaining surface is Cpanel. That matches the intent of not showing merchants internal integration plumbing, but it is a deliberate trade rather than a free removal.

dashboard with no banner
Dashboard on demo.staging — a Pro tenant with Odoo genuinely unlinked, asserted in the test itself so the removal can't be proven against a tenant that never showed the banner.
settings with no banner
Settings.
reports with no banner
Reports.
order analysis with no banner
Reports > Order Analysis.

Proof the tests aren't vacuous

The staging suite is written against the post-fix state, so it was run once before deploying. Same file, same assertions, both runs:

Staging runResultWhat it shows
Before the deploy6/11both bugs reproduce on the live stack; all 3 preconditions valid; the owner control already green
After the deploy11/11the 5 failures cleared, nothing else moved
✗ no "Odoo is not linked" banner on dashboard:      odoo-unlinked-banner still present
✗ no "Odoo is not linked" banner on settings:       odoo-unlinked-banner still present
✗ no "Odoo is not linked" banner on reports:        odoo-unlinked-banner still present
✗ no "Odoo is not linked" banner on order analysis: odoo-unlinked-banner still present
✗ member sees ONLY the NIX Cafe card (bug #2):      member still sees 1 Outdoor Sales card/link

The local suite has its own control: reverting only the entitlement filter while keeping every testid — so failures isolate behaviour rather than missing selectors — drops it to 4/8, failing on exactly the four entitlement assertions and reproducing Narong's bug verbatim:

✗ Cafe-only member sees ONLY the NIX Cafe card (bug #2): expected ["nix_cafe"], got ["nix_cafe","outdoor_sales"]

Every "banner is absent" and "product is absent" check is anchored on something that must be present first — the cafe card, a rendered page body — because an absence assertion passes happily on a blank page.

Checks

SuiteResult
Local — real Vue app on vite with /tenant/auth/me stubbed per entitlement shape (+ negative control)8/8
Staging — real SSO on the deployed Worker + Pages, asserted against Neon11/11
Staging smoke (SSO, cross-tenant guard, Starter login, no-session redirect)5/5
tsc --noEmit (cafe) · vite build (commerce) · unescaped-@ locale sweepclean

Prod exposure, checked read-only

Zero prod users are adversely affected — no account would lose a card it can currently use, and there are no legacy admin-role users who would fall through the owner shortcut. The inverse is the interesting part: get-coffee's live cafe-only member currently does see a NIX OS card they cannot open, so this fixes a real annoyance on production the moment it promotes.

nix-cafe staging cf483c0 (Worker f8e538a3) · nix-commerce staging 892a18b (Pages deployed). No migration — adds nothing to the six already parked. Parked for the scheduled prod promote.