feat(collectors): failure taxonomy — a 401 and a timeout are different problems (CashPilot-5bdm) - #313
Conversation
…e taxonomy end to end (CashPilot-5bdm) An expired credential earns $0 until a human acts; a provider outage fixes itself. They used to be the same free-text string, so the bell could only say 'collection failed' — teaching the user to ignore the one alert that needs them. EarningsResult.error_kind (auth/transient/shape, None = unknown, never guessed) with classify_exception for unclassified escapes; explicit kinds in honeygain, bytelixir, packetstream, salad and grass. A raised collector exception is now converted while the collector is still in hand, so its platform survives — it used to reach the gather() where attribution was unrecoverable and the failure was invisible. alerts.category column (closed enum, whitelisted at the boundary so a future error_kind=str(exc) cannot smuggle credential text into a durable any-role table) with a guarded migration; a dedupe hit inside the 24h window now refreshes the stored kind and message, because grass alternates auth and transient errors with no success in between and the first kind was pinned — a restart could render a dead credential as a muted self-healing blip. The push notification title carries the cause. The bell renders auth as 'credential expired' with a Fix-credential button, transient muted with NO button (never point a user at their credential for a network blip), shape without a button (our bug, their credential is fine), unknown keeps the button. Credentials past 75% of their known lifetime (or past it) join the bell as 'expiring' forecasts — their own category, because a prediction is not an observed rejection — with a muted badge when forecasts are all there is. 27 new tests including the negative controls that matter: a timeout is never auth, an unknown is never transient, history is never backfilled, the stored kind cannot go stale, the semaphore survives the new exception path.
|
Warning Review limit reached
Next review available in: 18 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (11)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #313 +/- ##
==========================================
+ Coverage 95.56% 95.57% +0.01%
==========================================
Files 51 51
Lines 6646 6685 +39
==========================================
+ Hits 6351 6389 +38
- Misses 295 296 +1
🚀 New features to boost your workflow:
|
An expired credential earns $0 until a human acts; a provider outage fixes itself. They were the same free-text
errorstring end to end, so the bell could only ever say "collection failed".Taxonomy:
EarningsResult.error_kind—auth/transient/shape,None= unknown and never guessed (an unknown labelled "self-heals" hides a real fault). Explicit kinds in honeygain, bytelixir, packetstream, salad, grass;classify_exceptionfor unclassified escapes. Ten remaining collectors' shape-errors tracked as CashPilot-dqaf.Attribution fix: a collector that RAISES is converted to an attributed result inside
_collect_bounded— the exception used to reach thegather()where the platform name was unrecoverable: no alert, no bell, no metric.Persistence:
alerts.categorycolumn (guarded migration; closed enum whitelisted at the boundary so error_kind can never smuggle unredacted exception text — which for several providers IS the credential — into a durable any-role table). A dedupe hit inside the 24h window now refreshes the stored kind+message: grass alternates auth/transient with no success in between, and the pinned first kind meant a restart could render a dead credential as a muted self-healing blip (review HIGH). Push titles carry the cause — the only channel an unattended install has.Bell: auth → "credential expired" + Fix credential; transient → muted, no button (never point a user at their credential for a network blip); shape → no button (our bug); unknown → button stays. Credentials ≥75% of known lifetime (or past it — the forecast must not vanish when it comes true) join as
expiring— a distinct category, because a prediction is not an observed 401 — and the badge goes muted when forecasts are all there is.27 new tests (negative controls: timeout-never-auth, unknown-never-transient, no history backfill, stale-kind refresh incl. the warm-rebuild path, closed-enum smuggling control, semaphore release). Full suite 4503 passed. Salad mutation (auth→transient) verified to fail the suite. Fresh review completed; all findings addressed or filed (dqaf).