Plain-English summary
This is the cheatsheet of every URL in Foodops — the sidebar icons with what they do, plus every route that returns 200 OK, grouped by what kind of work happens there. Useful when an agent or human is asked "where do I find the kitchen display?" or "what's the URL to create a supplier?" — look up the answer here without having to navigate the app.
When you'd use this
A user reports the old app at
app.foodops.iowon't load or log in — that legacy app is retired (July-2026 launch); nothing is wrong with their connection. Point them to the new apps: the counter POS at counter.foodops.io and the back-office at admin.foodops.io (same sso.hubits.io account works on both).Voice/chat agent answering navigation questions
Deep-linking from an external system directly into a Foodops screen
Training a new user on app structure before they click around
Troubleshooting — "does this page still exist?" URL probe reference
Building bookmarks or cheat sheets
Summary
REBUILT for the new stack (July-2026 launch). The legacy
app.foodops.iomonolith and its MVC URL map (/dashboards,/orders,/tables,/kitchen/index,/menuitems, …) are RETIRED. FoodOps is now two React SPAs:
- Counter app —
counter.foodops.io(foodops.counter.app): the on-the-floor POS. Routes insrc/App.tsx; nav rail insrc/components/layout/Sidebar.tsx.- Admin app —
admin.foodops.io(foodops-admin-app, foodops brand): the back-office. ~100 lazy routes inapps/admin/src/App.tsx; settings rail inapps/admin/src/pages/settings/settingsNavConfig.ts(7 groups).Both are client-side routed (React Router) — paths below are the in-app routes, not server-rendered pages. Note the foodops brand relabels the counter's "Counter" rail to "Orders", and Finance routes are tree-shaken out of the foodops build (they exist only on finance-v2).
Complete map of both Foodops SPAs, organized by functional area, code-verified against foodops.counter.app@32669a9 and foodops-admin-app@4173811 (both prod main).
Counter app — sidebar navigation (counter.foodops.io)
The counter rail is brand-filtered. For the foodops brand the allowedItems whitelist renders: Counter (shown as "Orders"), Dine-In, Deliveries, Takeouts, Reports. ('Dashboard' is mapped in code but excluded from allowedItems, so it's reachable only by URL.) [code: foodops.counter.app/src/components/layout/Sidebar.tsx:190-192,249]
| Rail item (foodops) | Navigates to | Description |
|---|---|---|
| Orders (label; "Counter" internally) | /counter |
Main till — active dine-in/takeout/delivery orders; open a register session |
| Dine-In | /counter?intent=dinein (or /sessions/:id/dinein in a session) |
Dine-in / table ordering |
| Deliveries | /counter?intent=delivery |
Delivery ordering mode |
| Takeouts | /counter?intent=takeout (or /takeout) |
Takeout ordering mode |
| Reports | /reports/day-summary |
End-of-day Day Summary report |
| (Dashboard — not in rail) | /dashboard |
KPI dashboard (URL-only on the counter) |
Order-mode rail items reuse the current session: with an open session they route to /sessions/:id/..., otherwise to /counter?intent=.... [code: Sidebar.tsx:325-341]
Kitchen Display (KDS) is a separate bundle, not a counter route — it builds from the same repo to
kds.html(src/kds/main.tsx,vite.kds.config.ts). There is no/kitchenroute in the counter SPA. Reservations is not a counter route either.
Counter app — all routes (counter.foodops.io)
Everything except /login, the auth callbacks and the print pages is behind ProtectedRoute. [code: foodops.counter.app/src/App.tsx:147-314]
| Route | Purpose |
|---|---|
/login · /auth/callback · /auth/silent-callback |
Auth (email+password; OIDC callbacks) |
/update-required |
PWA force-update screen |
/dashboard |
KPI dashboard (not in the rail; URL-only) |
/counter |
Main till ("Orders" for foodops) — also /counter?intent=dinein|delivery|takeout |
/sessions/:id/pos |
Session-scoped POS (the heart of the app) |
/sessions/:id/orders/create · /sessions/:id/orders/:orderId/edit |
Create / edit an order (session-gated) |
/sessions/:id/dinein |
Dine-in within a session |
/takeout · /dine-in |
Takeout / dine-in entry points |
/sales |
Sales list (online-only) |
/customers · /customers/:id |
Customers |
/register-sessions · /register-sessions/:id |
Register open/close + reconciliation |
/reports/day-summary |
End-of-day Day Summary report |
/conflicts |
Offline order version-conflict resolution |
/settings |
Counter settings |
/print/kot/:orderId/:kotId · /print/receipt/:orderId |
Print pages (no auth, new window) |
/ and * |
Redirect → /counter |
Admin app — route map (admin.foodops.io, foodops brand)
~100 lazy routes; the foodops-relevant domains (finance routes are tree-shaken out — see note). [code: foodops-admin-app/apps/admin/src/App.tsx:464-1258]
| Domain | Representative routes |
|---|---|
| Auth / onboarding | /login, /register, /verify-email, /approve/:token, /onboarding/business, /onboarding/locale, /onboarding/outlet |
| Dashboard | /dashboard, /assistant, /notifications |
| Catalog | /catalog/items (+/:variantId), /catalog/groups, /catalog/categories, /catalog/modifiers, /catalog/brands, /catalog/price-lists (+/:id), /catalog/order |
| Sales | /sales/register-sessions (+/:id), /sales/customers (+/:id), /sales/orders (+/new,/:id,/:id/edit,/imports), /sales/invoices (+/:id), /sales/payments (+/:id), /sales/returns, /sales/quotes, /sales/proforma-invoices, /sales/loyalty-programs |
| Expenses | /expenses (index), /expenses/suppliers, /expenses/purchase-orders, /expenses/purchase-receipts, /expenses/records, /expenses/bills, /expenses/payments-made |
| Inventory | /inventory |
| Costing | /costing/overview, /costing/recipes, /costing/wastage-logs, /costing/wastage-reasons, /costing/yield, /costing/variance, /costing/food-cost |
| Marketing | /marketing/overview, /marketing/campaigns, /marketing/promotions, /marketing/coupons (each + new/:id/edit) |
| Shopping list | /shopping-list |
| Reports | /reports/<name> — see Reports |
| Settings | /settings + the 7 settings groups below |
Finance is tree-shaken out of the foodops build. Accounting / banking / taxes / finance-reports routes (
/accounting/*,/banking/*,/taxes/*,/reports/profit-loss, etc.) render<Navigate to="/dashboard">on admin.foodops.io — they only exist onfinance-v2.hubits.io. Navigating to one on foodops silently redirects to the dashboard. [code: foodops-admin-app/apps/admin/src/App.tsx:28-48 —INCLUDE_FINANCE]
Admin app — Settings (7 nav groups)
The settings rail is data-driven from SETTINGS_NAV; for the foodops brand all 7 groups show (finance-only items hidden). [code: foodops-admin-app/apps/admin/src/pages/settings/settingsNavConfig.ts:33-107]
| # | Group | Items (foodops) |
|---|---|---|
| 1 | Organization | Account Profile /settings/organization/profile · Users /settings/organization/users · Audit Log /settings/audit-log |
| 2 | Accounting | Currencies /settings/organization/currencies · Taxes /settings/organization/taxes · Service Fees /settings/organization/service-fees · Payment Methods /settings/organization/payment-methods |
| 3 | Discounts | Discounts /settings/discounts/list · Discount Reason Types /settings/discounts/reason-types |
| 4 | Outlets | General /settings/restaurant/general · Outlets /settings/restaurant/outlets · Delivery Sectors /settings/restaurant/delivery-sectors |
| 5 | Inventory | Units of Measure /settings/inventory/units |
| 6 | Customisation | Pdf Templates /settings/customisation/pdf-templates · Transaction Series /settings/customisation/transaction-series · Import Wizard /settings/customisation/import-wizard |
| 7 | Integrations | Integrations /settings/integrations |
Finance-only settings items (Customer Portal, Approval Rules, Accountants, Period Locks, Organisation Groups) are hidden for foodops via
showForBrands: ['finance'].
Onboarding wizard (new)
The legacy /onboarding/home 8-task wizard is retired. New-org setup now runs in the admin app as a 3-step wizard — /onboarding/business → /onboarding/locale → /onboarding/outlet — gated by OnboardingGate (which checks the sales API /onboarding/status). See Onboarding for the full flow.
Key concepts
- Two SPAs — FoodOps is now two React Router apps: the counter (counter.foodops.io) and the admin (admin.foodops.io). Both are client-side routed; the paths above are in-app routes.
- Route prefix convention (admin) —
/settings/*config,/reports/*reports,/catalog/*menu,/sales/*selling,/expenses/*purchasing,/inventory+/costing/*stock & food-cost. - Brand relabel — for the foodops brand the counter's "Counter" rail item is displayed as "Orders".
- Finance is tree-shaken, not 404 — finance routes (
/accounting/*,/banking/*,/taxes/*, finance reports) don't exist in the foodops bundle; navigating to one redirects to/dashboard(they live on finance-v2). A missing finance route is by-design, not deleted. - User management — under admin Settings → Organization → Users (
/settings/organization/users); identity is shared with SSO.
Common questions
Q: Where do I find Users / Staff / Team management?
A: Admin → Settings → Organization → Users (/settings/organization/users). Identity is shared with SSO (sso.hubits.io).
Q: Where's the dashboard / analytics?
A: KPI snapshots are on the admin dashboard (/dashboard on admin.foodops.io) and the counter /dashboard; deeper analysis is in Reports (/reports/<name>). There is no separate /analytics route.
Q: I went to a finance/accounting page and it bounced me to the dashboard. Why?
A: Expected. Finance (accounting, banking, taxes, finance reports) is tree-shaken out of the foodops build — those routes only exist on finance-v2. On foodops they redirect to /dashboard.
Q: How do I find a specific setting I can't remember?
A: Admin /settings — the rail has 7 groups (Organization, Accounting, Discounts, Outlets, Inventory, Customisation, Integrations) plus a search box that filters items by label. [code: foodops-admin-app/apps/admin/src/pages/settings/settingsNavConfig.ts — filterNav]
Related
Onboarding — step-by-step setup guide
Menu Management — creating categories and items
Settings Overview — deep-dive on every settings sub-page
Users & Roles — SSO-based user management
2026-08-08 — foodops-admin-app 45736a4..3db92a1. None of this diff's 5 commit subjects (Projects page, invoice paging fix, invoice outlet field, finance dashboard layout, project-from-invoice) touch Costing, so most of the '+' Costing sidebar block in brands.ts is a re-surfacing artifact of this diff's base (45736a4) predating the already-verified 2026-08-07 pass (verified_against_commit 2eaf621), which documented a 7-item Costing group (Overview, Food Cost %, Cost Variance, Recipe Costing, Recipe Data Quality, Wastage Log, Yield Analysis) — no action needed on those 7. The one item beyond that prior count is new: an 8th Costing child, 'Recipe Migration' (
/costing/recipe-migration), gatedROLES.Costing.Manageonly (unlike its read-only Costing siblings) per an explicit code comment noting it commits recipe cost changes org-wide. Additive to the entry's already-representative-not-exhaustive Costing domain row — no existing claim contradicted. Also re-surfaced from the 2026-08-07 pass and requiring no new action: thebadgeKind: 'documents-review'type addition and the/expenses/documentssidebar wiring. Two changes in this diff are out of the entry's scope entirely: the Finance-brand rename ('Finance Admin' → 'Hubits Finance') and its newfavicon/sidebarIcon/logo assets apply only to the finance brand config, not foodops/admin.foodops.io; and App.tsx's swap of every route fromlazy()to a newlazyWithReload()helper is an internal deploy-resiliency change (auto-reloads a tab once if its hashed chunk 404s post-deploy) with no effect on any route path or the nav structure this entry documents. Worth a line next time this entry is touched: Costing now has a Manage-gated 'Recipe Migration' tool at/costing/recipe-migration, distinct from the group's otherwise read-only items. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)2026-08-07 — foodops-admin-app 45736a4..2eaf621 adds a new Expenses 'Documents inbox' surface —
/expenses/documents(DocumentsInboxPage) and/expenses/documents/:id(DocumentReviewPage), explicitly commented 'Phase 1.1 document intelligence' — and neither route isINCLUDE_FINANCE-gated, so both exist in the foodops build (not tree-shaken like Accounting/Banking/Taxes). Additive to the entry's Expenses domain row, which is already representative not exhaustive. The brands.ts hunk that wires a sidebar item + badge (badgeKind: 'documents-review') for this route sits in the Finance ('Hubits Finance', renamed from 'Finance Admin') brand's Expenses group in this diff slice — there's no evidence in this diff of a corresponding foodops-brand sidebar entry, so whether admin.foodops.io surfaces 'Documents' in-rail or only reaches it by URL (same pattern already documented for/dashboardand/creditcycle) is unconfirmed; worth checking on next read. Separately, a new Costing sub-item was added —/costing/data-quality(RecipeDataQualityPage, 'Recipe Data Quality') — alongside a full 7-item Costing sidebar group (Overview, Food Cost %, Cost Variance, Recipe Costing, Recipe Data Quality, Wastage Log, Yield Analysis) that maps directly onto the entry's existing Costing route list; additive only. A third new route,/accounting/projects(ProjectsPage), is wrapped in the sameINCLUDE_FINANCE ? lazy(...) : ExcludedRoutegate as the entry's other cited finance-only pages, so it does not appear on admin.foodops.io — consistent with the entry's already-documented tree-shaken-finance behavior, no action needed there. None of this contradicts a documented claim. (auto-applied by the truth pipeline; adversarially gated)2026-08-03 — foodops.counter.app 2e88679..f52b6dc changes how the counter sidebar handles clicks on any rail item flagged
external(e.g. a link out to admin.foodops.io): a plain click no longer does an unconditionalwindow.open, it now callsshouldConfirmAdminNav()and, unless the user has a saved opt-out preference, shows a newAdminAppRedirectDialog('Continue to Admin') with a same-tab/new-tab choice before navigating;openAdminNav()fires immediately only when the preference says to skip the prompt. Separately, modified-click handling (Cmd/Ctrl/Shift/middle-click) was unified — external rail rows now fall through to native anchor<a href>behavior for new-tab/new-window opens instead of the old explicititem.externalbranch that always intercepted withpreventDefault()+window.open, so an explicit open-in-new-tab gesture never triggers the confirmation dialog. This isn't a contradiction of the entry's documented rail table (Orders/Dine-In/Deliveries/Takeouts/Reports are all internal SPA routes, notexternal), but it's new cross-app navigation UX worth a line next time this entry is touched: any counter-sidebar item that jumps out to the admin app now interstitials through a confirm dialog on plain click (sticky via a saved preference), while modifier/middle-clicks bypass it. (auto-applied by the truth pipeline; adversarially gated)2026-07-21 — foodops-admin-app f361a7c..fc28099 adds two new user-reachable admin routes:
/catalog/items/product/:productId/edit(newProductFormPage, alongside the existing/catalog/items/:variantIdroute) and a top-level/creditcycleroute (newCreditCyclePage, explicitly commented 'intentionally not in sidebar nav' — the same URL-only pattern already documented for the counter's/dashboardand the admin's/settings/customisation/import-result). Neither contradicts the entry's Catalog/Sales route tables, which are explicitly representative, not exhaustive. Separately,apps/admin/src/config/brands.tsadds a newrequiredRolesfield and applies it across nearly every Catalog and Sales sidebar child item (Items, Modifiers, Categories, Brands, Menu Groups, Register Sessions, Customers, Quotes, Sales Orders, Invoices, Payments, Sales Returns, Loyalty Programs, Tip Pool) — these items are now hidden from the main admin sidebar unless the logged-in user holds at least one matching org-scoped role, layered on top of the brand-based (showForBrands) filter the entry already documents for Settings. Worth a line once the entry is next touched: a restricted-role staff account will now see a shorter Catalog/Sales sidebar than a full-access account — 'my sidebar item disappeared' for one user but not another is expected role-based behavior, not a bug. Also new but outside the entry's cited surface: aQueryClientProvider/React Query wrapper, plus lazyBillingSettingsPage,BmlPaymentGatewaySettingsPage, andStockReadinessSettingsPageimports, appear with no corresponding route hunk in this diff slice — insufficient evidence yet to document new billing/BML-gateway/stock-readiness routes. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)2026-07-13 — foodops-admin-app 45245b7..f361a7c adds two new top-level admin routes for Catalog > Categories:
/catalog/categories/newand/catalog/categories/:id/edit, both rendering a new lazy-loadedProductCategoryFormPage, alongside the pre-existing/catalog/categorieslist route. Additive, not contradictory — the entry's Catalog domain row already lists/catalog/categoriesas a representative route without claiming an exhaustive sub-route list, matching the same pattern already noted for Modifiers, Payments Made, and PDF templates. Worth a line once the entry is next touched: Product Categories now has a dedicated full-page create/edit form rather than only an inline/list-view editor. The rest of this diff — the/catalog/modifiers/newand/:id/editroutes viaModifierGroupFormPage, the/expenses/payments-made/newand/:id/editroutes viaPaymentMadeFormPage, and the PDF template editor's top-level full-screen routes — duplicates changes already captured in the 2026-07-13 (verified_against_commit 79be9d0), 2026-07-12 (verified_against_commit 3202946), and 2026-07-10 (verified_against_commit f1709e0) verification-history entries respectively; this diff's base (45245b7) simply predates all three prior verifications, so no further action needed on those. TheStockCountFormPagelazy import reappears with still no corresponding route hunk in this diff slice — insufficient evidence to document a stock-count route. The account-profile logo-management, grid-dropdown, and recipe-output-unit commit subjects in this range touch no file on the entry's cited surface (App.tsx routes / Sidebar.tsx / settingsNavConfig.ts) and need no action here. (auto-applied by the truth pipeline; adversarially gated)2026-07-13 — foodops-admin-app 45245b7..79be9d0 adds two new top-level admin routes for Catalog > Modifiers:
/catalog/modifiers/newand/catalog/modifiers/:id/edit, both rendering a new lazy-loadedModifierGroupFormPage, alongside the pre-existing/catalog/modifierslist route. Additive, not contradictory — the entry's Catalog domain row already lists/catalog/modifiersas a representative route without claiming an exhaustive sub-route list, matching the same pattern already noted for Payments Made and PDF templates. Worth a line once the entry is next touched: modifier groups now have dedicated full-page create/edit routes rather than only an inline/list-view editor. The rest of this diff (the/expenses/payments-made/newand/:id/editroutes viaPaymentMadeFormPage, and the PDF template editor's move to top-level full-screen routes) duplicates changes already captured in the 2026-07-12 (verified_against_commit 3202946) and 2026-07-10 (verified_against_commit f1709e0) verification-history entries respectively — this diff's base (45245b7) simply predates both prior verifications, so no further action needed on those two. AStockCountFormPagelazy import was also added but no corresponding route hunk is present in this diff slice, so there's insufficient evidence yet to document a new stock-count route. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)2026-07-12 — foodops-admin-app 45245b7..3202946 adds two new top-level admin routes under the Expenses > Payments Made surface:
/expenses/payments-made/newand/expenses/payments-made/:id/edit, both rendering a new lazy-loadedPaymentMadeFormPagecomponent, sitting alongside the pre-existing/expenses/payments-made/:iddetails route. This is additive, not contradictory — the entry's Expenses domain row already lists/expenses/payments-madeas a representative route without claiming an exhaustive sub-route list, so no existing claim is broken. Worth a line in the Expenses table (or a Related note) once the entry is next touched: Payments Made now has a dedicated full-page create/edit form rather than only a details/view page. Separately, this diff's PDF-template-editor hunk (moving/settings/customisation/pdf-templates/newand/:id/editout of the nested SettingsShell tree into top-level full-screen routes) is the SAME change already captured in the entry's 2026-07-10 verification-history entry (verified_against_commit f1709e0) — no new action needed there, it's just re-surfaced because this diff's base (45245b7) predates that prior verification. (auto-applied by the truth pipeline; adversarially gated)2026-07-10 — foodops-admin-app 45245b7..f1709e0 moves the PDF Template editor (
/settings/customisation/pdf-templates/newand/settings/customisation/pdf-templates/:id/edit) out of the nested SettingsShell route tree into two top-level routes rendered full-screen (own Toolbar with back/save, no settings nav rail). URLs are unchanged — still under the/settings/customisation/pdf-templates/...prefix documented in the entry's Settings table (item 6, Customisation group) — so no existing claim is contradicted, but the entry's Settings table only lists the list page (/settings/customisation/pdf-templates) and doesn't describe the editor's chrome; worth a line noting that opening 'New' or 'Edit' on a PDF template now opens a distraction-free full-screen canvas rather than a page boxed inside the Settings panel, since a user/agent reporting 'the settings sidebar disappeared' when editing a template is expected behavior, not a bug. (auto-applied by the truth pipeline; adversarially gated)2026-07-10 — foodops.counter.app 6885e57..e4e7aaa (icon-migration series). No contradiction of documented routes: the diff adds a new
resolveItemHref/handleNavAnchorClickpair that explicitly mirrors the existinghandleMenuClickbranching, and its logic matches this entry's documented rail routing (Dine-In →/sessions/:id/dineinor?intent=dinein; Deliveries/Takeouts →/sessions/:id/pos?mode=...or?intent=...; Reports →/reports/day-summary), so it confirms rather than changes the URL map. What's new and worth a line: desktop and mobile sidebar rail rows were converted from<button onClick>to<a href=...>, so right-click 'Open in new tab', Ctrl/Cmd+click, and middle-click now work natively on the counter rail (previously only in-app SPA navigation was possible). Separately, as part of an app-wide Hugeicons→lucide icon swap, the 'Counter' fallback icon class changed fromhgi hgi-stroke hgi-shipping-centerto lucide'sairplay— cosmetic only, not previously documented in this entry, no action needed. (auto-applied by the truth pipeline; adversarially gated)2026-07-04 — foodops-admin-app 88dfde2..cc539d1 adds a new 8th SETTINGS_NAV group, 'AI Assistant' (icon Sparkles), with two items — AI Autonomy (
/settings/ai/autonomy) and AI Activity (/settings/ai/activity) — both gatedshowForBrands: ['finance'], so consistent with the entry's existing 'finance-only items hidden for foodops' pattern these stay hidden on admin.foodops.io for now; the documented '7 nav groups' count for foodops is not contradicted but should be re-confirmed once the actual group-level filter (not just item-level) is read, since this is the first group whose items are 100% finance-gated. Also new: a URL-only result page/settings/customisation/import-result(ImportResultPage) was added under the existing Customisation group — not added to settingsNavConfig.ts, so it's reachable only by URL/redirect (e.g. after running the Import Wizard), same pattern as the counter's rail-less/dashboard. Separately, brands.ts now ships a brand-configurable AI 'docked panel' (assistant: {enabled, title, suggestions}) and this is explicitly enabled for the foodops brand with foodops-flavoured suggestion chips ('How did we do today?', 'Give me my margin brief', 'Which invoices are overdue?') — this substantiates/extends the entry's already-listed/assistantroute under the admin Dashboard domain and is worth a line noting the assistant panel is now live and brand-tuned for foodops. (auto-applied by the truth pipeline; adversarially gated)
Warning: 2026-06-29 — REBUILT for new stack (July-10 launch) · codebase Verified_by:
codebase· Last verified: 2026-06-29 ·foodops.counter.app@32669a9(main) +foodops-admin-app@4173811(main) Full re-point off the retiredhaafai.app.foodopsmonolith. Replaced the legacy MVC URL map with the two new SPAs: counter (counter.foodops.io — routes fromsrc/App.tsx:147-314, rail fromSidebar.tsx) and admin (admin.foodops.io — ~100 routes fromapps/admin/src/App.tsx:464-1258, settings fromsettingsNavConfig.ts). Confirmed: counterallowedItemsrail = Counter("Orders")/Dine-In/Deliveries/Takeouts/Reports (Dashboard URL-only); KDS is a separatekds.htmlbundle (no/kitchenroute); admin domains Catalog/Sales/Expenses/Inventory/Costing/Marketing/Reports/Settings; Settings = 7 nav groups (Organization, Accounting, Discounts, Outlets, Inventory, Customisation, Integrations). Documented Finance routes as tree-shaken out of the foodops build (redirect to/dashboard, not 404). Onboarding wizard re-pointed to the 3-step admin wizard. Dropped all legacy/dashboards,/orders,/tables,/kitchen/index,/menuitems,etc. Sidebar icon order + live nav-API payload not re-probed (code-only).
Success: Verified 2026-06-11 · codebase (LEGACY monolith — superseded) Status:
stable· Confidence: medium (routes code-confirmed; HTTP statuses and sidebar behaviour from the original live probe)
- 2026-06-11 — codebase validation pass against haafai.app.foodops@a8ea20b (main). Every 200-OK route in the tables maps to a real MVC controller under the default route pattern (
Startup.cs:1045-1047): Dashboards, Orders, Tables, Delivery, Takeouts, Kitchen, Reservations, SalesSessions, MenuCategories, MenuItems, Modifiers, Recipes, Ingredients, Reports, Onboarding inHaafai.Restaurant.App; Customers inHaafai.Sales; Suppliers + PurchaseOrders inHaafai.Expenses; Settings inHaafai.Layouts. All 8 onboarding-wizard task labels confirmed verbatim inViews/Onboarding/Home.cshtml(incl. "Send a Feedback" and the SSO users deep-link). 404 table upgraded with code-level causes:/analyticsIndex action is commented out inAnalyticsController;/shoppinglistsis a near-miss (controller is singularShoppingListController);/mealplanslikely lives at/mealsubscriptionplans. Sidebar icon order, SPAjavascript:void(0)behaviour, and live HTTP statuses were not re-probed — original Playwright observations retained.
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.