The kitchen can actually make a sound - #848
Merged
sridharkalaibala merged 4 commits intoSep 17, 2026
Merged
Conversation
dev to main: the two kitchen switches and the packaging completion
The tones are synthesised in the main process and handed to the page as data: WAV URLs, so that a till with no internet and no sound files on disk can still make a noise. helmet's defaults do not name media-src, so it fell back to default-src 'self', and the browser refused all of them. Found in a customer machine's log, where the new order alarm had been mute since the header was tightened: Loading media from 'data:audio/wav;base64,...' violates the following Content Security Policy directive: "default-src 'self'". Note that 'media-src' was not explicitly set, so 'default-src' is used as a fallback. The action has been blocked. This is the failure that looks like success: a console warning nobody reads, and a symptom of silence in a room where silence is expected. The kitchen announcement could not have been heard whatever else was fixed. data: only, and media only. A data: URL cannot reach the network and cannot execute, so the worst a bad one does is make a noise.
The announcement shipped with no way to turn it on. The setting was real
and the IPC was real, and the only way to reach either was to open the
developer console on the machine at the pass and type
posnic.kitchenCall.set({ ting: true, speak: true })
Nobody was going to do that, so nobody did, and a finished feature sat
switched off for its whole life. A setting nobody can find is not a
setting.
Two switches on Core Settings, beside the auto-focus ones and stored the
same way: per machine, saved immediately, because somebody flipping this
is standing next to the speaker waiting to hear the difference. Hidden
outside the desktop app, where there is no bridge behind it - a dead
control is worse than an absent one.
And a Test button, which is the point of the block. Until now the only
way to learn whether a kitchen would hear anything was to send it a real
order, which is why both faults found in this feature were found by
reading a log rather than by listening. It goes down the road a real
ticket takes: the same switches, the same tone, the same sentence, the
same window, and it says why when nothing happened.
Owner: "make female voice. more casual than machine voice. indian accent?" A SpeechSynthesisVoice carries a name and a language and nothing else, so the only way to ask for a particular voice is by name. The plain language match picked Ravi, the male half of the Windows en-IN pair, purely because Windows enumerates him first. Both voices satisfied "en-IN", nothing was wrong, and the wrong voice came out anyway. Now the accent is chosen first and the voice within it second, so an Indian woman beats a British one: the dish names are the whole point, and a name not on the list falls through to whatever that language does offer rather than failing. Delivery off the flat baseline as well, and kept close to normal on purpose. Past about 1.15 a synthesised voice stops sounding relaxed and starts sounding like a cartoon, which a kitchen laughs at twice and then ignores. Verified on this machine under Electron: it now picks Microsoft Heera, English (India), where it picked Ravi before.
Contributor
|
Merged to Try it at https://develop.posnic.io, or run it yourself: git fetch origin develop && git checkout develop
npm install && npm --prefix api install
npm run dev # then http://localhost:3000When you have tested it, say what you did and what happened, and set Reporting that something is broken is as useful as fixing it. It is |
This was referenced Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three faults, each of which alone was enough to keep a kitchen silent. All three were found on a customer machine with the current build installed, by reading files and a log rather than by listening, which is itself the point of the third change.
1. The CSP blocked every sound in the product
Every noise this product makes is a WAV synthesised in the main process and handed to the page as a
data:URL: the new order alarm and the kitchen ting both. Nothing is shipped as a sound file, nothing is read off disk and nothing is fetched, which is the right design for a till that has to work with the internet unplugged.helmet's default directives do not name
media-src. Without one declared it falls back todefault-src 'self', and'self'does not includedata:, so the browser refused all of them. From the customer machine's log, 240ms after a QR order arrived:That is the new order alarm being silenced. The same mechanism carries the kitchen ting.
Fixed with one directive,
media-src 'self' data:.data:only and media only: adata:URL cannot reach the network and cannot execute, so the worst a bad one does is make a noise.2. There was no way to turn it on
The setting was real and the IPC was real. The only way to reach either was to open the developer console on the machine at the pass and type:
Nobody was going to do that, so nobody did. A setting nobody can find is not a setting.
Two switches now sit on Core Settings beside the auto-focus ones, stored the same way: per machine, saved immediately, because somebody flipping this is standing next to the speaker waiting to hear the difference. They hide themselves outside the desktop app, where there is no bridge behind them, because a dead control is worse than an absent one.
3. There was no way to test it without a real order
Which is why both of the faults above went unnoticed for the feature's whole life, and why they were eventually found by reading a log.
A Test button on the same block goes down the road a real ticket takes: the same switches, the same tone, the same sentence, the same window. A test that took a shortcut would be the thing that passes while the kitchen stays silent. It says why when nothing happened, because "I pressed it and nothing happened" is where this feature has spent its life.
Not in this PR, but needed with it
The installed build carries a stale frontend bundle.
frontend/static/script/js/core/kitchen-call.jsis the half that plays the tone and speaks, and it is correctly listed underdashboardinpages_css_js_map.jsononmain, but the shippeddashboard.20f9c50d.jsdoes not contain it: nokitchenCall, nospeechSynthesis. Building the frontend frommainproduces a bundle that does (verified locally). So whatever staged that exe did not runprepare:frontend. The next installer has to be built throughnpm run build, which runs it and rejects stale artifacts.Tests
tests/a-sound-the-browser-will-actually-play.test.jsmedia-srcitself, so the line stays load-bearingmedia-srcand allowsdata:tests/the-kitchen-switch-has-somewhere-to-live.test.jsThe CSP test was verified failing on the parent commit and passing on this one.