Follow-up to #631 (shipped in #641). The randomized prefix hides a private repo's attachment URLs from guessing, but it does not anonymize the file once a URL is held: the unauthenticated `/public/files` projection passes `gh.repo` / `gh.number` / `gh.branch` through, and the `/f/` page renders a link to the private repo's PR. docs/private-attachments.md states this plainly today.
The fuller fix: for keys under `gh/private/`, filter the `gh.*` source-naming keys out of the public metadata projection (and the `/f/` GitHub-context derivation). Signed-in workspace views keep the full metadata.
Care points: the screenshots page and PR-activity index read these keys through workspace-authed surfaces, so only the public projection changes; keep the before/after pairing metadata intact (not source-naming).
Follow-up to #631 (shipped in #641). The randomized prefix hides a private repo's attachment URLs from guessing, but it does not anonymize the file once a URL is held: the unauthenticated `/public/files` projection passes `gh.repo` / `gh.number` / `gh.branch` through, and the `/f/` page renders a link to the private repo's PR. docs/private-attachments.md states this plainly today.
The fuller fix: for keys under `gh/private/`, filter the `gh.*` source-naming keys out of the public metadata projection (and the `/f/` GitHub-context derivation). Signed-in workspace views keep the full metadata.
Care points: the screenshots page and PR-activity index read these keys through workspace-authed surfaces, so only the public projection changes; keep the before/after pairing metadata intact (not source-naming).