Follow-up to the archive feature: archived healthchecks showed in both the
main All-sites list and the Archived section. allSitesSummary() now excludes
archived sessions from the aggregate (and from the per-site "latest session"
detail), so a site whose sessions are all archived drops off the main list
and appears only under "Archived". A site with a mix keeps its row, counting
only its live sessions. The per-site page still lists every session.
Also bumps the server version baseline in config.php.example to 0.1.8.
2 new tests (51 total).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Some audits are no longer needed. Add an archive toggle so they can be filed
away without deleting the history.
- Migration 0003 adds healthchecks.archived (INTEGER 0/1, NOT NULL DEFAULT 0
— portable across MySQL/SQLite).
- Per-site page (/dashboard?site=X): each session row gets an Archive /
Unarchive button and archived rows carry a muted "archived" badge.
- Home page: archived healthchecks are gathered under an "Archived" heading
at the foot, each with an Unarchive button.
- POST /dashboard/healthchecks/{id}/archive, mirroring the reopen flow:
session-cookie auth + CSRF token. archived=1 archives, else un-archives.
The redirect-back target is validated to a same-origin /dashboard path
(no open-redirect / header injection).
- setArchived() deliberately leaves updated_at alone, so filing a session
doesn't jump its site to the top of the dashboard ordering.
- Archived items are NOT hidden from their normal listings, per the request.
Dashboard-only; not exposed through the plugin API. 7 new tests (49 total).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lets a technician record when a site should next be looked at, and surfaces
that in the dashboard so it can be used for planning.
Server:
- migration 0002 adds healthchecks.next_due, a VARCHAR(10) 'YYYY-MM-DD'
calendar date rather than a timestamp — it's a diary date with no
time-of-day, and a timestamp would render as the wrong day off-server.
- Kept per-session rather than on a sites table, so the history of what was
scheduled when is preserved. A site's current next-due is the value on its
most recent session: if the latest visit scheduled nothing, the site reads
as unscheduled rather than showing the just-completed visit as overdue.
- Validate::optionalDate() round-trips through createFromFormat, which
rejects both '2026-2-3' and '2026-02-30' (silently rolled to March 2nd).
- next_due follows the same missing-vs-null PUT contract as finished_at, and
lives in its own Store::setNextDue() so finishing or reopening a session
never disturbs the date and vice versa.
- Dashboard shows it on the site list, the per-site session table and the
session detail, flagged overdue / today / soon (within a fortnight).
Plugin:
- Date control on both the active and finished panels — the moment you know
when to return is often wrap-up, after the report is generated.
- Write-through like every other mutation. Bad input is rejected with a
notice rather than silently clearing an existing date.
- Included in both the Markdown and HTML reports.
Tests (new — tests/, export-ignored from the plugin zip):
- Hand-rolled harness, no composer/PHPUnit, in keeping with the repo.
- 42 tests: plugin-side date parsing units, plus server integration tests
driven over real HTTP against a temp `php -S` instance with a throwaway
SQLite DB, so a real server/config.php is never touched.
- Mutation-checked: dropping the array_key_exists guard on PUT fails three
tests, as intended.