Changelog
Every release, verbatim from the repos. The platform ships as a pair — the frontend app and the ETL backend version together, and both histories are here.
Platform status
Live from the deployed services.
Frontend
Checking…
Backend API
Checking…
Frontend
v2.2.32026-10-31The PRMNews app — the feed, signals, Workbench, and everything you see.
v2.2.3
2026-10-31Security
- Carried, dev-only:
minimatchGHSA-g3hv-75wg-m249 (globparts DoS, patched only in the new 11.x major, published 2026-10-27) sits under the eslint chain (3.1.5 / 10.2.5). No same-major backport exists yet and the cross-major floor is forbidden by the cve-audit rule; no Dependabot alert is open. Re-check at the next sweep.
Added
- Bundles (sprint-149, owner FR 2026-10-27): a bundle is a published tag. On Saved Articles, Select → pick stories → Bundle… names them (the name becomes a tag, e.g. "Pastor Tim" →
#pastor-tim) and mints a public link; Share as bundle on a By-tag header publishes an existing tag. The public page/s/b/{token}(no sign-in) shows the title, intro, one card per story (kicker, headline, attribution, PRM summary, Watchman Briefing headline, placeholder art), Copy link, Share (Web Share on phones), aJSON for agentslink (/api/bundle/{token}.json), and the same attribution/takedown footer as the share page; each story opens at/s/b/{token}/{articleSK}in the share page's form with a back link. Membership is live: tagging more stories updates the link. Workbench → Bundles lists every bundle with expiry (30 days, Renew 30d), views, Copy link, Open, Stories, Edit, New link (rotate), Revoke and Delete. - Saved Articles tags (sprint-149, owner FR 2026-10-27 + subscriber FR):
#tagchips under every card with a tag editor (Enter or comma adds, your other tags as one-click suggestions, ≤10 per article),#tagtokens in the search box constrain the list beside free text (#ai drone), an All | By tag view switch kept in the URL (?view=tags) with the By-tag accordion (count, last saved, Open in grid; Untagged group last), Select mode for bulk tagging, and a save-moment toast whose Add tag action opens the card's editor (?focus=<articleSK>).
Changed
- Saved Articles follow-ups (owner, 2026-10-30): more room between the control row and the grid; the page size follows the layout's column count (3 columns → 21, 4 → 24, 2 → 20) so Dense pages fill every row; in the By-tag view each tag group has its own Export that walks only that tag (the whole-list Export shows on All only).
- PDF export: a linked cell (the article title) is now clickable over its whole area and set in the PRM blue; the URL still prints under it.
- Public share page
/s/{token}(owner decision 2026-10-27, sprint-149): no article text (the 30% excerpt, its meter and fade-out are gone), no publisher photograph (letterpress-style placeholder art keyed by category stands in, and the social card is PRM's own/og/prm-card.png), the continue-at-source card describes PRM's own summary and analysis, and the footer carries the "Powered by NewsData.io API" attribution the provider's terms require plus a Copyright & takedown link. Headline, attribution, PRM summary, Watchman Briefing and the metadata rail are unchanged. docs/bundles-and-tags.html: design analysis for Saved Article tags and share bundles, with the decisions and public-surface rules behind this change.
Backend
v2.2.42026-10-31The PRM ETL pipeline and API — ingestion, scoring, and the data behind the signals.
v2.2.4
2026-10-31Security
follow-redirects1.16.2 floor (GHSA-mrwp-f3q8-3g9p, high: cross-realmsensitiveHeadersarrays discarded, credentials could follow redirects; axios transitive, same-major override).- Carried, documented:
globGHSA-3g3m-2fjr-6pw4 (AbortSignal bypass) andminimatchGHSA-g3hv-75wg-m249 (globparts DoS) underswagger-jsdoc, which pinsglob@11.1.0exactly; the fixes exist only inglob14.0.2+ /minimatch11.0.1+ (new majors, 2026-10-27), no backport, and swagger-jsdoc globs repo-owned JSDoc paths at boot, never user input. Re-check next sweep.deepmergelow via resend still carried (no fix).
Changed
- Public article surfaces carry no article text and no publisher photograph (owner decision 2026-10-27, sprint-152).
GET /share/:tokenno longer returnsbody(the 30% fair-use clip) orarticle.contentExcerpt, omitsarticle.imageURL, and cuts a publisher description that is really the article's opening to the feed's 280-character teaser. The published feed drops the item image / RSS<enclosure>, and the agent article detail omitsimageURL. In-app article detail is unchanged.
Added
DELETE /api/v1/share/:tokenrevokes one of the caller's share links (the public page 404s from the next request; re-minting reactivates it).- Bundles (sprint-152, owner FR 2026-10-27): a bundle is a published tag — "Pastor Tim" owns the slug
pastor-tim, and the owner's saved articles carrying that tag are its members, resolved live. New collectionshare_bundles(128-bit rotatable token, title, intro, 30-day renewable serve-time expiry, view counters). Owner routes under/api/v1/share/bundles(create from a selection, list with member counts, patch/renew, rotate, revoke, delete); publicGET /share/bundles/public/:token[.json](title, intro, members in the share projection with a Watchman Briefing digest each; uniformNOT_FOUNDfor unknown/revoked/expired) andGET /share/bundles/public/:token/articles/:articleSK(membership grants access). Per-IP + per-token limiters (RATE_LIMIT_BUNDLE_TOKEN_HOURLY_MAX, default 600;RATE_LIMIT_SHARE_MAXnow in the env files). services/share/SharedArticleService.js: the public-article projection + briefing loader shared by the share and bundle surfaces (moved out of the share controller).
Fixed
ClerkUserService.getUserIdByEmailnow returns the id the app keys a person on (ClerkexternalIdfor readers migrated from the development instance, else the real id). Its two callers key app data with the result: the usage-meter reset by email missed a migrated reader's meters, and a team-chat cohort invitation by email was stored under an id the migrated invitee never signs in with. Found by the 2026-10-29 id sweep after the digest audience bug.
