Skip to content

feat(feeds): add ?since= filter for incremental feed polling#2179

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
glorydavid03023:feat/feeds-since-filter
Jun 28, 2026
Merged

feat(feeds): add ?since= filter for incremental feed polling#2179
JSONbored merged 1 commit into
JSONbored:mainfrom
glorydavid03023:feat/feeds-since-filter

Conversation

@glorydavid03023

Copy link
Copy Markdown
Contributor

Summary

Adds an optional ?since=<ISO-8601> lower bound to the content feeds (/api/v1/feeds/registry, /incidents, /subnets/{netuid}), alongside the existing ?tag= filter. It returns only items at or after that instant, so a consumer can poll a focused, incremental slice instead of re-fetching and re-diffing the whole window each time.

Closes #2178

Behavior

  • ?since=2026-06-20 or ?since=2026-06-20T00:00:00Z → only items with timestamp >= since.
  • Composes with ?tag= — e.g. ?tag=incident&since=<last_seen>.
  • Items are filtered by their existing timestamp; an item whose timestamp can't be parsed is dropped (never leaks past an explicit since).
  • A malformed since is a 400 (via the shared feed error envelope), matching the strict param validation used elsewhere in the API.
  • Absent since is a no-op (the whole feed) — fully backward-compatible.

Scope

  • Self-contained in src/feeds.mjs — Worker-computed at request time; no schema/contract/artifact change (feeds aren't part of the typed OpenAPI envelope), so nothing to regenerate.
  • Mirrors the existing filterByTag helper and the fail(...) error path.

Tests (tests/feeds.test.mjs)

  • filterSince unit tests: null no-op, at/after the bound, inclusivity of the exact bound, dropping unparseable timestamps.
  • Handler tests: a future since → empty-but-valid 200 feed; a past since keeps items and composes with ?tag=; a malformed since → 400.
✓ tests/feeds.test.mjs (56 tests)

eslint and prettier --check clean on both files. Full local vitest run shows no new failures (only pre-existing Windows-only env issues that pass on Linux CI).

Add an optional `?since=<ISO-8601>` lower bound to the content feeds: return
only items at or after that instant (e.g. ?since=2026-06-01 or
?since=2026-06-01T00:00:00Z). It composes with the existing ?tag= filter, so an
agent can poll a focused, incremental slice instead of re-diffing the whole
window each time.

- Items are filtered by their existing `timestamp`; an unparseable timestamp is
  dropped so it never leaks past an explicit `since`.
- A malformed `since` is a 400 via the shared feed error envelope, matching the
  strict param validation elsewhere in the API.
- Absent `since` is a no-op (the whole feed) — fully backward-compatible.

Worker-computed in src/feeds.mjs; no schema/contract/artifact change. Covered by
unit tests for filterSince (bound, inclusivity, bad timestamps) and handler
tests for the future/past cases, ?tag= composition, and the 400.

Closes JSONbored#2178
@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.26%. Comparing base (baf8822) to head (2289891).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2179   +/-   ##
=======================================
  Coverage   93.25%   93.26%           
=======================================
  Files          51       51           
  Lines        8076     8087   +11     
  Branches     2962     2966    +4     
=======================================
+ Hits         7531     7542   +11     
  Misses         92       92           
  Partials      453      453           
Files with missing lines Coverage Δ
src/feeds.mjs 94.37% <100.00%> (+0.41%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gittensory-orb

gittensory-orb Bot commented Jun 27, 2026

Copy link
Copy Markdown

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ Gittensory review — safe to merge

2 files · 1 AI reviewers · no blockers · readiness 55/100 · CI green · clean

✅ Approved — safe to merge

Review summary
Adds an optional `?since=<ISO-8601>` lower-bound filter to all three feed endpoints by parsing the param once before any artifact I/O (the correct early-rejection pattern), applying it as a composable post-filter after `filterByTag` and before `sortAndCap`, and exporting `filterSince` through `__test`. The implementation is correct: the inclusive `>=` comparison, the NaN-drop for unparseable item timestamps, the null no-op, and the 400 on a malformed param all behave exactly as documented. No contract artifact regeneration is needed since feeds aren't part of the typed OpenAPI envelope — the scoping call is sound.

Signal Result Evidence
Code review ✅ No blockers 1 reviewers, synthesized
Linked issue ✅ Linked #2178
Related work ⚠️ 2 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Review load ❌ 8/20 Readiness component derived from cached public PR metadata and labels.
Validation evidence ❌ 5/25 Cached preflight status is hold.
Open PR queue ❌ 3/10 15 open PR(s), 13 likely reviewable, 2 unlinked.
Contributor context ✅ Confirmed Gittensor contributor glorydavid03023; Gittensor profile; 188 PR(s), 7 issue(s).
Gate result ✅ Passing No configured blocker found.
Nits — 5 non-blocking
  • tests/feeds.test.mjs (`?since= filter` › `a past since keeps items and composes with ?tag=`): the bound `since=2000-01-01` is earlier than all fixture timestamps, so `filterSince` is a no-op and the test only proves the two filters don't crash together — it doesn't verify `since` actually narrows the result set in composition. Tighten the bound to e.g. `since=2026-06-14` (after `old` but before `new` in the fixture) so the composed case genuinely exercises both filters.
  • tests/feeds.test.mjs (ETag suite): there is no ETag-stability test for a `?since=`-parameterized feed, unlike the existing `'a tag-filtered feed has its own ETag and 304s on a match'` test for `?tag=`. Add a parallel test confirming a `?since=`-filtered feed emits a distinct ETag from the unfiltered feed and 304s correctly on a matching `If-None-Match`.
  • tests/feeds.test.mjs: in the composition test, use a bound like `since=2026-06-14T00:00:00.000Z` — it sits between the `old` and `new` fixture items and proves `filterSince` is still active when `?tag=` is also applied.
  • tests/feeds.test.mjs: mirror the existing `tag`-filtered ETag test for `since` — assert `feed('/api/v1/feeds/registry?since=2026-06-14').etag !== feed('/api/v1/feeds/registry').etag` and that a matching `If-None-Match` on the `since`-parameterized URL returns 304.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.
Review context
Contributor next steps
  • Review top overlaps.
  • Add scope summary.
  • Fix blocker.
  • Expect slower review.
  • Refresh registry data or choose a registered active repo.
  • Check active issues and PRs before submitting.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Review load = cached public PR metadata such as size labels, changed paths, and preflight status.
  • Open PR queue = repo-wide review pressure; it is not a PR quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
Review details

Generated from public PR metadata and the diff. Advisory only; deterministic signals remain authoritative.

Adds an optional `?since=<ISO-8601>` lower-bound filter to all three feed endpoints by parsing the param once before any artifact I/O (the correct early-rejection pattern), applying it as a composable post-filter after `filterByTag` and before `sortAndCap`, and exporting `filterSince` through `__test`. The implementation is correct: the inclusive `>=` comparison, the NaN-drop for unparseable item timestamps, the null no-op, and the 400 on a malformed param all behave exactly as documented. No contract artifact regeneration is needed since feeds aren't part of the typed OpenAPI envelope — the scoping call is sound.

Nits (4)

  • tests/feeds.test.mjs (`?since= filter` › `a past since keeps items and composes with ?tag=`): the bound `since=2000-01-01` is earlier than all fixture timestamps, so `filterSince` is a no-op and the test only proves the two filters don't crash together — it doesn't verify `since` actually narrows the result set in composition. Tighten the bound to e.g. `since=2026-06-14` (after `old` but before `new` in the fixture) so the composed case genuinely exercises both filters.
  • tests/feeds.test.mjs (ETag suite): there is no ETag-stability test for a `?since=`-parameterized feed, unlike the existing `'a tag-filtered feed has its own ETag and 304s on a match'` test for `?tag=`. Add a parallel test confirming a `?since=`-filtered feed emits a distinct ETag from the unfiltered feed and 304s correctly on a matching `If-None-Match`.
  • tests/feeds.test.mjs: in the composition test, use a bound like `since=2026-06-14T00:00:00.000Z` — it sits between the `old` and `new` fixture items and proves `filterSince` is still active when `?tag=` is also applied.
  • tests/feeds.test.mjs: mirror the existing `tag`-filtered ETag test for `since` — assert `feed('/api/v1/feeds/registry?since=2026-06-14').etag !== feed('/api/v1/feeds/registry').etag` and that a matching `If-None-Match` on the `since`-parameterized URL returns 304.

🟩 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 Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@JSONbored JSONbored merged commit 38739a0 into JSONbored:main Jun 28, 2026
8 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Feature / enhancement gittensor Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

feat(feeds): add ?since= filter for incremental feed polling

2 participants