Skip to content

feat(service-health-ping): tile health badge + archive#15

Merged
rubenvdlinde merged 2 commits into
developmentfrom
wip/build-health-ping-2026-07-23
Jul 23, 2026
Merged

feat(service-health-ping): tile health badge + archive#15
rubenvdlinde merged 2 commits into
developmentfrom
wip/build-health-ping-2026-07-23

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Implements and archives service-health-ping — the last of the nine market-gap changes. Answers the question a municipal IT landing page actually gets asked: is de zaakapplicatie bereikbaar?

What

  • HealthPingService — server-side HTTP check (avoids CORS/mixed-content), fail-closed host allow-list, ICache with a short TTL, online / offline / degraded classification.
  • HealthPingRefreshJob — TimedJob keeps the cache warm so page loads stay fast.
  • GET /api/health-ping/{placementId} (#[NoAdminRequired], placement view-ACL guarded) plus POST /api/health-ping/validate for save-time checks. The literal validate route is registered before the {placementId} route so it is never parsed as an id.
  • HealthPingBadge.vue overlay + tile config fields. Badge state is icon and text, never colour alone.

Verification (local, no CI wait)

Run after rebasing onto the full stack of the other eight changes:

  • phpunit full suite → 1472 tests, 3574 assertions, OK (3 pre-existing skips).
  • npx vitest run full suite → 615 tests across 56 files, all pass.

Merge-conflict resolution worth reviewing

This branch conflicted with tile-usage-analytics on TileWidget.vue and with iframe-embed-widget on routes.php. The first automatic resolution silently dropped recordTileClick, which would have removed tile-click analytics from the merged product. I caught it by diffing against origin/development and restored the import, the @click="handleActivate" binding and the methods block, so both features now coexist. Worth a second pair of eyes on that file.

Also: the build agent had hand-written openspec/specs/service-health-ping/spec.md; removed so openspec archive owns it.

Not done

Playwright e2e, left explicitly unchecked in the archived tasks.md.

…ealth badge

Adds an optional health ping to a tile: HealthPingService performs an
allow-listed, server-side HTTP check via IClientService, classifies the
result online/degraded/offline, and caches it in ICache (TTL = interval,
default 60s, min 15s). HealthPingController exposes the cached badge at
GET /api/health-ping/{placementId} with a placement view-ACL guard, never
leaking the health URL or response body. HealthPingRefreshJob (TimedJob,
15s tick) refreshes due, ping-enabled placements in the background so
viewers don't pay upstream latency.

The host allow-list (healthping_allowed_hosts) is enforced fail-closed at
both save time (POST /api/health-ping/validate) and ping time. Config
lives in the placement's existing content JSON blob - no schema change.

Frontend: HealthPingBadge.vue renders the state as an icon AND a text
label (never colour alone, WCAG AA), with an accessible checked-at/latency
tooltip, wired into both live tile-render paths (Views.vue's main grid and
WidgetRenderer.vue). TileEditor.vue gains the enable/URL/expected-status/
interval fields with a best-effort save-time allow-list check.

28 new PHPUnit tests (Service/Controller/BackgroundJob) and 22 new Vitest
tests (badge render states, config validation) - all green, no real
network calls in any test.
Replaces the hand-written canonical spec with the one openspec archive
generates, so the spec stays tool-owned.

Full suites after rebase: 1472 phpunit tests / 3574 assertions OK,
615 vitest tests across 56 files pass.
@rubenvdlinde
rubenvdlinde merged commit 468d7ce into development Jul 23, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant