From 97408418202536c8de2848a9069b635d43225c57 Mon Sep 17 00:00:00 2001 From: Sylvain Duchesne Date: Sun, 16 Aug 2026 13:53:00 +0200 Subject: [PATCH] A demo wallet keeps working: pick one of my own profiles, and say it is arbitrary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolving "my profile" by ownership left one case refusing: several profile documents are mine and none was created by this session, which is exactly a reloaded wallet carrying the fixture seed. Sign-up then rejected — in the very flow being built. The first by document reference is now used, stable across reloads and openly arbitrary. While the profile is not a built feature, "which of my fixtures am I" has no true answer and does not need one. This is not the impersonation that was removed. That one reached for a profile by NAME and could land on a document belonging to somebody else; every candidate here is a document I own. The invariant that matters holds: the app never presents another person's profile as mine. Downgraded to a warning, and reworded: the log now says the name shown as yours is demo data rather than announcing a refusal that no longer happens. --- src/shared/context/FestipodDataContext.tsx | 31 +++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/shared/context/FestipodDataContext.tsx b/src/shared/context/FestipodDataContext.tsx index baf5563..3cfbf88 100644 --- a/src/shared/context/FestipodDataContext.tsx +++ b/src/shared/context/FestipodDataContext.tsx @@ -610,7 +610,19 @@ function useNgData(): FestipodDataContextValue { if (myProfileDocId) return users.find(u => u.id === myProfileDocId); if (myOwnedProfiles === null) return undefined; // not answered yet if (myOwnedProfiles.length === 1) return myOwnedProfiles[0]; - return undefined; // none, or ambiguous + if (myOwnedProfiles.length === 0) return undefined; // none — one gets created + // SEVERAL profile documents are mine, and none was created by this session: + // the fixture seed writes its profiles into my own protected scope, so a + // reloaded demo wallet lands here. Pick the first by document reference — + // stable across reloads, and arbitrary, which is honest: while the profile + // is not a built feature, "which of my fixtures am I" has no true answer. + // + // This is NOT the impersonation that was removed. That one reached for a + // profile by NAME and could land on a document belonging to somebody else. + // Every candidate here is a document I own, so the invariant that holds is + // the one that matters: the app never presents another person's profile as + // mine. Delete this branch the day a profile is really created and known. + return [...myOwnedProfiles].sort((a, b) => a.id.localeCompare(b.id))[0]; }, [users, myProfileDocId, myOwnedProfiles]); const currentUserId = currentUser?.id || ''; // Identity-first log prefix, reused by every DATA log below (including the @@ -716,22 +728,23 @@ function useNgData(): FestipodDataContextValue { }); }, [ready, userQuery.isSuccess, myOwnedProfiles]); - // --- MY PROFILE: say it when the answer is ambiguous ------------------------ + // --- MY PROFILE: say it when the answer is arbitrary ------------------------ // Several profile documents are mine and none was created by this session (the - // opt-in fixture seed writes its profiles into my own protected scope). There - // is no honest way to tell which one is the person at the keyboard, so nothing - // is picked — `currentUser` stays undefined and the mutations that need it - // refuse. Silence here would look exactly like "the read has not landed". + // opt-in fixture seed writes its profiles into my own protected scope). One is + // picked deterministically so the app stays usable on a demo wallet, but the + // pick carries no meaning — say so once, or a fixture person silently becomes + // "you" and nobody wonders why. const warnedAmbiguousProfile = useRef(false); useEffect(() => { if (myProfileDocId) return; if (myOwnedProfiles === null || myOwnedProfiles.length <= 1) return; if (warnedAmbiguousProfile.current) return; warnedAmbiguousProfile.current = true; - console.error( + console.warn( `${logPrefix} ${myOwnedProfiles.length} profile documents are mine and none was created by ` + - `this session — which one is me cannot be told apart, so NO profile is resolved (a fixture ` + - `seed run on this wallet is the usual cause). Sign-up and profile edition will refuse.`, + `this session (a fixture seed run on this wallet is the usual cause). The first by document ` + + `reference is used as mine — a stable but ARBITRARY pick, so the name shown as yours is ` + + `demo data, not you.`, ); }, [myOwnedProfiles, myProfileDocId]);