From 24efc07f72279786992ac5d6e65006227463f18e Mon Sep 17 00:00:00 2001 From: Georgy Butaev <41178744+g-but@users.noreply.github.com> Date: Sat, 29 Aug 2026 12:31:39 +0200 Subject: [PATCH] fix(directory): a third audit fixture survived the filter that hid its two siblings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verifying #843 on the live site showed the context switcher had gone from three junk groups to one: "Audit WF009 …" and "Audit WF009b …" were correctly hidden, and "Audit Group 1783191071580" was still sitting there. `FIXTURE_GROUP_TITLE` is an allow-list of wordings we happened to have seen — `audit wf`, `ephemeral verify`, `workflow audit`. Audits keep inventing new ones, so the list is always one fixture behind, and the failure is silent: the row simply looks like a team the user joined. So match the *generating* signature instead of the wording: an audit-ish first word followed by the millisecond epoch a fixture appends to keep names unique. Keying on the timestamp is what makes widening safe — a real group is named by a person, and people do not append an epoch. That matters more here than in most products, because OrangeCat is heading for governance, where "Audit Committee" is a group somebody will genuinely create. Tests pin both directions, and the predicate is proven by mutation: drop the new clause and "Audit Group 1783191071580" comes back. Because this is the shared SSOT, it fixes Discover and People too, not just the switcher. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Sh5aTRjzkcZkTyiu9D5RCM --- .../unit/config/public-directory.test.ts | 19 +++++++++++++++++++ src/config/public-directory.ts | 16 +++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/__tests__/unit/config/public-directory.test.ts b/__tests__/unit/config/public-directory.test.ts index 3f9e549ca..91afc069d 100644 --- a/__tests__/unit/config/public-directory.test.ts +++ b/__tests__/unit/config/public-directory.test.ts @@ -25,6 +25,25 @@ describe('public-directory', () => { expect(isFixtureGroupTitle('Bitcoin Developers Circle')).toBe(false); }); + // A named-prefix list only knows the shapes it has already met. "Audit Group + // 1783191071580" was not one of them, so it survived into a live account's + // context switcher after its two "Audit WF…" siblings were filtered out. + it('hides audit groups whose wording nobody predicted', () => { + expect(isFixtureGroupTitle('Audit Group 1783191071580')).toBe(true); + expect(isFixtureGroupTitle('Workflow Smoke 1783191071580')).toBe(true); + expect(isFixtureGroupTitle('e2e reset 1783191071580')).toBe(true); + }); + + // The timestamp is what makes the rule safe to widen: a real group is named + // by a person, and people do not append an epoch. This matters here more than + // most products — OrangeCat is heading for governance, where "Audit + // Committee" is a group somebody will genuinely create. + it('leaves real groups alone even when they start with an audit word', () => { + expect(isFixtureGroupTitle('Audit Committee')).toBe(false); + expect(isFixtureGroupTitle('Audit Committee 2026')).toBe(false); + expect(isFixtureGroupTitle('Workflow Design Guild')).toBe(false); + }); + it('treats a profile as fixture if either field matches', () => { expect(isFixtureProfile({ username: 'adelina1996gry', name: 'E2E Reset User' })).toBe(true); expect(isFixtureProfile({ username: 'adelina1996gry', name: 'Adelina' })).toBe(false); diff --git a/src/config/public-directory.ts b/src/config/public-directory.ts index d1e4e62b4..b0e462025 100644 --- a/src/config/public-directory.ts +++ b/src/config/public-directory.ts @@ -57,6 +57,19 @@ const EXACT_FIXTURE_USERNAME_SET = new Set(EXACT_FIXTURE_USERNAMES); const FIXTURE_DISPLAY_NAME = /^(e2e reset user|user)$/i; const FIXTURE_GROUP_TITLE = /^(audit\s+wf|ephemeral\s+verify|workflow\s+audit)/i; +/** + * The named prefixes above are an allow-list of shapes we happened to have seen, + * and audits keep inventing new ones: "Audit Group 1783191071580" survived the + * list above and sat in a live account's context switcher. + * + * So also match the *generating* signature rather than the wording — an + * audit-ish first word followed by the millisecond epoch the fixture appends to + * keep names unique. Keying on the timestamp is what keeps a real group safe: a + * governance product will one day have an "Audit Committee", and it will not be + * called "Audit Committee 1783191071580". + */ +const FIXTURE_GROUP_STAMPED = /^(audit|ephemeral|workflow|e2e|wf\d)\b.*\b\d{10,}$/i; + export function isFixtureUsername(username: string | null | undefined): boolean { const u = (username ?? '').trim(); if (u.length === 0) { @@ -90,5 +103,6 @@ export function isFixtureProfile(profile: { } export function isFixtureGroupTitle(title: string | null | undefined): boolean { - return FIXTURE_GROUP_TITLE.test((title ?? '').trim()); + const t = (title ?? '').trim(); + return FIXTURE_GROUP_TITLE.test(t) || FIXTURE_GROUP_STAMPED.test(t); }