Add `ETag`/conditional-request support to read-only GET endpoints
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- nodejs, typescript
- Domain
- api, performance
Research direction
Start with src/discovery/agent-reviews.service.ts or the portfolio list route, and read src/common/cache/cache-invalidation.service.ts to see how mutations are signalled. Add a weak ETag and a 304 path for a matching If-None-Match, with Cache-Control: private on authenticated responses. Done when a test confirms user B never receives user A's cached response and the ETag changes after a mutation.
Written by the indexing model from the issue text.
Description
Problem
No response caching is implemented anywhere in the codebase. There is no ETag, no Cache-Control, and no conditional-request handling (If-None-Match) on any of the roughly 377 routes.
There is a caching service available — src/common/cache/ with cache.service.ts, cache-warming.service.ts, cache-invalidation.service.ts, and cache-stats.service.ts, plus a cacheable.decorator.ts — but that is an in-process/Redis cache for data access, which is a different concern from HTTP response caching.
Good candidates that are currently fully recomputed on every request: agent discovery and reviews (src/discovery/agent-reviews.service.ts), health component status, and portfolio performance endpoints.
Why it matters
Several of these endpoints are read-heavy and change rarely. Without conditional requests every dashboard poll re-serialises the same payload and every client re-downloads it, which is pure waste on both sides and inflates the API's egress costs. For an SDK-driven client polling a portfolio or agent list, this is the difference between a few KB and tens of KB per poll.
Suggested Direction
- Start with one endpoint and prove the pattern —
GET /api/v1/portfolio/portfolios(list) or the agent reviews endpoint is a good candidate. - Generate a weak ETag from a cheap content fingerprint. If the underlying rows have an
updatedAt, prefer a version or hash over serialising the response twice. The cursor-pagination utility insrc/common/pagination/may already have a hashing approach worth reusing. - Handle
If-None-Matchby returning304 Not Modifiedwith no body. - Set an appropriate
Cache-Control— note that authenticated responses are per-user, sopubliccaching would be a data leak across users. Useprivate, max-age=...orno-storewhere responses vary by identity. - Invalidate correctly. If the resource is mutated, the ETag must change. The existing
cache-invalidation.service.tsis a natural hook.
Constraints
- Never cache per-user responses as public. Verify by testing that user B's response is not served to user A — the hardcoded
userId = "system"issue infile-upload.controller.tsis a reminder that identity handling here is currently unreliable. - Respect
Authorizationheaders: do not serve a cached response to a request that carries credentials unless the entry is explicitly user-scoped. - A 304 must carry
ETagand must not include a body. - Do not add HTTP caching in front of endpoints with existing side effects.
Acceptance Criteria
- At least one read-only GET endpoint returns an
ETag. - A matching
If-None-Matchreturns304with no body. -
Cache-Controlis set and isprivate(orno-store) for authenticated responses. - A test asserts user A's cached response is never served to user B.
- The ETag changes after the underlying resource is mutated.
- The pattern is documented in
CONTRIBUTING.mdso other endpoints follow it.
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 55
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 5
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from SourceXXL/alian_structure-api
-
good first issue help wanted security
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#266 ·
-
Parallelize the cache-warming loop in `cache-warming.service.ts` — warmers run strictly sequentiallyPossibly taken @syntaxsuuvam-spec claimed this 4 days ago. Opengood first issue performance
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#240 ·
-
documentation help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
SourceXXL/alian_structure-api#215 ·
-
good first issue refactor tooling
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
SourceXXL/alian_structure-api#199 ·
-
help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
SourceXXL/alian_structure-api#196 ·
All issues in SourceXXL/alian_structure-api
Similar issues
-
fix(frontend): correct VITE_IS_DEVELPOMENT typo in shared/app.ts and align dev environment flagsOpen
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
vicharanashala/ajrasakha#1439 ·
Maintainers usually reply within 1 day
-
Add: TV5Monde AsieOpenapproved check:passed streams:add
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
codex-team/editor.js#3037 ·
-
complexity: trivial good first issue impact: low
Difficulty 1/5 Under an hour Newbie friendliness 78/100
ueberdosis/tiptap#8522 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
wormhole-foundation/wormhole#5062 ·
Maintainers usually reply within 1 day