CI has been failing on unstable for weeks, across four unit files and a set of
e2e specs. None of it was a product regression: every failure is a test that
encodes behavior a later commit deliberately changed. Each is corrected against
the spec that superseded it, not adjusted until it passed.
Unit:
- video-modal-moderation: the fixture set flat `blurThumbnail`/`trustedMuteCount`,
but normalizeVideoModerationContext derives shouldShow from
`original.blurThumbnail`/`trustedCount`, so the assertion ran against a
context whose early return had just deleted the blur it was checking. 4525c1c6
also made a lone trusted mute a non-blocking ranking signal (its sibling test
was renamed to say exactly that; this one was missed). Fixture now mirrors
what moderationDecorator emits.
- trustBootstrap: asserted a subscription to onWhitelistChange that 18e08bf2
deliberately removed -- buildTrustedSeeds derives seeds from the super admin,
editors and fallback seeds, so a whitelist change cannot alter them. The
removal is now pinned so it is not reinstated by reflex.
- moderation-service: 18e08bf2 removed `status.whitelisted ||` from
isTrustedReporter (being allowed to publish is not a statement that your
reports carry weight). A whitelisted reporter now counts toward the report
total but not toward trusted.
- playbackService_forcedSource: forced P2P now falls back to a hosted URL when
the torrent definitively fails -- playbackService documents the change and its
rollback. The old assertion did not merely fail, it HUNG: forced sources skip
the start timeout, so the now-reachable hosted attempt waited forever on a
<video> that never emits.
E2E:
- ui-modals: asserted exactly one `.bv-modal` per component page, but
profile-modal.html also bundles #storageCorsModal (d7ad1516). Requires at
least one and drives the primary, which is what the test's own injected
querySelector already used.
- coverage-utility-modules: used `author:abc123`, which 9afbc0cb correctly began
rejecting as undecodable. Uses a real pubkey for the success path and pins the
rejection separately.
- webseed-playback: asserted the FINAL src equals the CDN URL while also
tolerating "No playable source found" in its status check -- contradictory,
since a failed attempt calls resetVideoElement() and clears src. Headless CI
cannot decode the archive.org H.264 sample. Now records src attachments and
asserts the URL was attached, which is the behavior under test.
- nostr-runtime-coverage: asserted a legacy plaintext session-actor entry reads
back as null. Since 8692dac6 added per-account storage, readV1Entry PURGES the
plaintext entry and the reader falls back to the sole remaining encrypted
account -- so null no longer describes the security property. Asserts the
property directly: no plaintext key survives, in the entry or in raw storage.
Also drops the syncAuthUiState share-gate wiring added in d141c316. It was
redundant: Application.updateShareNostrAuthState() already fires on init, login,
logout, pubkey-change and signer-change and forwards to
videoModal.setShareNostrAuthState(). That call short-circuited on its own
`if (!this.videoModal?.setShareNostrAuthState) return;` guard purely because the
method did not exist -- adding it (d141c316) was the whole fix. The tests now
pin that contract instead of a second, competing code path.
All 416 unit files, all three CI shards, both DM suites and lint are green.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Two fixes for hosted (CDN) playback that users hit on a torrent-first instance:
1. Reliability: clear crossOrigin before direct hosted playback (in
resetVideoElement and right before video.src = httpsUrl). A leftover
crossOrigin="anonymous" from a prior WebTorrent attempt on the reused
<video> forced a CORS request that CDNs / redirect targets (e.g. archive.org
storage nodes) reject, failing with MEDIA_ERR_SRC_NOT_SUPPORTED ("source not
supported or blocked"). Direct <video> playback never needs CORS, so any URL
now plays.
2. CDN-first for dual-source: when a hosted URL exists, play it first for
instant, reliable startup; WebTorrent is reserved for URL-less videos (and
explicit forcedSource: "torrent"). Previously a torrent-first instance made
dual-source videos wait on a P2P cold start before falling back to the CDN.
The torrent-first branch is now only reached without a URL, so it waits
indefinitely for peers (no plan B) rather than on a fixed timeout.
Tests: hosted playback clears crossOrigin and plays; a torrent-first instance
plays the URL first when one exists and never calls WebTorrent; URL-less videos
still use WebTorrent. Spec-corrected two playbackService_order tests that
encoded the old torrent-first-for-dual-source behavior. All mutation-verified.
Co-Authored-By: Claude Opus 4.8 <[email protected]>