Foodops
All docs

Troubleshooting · Updated 2026-08-22 · v822347a

Common Foodops Setup Issues & Workarounds

Audio narration for this article is generated with the weekly docs refresh.

Plain-English summary

Issues new users hit in the first hour of using Foodops. Each has a symptom, a root cause, and a workaround. On the new stack several of the old jQuery / Razor-modal bugs no longer apply — those are marked RETIRED below — but the conceptual gaps (an item not assigned to its outlet won't show on the POS; the POS caches the menu) still trip people up. If you're a voice/chat agent answering setup questions, these cover the bulk of what people ask.

New-stack note (July-2026 launch): the legacy app.foodops.io Razor monolith is retired. Setup now happens in the admin app (admin.foodops.io — catalog, settings, onboarding) and the counter app (counter.foodops.io — POS). The legacy server-rendered-form bugs (jQuery / Bootstrap-modal) are gone with the monolith; the issues below are re-pointed to the new React apps.

When you'd use this

  • Customer support calls during onboarding
  • New user self-service help
  • Voice agent routing questions like "I can't log in / my items aren't showing"
  • Internal staff training on known issues to watch for
  • Pre-flight checklist before a demo or a new org goes live

Summary

Issues discovered during test organization setup via Playwright browser automation. These are real bugs or UX gaps that new users will encounter.

Key concepts

  • Severity: High — blocks normal operation; user can't proceed without the workaround
  • Severity: Medium — degraded UX; a feature appears broken until the workaround is applied
  • Severity: Low — cosmetic or minor; ignorable but annoying
  • Workaround — interim fix until the underlying bug is addressed in a future build
  • Root cause — the actual underlying reason (usually a failed event handler, cache staleness, or a missing default)

Common questions

Q: I see "No permission to use this application (foodops)" after signup — what do I do? A: Issue 1 below. On the new stack the name-related cause is fixed (name is auto-derived from email); if you still hit it, edit the user (SSO users, or admin Settings → Organization → Users), confirm the Name is set + grant the application/Owner role, save, and re-login.

Q: I created items but they're not showing on the POS counter. A: Issue 2 — most likely your outlet wasn't selected on the item (and/or its availability channel). In the admin Catalog → Items, edit the item, tick your outlet + availability, save, then refresh the menu on the counter.

Q: I changed a menu group / its categories but it didn't save. A: Issue 4 — the legacy modal-save bug is RETIRED; manage groups in the admin Catalog → Groups / Categories. If it still won't persist in the new React UI, file it as a new issue.

Q: My POS doesn't reflect a menu change I just made. A: Issue 5 — the counter caches the menu offline. Refresh/re-sync the menu on the counter (or re-open the app) to pull the latest.

Q: I see "Register X has an unclosed session from DATE" — is that bad? A: A session was opened earlier and never closed. The counter shows a persistent unclosed-session banner (View Details / Dismiss); close the session from Register Sessions so reports bucket correctly. [code: foodops.counter.app/src/components/session/SessionUnclosedBanner.tsx]


Issue 1: "No permission to use this application (foodops)" After Onboarding

Severity: High (when it occurs) — blocks access to the app entirely

Symptom: After completing registration, email verification, business info and outlet setup, you see: "You currently don't have permission to use this application (foodops). To gain access, please reach out to your system administrator."

Root Cause (status CHANGED on the new stack):

  • #1 — blank name — FIXED. The legacy flow needed a full name before app permissions could save, but the form didn't collect one. The new Identity API now auto-derives a Full Name from the email at registration. [code: haafai.app.identity/Haafai.Identity.Api/Controllers/RegistrationController.cs:72 @staging — FullName = DeriveFullNameFromEmail(email)]
  • #2 — app-grant — UNCONFIRMED. The new /organisations/provision endpoint grants an Administrator role group with every role + org-user links, but shows no explicit per-app "enable foodops" insert and self-describes as mirroring the legacy New() (the method the bug was attributed to). Whether the error still reproduces after a fresh self-signup is not determinable from code alone. [code: haafai.app.identity/Haafai.Identity.Api/Controllers/OrganisationsController.cs:279-432 @staging]

Workaround (if it appears):

  1. As an admin, open the Users surface (SSO users at sso.hubits.io/blazor/users, or admin app Settings → Organization → Users /settings/organization/users).
  2. Edit the user — confirm the Name is set (now auto-filled) and grant the relevant application + the Owner role.
  3. Update, log out completely, log back in (the old session token carries stale permissions).

Status: Root cause #1 fixed in code at haafai.app.identity@31e7739 (staging); the app-grant is unconfirmed — needs a fresh live signup to confirm whether the error still reproduces. See Onboarding Step 6.


Issue 2: Items Not Appearing in POS After Creation

Severity: High — POS is unusable without visible items

Symptom: After creating menu items in the admin catalog, the POS counter shows categories but no items, or "No items match your search."

Root Cause (re-pointed to the new stack): The legacy jQuery-modal "silent save" bugs are gone (the catalog is now a React form). The remaining real cause is the outlet assignment: an item only appears on a given outlet's POS if that outlet is selected on the item. In the new admin item editor this is the outletIds set, plus per-channel availability (dine-in / takeout / delivery). Create an item without ticking your outlet and it won't ring up there. [code: foodops-admin-app/apps/admin/src/components/menu/ItemFormPanel.tsx:234,255-257,406 — outletIds, availableForDineIn/Takeout/Delivery]

Workaround:

  1. In the admin app, open Catalog → Items (/catalog/items) and edit the affected item.
  2. Confirm your outlet is selected (the outletIds set) and the relevant availability channels are on.
  3. Confirm the item's category/group is set so it slots into the menu (Catalog → Groups / Categories).
  4. Save, then refresh the menu on the counter — the POS caches menu data (see Issue 5).

Status: Re-pointed. The legacy jQuery checkbox/modal save bug is RETIRED with the monolith; outlet assignment is now a React controlled outletIds set in ItemFormPanel.tsx. End-to-end persistence is UI-verifiable.


Issue 3: jQuery Not Loaded on Direct URL Access — RETIRED

Severity: Medium — no longer applicable

Was: On the legacy monolith, navigating directly to a server-rendered form URL (e.g. /menuitems/add) without the jQuery-loading SPA shell produced ReferenceError: $ is not defined on Save.

Status: RETIRED. The new apps (admin + counter) are React SPAs — there are no server-rendered jQuery forms, so this failure mode is gone with the app.foodops.io monolith. Direct-URL deep links to React routes are client-side routed and work normally. Left here as a historical note because the legacy symptom may still appear in old guides/screenshots.


Issue 4: Menu Group Edit Dialog Save Doesn't Persist — RETIRED (re-point)

Severity: Medium — legacy bug retired; manage groups in the React catalog

Was: On the legacy monolith the Bootstrap-modal Edit Group dialog could fail to serialize the category checkboxes, so selections didn't stick (a jQuery/modal event bug). The workaround was a direct POST to /menucategories/edit/{id}.

Status: RETIRED on the new stack. Menu groups/categories are now managed in the admin React catalog — Catalog → Groups (/catalog/groups) and Categories (/catalog/categories) — not a Razor/jQuery modal, so the legacy serialization bug doesn't apply. If group↔category assignments don't persist in the new UI, that's a new React-form issue to file separately.


Issue 5: POS Shows Stale Menu After Changes

Severity: Low — confusing but has a clear fix

Symptom: After adding items, changing categories, or updating pricing in the admin app, the counter POS doesn't immediately reflect the changes.

Root Cause: The counter app is offline-first — it preloads and caches menu data (restaurant menus, categories, products) in IndexedDB after login and reads from there for speed/offline resilience. Admin-side changes aren't pushed live to the till. [code: foodops.counter.app/src/services/dataPreloader.ts (preloads menus/categories/products); src/offline/cacheApiDecorator.ts]

Fix: Refresh the counter's menu cache — re-sync / reload the menu on the counter (pull-to-refresh / the menu-refresh control, or re-open the app so the preloader re-runs). The cached menu then updates from the server.

Note: Expected behaviour, not a bug — the offline cache is what keeps the till working with no network.


Issue 6: Wrong or Outdated Prices on the POS

Symptom: the POS / till shows the wrong price for an item — an old or outdated price, prices not updating after you changed them in the back office, or a price mismatch between the admin and the till.

Cause: same as stale items (Issue 5) — the POS device is holding a cached copy of the menu/price list from before your change synced.

Fix: Reload Cache on the POS device (the same reload that fixes missing items). After the reload the current prices pull down. If a specific item is still wrong after a reload, check that the price change was actually saved in the back office (and, for price-list-driven pricing, that the item is on the right price list / outlet).

(This is the grounded answer for "prices are wrong on the till" / "prices not updating" — the remedy is Reload Cache.)

Troubleshooting Checklist for "POS Shows No Items"

If the counter POS shows no items or categories:

  1. Items exist? — admin Catalog → Items (/catalog/items) — items should be listed with prices
  2. Items assigned to your outlet? — edit each item → confirm your outlet in the outletIds set + the availability channel is on
  3. Categories exist? — admin Catalog → Categories (/catalog/categories)
  4. Categories assigned to a Menu Group? — admin Catalog → Groups (/catalog/groups)
  5. Menu cache refreshed? — re-sync / reload the menu on the counter (offline cache)
  6. Register open? — you need an active register session to ring up on the POS

Related

  • Onboarding — permission bug documented in Step 6

  • Menu Management — known issues section

  • POS Takeaway Order — known issues section

  • 2026-08-20 — foodops.counter.app e2fe2fc..fe34047 (feat(salesmade counter): Collect Payment — receive credit payments from the POS; feat: discard log tab + export, route reprint by session register; feat: mode-gated discard review (acknowledge vs approve/reject)) touches dataPreloader.ts's register/session-bootstrap config caching — the same function already covered in the 2026-08-05 verification entry for introducing the org-gated enableVoidBin flag. This diff adds a new companion field, voidBinApprovalMode (0 Off / 1 Deterrent / 2 Hard-Block per the inline comment), forwarded from both the fresh-fetch and bootstrap-response paths into the cached register config alongside enableVoidBin. Per the commit subjects, this backs a new 'mode-gated discard review' capability — a void/discard can now be gated as an acknowledge-only deterrent vs. a hard approve/reject block, rather than the previous single on/off Void Bin toggle. The menus/categories/products preload logic Issue 5 documents, and the customer-record discountId caching already logged in the 2026-08-18 entry, are both untouched by this diff (the discountId line reappears unchanged in this wider diff range only because it predates fe34047 — already accounted for, not re-logged here). This doesn't contradict any documented claim in this entry (permission, POS item visibility, menu-group save, stale POS cache, unclosed-session banner) and, like the Void Bin toggle itself, is an org-gated counter feature rather than a setup/troubleshooting topic — not added as a new Issue. Flag for a UI/training pass only if a 'why do I have to approve/reject this void instead of just dismissing it' or 'void bin mode isn't behaving as configured' report surfaces — that would be a live-UI question about this new approval-mode gating, not a bug to troubleshoot from this diff alone. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-08-18 — foodops.counter.app f30dbeb..e2fe2fc (feat(counter): auto-apply the customer's assigned discount on ordering) touches dataPreloader.ts — the same file Issue 5 cites for menu/category/product preload-and-cache behavior — but only in the customer-caching block, adding a new discountId field (forwarded from the customer API payload, c.discountId ?? null) into the locally cached customer record alongside existing fields like cachedOutstanding and creditLimit. The menus/categories/products preload logic Issue 5 documents is untouched by this hunk, so Issue 5's stale-menu root cause and fix stand unaffected — no contradiction. Per the commit subject, this is plumbing for a new, unrelated counter feature: auto-applying a customer's assigned discount when an order is placed for them. The intersecting hunk only shows the field being cached for offline availability, not the application logic (order pricing / discount calculation), so the full behavior isn't verifiable from this diff alone. This doesn't fit any existing Issue in this entry (permission, POS item visibility, menu-group save, stale POS cache, unclosed-session banner) and is not a troubleshooting/bug topic — not added as a new Issue. Flag for a UI/support pass only if a 'customer's discount didn't apply' or 'wrong discount showed on an order' report surfaces, or if the cached discountId goes stale the same way menu data does (Issue 5) and a customer's discount lags a back-office change. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-08-16 — haafai.app.identity ba0ea73..9e5212a (feat(support-access): request, authorise, revoke and grant-aware resolution) touches OrganisationsController.cs's GetUserOrganisations() — the same method already covered by the 2026-07-19 verification entry for its stale-LastLoggedInApplicationOrganisationId self-heal — and SwitchOrganisation(). Neither is the Provision/New() app-grant flow Issue 1's root-cause #2 cites at lines 279-432, which is untouched by this diff, so that UNCONFIRMED status stands unchanged. What changed: a new 'Support Access Grant' mechanism lets a Hubits engineer be granted time-limited access into a client organisation without membership. GetUserOrganisations() now also returns orgs reached only via a live grant, listed separately (IsSupportAccess = true, rendered under their own 'SUPPORT ACCESS' switcher heading, never merged into the member-org list) — and the self-heal's hasValidLastUsed check now also accepts a supportOrgIds match, so switching into a support-accessed org no longer gets silently overwritten back to the engineer's own org by the self-heal (per the diff's own comment, this closes a bug where the self-heal would otherwise evict the engineer from the org seconds after switching in). SwitchOrganisation() now grants access via OrgAccessQueries.CanActInOrgAsync (membership OR a live grant) instead of a pure membership check, and every support-driven switch is now audit-logged on the target org (Touch(...SupportOrgSwitch, 'Hubits support entered this organisation. Access expires {expiry}.')) with CallContext populated synchronously so the log attributes the real engineer rather than a generic actor. None of this contradicts any documented claim in this entry (Issue 1's onboarding-permission root causes, POS item visibility, menu-group save, stale POS cache, or the unclosed-session banner) — it's an internal support-tooling feature, not a restaurant-staff-facing one, so no Issue/Q&A edit is warranted. Not added as a new Issue — flag only if a client-side report surfaces of an unexpected 'SUPPORT ACCESS'-labelled organisation appearing in a normal user's own org switcher, which would indicate a rendering/scoping bug rather than expected behaviour. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-08-08 — haafai.app.identity a982fab..731aa70 (feat: issue shared-secret HS256 user JWT on login for CRM-AI; fix: move per-process OTP and token state to Redis; fix: enforce login lockout, add distributed login throttle, cache session validation; feat: add auth error codes and trusted-proxy client addressing; fix: cap verification-code guesses and replace allow-all CORS) touches both files Issue 1 cites — OrganisationsController.cs's Provision method (the same lines cited for root-cause #2's app-grant question) and RegistrationController.cs (cited for root-cause #1's auto-derive-FullName fix) — but neither documented claim is contradicted. In Provision: the idempotent 'if the user already has an active org, return it' short-circuit is now gated behind !request.ForceNew; per the new inline comment, the old unconditional version incorrectly caught users merely INVITED into someone else's restaurant (not owners) — their provision request was silently answered with that existing org, reported as a successful provision, and their requested Name discarded. ForceNew now lets a caller that wants a genuinely new org opt out of that redirect. A related follow-on: when ForceNew produces a second org for a user who already belongs to one, IsDefault is now !alreadyBelongsToAnOrg (previously always true), so the second org no longer clobbers the first as the user's default. None of this touches the role-group/app-grant lines (ApplicationRoleGroup = adminRoleGroup etc.) that root-cause #2 says show no explicit per-app 'enable foodops' insert — those lines are unchanged context in this diff, so root-cause #2 remains UNCONFIRMED as documented. In RegistrationController.cs, the change is unrelated to FullName auto-derivation (untouched, not in this diff's hunks): OTP storage moves from per-process IMemoryCache to distributed IDistributedCache (Redis) so a code issued by one instance verifies correctly on another, and both the email-verify and resend-code endpoints gain throttling (IOtpVerifyThrottle capping guess attempts, IOtpSendThrottle capping resend spam) — a security hardening pass, not a behavior change to the onboarding-permission flow Issue 1 documents. Not added as a new Issue and no edit to Issue 1 — flag for a UI/support pass only if a 'my second organisation isn't showing as the one I land in' report surfaces from a multi-org user who used ForceNew, or if the OTP throttling produces a 'too many attempts' complaint during onboarding. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-08-05 — foodops.counter.app f52b6dc..37ad39c (feat: void bin offline plumbing; void-to-bin engine + immediate cancel wiring; reason-capture snackbar; discard buttons + read-only panel + live badge on dine-in) touches dataPreloader.ts — the same file already cited for Issue 5's menu/category/product preload-and-cache behavior — but only to add and forward a new enableVoidBin boolean (from the register-bootstrap and session-bootstrap API responses into local preloader state). The menus/categories/products fields Issue 5 documents are untouched by this diff, so Issue 5's root cause (offline-first menu caching causing stale POS display until refresh) stands unaffected — no contradiction. What this diff actually introduces is a new, unrelated counter feature: a per-outlet-gated 'Void Bin' flow (voiding an item moves it to a bin with a required reason, shown via a persistent stacking snackbar, with discard buttons, a read-only panel, and a live badge on dine-in orders), per the commit subjects and a Dexie schema bump to v26 adding a voidBinEntries table with associated sync actions. This is not a setup/troubleshooting issue and doesn't fit any existing Issue in this entry (permission, POS item visibility, menu-group save, stale POS cache, unclosed-session banner) — not added as a new Issue. Flag for a UI/training pass only if 'why do voided items show up in a Void Bin instead of disappearing' or 'why can't I void this item' becomes a live support question — that would be a new, org-gated (EnableVoidBin) feature question, not a bug to troubleshoot. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-29 — foodops-admin-app 50d093c..3776343 (fix(menu): remove hint from "Items sold at Outlets" field in ItemFormPanel) touches ItemFormPanel.tsx's outlet-selection Field, the same UI surface Issue 2/Checklist document for outletIds/availability — but this hunk only removes the Field's hint prop text ("Leave empty to make available at all outlets."); the outletIds state, checkbox logic, and availability-channel fields at the previously-cited lines are untouched, so Issue 2's documented root cause (an item needs its outlet ticked to show on that outlet's POS) stands unaffected. Noteworthy for context, not a contradiction: the now-removed hint implies the admin UI used to tell users that leaving the outlets selection empty makes an item available at ALL outlets — a "wildcard" default that this entry has never documented (Issue 2/Checklist are written as if an outlet must be explicitly ticked). This diff is text-only (no logic change), so it does NOT confirm whether that "empty = all outlets" behavior is still actually true, only that the UI no longer explains it to admins creating items. Not added as a new Issue — flag for a live UI pass to confirm current behavior when an item is saved with zero outlets ticked, and consider adding a line to Issue 2's workaround if it's confirmed that blank outlet selection still means "available everywhere" (this would be useful positive framing, not just the current "won't ring up if you forget" negative framing). (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-27 — haafai.app.identity 682f345..4d5cb5b (fix(identity): close cross-tenant authorization gaps on org/subscription/app routes) touches OrganisationsController.cs — the same file Issue 1's root-cause #2 cites for the Provision/app-grant flow at lines 279-432 — but every hunk falls in different methods (GetOrganisation, UpdateOrganisation, GetOrganisationUsers, GetOrganisationApplications, TransferOwnership, GetOrganisationSubscription); the Provision/New() method itself is untouched, so Issue 1's UNCONFIRMED app-grant status stands unchanged. What changed: those six routes previously had no ownership/membership check at all — any authenticated caller could read/rename any organisation, list its users, read its enabled apps, read its billing/subscription, and (most severely) transfer ownership of any org to themselves, a full account-takeover hole. They now require org membership (ownership specifically for the transfer route) via new IsOrgMemberAsync/IsOrgOwnerAsync/CanViewUsersInOrgAsync checks, returning 403 "You are not authorised to perform this action." on failure. This is unrelated to any Issue documented in this entry (onboarding permission error, POS item visibility, menu-group save, stale POS cache, unclosed-session banner) — no contradiction of any claim. Noted edge case from the diff's own comments: organisations with a null OwnerId can no longer have ownership transferred via this endpoint by anyone (needs an out-of-band fix) — not currently a documented setup issue. Not added as a new Issue — flag for a support/UI pass only if a legitimate member reports "can't view/edit my organisation" or "transfer ownership isn't working," which would point to a stale/broken membership record rather than to Issue 1's documented onboarding bug. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-23 — foodops-admin-app 985570b..35146e3 (Fix alcyon issues; fix: show "Use as Ingredient" for Service items to match legacy behavior; feat: allow editing recipe output quantity) touches ItemFormPanel.tsx's supportsIngredient helper — the same file Issue 2/Checklist cite for outletIds/availability, but a different, unrelated section (those lines are untouched by this diff, so Issue 2's documented root cause stands). The change: supportsIngredient(typeId) previously excluded both PRODUCT_TYPE_KIT_BUNDLE and PRODUCT_TYPE_SERVICE from showing the 'Use as Ingredient' toggle; it now excludes only PRODUCT_TYPE_KIT_BUNDLE, so Service-type items show 'Use as Ingredient' again, per the commit message deliberately restoring legacy behavior. Unrelated to any documented Issue in this entry (permission, POS visibility, menu-group save, stale POS cache, unclosed-session banner) — no contradiction of any claim. Not added as a new Issue — flag only if a 'why can't I mark this Service item as an ingredient' report surfaces (this fix should resolve it going forward). (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-21 — foodops-admin-app 289bf0e..53d3af8 further evolves the variant-item form (ItemFormPanel.tsx, the same file Issue 2/Checklist cite for outletIds/availability — those lines are untouched by this diff, so Issue 2's documented root cause stands). Four user-facing changes, none touching outlet/POS-visibility: (1) editing an existing variant now strips the stored 'Parent/Variant' prefix via stripVariantPrefix/VariantNameInput so the Variant Name box shows only the variant's own suffix instead of the full 'Parent/Variant' string — refines the two-field Name split already noted in the 2026-07-17 verification entry; (2) failed save validation now also raises an error toast ('Please fix the following before saving') listing every validation message, in addition to the existing tab-jump behavior; (3) the Item Preparation (kitchens) section is now hidden for variant-type products (!isVariantFlow) since kitchens are assigned per-variant in the VariantBuilder grid instead of once at the product level, avoiding a 'duplicate' kitchen picker; (4) a required 'Default Stock Location' field is now also enforced inside the variant-creation flow specifically (for inventory-tracked variant products) — extending the general inventory-item stock-location requirement already flagged as a candidate new issue in the 2026-07-11 verification entry. None of this contradicts any claim in Issue 2 or the Checklist. Not added as a new Issue — flag for a UI pass if a 'variant name looks wrong when editing' or 'kitchens tab disappeared for variant items' or 'can't save a new variant without a stock location' report surfaces. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-20 — foodops-admin-app 289bf0e..3555578 (fix(catalog): variant item create/edit) touches ItemFormPanel.tsx again (the same file Issue 2/Checklist cite for outletIds/availability), but all three changes are outside that documented surface — outletIds/availability lines are untouched, so Issue 2's root cause is unaffected. What changed: (1) a failed save now also pops a toast ('Please fix the following before saving') listing every validation error message, on top of the existing modal-mode tab-jump-to-first-error behavior — purely additive visibility, not a validation-logic change; (2) for variant-type products the product-level 'Item Preparation' (kitchens) section is now hidden entirely (showKitchens && !isVariantFlow), per the new inline comment because variant-type products assign kitchens per-variant in the grid instead — a layout change to where kitchen selection lives, not documented anywhere in this entry; (3) a new required 'Default Stock Location' field (defaultStockLocationId, own validation error) now appears inside the variant-builder flow when showInventory is true — this extends the already-noted 2026-07-11 inventory-tracked-item stock-location requirement (previously only confirmed at product level) into the per-variant editing flow specifically. None of this contradicts Issue 2's documented outlet/availability root cause or any other Issue. Continues the same variant-item-form overhaul already flagged in the 2026-07-17 entry (Product Name/Variant Name split). Not added as a new Issue — flag for a UI pass on the variant create/edit flow if a 'why do I need a stock location for this variant' or 'can't save variant, what am I missing' support question surfaces (the new toast should make the blocking field obvious, but worth confirming live). (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-19 — haafai.app.identity b43657e..b8cd332 adds self-healing for a stale LastLoggedInApplicationOrganisationId in OrganisationsController.GetUserOrganisations() (same file the entry already cites for Issue 1, but a different method — Issue 1's root-cause #2 concerns the Provision/New() app-grant flow at lines 279-432, which this diff doesn't touch). New behavior: if a user's last-used org isn't an active org they currently belong to (e.g. it was disabled/archived, or their membership was deactivated), the API previously left the pointer stuck on that stale org — downstream services (sales-api) filter inactive orgs out of the switcher list, so the user got stuck locked to an unreachable org with no way to switch to a valid one. The fix now repairs the pointer to the first valid active org (by name) and persists it, and marks that org IsLastUsed in the response. This is a distinct failure mode from Issue 1's 'no permission to use this application (foodops)' error (no permission-denial message, no Provision/role-grant involvement) — closer to a hidden 'wrong/unreachable org loads on login' complaint for multi-org users. Doesn't contradict any documented claim (Issue 1's cited Provision lines are untouched by this diff). Not added as a new Issue section — flag for a UI pass if a 'I can't get into my org' or 'it keeps loading the wrong/old org' report surfaces from a multi-org user whose previously-used org was recently archived or whose membership was removed. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-17 — foodops-admin-app 8ebb1d2..5d0938c touches ItemFormPanel.tsx (the same file Issue 2/Checklist cite for outletIds/availability), but the change is unrelated to outlet-assignment visibility: editing a single variant of a variant-type product now splits the 'Name' field into 'Product Name' (shared across the family, hint text 'Shared by every variant of this product.') and a new required 'Variant Name' field (state var variantDisplayName), with its own validation error 'Variant name is required' when blank. Previously a variant edit only had one Name field. This doesn't contradict Issue 2's documented root cause (outletIds/availability — those lines are untouched by this diff) but is a plausible new support question ('why does the item form now ask for two names / why is Variant Name required') if a user hits it live. Not added as a new Issue — flag for a UI pass on the variant-edit flow if a 'can't save variant' report surfaces. Also cosmetic/unrelated: the Toggle's unchecked background class changed bg-mutedbg-input. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-16 — foodops.counter.app b813f61..054a5b3 refines the exact mechanics behind Issue 5's fix (dataPreloader.ts, the same file already cited for menu preload/cache). preloadSalesmadeCatalog() now takes a forceRefresh flag: only forced callers (org switch, session join, open-register, the sidebar refresh control) clear the local products/categories tables and do a full cursor-reset re-pull via syncSalesmadeCatalog({ force: true }). The plain boot preload (useOrganizationInit, i.e. just reopening the app / logging back in) is now explicitly the non-force path — it leaves the cached tables intact and does an incremental delta pull from the persisted sync cursor instead. Per the commit's own inline rationale, this is a fix for a prior data-loss risk (clearing tables then delta-pulling from cursor could return zero rows, leaving the POS grid on "No products yet"), not a removal of refresh-on-reopen — a plain reopen should still surface new/changed admin catalog items via the delta cursor, so Issue 5's documented fix ("re-open the app so the preloader re-runs") remains functionally valid and is not contradicted. Worth a nuance if a future troubleshooting pass expands Issue 5: the guaranteed full hard-reset now only happens via the explicit menu-refresh control or the listed force-triggering actions (org switch/session join/open-register) — a plain app reopen is a lighter incremental sync, not a hard cache wipe-and-refetch. Not clear from this diff alone whether the delta cursor reliably captures every admin-side catalog edit (add/price/category move) in all cases — flag for a live UI pass if a "reopen didn't fix it, but the refresh button did" report ever surfaces. Also unrelated but in the same file: /user/permissions cache TTL in cacheApiDecorator.ts dropped from 12h to 5min so permission revokes/grants propagate faster — out of scope for this entry's topics but noted for completeness. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-11 — foodops-admin-app f1709e0..e6e2d0e (main) adds a new validation to the item form (ItemFormPanel.tsx, the same file Issue 2 already cites for outlet assignment): Default Stock Location is now a required field for any inventory-tracked item — previously it accepted "— None —" silently. The commit message explains the failure mode this closes: without a stock location, opening stock never lands in a warehouse (no StockLocationProductVariant row), so the item showed "No warehouse data available" in Stock by Location with no upfront error. This is a distinct root cause from Issue 2's outlet/POS-visibility bug (unaffected — outletIds/availability lines are untouched by this diff) and would warrant its own troubleshooting entry/issue (e.g. "inventory item has no warehouse stock data") rather than an edit to Issue 2. Not yet added as a new Issue section — flag for a UI pass to confirm the required-field error text and whether it's back-filled for existing items created before this change. (auto-applied by the truth pipeline; adversarially gated)

Warning: 2026-06-29 — new-stack re-verify for July-10 launch · codebase Verified_by: codebase · Last verified: 2026-06-29 · foodops-admin-app@4173811 (main) + foodops.counter.app@32669a9 (main) + haafai.app.identity@31e7739 (staging) Re-pointed off the retired haafai.app.foodops monolith. Issue 1 (permission): root cause #1 (blank name) FIXED — RegistrationController.cs:72 auto-derives FullName from email; app-grant unconfirmed (OrganisationsController.Provision grants all roles but no explicit app-enable) → flagged for a live signup. Issue 2 (items not on POS): re-pointed — outlet assignment is now a React outletIds set in admin ItemFormPanel.tsx:234,406 (+ availability channels); the legacy jQuery checkbox bug is retired. Issue 3 (jQuery on direct URL): RETIRED — React SPAs, no server-rendered jQuery forms. Issue 4 (menu-group modal save): RETIRED — groups now in admin React Catalog (/catalog/groups,/catalog/categories). Issue 5 (stale POS menu): re-pointed to the counter's offline cache/preloader (dataPreloader.ts, cacheApiDecorator.ts). Unclosed-session banner confirmed present (SessionUnclosedBanner.tsx). Fixed the legacy Issue-3/Issue-4 mis-numbering in the Q&A. Dropped legacy haafai.app.foodops citation; re-pinned all SHAs. No bug confirmed reproducing (code-only) — UI-TODOs flagged for a live pass.

Warning: Partially verified 2026-06-11 · codebase — status: needs-review The workaround anchors (routes, form fields, UI labels) are code-confirmed; whether each bug still reproduces is only confirmable in the live UI. Treat bug-reproduction claims as of 2026-04-14 until the UI-TODOs below are cleared.

  • 2026-06-11 — codebase validation pass (haafai.app.foodops@a8ea20b, haafai.app.identity@ebaa30a, foodops.counter.app@1f77fc6). Issue 1: workaround UI fully present in UserEdit.razor (required Name, "Select applications", "Select roles", Update User); no permission-auto-grant fix in identity's 3 commits since April → bug presumed live. Issues 2/4: "Items sold at Outlets" template, Reload Cache control, and the /menucategories/edit/{id} GET/POST + CategoryIds binding all confirmed. Issue 3 (jQuery on direct URL): architecture claim, not re-verified — plausible given the server-rendered-forms-in-SPA-shell layout; left as-is. Issue 5: menu cache + Reload Cache confirmed; unclosed-session warning machinery confirmed in both the monolith (Haafai.Layouts/Views/Shared/_Layout.cshtml, Registers settings controller) and the Counter PWA (SessionUnclosedBanner.tsx persistent toast with View Details/Dismiss). No issue could be confirmed FIXED, so all five stay documented.

Additional verification events are appended here by the weekly KB sync and by manual re-verification passes. See _meta/failure-log.md for the global failure index.

Go beyond POS.
Choose the total solution.

Focus on creating the best experience for your guests while we handle the rest.