fix(miner): sweep a claim with an unparseable claimedAt instead of retaining it forever - #7746
Conversation
…taining it forever claimAgeMs returns null when claim.claimedAt can't be parsed (Date.parse -> NaN), and findExpiredClaims skipped any claim with a null age entirely -- so a corrupted or hand-edited claim-ledger row was never swept and stayed permanently un-expirable. claimedAt is always written via new Date().toISOString() in claim-ledger.ts, so this is only reachable through a corrupted row, but when it happens the row is stuck active forever, which contradicts this module's own fail-closed posture. Treat a null (unparseable) age as expired, so such a row is swept rather than retained. claimAgeMs's signature and its behavior for valid timestamps are unchanged -- only how findExpiredClaims handles the null-age case. Closes JSONbored#7732
|
🚨 Contributor flagged. Click here for more info: Superagent Dashboard |
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7746 +/- ##
==========================================
Coverage 88.57% 88.58%
==========================================
Files 725 84 -641
Lines 76410 20685 -55725
Branches 22762 3656 -19106
==========================================
- Hits 67683 18323 -49360
+ Misses 7681 2184 -5497
+ Partials 1046 178 -868
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Warning ⏸️ LoopOver review result - manual review recommendedReview updated: 2026-07-21 13:55:34 UTC
Review summary Nits — 4 non-blocking
Flagged checks (non-blocking)
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionPartially addressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
JSONbored
left a comment
There was a problem hiding this comment.
.js is no longer necessary once my PR merges - c
What
claimAgeMs(packages/loopover-miner/lib/claim-ledger-expiry.ts) returnsnullwhenclaim.claimedAtcan't be parsed (Date.parse→NaN), andfindExpiredClaimsskipped any claim with anullage:So a corrupted or hand-edited claim-ledger row was never swept — it stayed permanently un-expirable.
claimedAtis always written vianew Date().toISOString()inclaim-ledger.ts, so this is only reachable through a corrupted row, but when it happens the row is stuck active forever, contradicting this module's own fail-closed posture.Fix
Treat a
null(unparseable) age as expired — fail closed — so the row is swept rather than retained:claimAgeMs's signature and its behavior for valid timestamps are unchanged; only howfindExpiredClaimshandles thenull-age case.Test
test/unit/miner-claim-ledger-expiry.test.ts's existing dangling-age test (previously asserting the bogus claim was skipped) is updated to assert the corrected fail-closed behavior: an unparseable-claimedAtclaim is now swept alongside a genuinely stale one, while a fresh claim stays within the window. Proven to fail against the pre-fix skip.Validation
npx vitest run test/unit/miner-claim-ledger-expiry.test.ts— 11/11.npm run typecheck— exit 0.npm run build:miner:check(committed.js/.d.tsmatches.ts),npm run test:miner-pack— pass.git diff --checkclean.Closes #7732