feat(demo): extend mask() to all breadcrumbs, page titles, and identifiers

Covers workspace IDs, session IDs, peer IDs in breadcrumbs and titles,
server base URL in sidebar, webhook URLs/IDs, and session metadata source
tags across all 11 components.
This commit is contained in:
Offending Commit
2026-04-27 14:27:37 -05:00
parent 8f9d806eef
commit 123828ccb6
11 changed files with 45 additions and 35 deletions

View File

@@ -80,7 +80,7 @@ export function ChatPage() {
params={{ workspaceId, peerId } as never} params={{ workspaceId, peerId } as never}
className="hover:underline font-mono" className="hover:underline font-mono"
> >
{peerId} {mask(peerId)}
</Link> </Link>
<span>/</span> <span>/</span>
<span>Chat</span> <span>Chat</span>
@@ -92,7 +92,8 @@ export function ChatPage() {
</SectionHeading> </SectionHeading>
</div> </div>
<p className="text-xs mt-0.5" style={{ color: "var(--text-3)" }}> <p className="text-xs mt-0.5" style={{ color: "var(--text-3)" }}>
Honcho responds using accumulated context for <span className="font-mono">{peerId}</span> Honcho responds using accumulated context for{" "}
<span className="font-mono">{mask(peerId)}</span>
</p> </p>
</div> </div>

View File

@@ -115,7 +115,7 @@ export function ConclusionBrowser() {
style={{ color: "var(--text-3)" }} style={{ color: "var(--text-3)" }}
> >
<ArrowLeft className="w-3 h-3" strokeWidth={1.5} /> <ArrowLeft className="w-3 h-3" strokeWidth={1.5} />
{workspaceId} {mask(workspaceId)}
</Link> </Link>
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<Lightbulb className="w-5 h-5" style={{ color: "var(--accent)" }} strokeWidth={1.5} /> <Lightbulb className="w-5 h-5" style={{ color: "var(--accent)" }} strokeWidth={1.5} />

View File

@@ -7,6 +7,7 @@ import type { components } from "@/api/schema.d.ts";
import { ErrorAlert } from "@/components/shared/ErrorAlert"; import { ErrorAlert } from "@/components/shared/ErrorAlert";
import { PageLoader } from "@/components/shared/LoadingSpinner"; import { PageLoader } from "@/components/shared/LoadingSpinner";
import { Body, Muted, PageTitle, SectionHeading } from "@/components/ui/typography"; import { Body, Muted, PageTitle, SectionHeading } from "@/components/ui/typography";
import { useDemo } from "@/hooks/useDemo";
import { COLOR } from "@/lib/constants"; import { COLOR } from "@/lib/constants";
import { formatCount } from "@/lib/utils"; import { formatCount } from "@/lib/utils";
@@ -15,6 +16,7 @@ type QueueStatus = components["schemas"]["QueueStatus"];
// ─── Per-workspace queue row ───────────────────────────────────────────────── // ─── Per-workspace queue row ─────────────────────────────────────────────────
function WorkspaceQueueRow({ workspaceId }: { workspaceId: string }) { function WorkspaceQueueRow({ workspaceId }: { workspaceId: string }) {
const { mask } = useDemo();
const { data, isLoading } = useQueueStatus(workspaceId); const { data, isLoading } = useQueueStatus(workspaceId);
const pending = data?.pending_work_units ?? 0; const pending = data?.pending_work_units ?? 0;
@@ -40,7 +42,7 @@ function WorkspaceQueueRow({ workspaceId }: { workspaceId: string }) {
className="font-mono text-xs truncate max-w-[200px] group-hover:underline" className="font-mono text-xs truncate max-w-[200px] group-hover:underline"
style={{ color: "var(--accent-text)" }} style={{ color: "var(--accent-text)" }}
> >
{workspaceId} {mask(workspaceId)}
</span> </span>
<ChevronRight <ChevronRight
className="w-3 h-3 opacity-0 group-hover:opacity-60 transition-opacity flex-shrink-0" className="w-3 h-3 opacity-0 group-hover:opacity-60 transition-opacity flex-shrink-0"
@@ -79,15 +81,14 @@ function WorkspaceQueueRow({ workspaceId }: { workspaceId: string }) {
{( {(
[ [
{ val: total, color: "var(--text-2)" }, { key: "total", val: total, color: "var(--text-2)" },
{ val: done, color: COLOR.success }, { key: "done", val: done, color: COLOR.success },
{ val: active, color: COLOR.warning }, { key: "active", val: active, color: COLOR.warning },
{ val: pending, color: "var(--text-3)" }, { key: "pending", val: pending, color: "var(--text-3)" },
] as Array<{ val: number; color: string }> ] satisfies Array<{ key: string; val: number; color: string }>
).map(({ val, color }, i) => ( ).map(({ key, val, color }) => (
<td <td
// biome-ignore lint/suspicious/noArrayIndexKey: static positional columns key={key}
key={i}
className="py-2 px-4 text-right font-mono text-xs" className="py-2 px-4 text-right font-mono text-xs"
style={{ color: isLoading ? "var(--text-4)" : color }} style={{ color: isLoading ? "var(--text-4)" : color }}
> >

View File

@@ -25,7 +25,7 @@ export function Sidebar() {
const matchRoute = useMatchRoute(); const matchRoute = useMatchRoute();
const config = loadConfig(); const config = loadConfig();
const { theme, toggle } = useTheme(); const { theme, toggle } = useTheme();
const { demo, toggle: toggleDemo } = useDemo(); const { demo, toggle: toggleDemo, mask } = useDemo();
return ( return (
<motion.aside <motion.aside
@@ -62,9 +62,9 @@ export function Sidebar() {
<p <p
className="text-xs mt-2 truncate font-mono hidden sm:block" className="text-xs mt-2 truncate font-mono hidden sm:block"
style={{ color: "var(--text-4)" }} style={{ color: "var(--text-4)" }}
title={config.baseUrl} title={mask(config.baseUrl)}
> >
{config.baseUrl.replace(/^https?:\/\//, "")} {mask(config.baseUrl.replace(/^https?:\/\//, ""))}
</p> </p>
)} )}
</div> </div>

View File

@@ -88,7 +88,7 @@ export function PeerDetail() {
params={{ workspaceId } as never} params={{ workspaceId } as never}
className="hover:underline font-mono" className="hover:underline font-mono"
> >
{workspaceId} {mask(workspaceId)}
</Link> </Link>
<span>/</span> <span>/</span>
<Link <Link
@@ -104,7 +104,7 @@ export function PeerDetail() {
<div> <div>
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<User className="w-5 h-5" style={{ color: "var(--accent)" }} strokeWidth={1.5} /> <User className="w-5 h-5" style={{ color: "var(--accent)" }} strokeWidth={1.5} />
<PageTitle className="font-mono break-all">{peerId}</PageTitle> <PageTitle className="font-mono break-all">{mask(peerId)}</PageTitle>
{observeMe !== undefined && ( {observeMe !== undefined && (
<span <span
className="inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full font-mono" className="inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full font-mono"
@@ -304,9 +304,9 @@ export function PeerDetail() {
<Users className="w-3.5 h-3.5" strokeWidth={2} /> <Users className="w-3.5 h-3.5" strokeWidth={2} />
{repTarget ? ( {repTarget ? (
<> <>
<MonoCaption as="span">{peerId}</MonoCaption> <MonoCaption as="span">{mask(peerId)}</MonoCaption>
<span className="opacity-50"></span> <span className="opacity-50"></span>
<MonoCaption as="span">{repTarget}</MonoCaption> <MonoCaption as="span">{mask(repTarget)}</MonoCaption>
</> </>
) : ( ) : (
"Memory Representation" "Memory Representation"

View File

@@ -112,7 +112,7 @@ export function PeerList() {
style={{ color: COLOR.dimText }} style={{ color: COLOR.dimText }}
> >
<ArrowLeft className="w-3 h-3" strokeWidth={1.5} /> <ArrowLeft className="w-3 h-3" strokeWidth={1.5} />
{workspaceId} {mask(workspaceId)}
</Link> </Link>
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<Users className="w-5 h-5" style={{ color: COLOR.accent }} strokeWidth={1.5} /> <Users className="w-5 h-5" style={{ color: COLOR.accent }} strokeWidth={1.5} />
@@ -139,7 +139,7 @@ export function PeerList() {
</div> </div>
</div> </div>
<MonoCaption className="mt-0.5" as="p"> <MonoCaption className="mt-0.5" as="p">
{workspaceId} {mask(workspaceId)}
</MonoCaption> </MonoCaption>
</motion.div> </motion.div>

View File

@@ -116,7 +116,7 @@ export function SessionDetail() {
params={{ workspaceId } as never} params={{ workspaceId } as never}
className="hover:underline font-mono" className="hover:underline font-mono"
> >
{workspaceId} {mask(workspaceId)}
</Link> </Link>
<span>/</span> <span>/</span>
<Link <Link
@@ -135,7 +135,7 @@ export function SessionDetail() {
style={{ color: "var(--accent)" }} style={{ color: "var(--accent)" }}
strokeWidth={1.5} strokeWidth={1.5}
/> />
<PageTitle className="font-mono break-all">{sessionId}</PageTitle> <PageTitle className="font-mono break-all">{mask(sessionId)}</PageTitle>
</div> </div>
<div className="flex items-center gap-2 flex-shrink-0"> <div className="flex items-center gap-2 flex-shrink-0">
<Button <Button
@@ -323,7 +323,7 @@ export function SessionDetail() {
<ConfirmDialog <ConfirmDialog
open={confirmDelete} open={confirmDelete}
title="Delete session" title="Delete session"
description={`Permanently delete session "${sessionId}"? This cannot be undone.`} description={`Permanently delete session "${mask(sessionId)}"? This cannot be undone.`}
confirmLabel="Delete session" confirmLabel="Delete session"
onConfirm={handleDelete} onConfirm={handleDelete}
onCancel={() => setConfirmDelete(false)} onCancel={() => setConfirmDelete(false)}

View File

@@ -10,6 +10,7 @@ import { PageLoader } from "@/components/shared/LoadingSpinner";
import { Pagination } from "@/components/shared/Pagination"; import { Pagination } from "@/components/shared/Pagination";
import { SortControl, type SortDir } from "@/components/shared/SortControl"; import { SortControl, type SortDir } from "@/components/shared/SortControl";
import { MonoCaption, PageTitle } from "@/components/ui/typography"; import { MonoCaption, PageTitle } from "@/components/ui/typography";
import { useDemo } from "@/hooks/useDemo";
import { COLOR } from "@/lib/constants"; import { COLOR } from "@/lib/constants";
type Session = components["schemas"]["Session"]; type Session = components["schemas"]["Session"];
@@ -30,6 +31,7 @@ const item: Variants = {
}; };
export function SessionList() { export function SessionList() {
const { mask } = useDemo();
const { workspaceId } = useParams({ strict: false }) as { workspaceId: string }; const { workspaceId } = useParams({ strict: false }) as { workspaceId: string };
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [sortField, setSortField] = useState("created_at"); const [sortField, setSortField] = useState("created_at");
@@ -71,7 +73,7 @@ export function SessionList() {
style={{ color: COLOR.dimText }} style={{ color: COLOR.dimText }}
> >
<ArrowLeft className="w-3 h-3" strokeWidth={1.5} /> <ArrowLeft className="w-3 h-3" strokeWidth={1.5} />
{workspaceId} {mask(workspaceId)}
</Link> </Link>
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<MessageSquare className="w-5 h-5" style={{ color: COLOR.accent }} strokeWidth={1.5} /> <MessageSquare className="w-5 h-5" style={{ color: COLOR.accent }} strokeWidth={1.5} />
@@ -98,7 +100,7 @@ export function SessionList() {
</div> </div>
</div> </div>
<MonoCaption className="mt-0.5" as="p"> <MonoCaption className="mt-0.5" as="p">
{workspaceId} {mask(workspaceId)}
</MonoCaption> </MonoCaption>
</motion.div> </motion.div>
@@ -142,7 +144,7 @@ export function SessionList() {
className="font-mono text-sm font-medium truncate" className="font-mono text-sm font-medium truncate"
style={{ color: COLOR.accentSoft }} style={{ color: COLOR.accentSoft }}
> >
{session.id} {mask(session.id)}
</span> </span>
<div className="flex items-center gap-2 shrink-0 ml-2"> <div className="flex items-center gap-2 shrink-0 ml-2">
{session.is_active && ( {session.is_active && (
@@ -189,7 +191,7 @@ export function SessionList() {
color: COLOR.dimText, color: COLOR.dimText,
}} }}
> >
{(session.metadata as Record<string, string>).source} {mask((session.metadata as Record<string, string>).source)}
</span> </span>
)} )}
</div> </div>

View File

@@ -11,6 +11,7 @@ import { PageLoader } from "@/components/shared/LoadingSpinner";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Body, Muted, PageTitle, SectionHeading } from "@/components/ui/typography"; import { Body, Muted, PageTitle, SectionHeading } from "@/components/ui/typography";
import { useDemo } from "@/hooks/useDemo";
import { COLOR } from "@/lib/constants"; import { COLOR } from "@/lib/constants";
const urlSchema = z.string().url({ message: "Must be a valid URL" }); const urlSchema = z.string().url({ message: "Must be a valid URL" });
@@ -20,6 +21,7 @@ interface Props {
} }
export function WebhookManager({ workspaceId }: Props) { export function WebhookManager({ workspaceId }: Props) {
const { mask } = useDemo();
const { data: webhooks, isLoading, error } = useWebhooks(workspaceId); const { data: webhooks, isLoading, error } = useWebhooks(workspaceId);
const createWebhook = useCreateWebhook(workspaceId); const createWebhook = useCreateWebhook(workspaceId);
const deleteWebhook = useDeleteWebhook(workspaceId); const deleteWebhook = useDeleteWebhook(workspaceId);
@@ -60,7 +62,7 @@ export function WebhookManager({ workspaceId }: Props) {
style={{ color: "var(--text-3)" }} style={{ color: "var(--text-3)" }}
> >
<ArrowLeft className="w-3 h-3" strokeWidth={1.5} /> <ArrowLeft className="w-3 h-3" strokeWidth={1.5} />
{workspaceId} {mask(workspaceId)}
</Link> </Link>
<div className="flex items-center justify-between mb-1"> <div className="flex items-center justify-between mb-1">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -163,7 +165,7 @@ export function WebhookManager({ workspaceId }: Props) {
className="text-xs font-mono truncate" className="text-xs font-mono truncate"
style={{ color: "var(--accent-text)" }} style={{ color: "var(--accent-text)" }}
> >
{(wh as { url: string }).url} {mask((wh as { url: string }).url)}
</span> </span>
<button <button
type="button" type="button"
@@ -181,7 +183,7 @@ export function WebhookManager({ workspaceId }: Props) {
</button> </button>
</div> </div>
<span className="text-xs font-mono" style={{ color: "var(--text-4)" }}> <span className="text-xs font-mono" style={{ color: "var(--text-4)" }}>
{(wh as { id: string }).id} {mask((wh as { id: string }).id)}
</span> </span>
</div> </div>
<Button <Button

View File

@@ -21,6 +21,7 @@ import { PageLoader } from "@/components/shared/LoadingSpinner";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Body, Caption, PageTitle, SectionHeading } from "@/components/ui/typography"; import { Body, Caption, PageTitle, SectionHeading } from "@/components/ui/typography";
import { ScheduleDreamModal } from "@/components/workspaces/ScheduleDreamModal"; import { ScheduleDreamModal } from "@/components/workspaces/ScheduleDreamModal";
import { useDemo } from "@/hooks/useDemo";
import { COLOR } from "@/lib/constants"; import { COLOR } from "@/lib/constants";
const NAV_SECTIONS = [ const NAV_SECTIONS = [
@@ -51,6 +52,7 @@ const NAV_SECTIONS = [
] as const; ] as const;
export function WorkspaceDetail() { export function WorkspaceDetail() {
const { mask } = useDemo();
const { workspaceId } = useParams({ strict: false }) as { workspaceId: string }; const { workspaceId } = useParams({ strict: false }) as { workspaceId: string };
const navigate = useNavigate(); const navigate = useNavigate();
@@ -87,7 +89,7 @@ export function WorkspaceDetail() {
style={{ color: "var(--accent)" }} style={{ color: "var(--accent)" }}
strokeWidth={1.5} strokeWidth={1.5}
/> />
<PageTitle className="font-mono break-all">{workspaceId}</PageTitle> <PageTitle className="font-mono break-all">{mask(workspaceId)}</PageTitle>
</div> </div>
<div className="flex items-center gap-2 flex-shrink-0"> <div className="flex items-center gap-2 flex-shrink-0">
<Button variant="accent" size="sm" onClick={() => setDreamOpen(true)}> <Button variant="accent" size="sm" onClick={() => setDreamOpen(true)}>
@@ -267,7 +269,7 @@ export function WorkspaceDetail() {
className="font-mono truncate block max-w-[180px] hover:underline" className="font-mono truncate block max-w-[180px] hover:underline"
style={{ color: "var(--accent-text)" }} style={{ color: "var(--accent-text)" }}
> >
{sid} {mask(sid)}
</Link> </Link>
</td> </td>
<td <td
@@ -324,7 +326,7 @@ export function WorkspaceDetail() {
<ConfirmDialog <ConfirmDialog
open={confirmDelete} open={confirmDelete}
title="Delete workspace" title="Delete workspace"
description={`This will permanently delete workspace "${workspaceId}" and all its data. This cannot be undone.`} description={`This will permanently delete workspace "${mask(workspaceId)}" and all its data. This cannot be undone.`}
confirmLabel="Delete workspace" confirmLabel="Delete workspace"
onConfirm={handleDelete} onConfirm={handleDelete}
onCancel={() => setConfirmDelete(false)} onCancel={() => setConfirmDelete(false)}

View File

@@ -10,6 +10,7 @@ import { PageLoader } from "@/components/shared/LoadingSpinner";
import { Pagination } from "@/components/shared/Pagination"; import { Pagination } from "@/components/shared/Pagination";
import { SortControl, type SortDir } from "@/components/shared/SortControl"; import { SortControl, type SortDir } from "@/components/shared/SortControl";
import { MonoCaption, Muted, PageTitle } from "@/components/ui/typography"; import { MonoCaption, Muted, PageTitle } from "@/components/ui/typography";
import { useDemo } from "@/hooks/useDemo";
import { COLOR } from "@/lib/constants"; import { COLOR } from "@/lib/constants";
type Workspace = components["schemas"]["Workspace"]; type Workspace = components["schemas"]["Workspace"];
@@ -29,6 +30,7 @@ const item: Variants = {
}; };
export function WorkspaceList() { export function WorkspaceList() {
const { mask } = useDemo();
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [sortField, setSortField] = useState("created_at"); const [sortField, setSortField] = useState("created_at");
const [sortDir, setSortDir] = useState<SortDir>("desc"); const [sortDir, setSortDir] = useState<SortDir>("desc");
@@ -131,7 +133,7 @@ export function WorkspaceList() {
className="font-mono text-sm font-medium" className="font-mono text-sm font-medium"
style={{ color: COLOR.accentSoft }} style={{ color: COLOR.accentSoft }}
> >
{ws.id} {mask(ws.id)}
</span> </span>
<ChevronRight <ChevronRight
className="w-4 h-4 opacity-30 group-hover:opacity-70 transition-opacity" className="w-4 h-4 opacity-30 group-hover:opacity-70 transition-opacity"