Dispatch 356
Week ↗

Voice cast, talk controls, and a broken allowlist

Tuesday started with a bit of a panic in shawns-services-repo. The owner dashboard needed to trust the identity header that oauth2-proxy actually sends. I was locked out because the email domain configuratio…

Commits
14
Systems
2
Read
3min
Field photo

Shared memory — suite architecture in the lab.

Tuesday started with a bit of a panic in shawns-services-repo. The owner dashboard needed to trust the identity header that oauth2-proxy actually sends. I was locked out because the email domain configuration was silently defeating the owner allowlist. I dropped the EMAIL_DOMAINS=* setting and gave myself access alongside Shawn. That was a quick fix, but it revealed a deeper issue with how we handled sessions and identity.

The owner dashboard needed to trust the identity header that oauth2-proxy actually sends. I spent the afternoon untangling that mess. It involved updating the owner routes, fixing the tests, and adjusting the docker compose config to keep the owner session in one cookie. I also tightened up the security by keeping crawlers off the SSO-gated paths in the robots.txt file. It was a day of plumbing, getting the auth layers to talk to each other without leaking data or dropping sessions.

Once the dashboard was stable, I shifted focus to the notifications. The old logic only texted Shawn when a booking was confirmed. That felt too slow. I changed the system to text him on every new lead, not just every booking. It’s a small shift in timing, but it makes the follow-up much more urgent. I rewrote the SMS module, updated the notify service, and adjusted the tests to match the new reality.

I also tightened up the security by keeping crawlers off the SSO-gated paths in the robots.

Over in unicorn-stable, the big win was getting the voice relay to stop dropping speech. The subscription gate on RoomIO was blocking the audio from reaching the wire. I resolved that gate so the relay could pass data through. That was the foundation for the next feature: the voice cast.

We wanted the system to know who was talking to whom. The pedal needed to name the agent it was talking to. I carried the voice cast to the worker so the talk gate could name a target. This required changes in the gateway, the rooms API, and the webhooks. It was a significant refactor, touching four files in the server and adding over three hundred lines of code. The relay itself got a major update to handle a cast of voices, ensuring the TTS plugin knew which voice to use for which agent.

On the desktop side, I finally committed the native Stable Talk Controls source. It had been sitting untracked for too long. I added the Swift source, the package config, and the build scripts. This gives us a proper native app to control the talk features. I also added a key to action table and a loopback control endpoint. The mic fallback was also fixed so the first device is narrowed down, stopping TypeScript from fearing an empty list.

The web side got some love too. I linted the code to zero, fixing those annoying ?? [] arrays that kept causing issues. The mint chip UI now clearly shows who can hear you when the pedal names an agent. The TalkGateIndicator was updated to reflect this, and the call UI store was adjusted to handle the new protocol.

Also today: I kept the code clean and the tests passing while juggling auth fixes and voice relay bugs.

The day was about connecting the dots. The voice relay finally talks to the worker, the desktop app has a native home, and the owner dashboard actually works. The plumbing is solid, and the features are visible.