Vendors / Open source & self-hostable

nutrixpos / pos

The most modern stack in this batch — Go plus React with an explicitly REST-API-first architecture — and verifiably alive with release v0.13.0 published 2026-05-09 and commits through 2026-07-17, but its own README warns it is in active development with no stable release and no guaranteed backward compatibility.

scored live legacy rubric

Claims in scope
278
Scored
45
Assessed
41
Unknown
237
Not applicable
36
Cells challenged
0
85% of in-scope claims are unknown. This record measures what nutrixpos / pos publishes at least as much as what it does. A vendor that documents little scores low here whether or not the capability exists. Absence of evidence is recorded as unknown, never as no.

Identity

Owner
nutrixpos (independent open-source project, GPL-2.0; docs at nutrixpos.com)
Who it is for
Small restaurants, cafes and shops wanting a modern self-hosted Go/React POS with a REST-API-first architecture rather than a Java desktop app
Site
https://github.com/nutrixpos/pos

Pricing

transparency: unknown · unit: free (GPL-2.0, self-hosted; MongoDB required) · processor lock-in: no

Software
Free and open source under GPL-2.0, self-hosted via Docker Compose or a Windows executable with MongoDB. No published commercial tiers, hosting plans, or per-terminal fees.

Capabilities

Every claim is binary and checkable. Grades: A primary documentation · B product documentation · C pricing or feature page · D marketing claim · E third-party reporting · F inference with no source. A yes on a differentiator claim requires A or B.

Order capture & FOH workflow

Unknown

order-capture-floor-plan-editor

Not scored by this record.

Unknown

order-capture-seat-level

Not scored by this record.

Unknown

order-capture-coursing-hold-fire

Not scored by this record.

No

order-capture-split-merge

The complete OpenAPI path list contains no split, merge or partial-tender resource. POST /orders/{id}/pay declares no request body, and its handler calls PayUnpaidOrder(order_id), which marks the whole order paid. The Order model carries a single IsPaid bool and one PaymentSource string, with no parent/child order reference, seat number or table field. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/specs.api.yaml · retrieved 2026-08-03

A
Unknown

order-capture-bar-tab-preauth differentiator

Not scored by this record.

Unknown

order-capture-transfer-audit

Not scored by this record.

Unknown

order-capture-native-handheld

Not scored by this record.

Unknown

order-capture-offline-order-entry

Self-hosted, but it is a client/server web app against MongoDB; no offline-capable terminal client or offline matrix is documented.

F
Unknown

order-capture-qr-same-check differentiator

Not scored by this record.

Unknown

order-capture-kiosk-first-party differentiator

Not scored by this record.

Unknown

order-capture-drive-thru

Not scored by this record.

Unknown

order-capture-drive-thru-timers

Not scored by this record.

Unknown

order-capture-voice-ai differentiator

Not scored by this record.

Unknown

order-capture-throttling differentiator

Not scored by this record.

No

order-capture-scheduled-orders

Order carries SubmittedAt, StartedAt, IsAutoStart and IsAutoFinish and no scheduled-for, promise-time or fire-time field; a repo-wide search for "scheduled" returns nothing. OrderSettings holds only queue prefix/next counters and a default cost-calculation method, so there is no per-channel lead time to compute a fire time from. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

order-capture-catering

Not scored by this record.

Unknown

order-capture-order-ready-signal differentiator

Not scored by this record.

Unknown

order-capture-void-comp-controls

Not scored by this record.

Menu, modifiers & pricing engine

No

menu-pricing-nested-modifiers

The Product struct is {Materials, SubProducts, Entries, Price, ImageURL, Unit, Quantity, Ready, EnableInventoryConsumption, EnableFixedCost, FixedCost} — there is no modifier-group entity. SubProducts are sub-recipes with a quantity, consumed by GetRecipeTree for BOM costing, not guest-selectable option groups. Repo-wide search finds no min/max selection count, no required/forced flag and no occurrence of "modifier", "option group", "addon" or "topping". https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
No

menu-pricing-modifier-price-by-parent-size

No modifier entity exists to price, and no size or variant entity exists to price it against: Product carries exactly one Price float64 and one Unit string. There is no price matrix, override table or parent-item-scoped price anywhere in the model package or the OpenAPI Product schema. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

menu-pricing-fractional-placement differentiator

Not scored by this record.

Unknown

menu-pricing-half-and-half-rule differentiator

Not scored by this record.

No

menu-pricing-topping-quantity-tiers

OrderItem carries a bare Quantity float64 with no tier, level or multiplier field, and no modifier entity exists to tier. Repo-wide search finds no "light", "extra", "double" or price-multiplier construct in either the Go models or the Vue ordering page. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

menu-pricing-size-style-matrix differentiator

Not scored by this record.

Unknown

menu-pricing-included-allowance differentiator

Not scored by this record.

Unknown

menu-pricing-combos

Not scored by this record.

Unknown

menu-pricing-upsell-prompts differentiator

Not scored by this record.

Unknown

menu-pricing-86-propagation

Not scored by this record.

Unknown

menu-pricing-countdown-auto-86 differentiator

Not scored by this record.

Unknown

menu-pricing-dayparting

Not scored by this record.

Unknown

menu-pricing-channel-price-books

Not scored by this record.

Unknown

menu-pricing-dual-pricing differentiator

Not scored by this record.

Unknown

menu-pricing-allergen-nutrition

Not scored by this record.

Unknown

menu-pricing-recipe-linkage differentiator

Not scored by this record.

Unknown

menu-pricing-3p-menu-push

Not scored by this record.

Unknown

menu-pricing-dynamic-pricing

Not scored by this record.

Payments & money movement

Unknown

payments-processor-choice differentiator

Not scored by this record.

Unknown

payments-published-rates differentiator

Not scored by this record.

Unknown

payments-dual-pricing differentiator

Not scored by this record.

Unknown

payments-surcharge-guardrails differentiator

Not scored by this record.

No

payments-emv-nfc

Open-source software project with no first-party payment terminal line; nothing to certify for EMV or NFC. https://github.com/nutrixpos/pos · retrieved 2026-08-01

E
Unknown

payments-softpos-tap-to-pay differentiator

Not scored by this record.

Unknown

payments-pay-at-table

Not scored by this record.

Unknown

payments-qr-guest-pay differentiator

Not scored by this record.

Unknown

payments-tip-adjust

Not scored by this record.

Unknown

payments-tip-pooling differentiator

Not scored by this record.

Unknown

payments-offline-store-and-forward differentiator

Not scored by this record.

Unknown

payments-offline-decline-liability differentiator

Not scored by this record.

No

payments-gift-cards

Tender handling is the PaymentSource struct — a list of {name} labels configured in Settings and stamped onto Order.PaymentSource as a free string. There is no card, balance, ledger or redemption entity in the model package and no gift-card resource in the complete OpenAPI path list, so nothing tracks a balance. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/settings.go · retrieved 2026-08-03

A
Unknown

payments-house-accounts

Not scored by this record.

Unknown

payments-split-tender

Not scored by this record.

Partial

payments-refund-void-controls

Refund and waste are role-gated — POST /orders/{order_id}/items/{item_id}/refund and .../waste are wrapped in AllowAnyOfRoles("admin","cashier") — a reason query parameter is mandatory (400 without it), and each writes a LogOrderItemRefund / LogWasteOrderItem row. Shortfall: a cashier refunds unilaterally, since no manager-approval or override endpoint exists in the route table; Order.Discount is an unauthorised free field set at submit time; and the audit row is not attributable by default, because every handler initialises user_id := "0" and overwrites it only when config.Zitadel.Enabled, which is off in the shipped config. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/handlers/order.go · retrieved 2026-08-03

A
Unknown

payments-chargeback-tooling differentiator

Not scored by this record.

Unknown

payments-card-on-file differentiator

Not scored by this record.

Unknown

payments-payout-timing differentiator

Not scored by this record.

Unknown

payments-p2pe-pci4

Not scored by this record.

Kitchen & production

No

kitchen-station-routing

There is no station entity anywhere in the product: a repo-wide, case-insensitive search for "station" across the Go backend, the OpenAPI spec and the Vue frontend returns zero hits. Kitchen.vue is the whole KDS — it GETs /api/orders?filter[state]=!finished&filter[state]=!stashed, i.e. every open order with no item, category, order-type or station filter, and displayOrders() merely deals them round-robin into screen-width columns. Settings enumerates exactly two printers, ClientReceiptPrinter and KitchenReceiptPrinter, each a PrinterSettings{Host} with one host, so there is no second kitchen target to route to either. The vendor's own docs landing page describes Kitchen as "On demand simple interface for displaying and finishing orders, to be used inside the kitchen". https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/src/pages/Kitchen.vue · retrieved 2026-08-04

A
No

kitchen-expo-consolidation

There is no prep-station entity. Settings holds exactly one KitchenReceiptPrinter{Host}, and the Kitchen page renders whole orders as QueueOrder cards in wrap columns with a single order-level finish action (POST /orders/{id}/finish). With no stations to route to, there is nothing for an expo view to consolidate and no per-station bump state to wait on. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/settings.go · retrieved 2026-08-03

A
Unknown

kitchen-course-firing differentiator

Not scored by this record.

Unknown

kitchen-prep-time-pacing differentiator

Not scored by this record.

Unknown

kitchen-order-throttling differentiator

Not scored by this record.

Unknown

kitchen-channel-pause-propagation differentiator

Not scored by this record.

Unknown

kitchen-order-ready-callback differentiator

Not scored by this record.

No

kitchen-bump-bar-hardware

The KDS is a Vue browser route driven entirely by PrimeVue buttons and dialogs (click/touch). There is no keyboard, HID, serial or bump-bar handling anywhere in the frontend, no key-mapping configuration in Settings, and the vendor publishes no supported-hardware list — nutrixpos.com carries only Installation, Architecture and docker-compose pages. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/src/pages/Kitchen.vue · retrieved 2026-08-03

A
Unknown

kitchen-all-day-counts

Not scored by this record.

Unknown

kitchen-sla-alerts

Not scored by this record.

Unknown

kitchen-printer-fallback differentiator

Not scored by this record.

Unknown

kitchen-offline-operation differentiator

Not scored by this record.

Unknown

kitchen-item-build-screens differentiator

Not scored by this record.

Unknown

kitchen-pizza-fractional-display differentiator

Not scored by this record.

Unknown

kitchen-recall-refire

Not scored by this record.

Unknown

kitchen-order-modification-alerts differentiator

Not scored by this record.

Unknown

kitchen-guest-ready-notification differentiator

Not scored by this record.

Unknown

kitchen-waste-logging

Not scored by this record.

Unknown

kitchen-speed-of-service-reporting

Not scored by this record.

Unknown

kitchen-prep-forecasting

Not scored by this record.

Delivery, dispatch & third-party channels

No

delivery-driver-roster

Delivery carries no driver at all: OrderDeliveryInfo is {ReceiverName, Address, PhoneNumber}, stamped onto the order for receipt printing, and Order has no driver, assignment-state or run field. A repo-wide case-insensitive search for "driver" matches only the mongo-driver library import, the only staff roles compiled into the route table are superuser, admin, cashier and chef, and no clock-in/out or time-entry construct exists anywhere in the codebase for a driver to use, so drivers are not an entity of any kind, let alone a first-class one with run history. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-04

A
No

delivery-dispatch-board

Delivery is an IsDelivery bool plus OrderDeliveryInfo{ReceiverName, Address, PhoneNumber} printed onto the receipt. There is no driver entity, no assignment field, no elapsed-time or run/batch construct, and the frontend router’s complete page list (Home, Kitchen, Admin > inventory/sales/products/categories/orders/settings/customers/users, Hubsync, Login, Setup, Profile, Languages) contains no dispatch screen. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

delivery-route-map differentiator

Not scored by this record.

Unknown

delivery-driver-tracking differentiator

Not scored by this record.

Unknown

delivery-zones-polygon differentiator

Not scored by this record.

No

delivery-zone-pricing

No zone entity exists in the model package or the OpenAPI schema list. Delivery addresses are a free-text Address string with no validation or geocoding, and neither Order nor Settings carries a delivery fee, order minimum or quoted promise-time field, so nothing can be applied per zone. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

delivery-address-validation

Not scored by this record.

Unknown

delivery-driver-comp differentiator

Not scored by this record.

Unknown

delivery-cash-reconcile

Not scored by this record.

Unknown

delivery-daas-dispatch

Not scored by this record.

Unknown

delivery-daas-fallback differentiator

Not scored by this record.

Unknown

delivery-3p-direct-integration differentiator

Not scored by this record.

Unknown

delivery-3p-injection

Not scored by this record.

Unknown

delivery-menu-push

Not scored by this record.

Unknown

delivery-86-sync

Not scored by this record.

Unknown

delivery-store-pause

Not scored by this record.

Unknown

delivery-3p-reconciliation differentiator

Not scored by this record.

Unknown

delivery-injection-error-visibility differentiator

Not scored by this record.

Unknown

delivery-tracking-page

Not scored by this record.

Unknown

delivery-promise-time differentiator

Not scored by this record.

Unknown

delivery-offline-behavior

Not scored by this record.

Digital ordering & guest-facing channels

No

digital-first-party-web

No guest-facing ordering site ships: every route in the frontend router is staff-facing and role-guarded (/, /kitchen, /admin/*, /login, /setup, /admin-setup, /profile, /no-access), and order creation is POST /api/orders wrapped in AllowAnyOfRoles("admin","cashier"), so an unauthenticated web guest has no path that writes an order. The nutrixpos GitHub organisation holds only pos, posui (archived), docs and devops — no ordering-site product — and nutrixpos.com's feature list is Cashier, Kitchen, Inventory and Reports with no online-ordering mention. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/src/router/index.ts · retrieved 2026-08-04

A
No

digital-menu-single-source

There is no first-party digital ordering channel for a menu to propagate to. Every route in the router is staff-facing and role-guarded (/, /kitchen, /admin/*, /login, /setup, /admin-setup, /profile, /no-access), and the nutrixpos GitHub organisation contains only four repositories — pos, posui (archived 2025-08-08), docs and devops — with no guest ordering client among them. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/src/router/index.ts · retrieved 2026-08-03

A
Unknown

digital-native-app differentiator

Not scored by this record.

No

digital-account-saved-payment

The Customer struct is {Id, Name, Phone, Address} — no credentials, no email, no address book, no tokenised payment instrument and no order-history link. There is no guest authentication path (the auth module issues staff JWTs with superuser/admin/cashier/chef roles) and no guest-facing channel in which to reorder. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

digital-upsell-engine differentiator

Not scored by this record.

Unknown

digital-scheduled-pacing

Not scored by this record.

Unknown

digital-fulfillment-modes

Not scored by this record.

Unknown

digital-qr-table

Not scored by this record.

Unknown

digital-kiosk differentiator

Not scored by this record.

Unknown

digital-group-ordering

Not scored by this record.

Unknown

digital-catering-portal differentiator

Not scored by this record.

Unknown

digital-voice-ai-phone differentiator

Not scored by this record.

Unknown

digital-drivethru-ai

Not scored by this record.

Unknown

digital-sms-ordering

Not scored by this record.

Unknown

digital-google-order differentiator

Not scored by this record.

Unknown

digital-apple-business-connect

Not scored by this record.

Unknown

digital-loyalty-attach

Not scored by this record.

Unknown

digital-subscriptions

Not scored by this record.

Unknown

digital-promo-parity

Not scored by this record.

Unknown

digital-guest-data-ownership differentiator

Not scored by this record.

Unknown

digital-checkout-pci-sca

Not scored by this record.

Unknown

digital-surcharge-transparency differentiator

Not scored by this record.

Guest data, loyalty & marketing

No

guest-loyalty-unified-profile

Customer is {Id, Name, Phone, Address} and is embedded into Order by value; there is no identity-match, dedup or merge logic in customers.go, no email field to match on, and no loyalty entity. There is also nothing to unify: the product ships no first-party web/app ordering and no kiosk channel, so all transactions originate from the in-store terminal. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

guest-loyalty-thirdparty-identity-attach differentiator

Not scored by this record.

No

guest-loyalty-accrual-models

None of the three accrual models exists, natively or otherwise: a repo-wide search returns zero occurrences of "loyalty", "reward", "points" or "punch"; Customer is {Id, Name, Phone, Address} with no balance, visit counter or tier field; and the complete OpenAPI path list (categories, materials, orders, products, salesperday, settings, languages, customers) has no loyalty resource. Settings holds printers, order-queue counters and payment-source labels — there is nothing in which an accrual rule could be configured. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/specs.api.yaml · retrieved 2026-08-04

A
Unknown

guest-loyalty-tiers differentiator

Not scored by this record.

Unknown

guest-loyalty-offline-behavior differentiator

Not scored by this record.

Unknown

guest-loyalty-offer-stacking-rules differentiator

Not scored by this record.

Unknown

guest-loyalty-targeted-offers differentiator

Not scored by this record.

Unknown

guest-loyalty-rfm-segmentation differentiator

Not scored by this record.

No

guest-loyalty-lifecycle-automation

The complete OpenAPI path list is categories, materials, orders, products, salesperday, settings, languages and customers — there is no campaign, segment, message, offer or automation resource. Repo-wide search returns zero occurrences of "loyalty" or "reward", and the only outbound messaging in the codebase is the in-app WebSocket topic feed. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/specs.api.yaml · retrieved 2026-08-03

A
Unknown

guest-loyalty-native-email-sms differentiator

Not scored by this record.

Unknown

guest-loyalty-consent-management

Not scored by this record.

Unknown

guest-loyalty-10dlc-registration

Not scored by this record.

Unknown

guest-loyalty-campaign-attribution differentiator

Not scored by this record.

Unknown

guest-loyalty-data-export-portability differentiator

Not scored by this record.

Unknown

guest-loyalty-review-capture-routing differentiator

Not scored by this record.

Unknown

guest-loyalty-referral-program

Not scored by this record.

Unknown

guest-loyalty-wallet-pass differentiator

Not scored by this record.

Unknown

guest-loyalty-privacy-rights-tooling

Not scored by this record.

Unknown

guest-loyalty-redemption-fraud-controls

Not scored by this record.

Unknown

guest-loyalty-ai-offer-recommendation differentiator

Not scored by this record.

Unknown

guest-loyalty-stored-value-gift

Not scored by this record.

Labor & workforce

No

labor-clock-in-at-pos

No time clock exists to clock into: the auth module's User model is {ID, Username, Email, PasswordHash, Roles, CreatedAt, UpdatedAt} — no PIN or badge field — and sign-on is a username/password JWT login (LoginRequest{Username, Password}). A repo-wide search for clock, punch, shift, timesheet or time-entry code returns nothing beyond two "pi pi-clock" icon classes, and the complete OpenAPI path list has no time-entry or shift resource, so worked hours cannot be recorded at the terminal at all. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/auth/models/user.go · retrieved 2026-08-04

A
Unknown

labor-photo-punch-verification differentiator

Not scored by this record.

Unknown

labor-offline-time-punch differentiator

Not scored by this record.

No

labor-granular-rbac

Permissions are compiled into the route table, not granted by the operator: every route is wrapped in auth_svc.AllowAnyOfRoles(handler, ...) against four hardcoded tiers — "superuser", "admin", "cashier", "chef" (refund is ("admin","cashier"); user management is ("superuser")). Roles is a free string list on User, but a new role name matches no route and therefore grants nothing. There is no per-action grant, no permission entity, and no location dimension. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/core.go · retrieved 2026-08-03

A
No

labor-manager-override-audit

No manager-override or approval mechanism exists: the complete route table has no approve, override or authorise endpoint, and refunds, wastes, cancels and discounts are executed directly by the acting cashier role. The Log struct does carry a UserId, but every handler initialises user_id := "0" and replaces it only inside if config.Zitadel.Enabled, so under the shipped internal-JWT auth every refund, waste and disposal row is attributed to user_id "0". https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/handlers/order.go · retrieved 2026-08-03

A
Unknown

labor-native-scheduling differentiator

Not scored by this record.

Unknown

labor-demand-labor-forecast differentiator

Not scored by this record.

Unknown

labor-realtime-labor-percent differentiator

Not scored by this record.

Unknown

labor-overtime-prevention differentiator

Not scored by this record.

Unknown

labor-break-compliance-by-state differentiator

Not scored by this record.

Unknown

labor-minor-labor-rules

Not scored by this record.

Unknown

labor-tip-pooling-rules

Not scored by this record.

Unknown

labor-tip-distribution-audit-trail

Not scored by this record.

Unknown

labor-qualified-tips-w2-reporting differentiator

Not scored by this record.

Unknown

labor-native-payroll differentiator

Not scored by this record.

Unknown

labor-payroll-export-formats

Not scored by this record.

Unknown

labor-shift-swap-workflow differentiator

Not scored by this record.

Unknown

labor-server-performance-metrics differentiator

Not scored by this record.

Inventory, purchasing & cost control

Unknown

inventory-recipe-bom-costing

README states it manages inventory, sales and products for a restaurant, but multi-level sub-recipe costing is not documented.

F
No

inventory-unit-conversion-yields

Material carries a single Unit string, and MaterialEntry records PurchaseQuantity and PurchasePrice in that same unit; average cost is computed as sum(PurchasePrice/PurchaseQuantity)/n. There is no purchase/recipe/count unit triple, no conversion-factor field, and no yield or waste-percentage field on Material, MaterialEntry or Product. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

inventory-theoretical-vs-actual differentiator

Not scored by this record.

Unknown

inventory-realtime-depletion differentiator

Not scored by this record.

Unknown

inventory-86-auto-sync differentiator

Not scored by this record.

No

inventory-count-modes

The complete material path list is /materials, /materials/{id}, /materials/{id}/entries, /materials/{material_id}/entries/{entry_id}, .../cost and /materials/{id}/logs — there is no count, stocktake or adjustment resource. On-hand is derived by summing entry quantities less consumption; corrections are made by adding an entry or a disposal. Nothing records a count event, so there is no per-count variance history to keep separate. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/specs.api.yaml · retrieved 2026-08-03

A
Unknown

inventory-mobile-count-offline

Not scored by this record.

Unknown

inventory-vendor-catalogs-edi differentiator

Not scored by this record.

Unknown

inventory-invoice-ocr differentiator

Not scored by this record.

Unknown

inventory-price-change-alerts differentiator

Not scored by this record.

Unknown

inventory-par-auto-suggest differentiator

Not scored by this record.

Unknown

inventory-waste-logging

Not scored by this record.

Unknown

inventory-shelf-life-expiry

Not scored by this record.

Unknown

inventory-bar-partial-bottle

Not scored by this record.

Unknown

inventory-cogs-gl-export

Not scored by this record.

Unknown

inventory-native-not-partner differentiator

Not scored by this record.

Unknown

inventory-menu-margin-linkage differentiator

Not scored by this record.

Reporting, BI & data access

Partial

reporting-realtime-dashboard

A browser dashboard exists and is current: Sales.vue renders a sales/cost/refunds/returns/profit line chart, a product-mix pie chart and a paginated sales log with CSV export, fed by GET /api/logs/salesperday, which queries the MongoDB "sales" collection at request time; FinishOrder calls SalesService.AddOrderToSalesDay, which upserts today's document on order completion, so a finished sale is readable immediately. Three shortfalls: there is no mobile app — frontend/package.json declares no Capacitor, Cordova, React Native or PWA plugin and the org's only repos are pos, posui (archived), docs and devops; the dashboard never auto-refreshes, since loadSales() runs once at mount and Sales.vue opens no WebSocket, so it updates only on manual reload or repaging; and the sales collection is keyed on date formatted "2006-01-02", so the charts have whole-day granularity with no intraday view. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/src/pages/Sales.vue · retrieved 2026-08-04

A
Partial

reporting-eod-closeout

GET /logs/salesperday returns a SalesPerDay row per day — date, orders, refunds, costs, total_sales, refunds_value — and GET /logs/salesperday/exportcsv emits Id, Display Id, Date, Cost, Sale Price, Payment Source, Refunds Value, Profit. Shortfall: it is a sales-and-margin day list, not a close-out packet. There is no tax field anywhere in the codebase (repo-wide search for tax/VAT returns nothing), no tips or discount totals in the day aggregate, no tender-type subtotals, and no expected-cash-deposit or drawer reconciliation — the only drawer feature is an auto_open_cash_drawer toggle. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/handlers/sales.go · retrieved 2026-08-03

A
Partial

reporting-pmix-modifier-level

The Sales page builds a product mix pie chart by walking loaded orders and summing order.items[k].quantity keyed on product.name. Shortfall: it is client-side aggregation over the currently loaded page of days only, carries quantity but no gross or net sales column, has no modifier level (no modifier entity exists in the product model), and offers no daypart or revenue-centre filter — the only server-side grouping is by calendar day. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/src/pages/Sales.vue · retrieved 2026-08-03

A
Unknown

reporting-comps-voids-audit

Not scored by this record.

Unknown

reporting-cash-over-short

Not scored by this record.

Unknown

reporting-labor-productivity

Not scored by this record.

Unknown

reporting-server-scorecards differentiator

Not scored by this record.

Unknown

reporting-channel-profitability differentiator

Not scored by this record.

Unknown

reporting-scheduled-delivery

Not scored by this record.

Unknown

reporting-public-api differentiator

Not scored by this record.

Unknown

reporting-webhooks differentiator

Not scored by this record.

Unknown

reporting-api-not-upcharged differentiator

Not scored by this record.

Unknown

reporting-tier-paywall differentiator

Not scored by this record.

Unknown

reporting-history-retention differentiator

Not scored by this record.

Unknown

reporting-anomaly-alerts differentiator

Not scored by this record.

Unknown

reporting-nl-query

Not scored by this record.

Unknown

reporting-guest-cohorts differentiator

Not scored by this record.

Unknown

reporting-sales-forecast differentiator

Not scored by this record.

Unknown

reporting-tip-tax-compliance

Not scored by this record.

Multi-location, franchise & enterprise governance

Unknown

multi-location-org-hierarchy

Checked the full Go model package, the complete OpenAPI path list and the frontend router: there is no location, branch, site, tenant or group entity, Settings is a single global document, and no report or permission is scoped to a location. The only above-store construct is the hubsync module, which pushes this instance’s materials and sales to a hub host using one bearer token and no hierarchy object. Whether the receiving hub models an enterprise > region > location hierarchy could not be determined: hub.nutrixpos.com returns an unrendered Vite/Vue SPA shell with no readable text, the nutrixpos GitHub organisation contains no hub repository (only pos, posui, docs, devops), and nutrixpos.com publishes only Installation, Architecture and docker-compose pages, none of which mention multiple locations.

F
No

multi-location-central-menu-publish

Hubsync is outbound only: SyncInventory issues PUT {host}/v1/api/inventories and UploadSalesToServer issues POST {host}/v1/api/logs on a timer. The module registers exactly two HTTP routes of its own, both /api/settings, so an instance exposes no inbound path on which a corporate menu could be received, and the core API has no bulk product-import or publish endpoint. There is consequently no publish/version history. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/hubsync/services/syncer.go · retrieved 2026-08-03

A
No

multi-location-price-zones

Product carries one Price float64 with no channel, daypart, location-group or price-tier dimension, and no separate price-list entity exists in the model package or the OpenAPI schema list. Order records IsDelivery/IsTakeAway/IsDineIn but no revenue centre, and nothing in the pricing path reads those flags — the receipt totals from item.SalePrice alone. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/models/models.go · retrieved 2026-08-03

A
Unknown

multi-location-consolidated-reporting

Not scored by this record.

Unknown

multi-location-cross-location-giftcard

Not scored by this record.

Unknown

multi-location-cross-location-loyalty

Not scored by this record.

Unknown

multi-location-multi-brand differentiator

Not scored by this record.

Unknown

multi-location-multi-tax-jurisdiction

Not scored by this record.

Unknown

multi-location-central-labor-policy

Not scored by this record.

Hardware & physical footprint

Unknown

hardware-commodity-devices differentiator

Not scored by this record.

Partial

hardware-os-platforms

Install guide documents a Windows executable and Docker Compose deployment with MongoDB; no minimum OS versions or client device specs. https://nutrixpos.com/userguide/installation.html · retrieved 2026-08-01

B
Unknown

hardware-handheld-purpose-built

Not scored by this record.

Unknown

hardware-handheld-battery-swap differentiator

Not scored by this record.

Unknown

hardware-handheld-lte

Not scored by this record.

Partial

hardware-offline-mode

The product is on-premise self-hosted (a Go binary or docker-compose against a local MongoDB), so a WAN outage does not by itself stop the terminal, the kitchen printer or cash sales — the whole stack is on the LAN. Shortfall: there is no client-side resilience and no published degradation matrix. The frontend declares no PWA, service-worker, Workbox or IndexedDB dependency and has no offline code path (localStorage is used only for the auth token and colour mode), so a server or LAN interruption stops order entry outright, and nutrixpos.com documents nothing about offline behaviour on any of its three pages. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/package.json · retrieved 2026-08-03

A
Partial

hardware-kds

A first-party, touch-operated KDS screen exists: Kitchen.vue is a Vue browser route that subscribes to the WebSocket feed (reacting to order_submitted and order_finished), loads every open order via /api/orders?filter[state]=!finished&filter[state]=!stashed into QueueOrder cards, and finishes an order with an on-screen confirm button that POSTs /orders/{id}/finish. Shortfall: display-and-finish is the entire feature — no station routing (no station entity anywhere in the repo), no course or fire timing (no course, fire or hold construct; Order carries only IsAutoStart/IsAutoFinish), no bump-bar support (PrimeVue click/touch only, no keyboard or HID handling), and no dedicated hardware — it runs on whatever browser device the operator supplies. The vendor's own docs describe it as an "on demand simple interface for displaying and finishing orders". https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/src/pages/Kitchen.vue · retrieved 2026-08-04

A
Unknown

hardware-kiosk differentiator

Not scored by this record.

Unknown

hardware-drive-thru

Not scored by this record.

Unknown

hardware-printer-compatibility

Not scored by this record.

Unknown

hardware-peripherals

Not scored by this record.

Unknown

hardware-p2pe-terminal

Not scored by this record.

Unknown

hardware-tap-to-phone differentiator

Not scored by this record.

Unknown

hardware-pricing-transparency differentiator

Not scored by this record.

Unknown

hardware-ownership-vs-lease differentiator

Not scored by this record.

Unknown

hardware-usable-after-churn differentiator

Not scored by this record.

Unknown

hardware-rma-sla differentiator

Not scored by this record.

Unknown

hardware-byod

Not scored by this record.

Unknown

hardware-remote-device-management differentiator

Not scored by this record.

Unknown

hardware-selfpour-scales

Not scored by this record.

Unknown

hardware-callerid-integration

Not scored by this record.

Integrations, API & extensibility

Partial

extensibility-public-api-docs

Publicly readable docs site and pkg.go.dev Go reference with an advertised REST API architecture; a complete endpoint reference was not verifiable. https://github.com/nutrixpos/pos · retrieved 2026-08-01

B
Unknown

extensibility-api-access-cost differentiator

Not scored by this record.

Unknown

extensibility-free-sandbox differentiator

Not scored by this record.

Partial

extensibility-oauth-partner-apps

The OpenAPI securitySchemes block declares oidcAuth as type oauth2 with an authorizationCode flow and scopes admin, cashier and chef, implemented by the optional Zitadel integration (ZitadelAuth introspects the bearer token via CheckAuthorization). Shortfall: those "scopes" are the same coarse staff role tiers, not per-resource operator-granted permissions; there is no partner-app registry, consent screen or per-integration revocation surface anywhere in the product; and the integration is off by default (config.Zitadel.Enabled), the shipped path being a self-issued internal JWT carrying role claims rather than OAuth at all. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/specs.api.yaml · retrieved 2026-08-03

A
Partial

extensibility-webhooks-push

Real-time push exists but is not webhooks. A Melody WebSocket endpoint at /ws lets a client subscribe to topics, and the server pushes on exactly three: order_submitted, order_finished and expire_soon (low stock). Shortfall: there is no HTTP callback registration, no subscriber endpoint, no delivery retry, no signing secret and no replay; the feed is designed for and consumed by the bundled Vue client, and it omits modified, paid, voided and refunded order events entirely. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/services/notification_singleton.go · retrieved 2026-08-03

A
Unknown

extensibility-webhook-reliability differentiator

Not scored by this record.

Unknown

extensibility-order-injection-api

Not scored by this record.

Unknown

extensibility-menu-write-api differentiator

Not scored by this record.

Unknown

extensibility-doordash-preferred differentiator

Not scored by this record.

Unknown

extensibility-first-party-delivery-integrations differentiator

Not scored by this record.

Unknown

extensibility-middleware-compatibility

Not scored by this record.

Unknown

extensibility-accounting-connectors

Not scored by this record.

Unknown

extensibility-payroll-export

Not scored by this record.

Unknown

extensibility-app-marketplace

Not scored by this record.

Unknown

extensibility-headless-embedded

Not scored by this record.

Unknown

extensibility-data-portability-exit differentiator

Not scored by this record.

Reliability, offline & operations

Partial

reliability-offline-order-entry

Because the server is on-premise, order entry, kitchen ticket printing and check printing all continue through an internet outage — they never leave the LAN. Shortfall: nothing continues on-terminal if the terminal loses the server. The frontend declares no service worker, PWA plugin or IndexedDB dependency and implements no local queue; even the "stashed"/draft order feature is server-side (a state field POSTed to /api/orders), and every action in Home.vue is a synchronous axios call that surfaces an error toast on failure. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/frontend/package.json · retrieved 2026-08-03

A
Unknown

reliability-offline-card-auth differentiator

Not scored by this record.

Unknown

reliability-offline-decline-liability differentiator

Not scored by this record.

Unknown

reliability-lan-degraded-multi-terminal differentiator

Not scored by this record.

Unknown

reliability-local-transaction-engine differentiator

Not scored by this record.

Partial

reliability-offline-kds-printing

Both paths are server-side and LAN-local, so they survive an internet outage: ReceiptService.Print dials the configured printer host directly on TCP 9100 and writes ESC/POS, and the KDS receives orders over the local WebSocket feed. Shortfall: neither survives loss of the server or the LAN, since the KDS is a browser page with no cached order store and the print job is initiated by the backend, and the vendor documents no offline behaviour for either. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/services/receipt.go · retrieved 2026-08-03

A
No

reliability-printer-fallback

ReceiptService.Print opens net.Dial("tcp", host+":9100") and, on failure, returns the dial error straight to the caller — there is no retry, no alternate target and no notification emitted. Settings holds exactly one ClientReceiptPrinter{Host} and one KitchenReceiptPrinter{Host}, so no backup printer or KDS station is configurable to fail over to. https://github.com/nutrixpos/pos/blob/69f435a0ba512c9fd5816f086928d185fde5e2c8/modules/core/services/receipt.go · retrieved 2026-08-03

A
Unknown

reliability-sync-conflict-handling

Not scored by this record.

Unknown

reliability-offline-feature-matrix

Not scored by this record.

Unknown

reliability-public-status-page

Not scored by this record.

Unknown

reliability-247-live-support

Not scored by this record.

Unknown

reliability-onsite-install differentiator

Not scored by this record.

Unknown

reliability-menu-build-service differentiator

Not scored by this record.

Unknown

reliability-hardware-replacement-sla

Not scored by this record.

Unknown

reliability-pci-dss-4-attestation

Not scored by this record.

Unknown

reliability-mfa-role-based-access

Not scored by this record.

Unknown

reliability-self-serve-training

Not scored by this record.

Unknown

reliability-failover-terminal-role differentiator

Not scored by this record.

Unknown

reliability-cellular-backup

Not scored by this record.

Commercial, compliance & data ownership

Unknown

commercial-month-to-month-contract differentiator

Not scored by this record.

Unknown

commercial-no-early-termination-fee differentiator

Not scored by this record.

Unknown

commercial-autorenew-terms-published

GPL-2.0 software with no subscription offering, so no auto-renewal term or cancellation window exists.

F
Unknown

commercial-processing-not-bundled differentiator

Not scored by this record.

Unknown

commercial-interchange-plus-published differentiator

Not scored by this record.

Unknown

commercial-rate-increase-clause differentiator

Not scored by this record.

Yes

commercial-pricing-published

Unambiguously free: GPL-2.0 licensed, self-hosted, with no commercial tier or hosted plan published. https://github.com/nutrixpos/pos · retrieved 2026-08-01

B
Unknown

commercial-module-unbundling differentiator

Not scored by this record.

Partial

commercial-hardware-purchase-outright

No first-party hardware sold, so no mandatory lease; operators supply their own devices and printers. https://github.com/nutrixpos/pos · retrieved 2026-08-01

E
Unknown

commercial-hardware-not-locked differentiator

Not scored by this record.

Unknown

commercial-data-export-self-serve

Not scored by this record.

Unknown

commercial-export-customer-and-loyalty differentiator

Not scored by this record.

Unknown

commercial-post-termination-export-window differentiator

Not scored by this record.

Unknown

commercial-data-ownership-clause differentiator

Not scored by this record.

Unknown

commercial-pci-p2pe-tokenization

Not scored by this record.

Unknown

commercial-pci-dss-4-controls

Not scored by this record.

Unknown

commercial-privacy-dsar-tooling

Not scored by this record.

Unknown

commercial-wcag-kiosk-accessibility differentiator

Not scored by this record.

Unknown

commercial-dual-pricing-compliant differentiator

Not scored by this record.

Adversarial verification

An independent pass was instructed to refute this record, defaulting to downgrade when uncertain. It challenged 36 values — 0 upheld, 0 downgraded, 0 upgraded. This is published in full because a reader who can see which values were contested, on what evidence, and which way they moved has something no affiliate-funded comparison offers.

Capability claims

ClaimAs first scoredVerdictWhat the verifier found
order-capture-split-mergeunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThe complete OpenAPI path list contains no split, merge or partial-tender resource. POST /orders/{id}/pay declares no request body, and its handler calls PayUnpaidOrder(order_id), which marks the whole order paid. The Order model carries a single IsPaid bool and one PaymentSource string, with no parent/child order reference, seat number or table field. source
order-capture-scheduled-ordersunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noOrder carries SubmittedAt, StartedAt, IsAutoStart and IsAutoFinish and no scheduled-for, promise-time or fire-time field; a repo-wide search for "scheduled" returns nothing. OrderSettings holds only queue prefix/next counters and a default cost-calculation method, so there is no per-channel lead time to compute a fire time from. source
menu-pricing-nested-modifiersunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThe Product struct is {Materials, SubProducts, Entries, Price, ImageURL, Unit, Quantity, Ready, EnableInventoryConsumption, EnableFixedCost, FixedCost} — there is no modifier-group entity. SubProducts are sub-recipes with a quantity, consumed by GetRecipeTree for BOM costing, not guest-selectable option groups. Repo-wide search finds no min/max selection count, no required/forced flag and no occurrence of "modifier", "option group", "addon" or "topping". source
menu-pricing-modifier-price-by-parent-sizeunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noNo modifier entity exists to price, and no size or variant entity exists to price it against: Product carries exactly one Price float64 and one Unit string. There is no price matrix, override table or parent-item-scoped price anywhere in the model package or the OpenAPI Product schema. source
menu-pricing-topping-quantity-tiersunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noOrderItem carries a bare Quantity float64 with no tier, level or multiplier field, and no modifier entity exists to tier. Repo-wide search finds no "light", "extra", "double" or price-multiplier construct in either the Go models or the Vue ordering page. source
payments-gift-cardsunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noTender handling is the PaymentSource struct — a list of {name} labels configured in Settings and stamped onto Order.PaymentSource as a free string. There is no card, balance, ledger or redemption entity in the model package and no gift-card resource in the complete OpenAPI path list, so nothing tracks a balance. source
payments-refund-void-controlsunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialRefund and waste are role-gated — POST /orders/{order_id}/items/{item_id}/refund and .../waste are wrapped in AllowAnyOfRoles("admin","cashier") — a reason query parameter is mandatory (400 without it), and each writes a LogOrderItemRefund / LogWasteOrderItem row. Shortfall: a cashier refunds unilaterally, since no manager-approval or override endpoint exists in the route table; Order.Discount is an unauthorised free field set at submit time; and the audit row is not attributable by default, because every handler initialises user_id := "0" and overwrites it only when config.Zitadel.Enabled, which is off in the shipped config. source
kitchen-expo-consolidationunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThere is no prep-station entity. Settings holds exactly one KitchenReceiptPrinter{Host}, and the Kitchen page renders whole orders as QueueOrder cards in wrap columns with a single order-level finish action (POST /orders/{id}/finish). With no stations to route to, there is nothing for an expo view to consolidate and no per-station bump state to wait on. source
kitchen-bump-bar-hardwareunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThe KDS is a Vue browser route driven entirely by PrimeVue buttons and dialogs (click/touch). There is no keyboard, HID, serial or bump-bar handling anywhere in the frontend, no key-mapping configuration in Settings, and the vendor publishes no supported-hardware list — nutrixpos.com carries only Installation, Architecture and docker-compose pages. source
delivery-dispatch-boardunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noDelivery is an IsDelivery bool plus OrderDeliveryInfo{ReceiverName, Address, PhoneNumber} printed onto the receipt. There is no driver entity, no assignment field, no elapsed-time or run/batch construct, and the frontend router’s complete page list (Home, Kitchen, Admin > inventory/sales/products/categories/orders/settings/customers/users, Hubsync, Login, Setup, Profile, Languages) contains no dispatch screen. source
delivery-zone-pricingunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noNo zone entity exists in the model package or the OpenAPI schema list. Delivery addresses are a free-text Address string with no validation or geocoding, and neither Order nor Settings carries a delivery fee, order minimum or quoted promise-time field, so nothing can be applied per zone. source
digital-menu-single-sourceunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThere is no first-party digital ordering channel for a menu to propagate to. Every route in the router is staff-facing and role-guarded (/, /kitchen, /admin/*, /login, /setup, /admin-setup, /profile, /no-access), and the nutrixpos GitHub organisation contains only four repositories — pos, posui (archived 2025-08-08), docs and devops — with no guest ordering client among them. source
digital-account-saved-paymentunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThe Customer struct is {Id, Name, Phone, Address} — no credentials, no email, no address book, no tokenised payment instrument and no order-history link. There is no guest authentication path (the auth module issues staff JWTs with superuser/admin/cashier/chef roles) and no guest-facing channel in which to reorder. source
guest-loyalty-unified-profileunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noCustomer is {Id, Name, Phone, Address} and is embedded into Order by value; there is no identity-match, dedup or merge logic in customers.go, no email field to match on, and no loyalty entity. There is also nothing to unify: the product ships no first-party web/app ordering and no kiosk channel, so all transactions originate from the in-store terminal. source
guest-loyalty-lifecycle-automationunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThe complete OpenAPI path list is categories, materials, orders, products, salesperday, settings, languages and customers — there is no campaign, segment, message, offer or automation resource. Repo-wide search returns zero occurrences of "loyalty" or "reward", and the only outbound messaging in the codebase is the in-app WebSocket topic feed. source
labor-granular-rbacunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noPermissions are compiled into the route table, not granted by the operator: every route is wrapped in auth_svc.AllowAnyOfRoles(handler, ...) against four hardcoded tiers — "superuser", "admin", "cashier", "chef" (refund is ("admin","cashier"); user management is ("superuser")). Roles is a free string list on User, but a new role name matches no route and therefore grants nothing. There is no per-action grant, no permission entity, and no location dimension. source
labor-manager-override-auditunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noNo manager-override or approval mechanism exists: the complete route table has no approve, override or authorise endpoint, and refunds, wastes, cancels and discounts are executed directly by the acting cashier role. The Log struct does carry a UserId, but every handler initialises user_id := "0" and replaces it only inside if config.Zitadel.Enabled, so under the shipped internal-JWT auth every refund, waste and disposal row is attributed to user_id "0". source
inventory-unit-conversion-yieldsunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noMaterial carries a single Unit string, and MaterialEntry records PurchaseQuantity and PurchasePrice in that same unit; average cost is computed as sum(PurchasePrice/PurchaseQuantity)/n. There is no purchase/recipe/count unit triple, no conversion-factor field, and no yield or waste-percentage field on Material, MaterialEntry or Product. source
inventory-count-modesunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noThe complete material path list is /materials, /materials/{id}, /materials/{id}/entries, /materials/{material_id}/entries/{entry_id}, .../cost and /materials/{id}/logs — there is no count, stocktake or adjustment resource. On-hand is derived by summing entry quantities less consumption; corrections are made by adding an entry or a disposal. Nothing records a count event, so there is no per-count variance history to keep separate. source
reporting-eod-closeoutunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialGET /logs/salesperday returns a SalesPerDay row per day — date, orders, refunds, costs, total_sales, refunds_value — and GET /logs/salesperday/exportcsv emits Id, Display Id, Date, Cost, Sale Price, Payment Source, Refunds Value, Profit. Shortfall: it is a sales-and-margin day list, not a close-out packet. There is no tax field anywhere in the codebase (repo-wide search for tax/VAT returns nothing), no tips or discount totals in the day aggregate, no tender-type subtotals, and no expected-cash-deposit or drawer reconciliation — the only drawer feature is an auto_open_cash_drawer toggle. source
reporting-pmix-modifier-levelunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialThe Sales page builds a product mix pie chart by walking loaded orders and summing order.items[k].quantity keyed on product.name. Shortfall: it is client-side aggregation over the currently loaded page of days only, carries quantity but no gross or net sales column, has no modifier level (no modifier entity exists in the product model), and offers no daypart or revenue-centre filter — the only server-side grouping is by calendar day. source
multi-location-central-menu-publishunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noHubsync is outbound only: SyncInventory issues PUT {host}/v1/api/inventories and UploadSalesToServer issues POST {host}/v1/api/logs on a timer. The module registers exactly two HTTP routes of its own, both /api/settings, so an instance exposes no inbound path on which a corporate menu could be received, and the core API has no bulk product-import or publish endpoint. There is consequently no publish/version history. source
multi-location-price-zonesunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noProduct carries one Price float64 with no channel, daypart, location-group or price-tier dimension, and no separate price-list entity exists in the model package or the OpenAPI schema list. Order records IsDelivery/IsTakeAway/IsDineIn but no revenue centre, and nothing in the pricing path reads those flags — the receipt totals from item.SalePrice alone. source
hardware-offline-modeunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialThe product is on-premise self-hosted (a Go binary or docker-compose against a local MongoDB), so a WAN outage does not by itself stop the terminal, the kitchen printer or cash sales — the whole stack is on the LAN. Shortfall: there is no client-side resilience and no published degradation matrix. The frontend declares no PWA, service-worker, Workbox or IndexedDB dependency and has no offline code path (localStorage is used only for the auth token and colour mode), so a server or LAN interruption stops order entry outright, and nutrixpos.com documents nothing about offline behaviour on any of its three pages. source
extensibility-oauth-partner-appsunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialThe OpenAPI securitySchemes block declares oidcAuth as type oauth2 with an authorizationCode flow and scopes admin, cashier and chef, implemented by the optional Zitadel integration (ZitadelAuth introspects the bearer token via CheckAuthorization). Shortfall: those "scopes" are the same coarse staff role tiers, not per-resource operator-granted permissions; there is no partner-app registry, consent screen or per-integration revocation surface anywhere in the product; and the integration is off by default (config.Zitadel.Enabled), the shipped path being a self-issued internal JWT carrying role claims rather than OAuth at all. source
extensibility-webhooks-pushunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialReal-time push exists but is not webhooks. A Melody WebSocket endpoint at /ws lets a client subscribe to topics, and the server pushes on exactly three: order_submitted, order_finished and expire_soon (low stock). Shortfall: there is no HTTP callback registration, no subscriber endpoint, no delivery retry, no signing secret and no replay; the feed is designed for and consumed by the bundled Vue client, and it omits modified, paid, voided and refunded order events entirely. source
reliability-offline-order-entryunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialBecause the server is on-premise, order entry, kitchen ticket printing and check printing all continue through an internet outage — they never leave the LAN. Shortfall: nothing continues on-terminal if the terminal loses the server. The frontend declares no service worker, PWA plugin or IndexedDB dependency and implements no local queue; even the "stashed"/draft order feature is server-side (a state field POSTed to /api/orders), and every action in Home.vue is a synchronous axios call that surfaces an error toast on failure. source
reliability-offline-kds-printingunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialBoth paths are server-side and LAN-local, so they survive an internet outage: ReceiptService.Print dials the configured printer host directly on TCP 9100 and writes ESC/POS, and the KDS receives orders over the local WebSocket feed. Shortfall: neither survives loss of the server or the LAN, since the KDS is a browser page with no cached order store and the print job is initiated by the backend, and the vendor documents no offline behaviour for either. source
reliability-printer-fallbackunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noReceiptService.Print opens net.Dial("tcp", host+":9100") and, on failure, returns the dial error straight to the caller — there is no retry, no alternate target and no notification emitted. Settings holds exactly one ClientReceiptPrinter{Host} and one KitchenReceiptPrinter{Host}, so no backup printer or KDS station is configurable to fail over to. source
kitchen-station-routingunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noNo station concept exists in the product. A case-insensitive repo-wide search for "station" across the Go modules, the OpenAPI spec and the Vue frontend returns zero hits. Kitchen.vue is the entire KDS and requests every open order unfiltered (/api/orders?filter[state]=!finished&filter[state]=!stashed), then deals them round-robin into screen-width columns; there is no per-item, per-category or per-order-type destination. Settings enumerates the printers exhaustively as ClientReceiptPrinter and KitchenReceiptPrinter, each PrinterSettings{Host} with a single host, so no second kitchen target exists to route to. source
reporting-realtime-dashboardunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialThe browser half is real and current: Sales.vue draws a sales/cost/refunds/profit line chart, a product-mix pie chart and a paginated sales log with CSV export from GET /api/logs/salesperday, which queries the "sales" collection live, and FinishOrder upserts the day's document via AddOrderToSalesDay the moment an order completes. Shortfalls: no mobile app of any kind (no Capacitor, Cordova, React Native or PWA plugin in frontend/package.json; org repos are only pos, posui archived, docs, devops); the page never auto-refreshes, as loadSales() fires once at mount with no WebSocket subscription; and the sales collection is keyed on a "2006-01-02" date string, giving whole-day granularity only. source
delivery-driver-rosterunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noDelivery carries no driver at all: OrderDeliveryInfo is {ReceiverName, Address, PhoneNumber}, stamped onto the order for receipt printing, and Order has no driver, assignment-state or run field. A repo-wide case-insensitive search for "driver" matches only the mongo-driver library import, the only staff roles compiled into the route table are superuser, admin, cashier and chef, and no clock-in/out or time-entry construct exists anywhere in the codebase for a driver to use. source
digital-first-party-webunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noNo guest-facing ordering site ships: every route in the frontend router is staff-facing and role-guarded (/, /kitchen, /admin/*, /login, /setup, /admin-setup, /profile, /no-access), and order creation is POST /api/orders wrapped in AllowAnyOfRoles("admin","cashier"), so an unauthenticated web guest has no path that writes an order. The nutrixpos GitHub organisation holds only pos, posui (archived), docs and devops — no ordering-site product — and nutrixpos.com's feature list is Cashier, Kitchen, Inventory and Reports with no online-ordering mention. source
guest-loyalty-accrual-modelsunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noNone of the three accrual models exists, natively or otherwise: a repo-wide search returns zero occurrences of "loyalty", "reward", "points" or "punch"; Customer is {Id, Name, Phone, Address} with no balance, visit counter or tier field; and the complete OpenAPI path list has no loyalty resource. Settings holds printers, order-queue counters and payment-source labels — there is nothing in which an accrual rule could be configured. source
labor-clock-in-at-posunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-noNo time clock exists to clock into: the auth module's User model is {ID, Username, Email, PasswordHash, Roles, CreatedAt, UpdatedAt} — no PIN or badge field — and sign-on is a username/password JWT login (LoginRequest{Username, Password}). A repo-wide search for clock, punch, shift, timesheet or time-entry code returns nothing beyond two "pi pi-clock" icon classes, and the complete OpenAPI path list has no time-entry or shift resource. source
hardware-kdsunknown (grade F) — placeholder rationale "No public documentation located during the 2026-08-01 research pass", i.e. the cell had never been examinedresolve-to-partialA first-party, touch-operated KDS screen exists: Kitchen.vue subscribes to the WebSocket feed (reacting to order_submitted and order_finished), loads every open order into QueueOrder cards, and finishes an order with an on-screen confirm button that POSTs /orders/{id}/finish. Shortfall: display-and-finish is the entire feature — no station routing, no course or fire timing, no bump-bar support and no dedicated hardware; the vendor's own docs describe it as an "on demand simple interface for displaying and finishing orders". source

Sources

Every URL this record cites. 22 in total.