Problem
Two places in this repo state what GET /voices returns for an unauthenticated caller, and they say opposite things. Neither is verified against the deployed API.
Scope
The client's anonymous-caller assumption only. Not the authenticated catalog, not curation, not the settings UI.
src/tts/TextToSpeechService.ts maps a 401 to an empty list — "signed out means no voices".
e2e/support/mock-servers.ts serves the /voices catalog to any caller, with no auth check — "signed out means the public catalog".
Reproduction / verification
Verified end state: one authenticated and one unauthenticated GET /voices against the deployed API, with the status code and body shape recorded in this issue. Then whichever of the two client-side statements is wrong is corrected, and a test pins the real contract.
Why it matters
It is currently possible to write a client change that is green in every unit test and wrong in the browser, because the unit tests and the E2E mock disagree about the same request. That is exactly what happened while fixing #227: a guard that suppressed the catalog fetch for any signed-out page passed the whole Vitest suite and failed 10 of 10 Layer-3 voices specs, because the mock serves an anonymous catalog and the unit tests assumed nobody would ask.
The guard was narrowed and #227 shipped correctly, so nothing is broken today. What is unresolved is which side is telling the truth — and until that is settled, the same trap is set for the next change in this area.
Notes (non-binding)
If the API does serve a public catalog to anonymous callers, the 401 → [] mapping is dead code with a misleading comment attached. If it does not, the E2E mock is teaching every Layer-3 spec a false contract. Settling it may need a question to saypi-api rather than a change here.
Problem
Two places in this repo state what
GET /voicesreturns for an unauthenticated caller, and they say opposite things. Neither is verified against the deployed API.Scope
The client's anonymous-caller assumption only. Not the authenticated catalog, not curation, not the settings UI.
src/tts/TextToSpeechService.tsmaps a401to an empty list — "signed out means no voices".e2e/support/mock-servers.tsserves the/voicescatalog to any caller, with no auth check — "signed out means the public catalog".Reproduction / verification
Verified end state: one authenticated and one unauthenticated
GET /voicesagainst the deployed API, with the status code and body shape recorded in this issue. Then whichever of the two client-side statements is wrong is corrected, and a test pins the real contract.Why it matters
It is currently possible to write a client change that is green in every unit test and wrong in the browser, because the unit tests and the E2E mock disagree about the same request. That is exactly what happened while fixing #227: a guard that suppressed the catalog fetch for any signed-out page passed the whole Vitest suite and failed 10 of 10 Layer-3 voices specs, because the mock serves an anonymous catalog and the unit tests assumed nobody would ask.
The guard was narrowed and #227 shipped correctly, so nothing is broken today. What is unresolved is which side is telling the truth — and until that is settled, the same trap is set for the next change in this area.
Notes (non-binding)
If the API does serve a public catalog to anonymous callers, the
401 → []mapping is dead code with a misleading comment attached. If it does not, the E2E mock is teaching every Layer-3 spec a false contract. Settling it may need a question to saypi-api rather than a change here.