88// is already durable, so a live weekly re-bucketing of the SAME rows can recompute any historical week correctly
99// on every request -- no cron-miss gap risk, and no second copy of the number to keep in sync.
1010//
11- // DELIBERATELY GLOBAL, not scoped to the public-stats repo allowlist: unlike accuracy/handled-PR counts, a
12- // cache-hit/miss event carries no PR content, author, or repo-specific outcome -- the aggregate reuse rate
13- // doesn't reveal anything about any one repo's activity, and target_key isn't uniformly shaped across all eight
14- // capabilities (some key by bare repoFullName, others by repoFullName#prNumber), so allowlist-filtering it would
15- // need a fragile per-capability parser for no real privacy benefit.
11+ // PUBLIC-SAFE SCOPE: only events whose target_key maps to GITTENSORY_PUBLIC_STATS_REPOS are included. Most
12+ // cache keys are either a bare repoFullName or repoFullName#prNumber; anything outside that allowlist is treated
13+ // as private operational telemetry and deliberately excluded from this unauthenticated payload.
1614//
1715// NAMING CONVENTION, not a hardcoded capability list: every instrumented capability already follows
1816// `github_app.<name>_cache_hit` / `github_app.<name>_cache_miss` (confirmed via a full-repo grep before writing
1917// this), so a single LIKE-pattern query picks up all eight today AND any future capability that follows the
2018// same convention, with zero code change here. ai_review's three additional REUSE variants (frozen/paused/
2119// one-shot) don't fit that exact suffix -- each is a genuine "skipped a redundant AI call" event, so they're
2220// folded into "hit" alongside the plain ai_review_cache_hit.
23- import { safeAll } from "../review/public-stats" ;
21+ import { publicStatsProjects , safeAll } from "../review/public-stats" ;
2422import { isoWeekStart } from "./public-quality-metrics" ;
2523
2624export const PUBLIC_REUSE_RATE_TREND_WEEKS = 8 ;
@@ -81,7 +79,9 @@ export function buildPublicReuseRateTrend(dayRows: DayRow[], nowMs: number, week
8179/** Day-bucketed hit/miss counts across every `github_app.<name>_cache_hit` / `_cache_miss` event, plus
8280 * ai_review's three non-suffix-conforming reuse variants (see file header). Fail-safe: degrades to [] on any
8381 * query error (safeAll), yielding under-counted weeks rather than throwing the whole public stats payload. */
84- async function loadReuseRateDayRows ( env : Env , sinceIso : string ) : Promise < DayRow [ ] > {
82+ async function loadReuseRateDayRows ( env : Env , projects : string [ ] , sinceIso : string ) : Promise < DayRow [ ] > {
83+ if ( projects . length === 0 ) return [ ] ;
84+ const projectPlaceholders = projects . map ( ( ) => "?" ) . join ( ", " ) ;
8585 const reuseTypePlaceholders = AI_REVIEW_REUSE_EVENT_TYPES . map ( ( ) => "?" ) . join ( ", " ) ;
8686 const rows = await safeAll < { day : string ; hits : number ; misses : number } > (
8787 env ,
@@ -90,10 +90,12 @@ async function loadReuseRateDayRows(env: Env, sinceIso: string): Promise<DayRow[
9090 SUM(CASE WHEN event_type LIKE 'github_app.%cache_miss' THEN 1 ELSE 0 END) AS misses
9191 FROM audit_events
9292 WHERE (event_type LIKE 'github_app.%cache_hit' OR event_type LIKE 'github_app.%cache_miss' OR event_type IN (${ reuseTypePlaceholders } ))
93+ AND LOWER(CASE WHEN instr(target_key, '#') > 0 THEN substr(target_key, 1, instr(target_key, '#') - 1) ELSE target_key END) IN (${ projectPlaceholders } )
9394 AND created_at >= ?
9495 GROUP BY day` ,
9596 ...AI_REVIEW_REUSE_EVENT_TYPES ,
9697 ...AI_REVIEW_REUSE_EVENT_TYPES ,
98+ ...projects ,
9799 sinceIso ,
98100 ) ;
99101 /* v8 ignore next -- SUM(CASE WHEN ... THEN 1 ELSE 0 END) over an existing GROUP BY day always yields a
@@ -105,7 +107,8 @@ async function loadReuseRateDayRows(env: Env, sinceIso: string): Promise<DayRow[
105107/** Assemble the public reuse-rate trend from the SAME live audit_events ledger every instrumented capability
106108 * already writes to. */
107109export async function loadPublicReuseRateTrend ( env : Env , nowMs : number = Date . now ( ) ) : Promise < PublicReuseRateTrendWeek [ ] > {
110+ const projects = publicStatsProjects ( env ) ;
108111 const sinceIso = new Date ( Date . parse ( isoWeekStart ( nowMs ) ) - ( PUBLIC_REUSE_RATE_TREND_WEEKS - 1 ) * MS_PER_WEEK ) . toISOString ( ) ;
109- const dayRows = await loadReuseRateDayRows ( env , sinceIso ) ;
112+ const dayRows = await loadReuseRateDayRows ( env , projects , sinceIso ) ;
110113 return buildPublicReuseRateTrend ( dayRows , nowMs ) ;
111114}
0 commit comments