Sample diagnostic report
Phone-order flow: what breaks between “that’s everything” and a saved order
This is what you receive at the end of an integration diagnostic. It is a real one. We ran it on our own system, KOTA, on November 12, 2026, and it found defects we hadn’t known about. The only thing missing is the fixed price and delivery time for each fix, which a client report includes.
- Findings
- 5: three high, two medium
- Checks that passed
- 2
- How it was tested
- Seven targeted tests against the real code, with the database and messaging provider replaced by controlled fakes
- Status
- Open. KOTA is not deployed, and these are fixed before it is.
Scope
Looked at
The English order path from the caller finishing an order to a stored order record and a confirmation text, plus the two web entry points that path depends on.
Not looked at
- The Mandarin order path, which has its own code.
- Two order requests arriving at the same instant.
- Behaviour under load, and against the real phone and messaging providers.
- Hosting and deployment settings.
Findings
HighReproduced
1. A failed save is announced as a confirmed order
When the database write fails, the save function hides the error and returns nothing. The order step doesn’t check the result, so it marks the order as placed, clears the cart, texts the caller, and says the order is confirmed.
The caller arrives to collect an order that doesn’t exist. The “#N/A” in the text is the only trace that something went wrong.
Save function, with the database write forced to fail
save_order_details on DB error -> None
What the agent then said
Perfect, your order at Golden Bowl Noodle House is confirmed for $30.40 and I just texted your order details. Thank you for calling.
The text it sent
Golden Bowl Noodle House: your pickup order is confirmed (#N/A). 2x Beef Noodle Soup, 1x Jasmine Tea. Total $30.40. Thank you.
- Proposed fix
- Treat a missing order number as a failure: keep the cart, tell the caller there was a problem, offer the transfer to staff, and raise an alert.
- Done when
- With the database write forced to fail, the agent does not say “confirmed”, no confirmation text is sent, the cart is unchanged, and an alert is logged.
HighReproduced
2. An order number can be issued for an order that was never stored
Orders are saved by updating a row created at the start of the call. If that row is missing, the update changes nothing, the database reports zero rows, and the function still returns a new order number.
The outcome is the same as finding 1, but with a believable reference number, so it is harder to notice. The row it depends on is written by a separate step that can fail on its own.
The statement
UPDATE calls SET order_id = $1, metadata = $2 WHERE call_sid
The database’s answer, and what the function returned anyway
DB said: UPDATE 0 | function returned: 'ORD-CA_SYNTHETIC-17...'
- Proposed fix
- Store each order as its own record, and return an order number only when exactly one record was written.
- Done when
- With no call row present, placing an order either creates a complete order record or fails as in finding 1. An order number is never returned without a stored record.
HighReproduced
3. Call transcripts and caller phone numbers are readable without a login
The routes that list calls and what was said on them have no authentication.
Anyone who finds the address can read what callers said, along with their phone numbers.
Request with no credentials (synthetic data)
GET /api/db/utterances (no credentials) -> 200 {'count': 1, 'data': [{'id': 1, 'call_sid': 'CA_SYNTHETIC_0001', 'speaker': 'caller', 'text': 'two beef noodle soups', 'caller_phone': '+15555550100'}]}
- Proposed fix
- Require authentication on every data route, remove the debug route, and limit each restaurant to its own calls.
- Done when
- Without valid credentials every data route answers 401. With one restaurant’s credentials, another restaurant’s calls are not returned.
MediumReproduced
4. The call webhook accepts requests that don’t come from the phone provider
The route the phone provider calls when a call starts does not verify the provider’s signature.
Anyone can start call flows with made-up caller details, which costs money and pollutes the call log.
A forged request with no signature
POST /api/incoming-call (no X-Twilio-Signature) -> 200 application/xml <?xml version="1.0" encoding="UTF-8"?><Response><Say voice="Polly.Joanna-Neural">Welcome to our restaurant.</Say><Gather …
- Proposed fix
- Verify the provider’s signature on every webhook and reject everything else.
- Done when
- An unsigned or wrongly signed request gets 403. A correctly signed one behaves as it does today.
MediumRead from the code, not run
5. Every restaurant’s “press 0” transfers to the same phone number
The transfer number is a single setting for the whole system, while menus and prompts are stored per restaurant.
With more than one restaurant, a caller asking for staff reaches the wrong business.
- Proposed fix
- Store the transfer number per restaurant, and define what happens when one isn’t set.
- Done when
- A call for restaurant A transfers to A’s number. A restaurant with no number set gets a spoken apology, never another restaurant’s staff.
What held up
Placing the same order twice in one call
The second attempt is refused and only one confirmation goes out.
SECOND place_order -> Your order has already been placed. | confirmations sent: 1
A failed text is not reported as sent
With the messaging provider returning a failure, the agent confirms the order and makes no claim about a text.
Perfect, your order at Golden Bowl Noodle House is confirmed for $30.40 (reference TEST_1-1). Thank you for calling.
Recommendation
Fix findings 1 and 2 together, since they share one code path and decide whether a confirmed order is real. Then 3, which exposes callers’ data. Then 4 and 5.
Separately, and not a defect: nothing in the system tells the restaurant that an order arrived. That is a new piece of work, scoped on its own.
In a client report, each group of fixes carries a fixed price and a delivery time, and you choose which to go ahead with. If the right answer is to stop, or to use an existing product instead, the report says that.
Want this for your agent or automation?
Tell us what it does today and where it goes wrong.