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-15The PRMNews app — the feed, signals, Workbench, and everything you see.
v1.0.1
2026-09-15Minor fix sprint (17 items), pairs with prm_etl Unreleased (facets
q,articleSKfilter, 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-nextmoved with it. Floors inpnpm-workspace.yaml:next>sharp^0.35.4 (libheif advisories),baseline-browser-mapping≥2.11.0,js-yaml≥4.3.2.pnpm audit --prodis clean. Note added to that file:pnpm.overridesin 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+matchesNeedlefilter. 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 viauseSearchPool, hides pagination and reads "N matching of M". - Copy / Export on Saved Searches and Custom RSS Feeds (new export
adapters
saved-searchesandexternal-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.dateSliceand the BFF maps it to Perplexity'ssearch_recency_filter/search_after_date_filter/search_before_date_filterviaproviderOptions(pure moduledate-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-15The PRM ETL pipeline and API — ingestion, scoring, and the data behind the signals.
v1.0.1
2026-09-15Added
/health.commit— short git SHA of the running checkout (APP_COMMITinsrc/config/apiVersion.js:git rev-parseon the droplet working copy,PRM_COMMIT_SHAoverride for git-less runtimes,nullnever 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):parseAppliedFiltersnow readsq/searchScopeandgetFacetsstarts from the same Atlas$searchhead the list uses (buildSearchHead(), extracted fromtextSearch), so panel counts describe the text-matched set andfacets.totalequals the list'spagination.totalagain — the measure-footing invariant was violated wheneverqwas set. articleSKlist filter (GET /articles?articleSK=N): exact pin to one article for the Advanced → "Article SK" box; positive integers only, pushed into$searchas anequalsclause; never a preset dimension.- Articles Validation list carries the keyword taxonomy
(
keyword.category/keyword.subCategory) via a$lookuponetl_keywordsbykeywordValidation.keywordID, for the new Sub-category column. Staging rows are purged after evaluation, so the optionalincludeStagingjoin (which now also projectscategory/subCategory) cannot supply it for older records. - Audit cluster pin (
ETL-AUDIT-005): pipeline step 327 now passes the backend'sEXPECTED_DB_CLUSTERto the prm_audit harness asAUDIT_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/.envon prod still pointed at prmdb-dev, so three nightly runs audited dev data, healed prod rollups, and re-audited dev —eq.rollup.band-matrixsat yellow with no error anywhere. Harness side:prm_auditaudit/pin.py(+ selfcheck fixtures, README, setup-script stub).
