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

v1.0.12026-09-15

The PRMNews app — the feed, signals, Workbench, and everything you see.

v1.0.1

2026-09-15

Minor fix sprint (17 items), pairs with prm_etl Unreleased (facets q, articleSK filter, validation keyword taxonomy, /health.commit).

Security

  • Next.js 16.2.11 → 16.3.5 (two critical advisories: unauthenticated RCE in the Windows host path and in Image Optimization, patched ≥16.3.3); eslint-config-next moved with it. Floors in pnpm-workspace.yaml: next>sharp ^0.35.4 (libheif advisories), baseline-browser-mapping ≥2.11.0, js-yaml ≥4.3.2. pnpm audit --prod is clean. Note added to that file: pnpm.overrides in package.json REPLACES the workspace block, which silently dropped every existing floor during this bump until caught.

Added

  • Search boxes on list screens — Saved Articles, Saved Searches, My Engagements (title only) and Custom RSS Feeds get a shared ListSearchInput + matchesNeedle filter. Copy acts on the displayed filtered rows; Export refetches then applies the same filter; the count and the Export menu follow the filtered set. On the two paginated screens (Saved Articles, My Engagements) a search walks every page once via useSearchPool, hides pagination and reads "N matching of M".
  • Copy / Export on Saved Searches and Custom RSS Feeds (new export adapters saved-searches and external-feeds).
  • Article SK everywhere — the Article Scores card on article detail shows the article's numeric key with click-to-copy, and Advanced filters gain a digits-only "Article SK" box (?articleSK=) that pins the grid to one article and counts as an active filter (so the Default preset no longer overwrites the deep link).
  • Articles Validation: Sub-category column between Decision and Score, from the keyword taxonomy joined on the backend.
  • Filter panel scopes to a text search — the facets request carries q, so after a search the panel's counts describe the matched set (the panel total equals the grid total again) and the categories the search hit are pre-checked once per distinct search, sub-categories cascading, for the user to uncheck down to their slice.

Changed

  • Perplexity time range is a real API filter. The slice now travels as config.dateSlice and the BFF maps it to Perplexity's search_recency_filter / search_after_date_filter / search_before_date_filter via providerOptions (pure module date-slice-options.ts). The prose suffix ("focus on information in the last 7 days") is gone, which also stops history replay from double-appending it.
  • My Engagements toolbar is one wrapping row (Type · Engaged · From/To) instead of three stacked rows.
  • Surge Analysis keyword Select trims keywords to 40 characters in the trigger and the dropdown (full text on hover) and bounds the dropdown width; leaderboard tooltip and table keep the full keyword.
  • The Last Baton — the letter editor no longer clamps paragraphs to 68ch (it fills the editor like a normal word processor), and the Arm/Disarm button is colour-coded: yellow outline while a draft, red outline when armed, with the editor status badge matching.
  • Sandbox scrolls to the top when a run starts so the keyword definition and hydrating results are in view.

Fixed

  • Article detail hero image falls back to the default thumbnail when the publisher image fails to load, not only when the URL is missing.

Docs

  • Reviews: docs/notification-preferences-review.html, docs/last-baton-ux-auth-review.html, docs/agent-feed-api-design.html.
  • Release skill / deployment guide: the BE dev gate now asserts /health.commit; preflight announces the target environment.

Backend

v1.0.12026-09-15

The PRM ETL pipeline and API — ingestion, scoring, and the data behind the signals.

v1.0.1

2026-09-15

Added

  • /health.commit — short git SHA of the running checkout (APP_COMMIT in src/config/apiVersion.js: git rev-parse on the droplet working copy, PRM_COMMIT_SHA override for git-less runtimes, null never fails startup). Dev's identity is the commit, prod's is the tag; until now the release loop's dev gate could only compare the BE version, which equals prod's until the bump commit. Mirrors FE /api/version.commit.
  • Facets honour the free-text q (GET /articles/facets, pairs with prm_news Unreleased): parseAppliedFilters now reads q/searchScope and getFacets starts from the same Atlas $search head the list uses (buildSearchHead(), extracted from textSearch), so panel counts describe the text-matched set and facets.total equals the list's pagination.total again — the measure-footing invariant was violated whenever q was set.
  • articleSK list filter (GET /articles?articleSK=N): exact pin to one article for the Advanced → "Article SK" box; positive integers only, pushed into $search as an equals clause; never a preset dimension.
  • Articles Validation list carries the keyword taxonomy (keyword.category / keyword.subCategory) via a $lookup on etl_keywords by keywordValidation.keywordID, for the new Sub-category column. Staging rows are purged after evaluation, so the optional includeStaging join (which now also projects category/subCategory) cannot supply it for older records.
  • Audit cluster pin (ETL-AUDIT-005): pipeline step 327 now passes the backend's EXPECTED_DB_CLUSTER to the prm_audit harness as AUDIT_EXPECTED_DB_CLUSTER; the harness refuses to run (exit 3) when either of its Atlas URIs points at a different cluster, and the step records the refusal under its own error code instead of the generic harness error. Found via audit ticket 5c2965f7: after the 2026-09-05 prod/dev split, /opt/prm_audit/.env on prod still pointed at prmdb-dev, so three nightly runs audited dev data, healed prod rollups, and re-audited dev — eq.rollup.band-matrix sat yellow with no error anywhere. Harness side: prm_audit audit/pin.py (+ selfcheck fixtures, README, setup-script stub).