test(admin): qualify status refresh and document diagnostics

This commit is contained in:
cesnimda
2026-11-10 12:42:57 +01:00
parent 4981a24238
commit 13c9c65352
128 changed files with 4723 additions and 8 deletions
@@ -9,7 +9,7 @@ Owner addendum received 9 November 2026. Source `E:/Storage/Projects/Active/temp
| Applications | [Title-first rows and explicit bulk mode](visual-correction/APPLICATION_SELECTION_REVIEW.md) qualified at 36 configurations. | Secondary action consolidation and final native/visual review remain open. |
| Admin Users and Audit | [User row alignment](visual-correction/ADMIN_USER_ALIGNMENT_REVIEW.md) passed 36 configurations. Review existing read metadata, available filters and expandable records next. The MFA proposal is in `docs/security/MFA_RECOVERY_PROPOSAL.md` on the security branch. | 2FA recovery and private support access require explicit owner approval of their technical and privacy designs. |
| Job Correspondence | Continue inbox layout, mailbox-status presentation and existing explicit consent flow. | Provider verification, restricted scopes, multiple-account persistence and retention decisions retain their gates. Signing in grants no mailbox access. |
| System Status | Review current operational owners and distinguish current, stale and unavailable readings. Keep the CV benchmark while qualification depends on it. | Predefined diagnostics require isolated execution, role checks and audit. Live diagnostics, workers and arbitrary command execution are outside this scope. |
| System Status | [Status refresh evidence](visual-correction/SYSTEM_STATUS_REFRESH_REVIEW.md) and [diagnostics design](SYSTEM_DIAGNOSTICS_DESIGN.md) distinguish current, stale and unavailable readings. CV Benchmark Review is retained. | Predefined diagnostics require approved suites, isolated execution, role checks and audit. Live execution and per-signal telemetry remain open. |
| Terminology | “Prepare application” / “Klargjør søknaden” is visible in the scoped EN/NB application checks. | Continue broader terminology and European catalogue review. |
| Bookmarklet | [Dependency review](#bookmarklet-dependency-review) confirms the URL form already provides the primary import path. | Retain the existing bookmark-bar shortcut pending device parity and retirement approval. |
| EUROPE-READY-01 | [Coverage companion](../i18n/00/EUROPE_RELEASE_COVERAGE.md) added for all 59 existing candidate codes. | Qualified data/licences, implementation entry, additional locales, native review and release approval are separate. |
@@ -0,0 +1,24 @@
# System Status and diagnostics
## What the page can report today
| Signal | Source and limit |
| --- | --- |
| Backend status and refresh | The admin status GET reports environment, build and runtime details. Its success indicates a response from that endpoint. The UI timestamp is when the browser received that response. A failed refresh retains the earlier timestamp with the existing warning. |
| Database | The status GET attempts database reads and reports connectivity and query warnings. This is a point-in-time observation. |
| AI | The status GET displays summarizer metrics and their own available timestamps. The manual probe is a separate existing action. A status response alone does not prove a model, OCR, or a processing task succeeded. |
| Processing | The Admin Processing monitor owns worker flags, recorded operations, counts, and recorded failures. A flag alone gives no liveness guarantee. Any future status summary should link to that owner and label unsupported queues or heartbeats as unavailable. |
| Mail, external providers and scheduled enrichment | No system-wide measurement is established in this slice. A per-user connection and configuration flags are insufficient evidence for service health. Aggregate only supported service signals and keep account or job content out of the admin view. |
| API errors and timings | Existing AI timings remain scoped to AI. General request error rates and latency need their own instrumented source, time window and sample counts. |
Source owners are `AdminSystemController.Get`, `AdminProcessingController` and `AdminSystemPage`. Preserve the separation between an observed value, an earlier value with its timestamp, a failure to read and a signal the app does not measure. Each eventual backend metric needs its own observation time and sampling window where applicable.
## Proposed operator flow
In an Advanced diagnostics section, list the approved suite name, description, target environment, last execution and result. An unavailable suite shows its reason and has no Start control. An authorised operator reviews the fixed environment and scope before starting. A run row shows queued, running and terminal status with time and progress from the runner. History exposes a bounded, sanitised summary and a run ID.
The existing `MaintenanceJobDispatcher` only accepts `cv-benchmark` and dispatches a fixed Gitea workflow from `main`. The workflow uses a private CV corpus and AI service on the production host and publishes reports back to the running backend. Its queue acknowledgement is not a completion receipt. Retain CV Benchmark Review and its historical evidence for CV extraction qualification. Keep dispatch separate from the proposed isolated suites. This review executed neither path.
The first candidate for isolated execution is a fixture-only API smoke suite with a disposable datastore, synthetic records and AI/mail/providers disabled. A server-side allowlist must bind each suite ID to an immutable executable, target and resource limits. Inputs must never include shell commands, arbitrary arguments, URLs, credentials or a caller-selected environment. Validate administrator role and current session on every read and start, and recheck authorisation at dispatch. Use a separate least-privilege runner without production credentials, mounts or network paths. Apply time and concurrency limits, deduplicate starts, and record actor, suite, environment, revision, time and outcome. User data and secrets must never enter logs or history. Show structured allowlisted results and retain them only for an agreed interval.
Before enabling Start, qualify role and session denial, unknown suite IDs, duplicate starts, expired runs, cancellation and timeout cleanup, sanitised output, and absence of access to production or provider routes. Qualify status and history with fixtures independently of execution. Actual suite approval, runner isolation, retention and deployment remain separate decisions.
+3 -1
View File
@@ -1,5 +1,7 @@
# A3-IM10 Cross-application qualification
System Status runtime `4981a242` displays the last successful browser read and preserves its timestamp when a refresh fails. See [refresh evidence](visual-correction/SYSTEM_STATUS_REFRESH_REVIEW.md) and the [separate diagnostics design](SYSTEM_DIAGNOSTICS_DESIGN.md).
Application list successor `1246994c` moves role ahead of employer and shows bulk controls in explicit selection mode. Passed 57 native tests, types, lint, build and 72 rendered states. [Application selection evidence](visual-correction/APPLICATION_SELECTION_REVIEW.md)
Discover Jobs search-first layout at `0540e84f` passed 26 native cases, types, lint, build and 108 controlled states across 36 configurations. [Search-first evidence](visual-correction/DISCOVERY_SEARCH_FIRST.md)
@@ -60,6 +62,6 @@ Secondary checkpoint7aa54bff1fe376b798922b9da75feafa202dbb76 is published/remote
Active bounded fix (uncommitted): AI privacy Save now invokes an optional refresh callback; App rereads /auth/me and updates only same-owner, validated plan/entitlements without resetting authResolved or dispatching auth-changed. Lifetime/session/sequence guards reject stale completion; general auth refresh invalidates the availability lane. Card distinguishes saved preferences from refresh failure and preserves its mounted draft.39 selected tests/three suites,types/lint/build passed; browser pilot is being corrected to respect existing API identity-mismatch invalidation (session reset, not an inline warning). Targeted malformed-entitlement and same-owner/no-reload journeys must pass before publication. No backend/model/provider changes. Do not discard the active regression/fix files or claim the display gap closed until its actual evidence is qualified.
4 November successor: the owner added global flat visual correction and a whole-application definition of done. These extend approved IM10; earlier functional approvals remain evidence, not visual parity. Shared compact shell/open CV studio/flat continuous Settings sections are implemented. Mounted availability gap now has16 successful controlled journeys/64 scans with node/draft retention, malformed-grant rejection and wrong-identity session reset. CV visual matrix:36 configurations/108 scans/captures across all nine required widths, EN/NB and themes. Failed NB notice/tablet overlap attempts retained and fixed. Types/lint/build/census passed; independent source review found no actionable findings. The full34-route visual review, connected workflows, human/device/native language and final visual approval remain OPEN. See visual-correction/VALIDATION.md and DISCREPANCIES.md. Next eligible work: remaining route review and bounded remediation, beginning six secondary routes. Do not request final IM10 acceptance yet.
# Admin Users alignment checkpoint
## Admin Users alignment checkpoint
10 November 2026. Runtime `dddec043664cd1e65f93469e112c92f4794b8821` passed 12 selected native tests, types, lint, export build and 36 controlled responsive accessibility scans. See [alignment review](visual-correction/ADMIN_USER_ALIGNMENT_REVIEW.md).
@@ -37,6 +37,7 @@ Owner correction: 3 November 2026. This register extends IM10 and the original 3
| V27 | Public homepage baseline | Earlier mockups, missing landmarks and crawlable locale content, anonymous preference request rejected | OPEN in LAUNCH-SITE-01 | [Rendered baseline](LANDING_BASELINE_REVIEW.md) captures mobile, tablet and desktop without choosing a launch design |
| V28 | Application list | Ordinary rows show permanent selection controls and company before the role | RESOLVED in `1246994c` | [Selection review](APPLICATION_SELECTION_REVIEW.md) covers title-first hierarchy and the explicit mode. Secondary action consolidation remains open. |
| V29 | Admin Users | Row details sit above the centre of the action controls | RESOLVED in `dddec043` | [Alignment review](ADMIN_USER_ALIGNMENT_REVIEW.md) records the before and after geometry and phone layout. |
| V30 | Admin System | Operators cannot tell when the displayed status response last succeeded | RESOLVED in `4981a242` | [Status refresh review](SYSTEM_STATUS_REFRESH_REVIEW.md) qualifies timestamp, stale warning and keyboard retry. Per-signal telemetry remains open. |
The owner-approved design foundation remains original A1 dashboard, D1 visual system, B1 tracking, editor left / preview right, application context right, desktop sidebar and hybrid mobile navigation. No controls, imports, revisions, permissions or provider rights may be removed to obtain visual simplicity.
@@ -239,9 +239,9 @@
"AdminSystemPage"
],
"visualStatus": "OPEN_DIAGNOSTICS_DIVIDED_BENCHMARK_SCOPED_RENDERED_REVIEW",
"afterStatus": "PASSED:36 configurations /324 admin states combined; synthetic populated/unavailable/benchmark/settings read states; no live qualification or mutations",
"afterStatus": "PASSED:36 configurations for unavailable, successful, stale and recovered status reads, including stale timestamp placement; earlier benchmark and settings coverage retained",
"functionalCriteria": "Original preservation register retained; no capability acceptance promotion",
"evidence": "ADMIN_HEADINGS_REVIEW.md; evidence/admin-headings/BROWSER.json; prior ADMIN_REVIEW.md"
"evidence": "SYSTEM_STATUS_REFRESH_REVIEW.md; evidence/system-status-refresh/BROWSER.json; earlier ADMIN_HEADINGS_REVIEW.md and ADMIN_REVIEW.md"
},
{
"route": "/trash",
@@ -0,0 +1,9 @@
# System Status refresh time
Runtime `4981a24238ebd133788f393719ec2c8f0f2c0f43`. The status response and browser receipt time are stored together. A transient error leaves both in place and shows the existing warning. A successful retry replaces both. An initial failure has no timestamp, and a denied read clears the snapshot. The display uses a semantic time element with a localised date and time.
The first test failed against the missing timestamp. The first rendered matrix passed its functional checks on `320bf6d1`, but the 320 px Bokmål dark screenshot showed unrelated benchmark and maintenance warnings pushing the stale timestamp below the fold. The retained before screenshot and report document that result. The final implementation moves the timestamp above those warnings. The final browser check asserts that order.
20 selected native tests, types, lint and export build passed. The final matrix passed 36 configurations and 108 captures and scoped axe scans across nine widths, both languages and both themes. It captures initial unavailable, successful and stale states and checks keyboard recovery in each configuration. The fixture generates 288 deliberate System 503 responses across four endpoints and 36 unavailable company reads. It recorded zero writes and page errors.
The timestamp is the browser's receipt time for the existing admin status endpoint. Individual subsystem observations retain their existing semantics. The [diagnostics design](../SYSTEM_DIAGNOSTICS_DESIGN.md) records the missing signals and a proposed isolated run flow. Native device and language review, live telemetry and diagnostics qualification remain open.
Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

@@ -0,0 +1,98 @@
{
"screens": [
{
"width": 320,
"language": "en",
"mode": "light",
"state": "system-unavailable",
"capture": "viewport at top",
"violations": []
},
{
"width": 320,
"language": "en",
"mode": "light",
"state": "system-normal",
"capture": "viewport at top",
"violations": []
},
{
"width": 320,
"language": "en",
"mode": "light",
"state": "system-stale",
"capture": "viewport at top",
"violations": []
},
{
"width": 1440,
"language": "en",
"mode": "light",
"state": "system-unavailable",
"capture": "full page at top",
"violations": []
},
{
"width": 1440,
"language": "en",
"mode": "light",
"state": "system-normal",
"capture": "full page at top",
"violations": []
},
{
"width": 1440,
"language": "en",
"mode": "light",
"state": "system-stale",
"capture": "full page at top",
"violations": []
}
],
"journeys": [
{
"width": 320,
"language": "en",
"mode": "light",
"lastSuccessfulReadPreservedAndRenewed": "PASS"
},
{
"width": 1440,
"language": "en",
"mode": "light",
"lastSuccessfulReadPreservedAndRenewed": "PASS"
}
],
"errors": [],
"unexpectedWrites": [],
"exportDenials": [],
"unavailableReads": [
"/api/admin/system",
"/api/admin/system/email-settings",
"/api/admin/system/cv-benchmark",
"/api/admin/system/maintenance-jobs",
"/api/companies",
"/api/admin/system",
"/api/admin/system/email-settings",
"/api/admin/system/cv-benchmark",
"/api/admin/system/maintenance-jobs",
"/api/admin/system",
"/api/admin/system/email-settings",
"/api/admin/system/cv-benchmark",
"/api/admin/system/maintenance-jobs",
"/api/companies",
"/api/admin/system",
"/api/admin/system/email-settings",
"/api/admin/system/cv-benchmark",
"/api/admin/system/maintenance-jobs"
],
"blockedExternal": [
"https://fonts.googleapis.com",
"https://fonts.googleapis.com"
],
"limits": [
"Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.",
"Only initial unavailable, successful, stale and recovered System Status reads are exercised. No diagnostic action executed.",
"No real credentials, provider activation, model, native device, integrated security, production or release acceptance."
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Some files were not shown because too many files have changed in this diff Show More