# What works today and what still needs app work Updated 2026-11-14. "Works today" means the endpoint exists in the deployed app and the kit's templates call it where they should. Ming Apothecary is the first live tenant store (cart, checkout, accounts, shipping, tax, order emails and inventory have been run there). Nothing here is faked: where the app can't do something, the templates say so to the shopper instead of pretending. | # | Piece | Status | Kit file | Notes | |---|---|---|---|---| | 1 | Store page at /store/ served from /files | Works, live on Ming | store/index.html | | | 2 | Product pages /store/.html | Works, live on Ming | store/product.html | Pre-rendered by build.py, then refreshed live by store.js. | | 3 | Categories with JSON descriptions | Works | build.py | Category images exist in the database but /store/products/categories/ does not return them, so the kit doesn't show them. See G6. | | 4 | Live price and stock on pages | Works | store.js | One read per product because list has no stock (G5). Fine for a small catalog. | | 5 | Search | Works | store.js | /store/search/ | | 6 | Add to cart, change quantity, remove (anonymous) | Works, live on Ming | cart.js, store/cart.html | The cart id is kept in localStorage. Stock limits are enforced by the server. | | 7 | Variant picker | Works | store.js | Shown only when a product has 2+ variants. | | 8 | New-customer sign-up with an email code | Works, live on Ming | cart.js (checkout/account) | /end_user_account_setup/ request_code → verify → profile. Allowed from US networks only (Tor, VPN and datacenter addresses are refused). Codes go only to real inboxes; example.com and .test addresses are never mailed. | | 9 | Returning-customer sign-in with an email code | Works, live on Ming | cart.js | /customer_session/. The session lasts 30 days and is bound to the exact host. | | 10 | Shipping address (saved, more than one, pick at checkout) | Works, live on Ming | cart.js | /address/ create and list. Checkout needs shipping_address_id, and billing defaults to the shipping address. | | 11 | Place order, with shipping and tax | Works, live on Ming | cart.js | /store/checkout/ quote then checkout. Flat-rate shipping, optional free-over, and Hawaii GET for Hawaii shipping addresses are computed at checkout. A sale movement is written. A confirmation is emailed to the customer and a copy to the store. | | 12 | Customer order history and delete account | Works, live on Ming | store/account.html, cart.js | /store/invoice/ list. delete_account on /end_user_account_setup/. | | 13 | Owner takes payment outside the site, then marks it paid | Works today (staff API) | AGENT.txt §10 | /store/invoice/payment/ create, COMPLETED by default, turns the invoice PAID. Staff can still adjust tax and shipping on a PENDING invoice. | | 14 | Owner ships with tracking | Works today (staff API) | AGENT.txt §10 | /store/shipment/ create and update. Customers can read their own shipments. | | 15 | Inventory: locations, receive, adjust, stock, rebuild, movement history | Works, live on Ming | AGENT.txt §6 | Movements are insert-only and never overwritten. Checkout writes a sale movement. | | 16 | Per-store settings (shipping, tax, store email) | Works, live on Ming | AGENT.txt §2 | /store/settings/ | | 17 | Online payment (card or PayPal charged on the site) | Not switched on yet | cart.js has payment_mode:"offline" only | Each store can connect its own PayPal account. paypal_start and paypal_capture exist but answer 501 until the platform flag and the store's PayPal flag are both on. A customer payment create only records PENDING, with no charge. See G1. | | 18 | Owner sees orders and customers without the API | Needs app work | | There's no staff order screen. /crm/ has no read or list action. See G7, G8. | | 19 | Stock returned when an order is voided | Needs app work | | VOIDED does not automatically restore stock. Use /store/inventory/ adjust. See G4. | | 20 | Same sign-in on www and apex | Needs a redirect | | The cookie and site_session are host-bound. See G10. | ## Gaps that remain - G1 Payment provider on the site. paypal_start, paypal_capture and a PayPal webhook path exist but are not switched on. Credentials stay off the HTTP JSON. The kit stays on payment_mode:"offline" until both flags are on. - G4 Stock on void or refund. VOIDED from PENDING does not add a reversing inventory movement. Restore stock with adjust, or wait for an app change. - G5 Batch stock. Add stock (and images with URLs) for the default variant to the product list card, so one list call can drive a whole page. - G6 Image URLs. Product read returns file_id only, and the categories list returns no images. Workarounds in the kit: build.py resolves URLs through the public /files/ read, or staff put {"src":"/path.jpg","alt":"…"} in the image description JSON when attaching. - G7 Staff order screen. There's no HTML for staff to see new orders, mark paid or add tracking. All of it can be done with the API today. - G8 CRM read. /crm/ has only create, update and delete. Needed: read_person, list_people and read_company. - G10 One canonical host. Redirect www. to the apex (or the reverse) for the whole site. Until then the kit links stay relative, and the runbook tells the tenant AI to test on the canonical host. - G11 Customer profile for people not created by sign-up. profile returns 403 for customers who exist in CRM but never verified through /end_user_account_setup/. - G12 Abandoned carts. There's no purge of old anonymous carts. Low priority. - G13 File listing for publishers. /files/ search returns only files the calling person uploaded, at most 100, with no offset. Until a brand-wide search exists, publish.py takes known ids from known_ids.json. Closed since the first draft of this kit: shipping and tax at checkout (including quote), order emails, inventory, delete account, and the slashless /store redirect that used to send browsers to http://.