Tutors release harness — upgrade pass

2026-10-18T01:49:20.815Z · clock 2026-09-16T09:05:00.000Z · 1 run(s) per side · harness 1.44.0

6 unclaimed differences, 2 causes

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.

causedifferencesappspagesexample
dom semantic DOM differs (+# −# lines at line #)5reader5
reader: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)1reader1
reader:home
reader:home: keyboard order changed (12 stops on a, 12 on b)

Moved together on the same pages, so likely one change each:

ab
readerquay.io/tutors-sdk/tutors-reader:17.0.0quay.io/tutors-sdk/tutors-reader:sha-83d4ccf
cataloguequay.io/tutors-sdk/tutors-catalogue:17.0.0quay.io/tutors-sdk/tutors-catalogue:sha-83d4ccf
livequay.io/tutors-sdk/tutors-live:17.0.0quay.io/tutors-sdk/tutors-live:sha-83d4ccf
timequay.io/tutors-sdk/tutors-time:17.0.0quay.io/tutors-sdk/tutors-time:sha-83d4ccf
provenancea — pulled+verifiedb — pulled+verified
readerdigest sha256:15e3aa22476d608db97e05917b1990ade0a7871e7ec6e113da5fec741b427233
revision 432d46864626
version 17.0.0-rc.1
digest sha256:0627d3940eb982013b4491015586ea36e738fa1f22aebf648ad94e049a9e6d99
revision 83d4ccf7f5ca
version sha-83d4ccf
cataloguedigest sha256:e9f2764654cb074d7dd4412ca163bf4c2666870444d5520361d5425bda4cec0b
revision 432d46864626
version 17.0.0-rc.1
digest sha256:8c61baa1c1e97df5cd6db100733809c404ca87044b0a05c40a2acbfccb996195
revision 83d4ccf7f5ca
version sha-83d4ccf
livedigest sha256:52740e55cfa7e7db3b2944137caada4e876990b937f1034c0c5e79796054f8a0
revision 432d46864626
version 17.0.0-rc.1
digest sha256:af5231fe19ed7c74d30dc7fec5a55ea3819c7b3ff1a22c3d4e803436aef97bd2
revision 83d4ccf7f5ca
version sha-83d4ccf
timedigest sha256:d0a9f4a2f4624038ecea3629d1a536567756d458410bee43b45e060d738d195d
revision 432d46864626
version 17.0.0-rc.1
digest sha256:4db2acd4bfa8059eb2ad18a87f68583a19dbd358cd6b6e99e1aab4913830abc8
revision 83d4ccf7f5ca
version sha-83d4ccf

Image artefacts

Collected from the images, not the running apps. A cell that says NOT COLLECTED was not compared.

appartefactab
readermanifest10 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)
readersbom134 distinct package(s) (cosign attestation (signature verified))134 distinct package(s) (cosign attestation (signature verified))
readervulnsNOT 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)
cataloguemanifest10 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)
cataloguesbom134 distinct package(s) (cosign attestation (signature verified))134 distinct package(s) (cosign attestation (signature verified))
cataloguevulnsNOT 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)
livemanifest10 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)
livesbom134 distinct package(s) (cosign attestation (signature verified))134 distinct package(s) (cosign attestation (signature verified))
livevulnsNOT 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)
timemanifest10 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)
timesbom143 distinct package(s) (cosign attestation (signature verified))143 distinct package(s) (cosign attestation (signature verified))
timevulnsNOT 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)

Upgrade rehearsal (compose)

upstreamrequestsfailed5xxp95
a300004.4 ms
b601003.4 ms
all90100switched at 16.0 s

Differences (35; 6 unclaimed)

artefactscopewhat changedclaimed by
domreader: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
domreader: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
domreader: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
domreader: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
domreader: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
focusreader:home
/
reader:home: keyboard order changed (12 stops on a, 12 on b)
detail
 a "My courses"
-button "Open Theme Menu"
+button "Preferences"
 button "Anonymous Tutors Profile"
unclaimed
vulnsreader/not-collectedNOT 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)
detail
a: 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
vulnscatalogue/not-collectedNOT 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)
detail
a: 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
vulnslive/not-collectedNOT 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)
detail
a: 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
vulnstime/not-collectedNOT 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)
detail
a: 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
runtimeruntime/summarycontainer posture collected for catalogue, live, reader, reader-auth, time on both sides (compose)
detail
catalogue: 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
startupstartup/not-collectedNOT COLLECTED: startup time on side a: switched off with --startup-restarts 0informational
startupstartup/not-collectedNOT COLLECTED: startup time on side b: switched off with --startup-restarts 0informational
image-hardeningreader/healthcheckreader: declares no HEALTHCHECK (production too)informing (reported, never gates)
image-hardeningcatalogue/healthcheckcatalogue: declares no HEALTHCHECK (production too)informing (reported, never gates)
image-hardeninglive/healthchecklive: declares no HEALTHCHECK (production too)informing (reported, never gates)
image-hardeningtime/healthchecktime: declares no HEALTHCHECK (production too)informing (reported, never gates)
build-provenancereader/slsareader: carries no SLSA provenance verified under the publishing identity on 0627d3940eb9 (production too)informing (reported, never gates)
build-provenancecatalogue/slsacatalogue: carries no SLSA provenance verified under the publishing identity on 8c61baa1c1e9 (production too)informing (reported, never gates)
build-provenancelive/slsalive: carries no SLSA provenance verified under the publishing identity on af5231fe19ed (production too)informing (reported, never gates)
build-provenancetime/slsatime: carries no SLSA provenance verified under the publishing identity on 4db2acd4bfa8 (production too)informing (reported, never gates)
vuln-ceilingreader/not-evaluatedreader: 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-ceilingcatalogue/not-evaluatedcatalogue: 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-ceilinglive/not-evaluatedlive: 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-ceilingtime/not-evaluatedtime: 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-graphreaderreader: 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 churninforming (reported, never gates)
sloreader-availability/not-evaluatedreader-availability: not evaluated on b: 4 request(s) from its /metrics across the journeys, fewer than 20informational
sloreader-latency/not-evaluatedreader-latency: not evaluated on b: 4 request(s) from its /metrics across the journeys, fewer than 20informational
slocatalogue-availability/not-evaluatedcatalogue-availability: not evaluated on b: its /metrics across the journeys carries no availability SLI for catalogueinformational
slocatalogue-latency/not-evaluatedcatalogue-latency: not evaluated on b: its /metrics across the journeys carries no latency SLI for catalogueinformational
slolive-availability/not-evaluatedlive-availability: not evaluated on b: its /metrics across the journeys carries no availability SLI for liveinformational
slolive-latency/not-evaluatedlive-latency: not evaluated on b: its /metrics across the journeys carries no latency SLI for liveinformational
slotime-availability/not-evaluatedtime-availability: not evaluated on b: its /metrics across the journeys carries no availability SLI for timeinformational
slotime-latency/not-evaluatedtime-latency: not evaluated on b: its /metrics across the journeys carries no latency SLI for timeinformational
upgraderollout901 requests through the rollout, none failed; switched at 16.0sinformational

Policy: what b must be informing

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.

appimage-hardeningbuild-provenancevuln-ceiling
reader1 finding (1 on production too)1 finding (1 on production too)not evaluated
catalogue1 finding (1 on production too)1 finding (1 on production too)not evaluated
live1 finding (1 on production too)1 finding (1 on production too)not evaluated
time1 finding (1 on production too)1 finding (1 on production too)not evaluated

Informing (9; 9 unclaimed) reported, never gates

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.

enginescopewhat it foundlevelclaimed by
image-hardeningreader/healthcheckreader: declares no HEALTHCHECK (production too)no date setunclaimed
image-hardeningcatalogue/healthcheckcatalogue: declares no HEALTHCHECK (production too)no date setunclaimed
image-hardeninglive/healthchecklive: declares no HEALTHCHECK (production too)no date setunclaimed
image-hardeningtime/healthchecktime: declares no HEALTHCHECK (production too)no date setunclaimed
build-provenancereader/slsareader: carries no SLSA provenance verified under the publishing identity on 0627d3940eb9 (production too)no date setunclaimed
build-provenancecatalogue/slsacatalogue: carries no SLSA provenance verified under the publishing identity on 8c61baa1c1e9 (production too)no date setunclaimed
build-provenancelive/slsalive: carries no SLSA provenance verified under the publishing identity on af5231fe19ed (production too)no date setunclaimed
build-provenancetime/slsatime: carries no SLSA provenance verified under the publishing identity on 4db2acd4bfa8 (production too)no date setunclaimed
asset-graphreaderreader: 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 churnno date setunclaimed

Masks

Fired: response-date×4, request-id×4, etag×4, metrics-process×602, metrics-timing-histograms×4, third-party-requests×62, hashed-assets×222, footer-tutors-version×28, 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.