apps/backend/src/routes/analytics.ts computes totalFollows as:
app.prisma.followLog.count({
where: { targetUsername: username, status: 'success' },
})
i.e. it counts followLog rows where targetUsername equals the current user's own username and status === 'success'.
But apps/backend/src/routes/follow.ts writes followLog rows with targetUsername: targetUsername (the route param — the person being followed, not the authenticated user) and followerId: userId. The targetUsername field in followLog therefore always stores "who this user followed", never "who followed this user".
Consequence: totalFollows in the analytics overview will essentially always be 0 for real users (it only matches the edge case where a user's own username happens to coincide with a targetUsername they followed, which is nonsensical), because the analytics query is matching on the wrong field/semantic — it should be querying for follow events directed at this user, but the followLog schema as populated by follow.ts has no concept of "this user was followed by someone" (there's no inbound-follow tracking at all; followLog only records outbound follow actions by followerId).
This is a state-desynchronization between what follow.ts writes (outbound follow attempts by the authenticated user, targeting external platform usernames like GitHub handles) and what analytics.ts reads (looking for inbound follows of the DevCard user by DevCard username) — two different domains (external-platform-follow vs in-app-follow) conflated through the same followLog table and totalFollows field, producing a metric that is permanently zero/incorrect for the documented purpose ("Follows performed BY this user" comment in analytics.ts even contradicts the status:'success', targetUsername: username filter, which would actually mean "follows where someone followed this user").
Affected: apps/backend/src/routes/analytics.ts (totalFollows query, /overview handler) and apps/backend/src/routes/follow.ts (writes to followLog via app.prisma.followLog.create, both the API-follow path and the /log endpoint).
apps/backend/src/routes/analytics.tscomputestotalFollowsas:i.e. it counts
followLogrows wheretargetUsernameequals the current user's own username andstatus === 'success'.But
apps/backend/src/routes/follow.tswritesfollowLogrows withtargetUsername: targetUsername(the route param — the person being followed, not the authenticated user) andfollowerId: userId. ThetargetUsernamefield infollowLogtherefore always stores "who this user followed", never "who followed this user".Consequence:
totalFollowsin the analytics overview will essentially always be 0 for real users (it only matches the edge case where a user's own username happens to coincide with atargetUsernamethey followed, which is nonsensical), because the analytics query is matching on the wrong field/semantic — it should be querying for follow events directed at this user, but thefollowLogschema as populated byfollow.tshas no concept of "this user was followed by someone" (there's no inbound-follow tracking at all;followLogonly records outbound follow actions byfollowerId).This is a state-desynchronization between what
follow.tswrites (outbound follow attempts by the authenticated user, targeting external platform usernames like GitHub handles) and whatanalytics.tsreads (looking for inbound follows of the DevCard user by DevCard username) — two different domains (external-platform-follow vs in-app-follow) conflated through the samefollowLogtable andtotalFollowsfield, producing a metric that is permanently zero/incorrect for the documented purpose ("Follows performed BY this user" comment in analytics.ts even contradicts thestatus:'success', targetUsername: usernamefilter, which would actually mean "follows where someone followed this user").Affected:
apps/backend/src/routes/analytics.ts(totalFollowsquery,/overviewhandler) andapps/backend/src/routes/follow.ts(writes tofollowLogviaapp.prisma.followLog.create, both the API-follow path and the/logendpoint).