Tutors release harness — upgrade pass

2026-10-19T09:52:33.822Z · clock 2026-09-16T09:05:00.000Z · 1 run(s) per side · harness 1.48.6

7 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
metrics new series on b
2 names: http_request_duration_seconds_count, http_requests_total
6catalogue, live, time—catalogue: new series on b: http_request_duration_seconds_count
logs info-level lines
1 field: info
1reader—reader: info-level lines: 3 on a, 6 on b
ab
readerquay.io/tutors-sdk/tutors-reader:17.0.0quay.io/tutors-sdk/tutors-reader:sha-2bff81a
cataloguequay.io/tutors-sdk/tutors-catalogue:17.0.0quay.io/tutors-sdk/tutors-catalogue:sha-2bff81a
livequay.io/tutors-sdk/tutors-live:17.0.0quay.io/tutors-sdk/tutors-live:sha-2bff81a
timequay.io/tutors-sdk/tutors-time:17.0.0quay.io/tutors-sdk/tutors-time:sha-2bff81a
provenancea — pulled+verifiedb — pulled+verified
readerdigest sha256:15e3aa22476d608db97e05917b1990ade0a7871e7ec6e113da5fec741b427233
revision 432d46864626
version 17.0.0-rc.1
digest sha256:73b1ebbdfe9bce2ab10e7a98152233b228b9fc77cdbb734fc1bce265f4fa4d6e
revision 2bff81a77942
version sha-2bff81a
cataloguedigest sha256:e9f2764654cb074d7dd4412ca163bf4c2666870444d5520361d5425bda4cec0b
revision 432d46864626
version 17.0.0-rc.1
digest sha256:b2ab9fd4335643301310e95f2cf72b5b92bd7a7dd5fd18294829d29195c78cdf
revision 2bff81a77942
version sha-2bff81a
livedigest sha256:52740e55cfa7e7db3b2944137caada4e876990b937f1034c0c5e79796054f8a0
revision 432d46864626
version 17.0.0-rc.1
digest sha256:186f1ca2bdb02c72334940831a2f1addcc88bcfa7fc7e53a5f635e49e41e135f
revision 2bff81a77942
version sha-2bff81a
timedigest sha256:d0a9f4a2f4624038ecea3629d1a536567756d458410bee43b45e060d738d195d
revision 432d46864626
version 17.0.0-rc.1
digest sha256:5925f643dc9a39f96eb5e9625fc1669662a23f91655b55d68bbad8cb061a3f76
revision 2bff81a77942
version sha-2bff81a

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, 309.0 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.9 ms
b601004 ms
all90100switched at 17.3 s

Differences (36; 7 unclaimed)

artefactscopewhat changedclaimed by
domanonymous-student-reads-coursejourney "anonymous-student-reads-course" failed on a but completed on b (fixed)
detail
locator.waitFor: Timeout 15000ms exceeded.
informational
metricscatalogue/http_request_duration_seconds_countcatalogue: new series on b: http_request_duration_seconds_countunclaimed
metricscatalogue/http_requests_totalcatalogue: new series on b: http_requests_totalunclaimed
metricslive/http_request_duration_seconds_countlive: new series on b: http_request_duration_seconds_countunclaimed
metricslive/http_requests_totallive: new series on b: http_requests_totalunclaimed
metricstime/http_request_duration_seconds_counttime: new series on b: http_request_duration_seconds_countunclaimed
metricstime/http_requests_totaltime: new series on b: http_requests_totalunclaimed
logsreader/inforeader: info-level lines: 3 on a, 6 on bunclaimed
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/summaryreader: image-hardening holds on b: USER 1001, HEALTHCHECK CMD node -e fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + '/healthz/live').then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1)), 0 secret-looking environment variable(s), 0 in the layer historyinformational
image-hardeningcatalogue/summarycatalogue: image-hardening holds on b: USER 1001, HEALTHCHECK CMD node -e fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + '/healthz/live').then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1)), 0 secret-looking environment variable(s), 0 in the layer historyinformational
image-hardeninglive/summarylive: image-hardening holds on b: USER 1001, HEALTHCHECK CMD node -e fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + '/healthz/live').then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1)), 0 secret-looking environment variable(s), 0 in the layer historyinformational
image-hardeningtime/summarytime: image-hardening holds on b: USER 1001, HEALTHCHECK CMD node -e fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + '/healthz/live').then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1)), 0 secret-looking environment variable(s), 0 in the layer historyinformational
build-provenancereader/summaryreader: build-provenance holds on b: SLSA provenance v1 by .github/workflows/image-build.yml@refs/heads/maininformational
build-provenancecatalogue/summarycatalogue: build-provenance holds on b: SLSA provenance v1 by .github/workflows/image-build.yml@refs/heads/maininformational
build-provenancelive/summarylive: build-provenance holds on b: SLSA provenance v1 by .github/workflows/image-build.yml@refs/heads/maininformational
build-provenancetime/summarytime: build-provenance holds on b: SLSA provenance v1 by .github/workflows/image-build.yml@refs/heads/maininformational
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
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: 0 request(s) from its /metrics across the journeys, fewer than 20informational
slocatalogue-latency/not-evaluatedcatalogue-latency: not evaluated on b: 0 request(s) from its /metrics across the journeys, fewer than 20informational
slolive-availability/not-evaluatedlive-availability: not evaluated on b: 0 request(s) from its /metrics across the journeys, fewer than 20informational
slolive-latency/not-evaluatedlive-latency: not evaluated on b: 0 request(s) from its /metrics across the journeys, fewer than 20informational
slotime-availability/not-evaluatedtime-availability: not evaluated on b: 0 request(s) from its /metrics across the journeys, fewer than 20informational
slotime-latency/not-evaluatedtime-latency: not evaluated on b: 0 request(s) from its /metrics across the journeys, fewer than 20informational
upgraderollout901 requests through the rollout, none failed; switched at 17.3sinformational

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
readerholdsholdsnot evaluated
catalogueholdsholdsnot evaluated
liveholdsholdsnot evaluated
timeholdsholdsnot evaluated

Informing (0) 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.

No informing results on this run.

Masks

Fired: response-date×2, request-id×2, etag×2, metrics-process×605, metrics-timing-histograms×18, third-party-requests×31, hashed-assets×111, footer-tutors-version×10, transport-length×2, transport-connection×2, transport-keepalive×2.
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.