Connect services 6
RPC services registered with server.RegisterConnect(), mounted under /connect/. Click a service to expand its methods, request/response types, and the full dispatch chain (framework infra → per-route). Hover any chip for the middleware description. Live metrics appear when server.ConnectMetricsInterceptor() is wired in.
›RpcAdmin/connect/nofo.pb_admin.RpcAdmin/
framework infra
ConnectInfo→BasicRecoverer→BasicErrorCatcher→extra interceptor
CheckAuthCheckAuthRequest → CheckAuthResponse
/nofo.pb_admin.RpcAdmin/CheckAuth
Validates the X-Admin-Token header. The admin frontend calls this once at
login: 200 => token good, 401/403 => rejected. Cheapest possible authed
call (no DB access).
no per-route middleware
GetCollectionLabelsGetCollectionLabelsRequest → GetCollectionLabelsResponse
/nofo.pb_admin.RpcAdmin/GetCollectionLabels
The collection's membership rule, read-only: the label_alias rows whose
collection_id points at it (a raw scraper tag normalizing to one of these
is what attaches an event at import time), plus the legacy query-shim
aliases. Powers the admin "why is an event in this collection" panel.
no per-route middleware
GetCollectionTimeseriesGetCollectionTimeseriesRequest → GetCollectionTimeseriesResponse
/nofo.pb_admin.RpcAdmin/GetCollectionTimeseries
Daily event counts for one collection (Info-tab chart).
no per-route middleware
GetConversationGetConversationRequest → GetConversationResponse
/nofo.pb_admin.RpcAdmin/GetConversation
One conversation's full transcript (every ask_message row, oldest first)
plus the conversation's rollup header. The transcript view in the AI Chat
page renders this; raw llm_json is included for inspection.
no per-route middleware
GetDashboardTimeseriesGetDashboardTimeseriesRequest → GetDashboardTimeseriesResponse
/nofo.pb_admin.RpcAdmin/GetDashboardTimeseries
Daily per-scrapper event counts across ALL scrappers in a single call,
powering the Dashboard overview chart. Unlike GetScrapperTimeseries (one
scrapper, zero-filled), this returns every scrapper's sparse non-zero days
so the client can pivot/stack/filter without N round-trips.
no per-route middleware
GetEmbeddingStatsGetEmbeddingStatsRequest → GetEmbeddingStatsResponse
/nofo.pb_admin.RpcAdmin/GetEmbeddingStats
Embeddings overview: vector coverage of in-scope events + Voyage token
usage/cost rollups (30d + all-time) for the Embeddings page header cards.
no per-route middleware
GetEmbeddingTimeseriesGetEmbeddingTimeseriesRequest → GetEmbeddingTimeseriesResponse
/nofo.pb_admin.RpcAdmin/GetEmbeddingTimeseries
Per-UTC-day embedded-event / token / cost counts over a window, for the
Embeddings page chart. Zero-filled like GetScrapperTimeseries.
no per-route middleware
GetScrapperTimeseriesGetScrapperTimeseriesRequest → GetScrapperTimeseriesResponse
/nofo.pb_admin.RpcAdmin/GetScrapperTimeseries
Daily event counts for one scrapper over a window, for the Info-tab chart.
no per-route middleware
GetUserCostTimeseriesGetUserCostTimeseriesRequest → GetUserCostTimeseriesResponse
/nofo.pb_admin.RpcAdmin/GetUserCostTimeseries
Per-user AI spend + sent-message counts bucketed by day or month (NY tz),
powering the Users detail chart.
no per-route middleware
GetUserDetailGetUserDetailRequest → GetUserDetailResponse
/nofo.pb_admin.RpcAdmin/GetUserDetail
Everything the per-user detail page shows above its event list: the same
rollup row ListUsers returns, the install/build fingerprint, an
upcoming/today/past breakdown of the events they saved, and their top
sources / neighborhoods.
no per-route middleware
GetUserMemoriesGetUserMemoriesRequest → GetUserMemoriesResponse
/nofo.pb_admin.RpcAdmin/GetUserMemories
A user's long-lived agent memories (the db_memories rows — the taste
profile injected into the Ask system prompt). Shown in the AI Chat page's
right rail. Empty when the refresh cron hasn't summarized this user yet.
no per-route middleware
GetUserMessageTimeseriesGetUserMessageTimeseriesRequest → GetUserMessageTimeseriesResponse
/nofo.pb_admin.RpcAdmin/GetUserMessageTimeseries
Daily Ask-message counts per user across ALL users in one call, powering
the Dashboard "AI messages per user" chart. Mirrors GetDashboardTimeseries
(sparse non-zero days; the client zero-fills a continuous axis) but the
series dimension is the user, not the scrapper. Only user-authored messages
(role='user') are counted, bucketed by created_at on UTC days.
no per-route middleware
ListCollectionEventsListCollectionEventsRequest → ListCollectionEventsResponse
/nofo.pb_admin.RpcAdmin/ListCollectionEvents
Searchable, paginated list of a collection's events.
no per-route middleware
ListCollectionsListCollectionsRequest → ListCollectionsResponse
/nofo.pb_admin.RpcAdmin/ListCollections
Collections (curated taxonomy in the `collection` table). Same Info shape
as scrappers: list + daily timeseries + searchable events.
no per-route middleware
ListContextPeopleListContextPeopleRequest → ListContextPeopleResponse
/nofo.pb_admin.RpcAdmin/ListContextPeople
Per-person rollup of the discovery loop: for each letmeknow user who has
written a context, how their stated interests measured against the
catalog, which domains their gaps surfaced, and how many events now exist
because of them. The answer to "what did asking this person get us?".
no per-route middleware
ListDigestHistoryListDigestHistoryRequest → ListDigestHistoryResponse
/nofo.pb_admin.RpcAdmin/ListDigestHistory
Every digest the daily recommender has sent one letmeknow person, and
everything it ruled out for them.
no per-route middleware
ListDiscoveredSourcesListDiscoveredSourcesRequest → ListDiscoveredSourcesResponse
/nofo.pb_admin.RpcAdmin/ListDiscoveredSources
The source-discovery review queue (`discovered_source`): candidate websites
the weekly discovery run found while searching for the organisers behind
the interests the catalog does not currently serve.
no per-route middleware
ListEmbeddingRunsListEmbeddingRunsRequest → ListEmbeddingRunsResponse
/nofo.pb_admin.RpcAdmin/ListEmbeddingRuns
Recent embedding_run rows (inline-import + backfill batches), newest first,
for the Embeddings page activity feed.
no per-route middleware
ListFacetNodesListFacetNodesRequest → ListFacetNodesResponse
/nofo.pb_admin.RpcAdmin/ListFacetNodes
The controlled taxonomy (facet_node) with per-node event counts — the
target picker for triage, and the "which chips are empty" view.
no per-route middleware
ListLabelTriageListLabelTriageRequest → ListLabelTriageResponse
/nofo.pb_admin.RpcAdmin/ListLabelTriage
The label triage queue: raw scraper tags that resolved to no facet and no
collection at import (the `label_triage` view). This backlog is why
category chips sit empty, so the list is ordered by how many events each
label would attach.
no per-route middleware
ListReportsListReportsRequest → ListReportsResponse
/nofo.pb_admin.RpcAdmin/ListReports
Searchable, paginated list of user-submitted reports (the app's block/report
flow) for the Reports triage page. Each row carries both the reporter and
the reported user. Open (unresolved) reports only unless include_resolved.
no per-route middleware
ListScrapperEventsListScrapperEventsRequest → ListScrapperEventsResponse
/nofo.pb_admin.RpcAdmin/ListScrapperEvents
Searchable, paginated list of a scrapper's events for the Info-tab list +
preview (HTML card / JSON viewer).
no per-route middleware
ListScrapperHostsListScrapperHostsRequest → ListScrapperHostsResponse
/nofo.pb_admin.RpcAdmin/ListScrapperHosts
The host registry a scrapper crawls (`scraper_host`): the accumulating
list of recurring organisers it re-visits every run, independent of who
happens to be on the source's discover feed today.
no per-route middleware
ListScrapperStatsListScrapperStatsRequest → ListScrapperStatsResponse
/nofo.pb_admin.RpcAdmin/ListScrapperStats
Per-scrapper rollup powering the left scrapper list: one row per distinct
source_parser found in imported_event.
no per-route middleware
ListUserConversationsListUserConversationsRequest → ListUserConversationsResponse
/nofo.pb_admin.RpcAdmin/ListUserConversations
A user's "Ask" AI conversations (ask_conversation rows bound to user_id),
newest-active first, with per-conversation rollups (turn count, sent count,
billed spend). Powers the AI Chat page's per-user chat list.
no per-route middleware
ListUserEventsListUserEventsRequest → ListUserEventsResponse
/nofo.pb_admin.RpcAdmin/ListUserEvents
One user's saved events (asso_user_wishlist joined to imported_event),
filterable by time bucket (upcoming/today/past) and relationship
(going/wishlist), for the per-user detail page.
no per-route middleware
ListUsersListUsersRequest → ListUsersResponse
/nofo.pb_admin.RpcAdmin/ListUsers
Searchable, paginated list of users with per-user activity rollups
(saved/wishlist counts, Ask messages sent, total AI spend) for the Users
page list + collapsible detail.
no per-route middleware
ResolveReportResolveReportRequest → ResolveReportResponse
/nofo.pb_admin.RpcAdmin/ResolveReport
Flip a report's resolved flag (triage state toggle).
no per-route middleware
SetCollectionActiveSetCollectionActiveRequest → SetCollectionActiveResponse
/nofo.pb_admin.RpcAdmin/SetCollectionActive
Toggle a collection's active flag (inactive = hidden from the app, kept in
the DB). Returns the updated stat row.
no per-route middleware
SetCollectionWindowSetCollectionWindowRequest → SetCollectionWindowResponse
/nofo.pb_admin.RpcAdmin/SetCollectionWindow
Set a collection's [starts_at, ends_at] window (0 ms = clear that bound,
i.e. evergreen on that side). Returns the updated stat row.
no per-route middleware
SetDiscoveredSourceStatusSetDiscoveredSourceStatusRequest → SetDiscoveredSourceStatusResponse
/nofo.pb_admin.RpcAdmin/SetDiscoveredSourceStatus
Triage one candidate: start building it, mark it live, snooze it, or
tombstone it. Rejection is permanent by design — discovery skips a rejected
domain forever rather than re-probing the same dead ends every week.
no per-route middleware
SetLabelMappingSetLabelMappingRequest → SetLabelMappingResponse
/nofo.pb_admin.RpcAdmin/SetLabelMapping
Triage one label: point it at a facet node or a collection, or mark it
ignored. Applies retroactively to events already carrying the label
(import dedup means they would otherwise never pick the mapping up).
no per-route middleware
UpdateCollectionUpdateCollectionRequest → UpdateCollectionResponse
/nofo.pb_admin.RpcAdmin/UpdateCollection
Edit a collection's display name, description, and image (looked up by
slug, which is immutable). Returns the updated stat row.
no per-route middleware
UploadImageUploadImageRequest → UploadImageResponse
/nofo.pb_admin.RpcAdmin/UploadImage
Upload raw image bytes to Cloudflare Images (same account as the events
pipeline) and return the optimized imagedelivery.net URL. Generic — used
by the collection image picker, reusable elsewhere.
no per-route middleware
›RpcDebug/connect/nofo.pb_debug.RpcDebug/
framework infra
ConnectInfo→BasicRecoverer→BasicErrorCatcher→extra interceptor
ListImportRunsListImportRunsRequest → ListImportRunsResponse
/nofo.pb_debug.RpcDebug/ListImportRuns
Admin: list recent events_importer Cloud Run invocations.
Requires the X-Admin-Password header to match NOFO_ADMIN_PASSWORD.
no per-route middleware
ListScrapeRunsListScrapeRunsRequest → ListScrapeRunsResponse
/nofo.pb_debug.RpcDebug/ListScrapeRuns
Admin: list recent scraper Cloud Run invocations.
Requires the X-Admin-Password header to match NOFO_ADMIN_PASSWORD.
no per-route middleware
PingPingRequest → PingResponse
/nofo.pb_debug.RpcDebug/Ping
Ping
no per-route middleware
›RpcEvents/connect/nofo.pb_events.RpcEvents/
framework infra
ConnectInfo→BasicRecoverer→BasicErrorCatcher→extra interceptor
AddToWishListAddToWishListRequest → AddToWishListResponse
/nofo.pb_events.RpcEvents/AddToWishList
Wishlist
per-route
AuthBearer
GetEventGetEventRequest → GetEventResponse
/nofo.pb_events.RpcEvents/GetEvent
Get one event
no per-route middleware
ListEventsListEventsRequest → ListEventsResponse
/nofo.pb_events.RpcEvents/ListEvents
List all events
no per-route middleware
ListFacetsListFacetsRequest → ListFacetsResponse
/nofo.pb_events.RpcEvents/ListFacets
Facets + collections vocabulary (controlled taxonomy tree + curated
collections). One call returns the whole tree the client renders chips
from. See plans/tags-refactor.md.
no per-route middleware
ListRecommendedEventsListRecommendedEventsRequest → ListRecommendedEventsResponse
/nofo.pb_events.RpcEvents/ListRecommendedEvents
Personalized "For You" recommendations for the authenticated user
(bearer-gated). Taste comes from the model-written preference memory
(refreshed by the memories cron), falling back to a summary of the
user's saved events; retrieval is the shared semantic pipeline. Events
the user already saved are excluded.
per-route
AuthBearer
ListTagsListTagsRequest → ListTagsResponse
/nofo.pb_events.RpcEvents/ListTags
Tags
no per-route middleware
ListWishListListWishListRequest → ListWishListResponse
/nofo.pb_events.RpcEvents/ListWishList
ListWishList
per-route
AuthBearer
RemoveFromWishListRemoveFromWishListRequest → RemoveFromWishListResponse
/nofo.pb_events.RpcEvents/RemoveFromWishList
RemoveFromWishList
per-route
AuthBearer
SearchEventsSearchEventsRequest → SearchEventsResponse
/nofo.pb_events.RpcEvents/SearchEvents
Search — the app's Search tab. Combines exact/fuzzy title matching with
the semantic (vibe) pipeline behind /v1/events/search. Title matches are
ALWAYS ranked above semantic matches (the two response lists encode
that); semantic results are deduped against the title list. When the
semantic pipeline is unavailable the RPC degrades to title-only instead
of failing.
no per-route middleware
›RpcFriends/connect/nofo.pb_friends.RpcFriends/
framework infra
ConnectInfo→BasicRecoverer→BasicErrorCatcher→extra interceptor
AcceptFriendRequestAcceptFriendRequestRequest → AcceptFriendRequestResponse
/nofo.pb_friends.RpcFriends/AcceptFriendRequest
Accept a pending incoming request → forms the friendship.
per-route
AuthBearer
BlockUserBlockUserRequest → BlockUserResponse
/nofo.pb_friends.RpcFriends/BlockUser
Block a user: tears down any friendship/pending requests between you and
them, hides you from each other everywhere, and bars new friend requests in
either direction until you unblock. Idempotent.
per-route
AuthBearer
DeclineFriendRequestDeclineFriendRequestRequest → DeclineFriendRequestResponse
/nofo.pb_friends.RpcFriends/DeclineFriendRequest
Decline (delete) a pending incoming request.
per-route
AuthBearer
GetEventFriendsGetEventFriendsRequest → GetEventFriendsResponse
/nofo.pb_friends.RpcFriends/GetEventFriends
Your friends who are GOING to a given event (the event-screen avatars).
per-route
AuthBearer
GetMyCodeGetMyCodeRequest → GetMyCodeResponse
/nofo.pb_friends.RpcFriends/GetMyCode
Your rotatable share code (minted on first call). Share it as a link; when
someone redeems it you get a friend request.
per-route
AuthBearer
GetProfileGetProfileRequest → GetProfileResponse
/nofo.pb_friends.RpcFriends/GetProfile
A user's profile. Friends/self get the full view (their upcoming GOING
events); everyone else gets the limited preview.
per-route
AuthBearer
ListBlockedListBlockedRequest → ListBlockedResponse
/nofo.pb_friends.RpcFriends/ListBlocked
The users you've blocked, for the "blocked accounts" management screen.
per-route
AuthBearer
ListFriendsListFriendsRequest → ListFriendsResponse
/nofo.pb_friends.RpcFriends/ListFriends
Your friends.
per-route
AuthBearer
ListFriendsAttendanceListFriendsAttendanceRequest → ListFriendsAttendanceResponse
/nofo.pb_friends.RpcFriends/ListFriendsAttendance
Your friend feed: (friend, event) pairs for friends GOING to events in a
time window — "who's coming to what".
per-route
AuthBearer
ListIncomingRequestsListIncomingRequestsRequest → ListIncomingRequestsResponse
/nofo.pb_friends.RpcFriends/ListIncomingRequests
Pending requests addressed to you (people who want to be your friend).
per-route
AuthBearer
ListOutgoingRequestsListOutgoingRequestsRequest → ListOutgoingRequestsResponse
/nofo.pb_friends.RpcFriends/ListOutgoingRequests
Pending requests you've sent that aren't accepted yet.
per-route
AuthBearer
RefreshMyCodeRefreshMyCodeRequest → RefreshMyCodeResponse
/nofo.pb_friends.RpcFriends/RefreshMyCode
Rotate your share code, invalidating the previous one.
per-route
AuthBearer
RemoveFriendRemoveFriendRequest → RemoveFriendResponse
/nofo.pb_friends.RpcFriends/RemoveFriend
Unfriend someone (symmetric — removes the single friendship).
per-route
AuthBearer
ReportUserReportUserRequest → ReportUserResponse
/nofo.pb_friends.RpcFriends/ReportUser
Report a user to the nofo team. Stored server-side for back-office triage;
does not itself block (the app offers blocking alongside).
per-route
AuthBearer
RequestFriendByCodeRequestFriendByCodeRequest → RequestFriendByCodeResponse
/nofo.pb_friends.RpcFriends/RequestFriendByCode
Redeem someone's code → send them a friend request (or, if they already
requested you, become friends immediately).
per-route
AuthBearer
UnblockUserUnblockUserRequest → UnblockUserResponse
/nofo.pb_friends.RpcFriends/UnblockUser
Unblock a user you'd previously blocked. Does NOT restore a prior
friendship — they have to re-add.
per-route
AuthBearer
›RpcSecurity/connect/nofo.pb_security.RpcSecurity/
framework infra
ConnectInfo→BasicRecoverer→BasicErrorCatcher→extra interceptor
AskForCodeAskForCodeRequest → AskForCodeResponse
/nofo.pb_security.RpcSecurity/AskForCode
Ask for code -- used to login or signup...
no per-route middleware
ReplyWithCodeReplyWithCodeRequest → ReplyWithCodeResponse
/nofo.pb_security.RpcSecurity/ReplyWithCode
Reply with received code
no per-route middleware
›RpcUser/connect/nofo.pb_user.RpcUser/
framework infra
ConnectInfo→BasicRecoverer→BasicErrorCatcher→extra interceptor
DeleteMeDeleteMeRequest → DeleteMeResponse
/nofo.pb_user.RpcUser/DeleteMe
DeleteMe permanently deletes the calling user's account and everything tied
to it: friends, friend requests, friend code, saved/going events, and chat
history. Bearer-authed; the caller is taken from the token, never the body.
Irreversible — afterward the phone number is free and the person can sign
up again with a completely fresh account.
per-route
AuthBearer
GetUserGetUserRequest → GetUserResponse
/nofo.pb_user.RpcUser/GetUser
GetUser
per-route
AuthBearer
UpdateMeUpdateMeRequest → UpdateMeResponse
/nofo.pb_user.RpcUser/UpdateMe
UpdateMe edits the calling user's own profile. Bearer-authed; the caller is
taken from the token, never the body.
per-route
AuthBearer