The Telegram feed path appears to have a contract mismatch between the edge relay endpoint, the browser UI model, and the public intelligence API.
What I found:
/api/telegram-feed proxies the relay response body through unchanged.
- The browser-side Telegram service/panel expects
items[] with fields like ts, url, and channelTitle:
- The server/public API defines
messages[] with fields like timestampMs, sourceUrl, and channelName:
Why this matters:
- The browser code currently does a plain cast after
res.json() and does not normalize or validate the payload shape.
- If the relay returns the documented server-style shape (
messages[]), the panel reads response.items || [] and silently shows an empty list / zero count.
- Even beyond the top-level array name, the item field names differ enough that the panel cannot consume the API model directly.
Related issue:
api/telegram-feed.js also checks only parsed.items when deciding whether to apply the “empty feed” short cache TTL, so a non-empty messages[] payload may be cached as if it were empty.
Suggested fix:
- Pick one canonical raw Telegram payload shape.
- Add an explicit adapter for the browser panel instead of relying on a TypeScript cast.
- Make the edge proxy/cache logic understand the canonical shape.
- Add regression tests for:
- browser mapping from raw Telegram payload -> UI model
- server/API handler mapping from relay payload ->
ListTelegramFeedResponse
I did not verify the live Railway relay payload, so the main problem here is repo-internal inconsistency: the UI contract and the API contract currently disagree.
The Telegram feed path appears to have a contract mismatch between the edge relay endpoint, the browser UI model, and the public intelligence API.
What I found:
/api/telegram-feedproxies the relay response body through unchanged.items[]with fields likets,url, andchannelTitle:messages[]with fields liketimestampMs,sourceUrl, andchannelName:Why this matters:
res.json()and does not normalize or validate the payload shape.messages[]), the panel readsresponse.items || []and silently shows an empty list / zero count.Related issue:
api/telegram-feed.jsalso checks onlyparsed.itemswhen deciding whether to apply the “empty feed” short cache TTL, so a non-emptymessages[]payload may be cached as if it were empty.Suggested fix:
ListTelegramFeedResponseI did not verify the live Railway relay payload, so the main problem here is repo-internal inconsistency: the UI contract and the API contract currently disagree.