SAUTV WEB 1.0.0 — VALIDATION — 13 OCTOBER 2026

BUILD 15 R2 MIGRATION RESULTS
86/86 local regressions passed: 28 backend, 35 updater, 16 isolated Chrome
browser, 7 isolated Chrome OTA browser. Full run: 93,676.6423 ms. The exact
candidate bundle identity is version 1.0.0 / build15. A final URL-boundary
hardening rejected trailing CR/LF; all 23 affected trust/URL cases reran PASS.
Release tooling and R2 publication validation: 46/46 local tests passed.

The production update feed is fixed to:
https://sautv-downloads.mss.sa/sautv-update.json
Signed artifact URLs are bound to their exact platform filename and signed
version/build under /releases/<version>-b<build>/. Other origins, legacy GitHub
URLs, arbitrary paths, encoded paths, explicit ports, credentials, query strings,
fragments and noncanonical trailing whitespace are rejected. Redirects retain
the same canonical URL. The RSA public key/key ID are unchanged.

The actual local gateway 15-to-16 handoff passed using isolated signed R2-path
fixtures: new identity starts, existing cookie session remains authenticated,
then restart loads the new verified launcher/runtime. The remaining synthetic
11-to-12 tests compile current R2-aware source under fixture identities. They do
not demonstrate that an original GitHub-pinned build11 can read the R2 feed.
Original builds11–14 require one manual build15 installation; this pass neither
changes old signed artifacts nor publishes a GitHub migration bridge.

Existing browser presentation gates passed: 3,068 ms visible update before
handoff; normal success 3,513.3 ms after animation; reduced motion 3,524.3 ms;
return from injected focus loss 3,516.5 ms. Success dismisses automatically,
requires visible focused dwell, has no button, preserves an unseen receipt,
and does not repeat after acknowledgment. All browser contexts were isolated
and headless; focus/visibility loss is an explicitly injected test signal.

No provider credentials, user profile, real provider traffic, cloud write or
public deployment was used in this pass. Historical provider sampling below
was not repeated. Local tests used injected transports and keys only inside
the test harness; production has no URL/key/security override.

HISTORICAL BUILD 14 RESULTS
Build 14 local candidate: 80/80 regression tests passed.
28/28 backend unit/integration; 29/29 updater; 16/16 isolated Chrome browser;
7/7 isolated Chrome OTA browser. Candidate identity is version 1.0.0 / build 14.
Local bundle compilation passed. No publication was performed in this pass.
Earlier real-provider checks passed for the first live channel, movie and episode;
those checks were not repeated for build 14. Their historical evidence is below.

BUILD 14 IMPROVEMENTS AND CHECKS
- Failed active catalog retries once after reconnection, retaining search/sort.
- Stale catalog recovery waits for open dialogs and retains category/card focus.
- Closing details or a connecting player aborts its browser request, prevents
  stale UI and avoids recording history before playback actually starts.
- Paused local video remains paused across browser offline/online transitions.
- An injected MediaError network event under real browser offline emulation
  shows an accurate offline state; keyboard Retry restores the saved position.
  This deterministic event check is not a new real-provider outage test.
- Known playlist movies/episodes have no browser download URL. The UI explains
  the limitation; regular local-file browser downloads still complete exactly.
- Season-zero Specials retain their correct history metadata.
- New versioned SAUTV vector branding and favicon/install-icon references render
  across the existing 320/390/768/1280/1920 px responsive regression suite.
- Existing update presentation, signed local replacement, rollback, session/data
  preservation and automatic success dismissal remain covered. Success has no
  button, waits for animation completion plus 3500 ms of visible focused dwell,
  restarts dwell after focus loss, and acknowledges only once. Hidden-reload and
  storage/server-ack failure fixtures protect unread receipts and repeat notices.

Expected network errors from intentionally forced offline requests are classified
separately from unexpected console/runtime errors. Browser focus/visibility loss
in the OTA suite is an explicitly injected headless fixture; normal success uses
the browser's actual focus and animation events. All runtime contexts are local.

ENVIRONMENT
Windows; Node.js 22.23.2; Chrome 154.0.8037.98; Playwright 1.62.1.
Browser automation used isolated headless contexts and a separate local fixture
server. Real-provider checks used the production gateway with normal public-host,
secure DNS, redirect, TLS and session validation. No security bypass or production
test route was added.

BACKEND COVERAGE
Address normalization and bare/explicit protocol handling; eligible transport
fallback; no fallback on authentication/refusal/format failures;403 identity
negotiation; cancellation/deadlines; public DNS answers; secret-safe errors;
bounded response bodies; authenticated encrypted resource references; HLS segment,
variant, key, map and subtitle URI rewriting; download names;206/416 byte ranges;
catalog/detail normalization and cache/coalescing; session cookies, idle expiry,
replacement, logout, canceled login and in-flight replacement-login races;
active media cancellation; Host, origin and static-path defenses.

BROWSER COVERAGE
320,390,768,1280 and 1920 px viewport widths; touch and keyboard navigation;
long titles; readable narrow-phone filters; no horizontal overflow or unexpected
console errors; local assets without CDN requests; search, categories, ordering,
pagination and favorites; account-scoped metadata storage without credentials;
40-row episode pagination within a 15,000-episode season; saved episode page;
dialog focus trap/return; enlarged text; reduced motion; offline/session expiry;
delayed logout while playback opens; cached-library warning and unsupported codec
state with loading stopped.

LOCAL MEDIA EVIDENCE
A 640 x 360 local MP 4 produced decoded frames through requestVideoFrameCallback.
Pause/resume, fullscreen and Escape behavior passed. Browser download completed
and matched the source file exactly: 13,058,604 bytes.

REAL PROVIDER EVIDENCE
Authentication succeeded over the configured HTTP provider connection.
Catalogs loaded without stale data: 10,094 live channels,15,965 movies,7,068 shows.
The first returned candidate in each section decoded frames:
  Live: 1920 x 1080; pause/resume passed.
  Movie: 1920 x 800; pause/resume passed.
  Episode: 1920 x 1080; pause/resume passed.
A real browser download wrote 2,416,318 bytes and was intentionally canceled.
A separate bounded 1,048,576-byte request returned HTTP 206 and the matching
Content-Range. Signout passed; no page errors were observed. The isolated browser,
session and local server were closed afterward. Credentials and provider address
are absent from this report and from application source.

FIXES VERIFIED IN THIS PASS
Prompt cancellation while awaiting DNS; trailing-dot localhost rejection;
empty byte-range rejection; logout revocation of in-flight replacement login;
Escape exits fullscreen without closing the player; readable narrow-phone
category/sort rows; two-line phone titles and 44 px favorite/refresh targets.

LIMITS
Provider checks were brief samples of the first three candidates, not an audit
of every title or sustained playback. Headless decoded-frame checks do not verify
audible sound. A full provider movie download was deliberately not completed.
Safari/iOS, physical TV browsers, every browser/codec, long-term reconnection and
durable offline download/resume were not established by this validation. Browser
format limitations documented in README.txt still apply.

REPRODUCTION FROM SOURCE
npm test
npm run build
npm run test:browser
See README.txt for optional Playwright/browser/fixture path overrides.
tests/provider.manual.mjs is a separate opt-in verifier; it reads a private input
file selected by SAUTV_PRIVATE_PROVIDER and never contains account/provider values.
Do not run it concurrently with another player using a limited provider account.

OTA VALIDATION — BUILD 11, 2026-10-13
Historical initial OTA baseline (the current build 14 totals are above).
The local combined gate contains 72 tests: 27 existing backend regressions,
29 updater tests, 11 existing browser regressions, and 5 OTA browser scenarios.
Build identity remains version 1.0.0 / internal build 11. The upgrade fixtures
build actual isolated version 1.0.0 / build 12 bundles from the same source.
No real provider requests or publishing were performed during this OTA pass.

The 29 updater cases include all 16 shared signed-manifest vectors; duplicate
and malformed JSON, URL/redirect allowlists, traversal/symlink/device/alias ZIP
rejection, checksum/size mismatch, transfer interruption and cancellation,
disk-space failure, stale sequence replay, no-update cases, one-operation
serialization, client idle boundaries, actual 11-to-12 gateway replacement,
session-cookie preservation, updated-launcher restart, failed startup rollback,
corrupt archive recovery, hosted mutation denial, durable success acknowledgment,
bounded owned-file cleanup, and an unavailable updater folder failing open.

Five isolated Chrome OTA scenarios verify:
- Fast actual upgrade retains at least 2100 ms of visible update presentation.
- Expected build 12 loads before success; success stays readable at least
  3500 ms, cannot be dismissed early, and is not repeated in another tab.
- Session, current Movies view and a saved favorite survive the handoff.
- Paused playback and a held real local-file download both defer installation.
- Automatic transfer failure stays readable and leaves build 11 usable.
- Offline startup has no update/success flash; reduced motion retains timing.

The initial build11 used the production public key and fixed GitHub feed.
Build15 replaces that compiled feed/origin policy with the R2 host described above.
QA signatures and transports are injected into isolated test factories only;
there is no production test route, feed/key override or private-network bypass.
No private signing key, IPTV account or provider host is included in the bundle.

The updater checks TLS and public IPv4 DNS answers for its restricted update
hosts (R2 in build15; GitHub in the original build11). Its transport is separate from provider networking. The ZIP extractor
accepts ordinary single-disk ZIPs; ZIP64, encryption and symlinks are rejected.
No custom durable browser download queue or codec/transcoding capability is
implied. Actual public publication remains the release operator's
separate step; this pass validates the signed protocol with local fixtures.
