fix(demo): hide the Coach FAB in demo mode

The Coach floating button was mounted unconditionally, so a demo
visitor could tap it and send a message. /api/insights/chat is not in
the proxy's demo-mutation allowlist, so the send returned a raw 403.
Demo is read-only by design, so the FAB has no job there — gate its
mount on !demoMode and pin the contract in the hoist test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.8 committed 2026-06-14 10:52:44 +02:00
1 parent b7b160d4fa
commit f846b0681d
2 files changed
+14 -1

No files matched your search

@@ -51,6 +51,14 @@ describe("v1.4.34 IW-B — CoachLaunchProvider hoist", () => {
expect(source).toContain("<LayoutCoachFab />");
});
it("gates the LayoutCoachFab on `!demoMode` so demo visitors can't hit the proxy-blocked send (v1.16.13)", () => {
const source = readFileSync(AUTH_SHELL_PATH, "utf8");
// `/api/insights/chat` is not in the proxy's DEMO_MUTATION_ALLOWLIST,
// so a tappable FAB in demo mode produces a raw 403 on send. The mount
// must be conditioned on the demo flag.
expect(source).toContain("{!demoMode && <LayoutCoachFab />}");
});
it("no longer mounts any Coach surface in the routed insights layout", () => {
const source = readFileSync(INSIGHTS_LAYOUT_PATH, "utf8");
// The provider import drops; the drawer mount lives on the shell.
+6 -1
View File
@@ -272,7 +272,12 @@ export function AuthShell({
<BottomNav />
</div>
<LayoutCoachMount />
<LayoutCoachFab />
{/* v1.16.13 — the Coach FAB stays hidden in demo mode. Its send hits
`/api/insights/chat`, which is not in the proxy's
`DEMO_MUTATION_ALLOWLIST`, so a demo visitor who tapped it and sent
got a raw 403. Demo is read-only by design; the FAB has no job
here, so it's mounted only outside demo mode. */}
{!demoMode && <LayoutCoachFab />}
</CoachLaunchProvider>
);
}