Found by an independent Fable review, verified against source.
What happens
dashboard/src/ui/dashboard/components/ProjectUsagePanel.jsx:70 calls, from the user's browser:
fetch(`https://api.github.com/repos/${repoId}`)
repoId is derived from the local project key — i.e. the repositories you work on, including private ones. dashboard/src/ui/components/HeaderGithubStar.jsx does the same for this repo's own star count.
There is a gate (shouldFetchGithubStars({ prefersReducedMotion, screenshotCapture })) but it gates on reduced-motion and screenshot-capture mode. It is not a privacy control and the user is never asked.
Why it matters
It contradicts the README's own privacy section, rewritten in #95:
- README:154 claims avatars are "Fetched server-side so your browser doesn't contact them directly."
- README:152 lists
api.github.com only under "Quota chips + Limits page" — asking your provider about your own plan.
Neither covers a browser-side request whose URL path is the name of a repo you have checked out. Sending a private repo name to a third party is a different class of disclosure from fetching a public price list, and it is the one thing the product's headline claim is about.
Why it slipped
The outbound-call table in #95 was assembled by grepping src/ only. dashboard/src/ was never scanned, and both offending files live there. The claim was researched, just not exhaustively — which is precisely why it needs a validator rather than another careful read (#101, filed alongside this).
Options
- Route it through the existing avatar proxy (
/api/avatar-proxy in src/lib/local-api.js, already host-allowlisted) so the browser talks only to loopback. Makes README:154 true as written. Note the repo name still reaches GitHub — from the local server rather than the browser — so the README must say so either way.
- Make it genuinely opt-in, default off, with a Settings toggle.
- Drop the enrichment. Star counts and owner avatars on a private-usage dashboard are decoration; the panel works without them.
My preference is 3 for ProjectUsagePanel (the feature earns little and costs the strongest claim in the product) and 1 or 2 for HeaderGithubStar, which only ever requests this public repo and discloses nothing about the user.
Whatever is chosen, the README outbound table must match it exactly.
Found by an independent Fable review, verified against source.
What happens
dashboard/src/ui/dashboard/components/ProjectUsagePanel.jsx:70calls, from the user's browser:repoIdis derived from the local project key — i.e. the repositories you work on, including private ones.dashboard/src/ui/components/HeaderGithubStar.jsxdoes the same for this repo's own star count.There is a gate (
shouldFetchGithubStars({ prefersReducedMotion, screenshotCapture })) but it gates on reduced-motion and screenshot-capture mode. It is not a privacy control and the user is never asked.Why it matters
It contradicts the README's own privacy section, rewritten in #95:
api.github.comonly under "Quota chips + Limits page" — asking your provider about your own plan.Neither covers a browser-side request whose URL path is the name of a repo you have checked out. Sending a private repo name to a third party is a different class of disclosure from fetching a public price list, and it is the one thing the product's headline claim is about.
Why it slipped
The outbound-call table in #95 was assembled by grepping
src/only.dashboard/src/was never scanned, and both offending files live there. The claim was researched, just not exhaustively — which is precisely why it needs a validator rather than another careful read (#101, filed alongside this).Options
/api/avatar-proxyinsrc/lib/local-api.js, already host-allowlisted) so the browser talks only to loopback. Makes README:154 true as written. Note the repo name still reaches GitHub — from the local server rather than the browser — so the README must say so either way.My preference is 3 for
ProjectUsagePanel(the feature earns little and costs the strongest claim in the product) and 1 or 2 forHeaderGithubStar, which only ever requests this public repo and discloses nothing about the user.Whatever is chosen, the README outbound table must match it exactly.