From b92143f71080aa7df13e409e96098619d3f04840 Mon Sep 17 00:00:00 2001 From: "Beau Beauchamp, WebTigers" Date: Sat, 24 Oct 2026 13:41:43 -0400 Subject: [PATCH] =?UTF-8?q?release:=20tiger-core=201.42.0=20=E2=80=94=20re?= =?UTF-8?q?set=20dead-link=20UX=20(TIGER-387),=20Updates=20grid=20on=20/ap?= =?UTF-8?q?i=20(TIGER-383),=20UI=20test=20harness=20(TIGER-386)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor, not patch: three new @api methods ship (Tiger_Service_Authentication:: resetTokenIsLive, Tiger_Model_UpdateHistory::datatable, System_Service_Updates:: datatable). No breaking changes — System_Service_Updates::history() is kept for API/MCP callers, and the reset submit path is unchanged. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_013vdyTeoDrGE4hKxt53TsE8 --- CHANGELOG.md | 37 +++++++++++++++++++++++++++++++++++++ library/Tiger/Version.php | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a369d2f..2b368efb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,43 @@ All notable changes to **Tiger Core** (`webtigers/tiger-core`). Format follows ## [Unreleased] +## [1.42.0] — 2026-10-24 + +### Fixed +- **A dead password-reset link now says so BEFORE you choose a password** (TIGER-387). An expired, + already-used or malformed reset link used to render an ordinary "Set a new password" screen: the user + picked a password, typed it twice, submitted — and only then learned the link was dead. The refusal was + always correct and safe; it arrived after the work instead of before it, and the people who hit it are + the ones already locked out. `AuthController::resetAction` now checks the token on GET and renders a + dead-link card with a one-click **Request a new link**. New + `Tiger_Service_Authentication::resetTokenIsLive()` is a READ-ONLY peek — it never consumes the challenge + and never costs an attempt, so it is safe at render time; it checks the challenge, not the code (a code + cannot be verified without spending an attempt, and the challenge id is an opaque v4 UUID the link holder + already has). `resetPassword()` still re-checks at submit, because a token can expire in between. Three + new i18n keys in all six shipped locales. + +### Changed +- **The Updates history is a real grid, fetched from `/api`** (TIGER-383). It was the one admin screen + still server-rendering list data, against the client/server contract (WEBSERVICES.md §5) — and behind the + consistency point was a real gap: the screen could only ever show the newest 15 runs, so older history + was unreachable, unsearchable and unpageable. Converted to the house DataTables pattern: + `Tiger_Model_UpdateHistory::datatable()` owns the query (search / sort / paging / counts, so no predicate + is built in a service), `System_Service_Updates::datatable()` returns the standard envelope with + STRUCTURED rows only, and the controller renders the shell with `useDataTables`. The per-run step log + became a DataTables child row and rides with the row payload, so expanding it costs no round trip. + `System_Service_Updates::history()` is kept — it is the plain read an API/MCP caller wants without + DataTables semantics, and `history` is a READ_VERB, so a read-only token can reach it. + +### Added +- **Functional UI test harness** (`tests/ui/`, TIGER-386). Three layers, each answering a different + question: `bin/paradigm-scan.php` checks the client/server contract statically across every view script + in milliseconds; `bin/auth-probe.php` exercises the auth surface's AJAX/JSON contract with no browser + (CI-able); `scenarios/auth.json` drives a real browser through sign-in, failed sign-in, reset and + sign-out. The scan's first run over 108 views found **zero page-POST violations** — the paradigm holds — + and the two defects above. Dev-only by construction: both probes refuse a production base URL and + negative-path scenarios use `@example.invalid` identifiers so a run can never trip a real account's + lockout. A check that could not actually run reports GATED, never PASS. + ## [1.41.0] — 2026-10-24 ### Added diff --git a/library/Tiger/Version.php b/library/Tiger/Version.php index 8da5756b..7dd255b9 100644 --- a/library/Tiger/Version.php +++ b/library/Tiger/Version.php @@ -9,5 +9,5 @@ class Tiger_Version { /** Current Tiger Core version. Keep in lockstep with the git tag cut for a release. */ - const VERSION = '1.41.0'; + const VERSION = '1.42.0'; }