@@ -55,6 +55,16 @@ export const ADS_EXTERNAL_CONVERSION_POSTBACK_EVENT =
5555 * raw provider errors never enter this event. */
5656export const ADS_IMPREZIA_FETCH_COMPLETED_EVENT =
5757 'ads.imprezia_fetch_completed' as const
58+ /**
59+ * Ad routes refusing a request (COD-372) — rate limits and capability
60+ * failures on both rails, one event per refusal.
61+ *
62+ * A census of REFUSALS, never a forensic record: the capability token, the
63+ * impression id, the campaign and the ip are all absent by construction, so
64+ * this stream can be aggregated without ever having handled a bearer secret.
65+ * `reason` is a closed enum owned by `ad-route-rate-limit.ts`.
66+ */
67+ export const ADS_REQUEST_REJECTED_EVENT = 'ads.request_rejected' as const
5868
5969type AxiomOnlyFieldType = 'string' | 'number' | 'boolean'
6070type AxiomOnlyFieldSchema = Record < string , AxiomOnlyFieldType >
@@ -513,6 +523,18 @@ const ADS_EXTERNAL_CONVERSION_POSTBACK_FIELDS = {
513523 match_outcome : 'string' ,
514524} as const satisfies AxiomOnlyFieldSchema
515525
526+ /** The refusal census. Bounded producer-encoded labels only; the closed
527+ * `reason` enum lives beside the limiter that produces it. */
528+ const ADS_REQUEST_REJECTED_FIELDS = {
529+ route : 'string' ,
530+ rail : 'string' ,
531+ reason : 'string' ,
532+ limiter_backend : 'string' ,
533+ /** True in the `observe` phase: the request was SERVED and this records the
534+ * verdict enforcement would have produced. */
535+ would_limit : 'boolean' ,
536+ } as const satisfies AxiomOnlyFieldSchema
537+
516538export type AxiomOnlyLogEvent = {
517539 event :
518540 | typeof CONTEXT_PRUNING_COMPLETED_EVENT
@@ -525,6 +547,7 @@ export type AxiomOnlyLogEvent = {
525547 | typeof ADS_FIRST_PARTY_IMPRESSION_RECORDED_EVENT
526548 | typeof ADS_EXTERNAL_CONVERSION_POSTBACK_EVENT
527549 | typeof ADS_IMPREZIA_FETCH_COMPLETED_EVENT
550+ | typeof ADS_REQUEST_REJECTED_EVENT
528551 data : Record < string , string | number | boolean >
529552}
530553
@@ -623,6 +646,12 @@ export function getAxiomOnlyLogEvent(
623646 data : sanitizeAllowlistedFields ( record , ADS_FIRST_PARTY_TRACKING_FIELDS ) ,
624647 }
625648 }
649+ if ( eventName === ADS_REQUEST_REJECTED_EVENT ) {
650+ return {
651+ event : eventName ,
652+ data : sanitizeAllowlistedFields ( record , ADS_REQUEST_REJECTED_FIELDS ) ,
653+ }
654+ }
626655 if ( eventName === ADS_EXTERNAL_CONVERSION_POSTBACK_EVENT ) {
627656 return {
628657 event : eventName ,
0 commit comments