You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#4572 added plan_key attribution to API-key usage events so the #3199 limit-abuse audit could be self-serve. But a live audit (30d) shows the attribution is incomplete on keyed / non-tier-gated routes: a large share of user_api_key served events still emit plan_key=None.
Evidence (Axiom wm_api_usage, last 30d)
~65k auth_kind='user_api_key' served (reason='ok') events have isnull(plan_key).
~60k (~92%) come from ACTIVE api_starter customers — verified apiAccess:true, tier:2, future validUntil via Convex internal-entitlements: user_3CUolmnQ (21,998), user_3CZ8vEx (18,064), user_3FJlaDjk (11,260), user_3F99IpSC (5,955), user_3Eox4iLM (3,789), …
These land on keyed routes: list-cyber-threats, list-stablecoin-markets, list-market-quotes, get-macro-signals, get-sector-dependency, etc.
The limit-abuse / per-plan usage audit that #4572 was built to enable cannot group these events by plan — the exact customers most relevant to cap tuning (the high-volume Starter accounts flagged in the #3199 shadow audit) show up unattributed.
Where to look
#4572 sets usage.planKey via recordUsageEntitlement() in the gateway per-account rate-limit block (server/gateway.ts). For isUserApiKey requests that reach a successful terminal emitRequest(200,'ok'), planKey should be populated. Investigate the emit path(s) where an active keyed request produces an ok event withoutrecordUsageEntitlement having run first (e.g. an early/edge-cache return, a handler emitting its own usage event, or a getEntitlements null at that instant). Note: PR #4612 (#4611) now also calls recordUsageEntitlement earlier in the flow (the active-subscription gate), which may narrow but not fully close this.
Repro (audit recipe)
AXIOM_API_TOKEN (query-capable) + Convex CONVEX_SITE_URL/CONVEX_SERVER_SHARED_SECRET in .env.local; query ['wm_api_usage'] | where auth_kind=='user_api_key' and isnull(plan_key) and reason=='ok' | summarize count() by customer_id, then check each customer_id against /api/internal-entitlements.
Summary
#4572addedplan_keyattribution to API-key usage events so the #3199 limit-abuse audit could be self-serve. But a live audit (30d) shows the attribution is incomplete on keyed / non-tier-gated routes: a large share ofuser_api_keyserved events still emitplan_key=None.Evidence (Axiom
wm_api_usage, last 30d)auth_kind='user_api_key'served (reason='ok') events haveisnull(plan_key).api_startercustomers — verifiedapiAccess:true,tier:2, futurevalidUntilvia Convexinternal-entitlements: user_3CUolmnQ (21,998), user_3CZ8vEx (18,064), user_3FJlaDjk (11,260), user_3F99IpSC (5,955), user_3Eox4iLM (3,789), …list-cyber-threats,list-stablecoin-markets,list-market-quotes,get-macro-signals,get-sector-dependency, etc.Impact
The limit-abuse / per-plan usage audit that #4572 was built to enable cannot group these events by plan — the exact customers most relevant to cap tuning (the high-volume Starter accounts flagged in the #3199 shadow audit) show up unattributed.
Where to look
#4572setsusage.planKeyviarecordUsageEntitlement()in the gateway per-account rate-limit block (server/gateway.ts). ForisUserApiKeyrequests that reach a successful terminalemitRequest(200,'ok'),planKeyshould be populated. Investigate the emit path(s) where an active keyed request produces anokevent withoutrecordUsageEntitlementhaving run first (e.g. an early/edge-cache return, a handler emitting its own usage event, or a getEntitlements null at that instant). Note: PR #4612 (#4611) now also callsrecordUsageEntitlementearlier in the flow (the active-subscription gate), which may narrow but not fully close this.Repro (audit recipe)
AXIOM_API_TOKEN(query-capable) + ConvexCONVEX_SITE_URL/CONVEX_SERVER_SHARED_SECRETin.env.local; query['wm_api_usage'] | where auth_kind=='user_api_key' and isnull(plan_key) and reason=='ok' | summarize count() by customer_id, then check eachcustomer_idagainst/api/internal-entitlements.Surfaced during #4611 / PR #4612.