upgrade pass2026-10-19T01:58:17.976Z · clock 2026-09-16T09:05:00.000Z · 1 run(s) per side · harness 1.48.5
The unclaimed differences folded by kind across apps, pages and packages: a number, a hash or a package name does not make a new cause. Read beside the verdict; it never changes it.
| cause | differences | apps | pages | example |
|---|---|---|---|---|
dom semantic DOM differs (+# −# lines at line #) | 5 | reader | 5reader:course, reader:home, reader:lab-step, reader:lab-step-2, reader:topic | reader:home: semantic DOM differs (+1 −1 lines at line 10) |
focus keyboard order changed (# stops on a, # on b) | 5 | reader | 5reader:course, reader:home, reader:lab-step, reader:lab-step-2, reader:topic | reader:home: keyboard order changed (12 stops on a, 12 on b) |
Moved together on the same pages, so likely one change each:
dom, focus on 5 pages (10 differences): reader:course, reader:home, reader:lab-step, reader:lab-step-2, reader:topic| a | b | |
|---|---|---|
| reader | quay.io/tutors-sdk/tutors-reader:17.0.0 | quay.io/tutors-sdk/tutors-reader:sha-83d4ccf |
| catalogue | quay.io/tutors-sdk/tutors-catalogue:17.0.0 | quay.io/tutors-sdk/tutors-catalogue:sha-83d4ccf |
| live | quay.io/tutors-sdk/tutors-live:17.0.0 | quay.io/tutors-sdk/tutors-live:sha-83d4ccf |
| time | quay.io/tutors-sdk/tutors-time:17.0.0 | quay.io/tutors-sdk/tutors-time:sha-83d4ccf |
| provenance | a — pulled+verified | b — pulled+verified |
|---|---|---|
| reader | digest sha256:15e3aa22476d608db97e05917b1990ade0a7871e7ec6e113da5fec741b427233revision 432d46864626version 17.0.0-rc.1 | digest sha256:0627d3940eb982013b4491015586ea36e738fa1f22aebf648ad94e049a9e6d99revision 83d4ccf7f5caversion sha-83d4ccf |
| catalogue | digest sha256:e9f2764654cb074d7dd4412ca163bf4c2666870444d5520361d5425bda4cec0brevision 432d46864626version 17.0.0-rc.1 | digest sha256:8c61baa1c1e97df5cd6db100733809c404ca87044b0a05c40a2acbfccb996195revision 83d4ccf7f5caversion sha-83d4ccf |
| live | digest sha256:52740e55cfa7e7db3b2944137caada4e876990b937f1034c0c5e79796054f8a0revision 432d46864626version 17.0.0-rc.1 | digest sha256:af5231fe19ed7c74d30dc7fec5a55ea3819c7b3ff1a22c3d4e803436aef97bd2revision 83d4ccf7f5caversion sha-83d4ccf |
| time | digest sha256:d0a9f4a2f4624038ecea3629d1a536567756d458410bee43b45e060d738d195drevision 432d46864626version 17.0.0-rc.1 | digest sha256:4db2acd4bfa8059eb2ad18a87f68583a19dbd358cd6b6e99e1aab4913830abc8revision 83d4ccf7f5caversion sha-83d4ccf |
Collected from the images, not the running apps. A cell that says NOT COLLECTED was not compared.
| app | artefact | a | b |
|---|---|---|---|
| reader | manifest | 10 layers, 309.2 MB, USER 1001, ports 3000/tcp (docker image inspect) | 10 layers, 308.9 MB, USER 1001, ports 3000/tcp (docker image inspect) |
| reader | sbom | 134 distinct package(s) (cosign attestation (signature verified)) | 134 distinct package(s) (cosign attestation (signature verified)) |
| reader | vulns | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) |
| catalogue | manifest | 10 layers, 274.2 MB, USER 1001, ports 3000/tcp (docker image inspect) | 10 layers, 274.2 MB, USER 1001, ports 3000/tcp (docker image inspect) |
| catalogue | sbom | 134 distinct package(s) (cosign attestation (signature verified)) | 134 distinct package(s) (cosign attestation (signature verified)) |
| catalogue | vulns | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) |
| live | manifest | 10 layers, 274.5 MB, USER 1001, ports 3000/tcp (docker image inspect) | 10 layers, 274.5 MB, USER 1001, ports 3000/tcp (docker image inspect) |
| live | sbom | 134 distinct package(s) (cosign attestation (signature verified)) | 134 distinct package(s) (cosign attestation (signature verified)) |
| live | vulns | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) |
| time | manifest | 10 layers, 285.2 MB, USER 1001, ports 3000/tcp (docker image inspect) | 10 layers, 285.2 MB, USER 1001, ports 3000/tcp (docker image inspect) |
| time | sbom | 143 distinct package(s) (cosign attestation (signature verified)) | 143 distinct package(s) (cosign attestation (signature verified)) |
| time | vulns | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | NOT COLLECTED: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) |
| upstream | requests | failed | 5xx | p95 |
|---|---|---|---|---|
| a | 300 | 0 | 0 | 4 ms |
| b | 600 | 0 | 0 | 3.9 ms |
| all | 900 | 0 | 0 | switched at 16.9 s |
| artefact | scope | what changed | claimed by |
|---|---|---|---|
dom | reader:home/ | reader:home: semantic DOM differs (+1 −1 lines at line 10)detail - link "My courses":
- /url: /
- - button "Open Theme Menu": Preferences
+ - button "Preferences"
- button "Anonymous Tutors Profile"
- complementary "Course navigation": | unclaimed |
dom | reader:course/course/localhost:8080 | reader:course: semantic DOM differs (+1 −1 lines at line 9)detail - text: Tutors CI
- button "Search this course": Search
- - button "Open Theme Menu": Preferences
+ - button "Preferences"
- button "Anonymous Tutors Profile"
- complementary "Course navigation": | unclaimed |
dom | reader:topic/topic/localhost:8080/unit-1/topic-01 | reader:topic: semantic DOM differs (+1 −1 lines at line 8)detail - text: Tutors CI
- button "Search this course": Search
- - button "Open Theme Menu": Preferences
+ - button "Preferences"
- button "Anonymous Tutors Profile"
- complementary "Course navigation": | unclaimed |
dom | reader:lab-step/lab/localhost:8080/unit-1/topic-01/book-lab-01 | reader:lab-step: semantic DOM differs (+1 −1 lines at line 8)detail - text: Tutors CI
- button "Search this course": Search
- - button "Open Theme Menu": Preferences
+ - button "Preferences"
- button "Anonymous Tutors Profile"
- complementary "Course navigation": | unclaimed |
dom | reader:lab-step-2/lab/localhost:8080/unit-1/topic-01/book-lab-01/Step-01 | reader:lab-step-2: semantic DOM differs (+1 −1 lines at line 8)detail - text: Tutors CI
- button "Search this course": Search
- - button "Open Theme Menu": Preferences
+ - button "Preferences"
- button "Anonymous Tutors Profile"
- complementary "Course navigation": | unclaimed |
focus | reader:home/ | reader:home: keyboard order changed (12 stops on a, 12 on b)detaila "My courses" -button "Open Theme Menu" +button "Preferences" button "Anonymous Tutors Profile" | unclaimed |
focus | reader:course/course/localhost:8080 | reader:course: keyboard order changed (12 stops on a, 12 on b)detailbutton "Search this course" -button "Open Theme Menu" +button "Preferences" button "Anonymous Tutors Profile" | unclaimed |
focus | reader:topic/topic/localhost:8080/unit-1/topic-01 | reader:topic: keyboard order changed (12 stops on a, 12 on b)detailbutton "Search this course" -button "Open Theme Menu" +button "Preferences" button "Anonymous Tutors Profile" | unclaimed |
focus | reader:lab-step/lab/localhost:8080/unit-1/topic-01/book-lab-01 | reader:lab-step: keyboard order changed (12 stops on a, 12 on b)detailbutton "Search this course" -button "Open Theme Menu" +button "Preferences" button "Anonymous Tutors Profile" | unclaimed |
focus | reader:lab-step-2/lab/localhost:8080/unit-1/topic-01/book-lab-01/Step-01 | reader:lab-step-2: keyboard order changed (12 stops on a, 12 on b)detailbutton "Search this course" -button "Open Theme Menu" +button "Preferences" button "Anonymous Tutors Profile" | unclaimed |
vulns | reader/not-collected | NOT COLLECTED: vulns of reader on both sides: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy)detaila: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) b: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
vulns | catalogue/not-collected | NOT COLLECTED: vulns of catalogue on both sides: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy)detaila: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) b: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
vulns | live/not-collected | NOT COLLECTED: vulns of live on both sides: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy)detaila: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) b: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
vulns | time/not-collected | NOT COLLECTED: vulns of time on both sides: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy)detaila: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) b: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
runtime | runtime/summary | container posture collected for catalogue, live, reader, reader-auth, time on both sides (compose)detailcatalogue: a — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
b — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
live: a — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
b — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
reader: a — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
b — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
reader-auth: a — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
b — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
time: a — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter
b — uid 1001:0, caps none, root fs ro, /tmp rw, no-new-privileges, seccomp filter | informational |
startup | startup/not-collected | NOT COLLECTED: startup time on side a: switched off with --startup-restarts 0 | informational |
startup | startup/not-collected | NOT COLLECTED: startup time on side b: switched off with --startup-restarts 0 | informational |
image-hardening | reader/healthcheck | reader: declares no HEALTHCHECK (production too) | informing (reported, never gates) |
image-hardening | catalogue/healthcheck | catalogue: declares no HEALTHCHECK (production too) | informing (reported, never gates) |
image-hardening | live/healthcheck | live: declares no HEALTHCHECK (production too) | informing (reported, never gates) |
image-hardening | time/healthcheck | time: declares no HEALTHCHECK (production too) | informing (reported, never gates) |
build-provenance | reader/slsa | reader: carries no SLSA provenance verified under the publishing identity on 0627d3940eb9 (production too) | informing (reported, never gates) |
build-provenance | catalogue/slsa | catalogue: carries no SLSA provenance verified under the publishing identity on 8c61baa1c1e9 (production too) | informing (reported, never gates) |
build-provenance | live/slsa | live: carries no SLSA provenance verified under the publishing identity on af5231fe19ed (production too) | informing (reported, never gates) |
build-provenance | time/slsa | time: carries no SLSA provenance verified under the publishing identity on 4db2acd4bfa8 (production too) | informing (reported, never gates) |
vuln-ceiling | reader/not-evaluated | reader: vuln-ceiling could not be evaluated on b: no vulnerability scan: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
vuln-ceiling | catalogue/not-evaluated | catalogue: vuln-ceiling could not be evaluated on b: no vulnerability scan: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
vuln-ceiling | live/not-evaluated | live: vuln-ceiling could not be evaluated on b: no vulnerability scan: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
vuln-ceiling | time/not-evaluated | time: vuln-ceiling could not be evaluated on b: no vulnerability scan: grype is not installed (https://github.com/anchore/grype#installation, or set HARNESS_VULN_CMD to another scanner, e.g. trivy) | informational |
asset-graph | reader | reader: the asset graph changed: 111 → 111 immutable requests (JS 92 → 92, CSS 19 → 19), 1.1 MB → 1.1 MB; 0 network and 0 headers difference(s) are this churn | informing (reported, never gates) |
slo | reader-availability/not-evaluated | reader-availability: not evaluated on b: 4 request(s) from its /metrics across the journeys, fewer than 20 | informational |
slo | reader-latency/not-evaluated | reader-latency: not evaluated on b: 4 request(s) from its /metrics across the journeys, fewer than 20 | informational |
slo | catalogue-availability/not-evaluated | catalogue-availability: not evaluated on b: its /metrics across the journeys carries no availability SLI for catalogue | informational |
slo | catalogue-latency/not-evaluated | catalogue-latency: not evaluated on b: its /metrics across the journeys carries no latency SLI for catalogue | informational |
slo | live-availability/not-evaluated | live-availability: not evaluated on b: its /metrics across the journeys carries no availability SLI for live | informational |
slo | live-latency/not-evaluated | live-latency: not evaluated on b: its /metrics across the journeys carries no latency SLI for live | informational |
slo | time-availability/not-evaluated | time-availability: not evaluated on b: its /metrics across the journeys carries no availability SLI for time | informational |
slo | time-latency/not-evaluated | time-latency: not evaluated on b: its /metrics across the journeys carries no latency SLI for time | informational |
upgrade | rollout | 900 requests through the rollout, none failed; switched at 16.9s | informational |
Checks on the candidate alone, whatever production is: image hardening (root user, no healthcheck, a secret in the environment or the layer history), build provenance (SLSA provenance from image-build.yml) and the vulnerability ceiling (a critical or high advisory with a fix available). Informing: reported, never gates; a claim can still cover a finding. Hover a cell for what was checked.
| app | image-hardening | build-provenance | vuln-ceiling |
|---|---|---|---|
reader | 1 finding (1 on production too) | 1 finding (1 on production too) | not evaluated |
catalogue | 1 finding (1 on production too) | 1 finding (1 on production too) | not evaluated |
live | 1 finding (1 on production too) | 1 finding (1 on production too) | not evaluated |
time | 1 finding (1 on production too) | 1 finding (1 on production too) | not evaluated |
18 of 27 engines are blocking; informing (reported, never gates): timing (no date set to block; load/errors still blocks), image-hardening (no date set to block), build-provenance (no date set to block), vuln-ceiling (no date set to block), timing-tolerance (no date set to block), asset-graph (no date set to block), replay (no date set to block), slo (no date set to block), realtime (no date set to block). An informing engine's findings are listed here and never change the verdict, the Gate or the exit code; a claim can still cover one.
| engine | scope | what it found | level | claimed by |
|---|---|---|---|---|
image-hardening | reader/healthcheck | reader: declares no HEALTHCHECK (production too) | no date set | unclaimed |
image-hardening | catalogue/healthcheck | catalogue: declares no HEALTHCHECK (production too) | no date set | unclaimed |
image-hardening | live/healthcheck | live: declares no HEALTHCHECK (production too) | no date set | unclaimed |
image-hardening | time/healthcheck | time: declares no HEALTHCHECK (production too) | no date set | unclaimed |
build-provenance | reader/slsa | reader: carries no SLSA provenance verified under the publishing identity on 0627d3940eb9 (production too) | no date set | unclaimed |
build-provenance | catalogue/slsa | catalogue: carries no SLSA provenance verified under the publishing identity on 8c61baa1c1e9 (production too) | no date set | unclaimed |
build-provenance | live/slsa | live: carries no SLSA provenance verified under the publishing identity on af5231fe19ed (production too) | no date set | unclaimed |
build-provenance | time/slsa | time: carries no SLSA provenance verified under the publishing identity on 4db2acd4bfa8 (production too) | no date set | unclaimed |
asset-graph | reader | reader: the asset graph changed: 111 → 111 immutable requests (JS 92 → 92, CSS 19 → 19), 1.1 MB → 1.1 MB; 0 network and 0 headers difference(s) are this churn | no date set | unclaimed |
Fired: response-date×4, request-id×4, etag×4, metrics-process×599, metrics-timing-histograms×4, third-party-requests×62, hashed-assets×222, footer-tutors-version×20, transport-length×4, transport-connection×4, transport-keepalive×4.
Silent this run: persistence-stub-requests, realtime-rest-fallback-warning, oauth-callback-state, media-range-status, chromium-compute-pressure-policy, transport-encoding, transport-transfer — a mask that never fires is a mask to delete.