From b41e8c330a9eaa2a22bdd84fa3154fa6e90ef7ad Mon Sep 17 00:00:00 2001 From: rob thijssen Date: Mon, 11 May 2026 15:35:22 +0300 Subject: [PATCH] feat: include private repo contributions in graph metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aggregate graph endpoints (daily counts, language daily counts, source summaries, OG image) now include private repository activity. These endpoints only expose numeric counts — no commit messages, repo names, or other metadata — so private details remain hidden. The activity timeline continues to serve only public events. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/moments-api/src/main.rs | 10 +++++----- crates/moments-core/src/lib.rs | 4 ++-- crates/moments-data/src/lib.rs | 10 ++++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/crates/moments-api/src/main.rs b/crates/moments-api/src/main.rs index ec634ba..143d6b0 100644 --- a/crates/moments-api/src/main.rs +++ b/crates/moments-api/src/main.rs @@ -130,7 +130,7 @@ async fn list_sources( ) -> Result>, ApiError> { let summaries = state .store - .source_summaries(/* include_private */ false) + .source_summaries(/* include_private */ true) .await .map_err(internal)?; Ok(Json(summaries)) @@ -155,7 +155,7 @@ async fn daily_counts( ) -> Result>, ApiError> { let to = params.to.unwrap_or_else(|| Utc::now().date_naive()); let from = params.from.unwrap_or_else(|| to - chrono::Duration::days(365)); - let counts = state.store.daily_counts(from, to).await.map_err(internal)?; + let counts = state.store.daily_counts(from, to, /* include_private */ true).await.map_err(internal)?; Ok(Json(counts)) } @@ -165,7 +165,7 @@ async fn language_daily_counts( ) -> Result>, ApiError> { let to = params.to.unwrap_or_else(|| Utc::now().date_naive()); let from = params.from.unwrap_or_else(|| to - chrono::Duration::days(365)); - let counts = state.store.language_daily_counts(from, to).await.map_err(internal)?; + let counts = state.store.language_daily_counts(from, to, /* include_private */ true).await.map_err(internal)?; Ok(Json(counts)) } @@ -182,7 +182,7 @@ async fn og_contributions( // Get date range from source summaries let summaries = state .store - .source_summaries(false) + .source_summaries(/* include_private */ true) .await .map_err(internal)?; let earliest = summaries @@ -195,7 +195,7 @@ async fn og_contributions( let counts = state .store - .daily_counts(earliest, today) + .daily_counts(earliest, today, /* include_private */ true) .await .map_err(internal)?; diff --git a/crates/moments-core/src/lib.rs b/crates/moments-core/src/lib.rs index a355dc5..1c8b4ba 100644 --- a/crates/moments-core/src/lib.rs +++ b/crates/moments-core/src/lib.rs @@ -20,8 +20,8 @@ pub trait EventReader: Send + Sync { async fn list_events(&self, query: &EventQuery) -> Result, StoreError>; async fn source_summaries(&self, include_private: bool) -> Result, StoreError>; async fn list_projects(&self) -> Result, StoreError>; - async fn daily_counts(&self, from: NaiveDate, to: NaiveDate) -> Result, StoreError>; - async fn language_daily_counts(&self, from: NaiveDate, to: NaiveDate) -> Result, StoreError>; + async fn daily_counts(&self, from: NaiveDate, to: NaiveDate, include_private: bool) -> Result, StoreError>; + async fn language_daily_counts(&self, from: NaiveDate, to: NaiveDate, include_private: bool) -> Result, StoreError>; async fn repo_languages(&self) -> Result, StoreError>; } diff --git a/crates/moments-data/src/lib.rs b/crates/moments-data/src/lib.rs index 9fb2ffb..d503f88 100644 --- a/crates/moments-data/src/lib.rs +++ b/crates/moments-data/src/lib.rs @@ -196,7 +196,7 @@ impl EventReader for PgStore { .collect() } - async fn daily_counts(&self, from: NaiveDate, to: NaiveDate) -> Result, StoreError> { + async fn daily_counts(&self, from: NaiveDate, to: NaiveDate, include_private: bool) -> Result, StoreError> { let rows = sqlx::query( r#" SELECT d::date AS date, @@ -205,13 +205,14 @@ impl EventReader for PgStore { LEFT JOIN events e ON e.occurred_at >= (d::date || 'T00:00:00Z')::timestamptz AND e.occurred_at < ((d::date + 1) || 'T00:00:00Z')::timestamptz - AND e.public = true + AND ($3::bool OR e.public = true) GROUP BY d::date ORDER BY d::date "#, ) .bind(from) .bind(to) + .bind(include_private) .fetch_all(&self.pool) .await .map_err(map_err)?; @@ -226,7 +227,7 @@ impl EventReader for PgStore { .collect() } - async fn language_daily_counts(&self, from: NaiveDate, to: NaiveDate) -> Result, StoreError> { + async fn language_daily_counts(&self, from: NaiveDate, to: NaiveDate, include_private: bool) -> Result, StoreError> { let rows = sqlx::query( r#" SELECT date, language, color, @@ -244,7 +245,7 @@ impl EventReader for PgStore { JOIN events e ON e.occurred_at >= (d::date || 'T00:00:00Z')::timestamptz AND e.occurred_at < ((d::date + 1) || 'T00:00:00Z')::timestamptz - AND e.public = true + AND ($3::bool OR e.public = true) AND e.action IN ('Commit', 'PushEvent', 'commit_repo') JOIN repo_languages rl ON rl.source = e.source @@ -273,6 +274,7 @@ impl EventReader for PgStore { ) .bind(from) .bind(to) + .bind(include_private) .fetch_all(&self.pool) .await .map_err(map_err)?;