fix(demo): the setup flow's baseline writes are allowlisted

A demo visitor who typed a height on the confirm screen got a 403 and a
generic toast, and the "someone I look after" arm could only take
"Finish without the profile": the profile PUT, the self-context PUT and
the managed-profile POST were missing from the demo allowlist, so only
the empty-form path completed.

All three are added, pinned per method as the rest of the list is. None
of them creates health data.
This commit is contained in:
Marc-André Bombeck committed 2026-09-11 09:26:10 +02:00
1 parent a6dedffdb8
commit 982c35287d
2 files changed
+43

No files matched your search

@@ -106,6 +106,36 @@ describe("proxy.ts DEMO_MODE mutation allowlist", () => {
expect(missing, "onboarding writes the demo cannot make").toEqual([]);
});
it("permits the baseline writes the confirm screen makes (M-m)", () => {
// v1.39 (Wave C, C6) — a demo visitor who typed a height got a 403 and a
// generic toast, and "someone I look after" could only take "Finish
// without the profile": the three writes the confirm screen makes were
// not on the list. None of them is health data — the account's own
// profile fields, the encrypted self-context the anamnesis card writes,
// and the managed record the flow's guardian arm creates.
for (const [path, method] of [
["/api/auth/profile", "PUT"],
["/api/coach/about-me", "PUT"],
["/api/managed-profiles", "POST"],
] as const) {
expect(
proxy(makeRequest(path, method)).status,
`${method} ${path} is blocked in the demo`,
).not.toBe(403);
}
});
it("does not drag in a sibling verb on the baseline paths", () => {
expect(proxy(makeRequest("/api/auth/profile", "DELETE")).status).toBe(403);
expect(proxy(makeRequest("/api/managed-profiles", "DELETE")).status).toBe(
403,
);
// The per-profile routes are a different path and stay closed.
expect(
proxy(makeRequest("/api/managed-profiles/abc", "DELETE")).status,
).toBe(403);
});
it("still blocks a health-data mutation (POST /api/measurements)", () => {
const res = proxy(makeRequest("/api/measurements", "POST"));
expect(res.status).toBe(403);
+13
View File
@@ -174,6 +174,19 @@ const DEMO_MUTATION_ALLOWLIST: ReadonlyArray<{ path: string; method: string }> =
// Neither creates health data.
{ path: "/api/onboarding/disclaimer", method: "POST" },
{ path: "/api/onboarding/tour", method: "POST" },
// v1.39 (Wave C, C6) — the three writes the confirm screen makes. Without
// them a demo visitor who typed a height got a 403 and a generic toast,
// and the "someone I look after" arm could only take "Finish without the
// profile" — only the empty-form/Skip path completed, so the demo did not
// in fact walk the same flow (design spec §Principles 5). None of the
// three creates health data: the caller's own profile fields, the
// encrypted self-context behind the optional anamnesis card, and the
// managed record the guardian arm of the flow exists to create. The
// per-profile routes (`/api/managed-profiles/{id}`, its guardians) are
// different paths and stay closed.
{ path: "/api/auth/profile", method: "PUT" },
{ path: "/api/coach/about-me", method: "PUT" },
{ path: "/api/managed-profiles", method: "POST" },
];
// Legacy route redirects (German → English)