Skip to main content

ADR-0004: Profiles are never public

FieldValue
StatusProposed
Date2026-09-24
DecidersWes Huber
RelatedADR-0005

Context​

Vegan Grove's members are activists. A public profile page is a directory of activists, and a directory is the single artifact the threat model most wants to prevent. The Trick Book has public profiles, a riders directory, a GET /users?email= lookup, and a GET /user/:id that returns any user's full document to any signed-in caller. Wes also wants a feed that works like a normal social app, which normally implies public profiles.

Decision​

  • No public profile route exists on the web or in the app. No GET /users/:id. No search by handle unless the target has set discoverable on, and even then the result is "exists, send invite", not a profile.
  • Friends connect by invite code (a short code or QR shown in person), with a 7-day expiry and a use limit.
  • A handle is rendered only in contexts where the viewer is allowed to see the underlying object: a friend's post, a Grove post to a fellow member, an attendee to that event's organizer, a review where the author opted to show it.
  • Public posts (opt-in, see Feed) show a handle and avatar. Tapping the handle opens a public-posts view: that handle's public posts and nothing else. No bio, area, friends, counts, or join date. This view is a list of posts, not a profile, and the API route is GET /api/handles/:handle/posts, which returns 404 when the handle has no public posts, so the route cannot be used to test whether a handle exists.
  • Admin tooling never lists members beyond the handle and never exports.

Alternatives considered​

  • Private-by-default profiles with a public toggle. Common in social apps. Rejected because the toggle would be used, and one public activist profile with a location and a friends list is the failure mode.
  • Public profiles for organizers only. Organizers are the most exposed people in the movement already. Rejected; organizers are represented by their Grove or organization page, which carries no personal detail.

Consequences​

Positive​

  • The product cannot leak a member list through its own UI.
  • The reconciliation with the feed (opt-in public posts, a posts view instead of a profile) keeps the normal social loop without the directory.

Negative​

  • Finding friends is harder than in other apps. Mitigation: invite codes at events, and Groves as the place you meet people.
  • A member who posts publicly under a handle they use elsewhere is linkable. The app warns once when public posting is enabled.