diff --git a/docs/release-1.9.0-acceptance.md b/docs/release-1.9.0-acceptance.md index b998a4ab..4fd2b940 100644 --- a/docs/release-1.9.0-acceptance.md +++ b/docs/release-1.9.0-acceptance.md @@ -1016,3 +1016,35 @@ Durable public receipts and failed-attempt evidence: `~/.local/state/archipelago/release-qualification/ngit-iso-190-20261007/`. Existing known limitations are retained in the release notes. Current IndeeHub, artwork and payment follow-ups are not included in this original ISO. + +### Publication status and subsequent storage regression + +OTA metadata promotion proposal +`0e90b3847ff377ad5c9e400037651b565defa4ee229eac785a7897c30423a4e7` +was marked applied. Exact main/tag parity and public metadata bytes passed. Dev, +Yaya and Shorty now use the public catalog; their app IDs/start times and guard +configuration were preserved. Thirty-two external management-denial probes and +tailnet UI access passed after the change. Framework reaches the public manifest +and its saved current version is already1.9.0-alpha; this is a read-only result, +not a fresh authenticated update RPC acceptance. + +The public demo was deployed with immutable qualified images and preserved +configuration/rollback. Public version is1.9.0-alpha-demo. Mobile login/dashboard +passed on retry after the initial30-second form wait timed out. Public resumable +upload recovery/exact bytes/visitor isolation and replace/zero-byte/cancel cases +passed. Fixed-quota and interrupted-TCP scenarios retain their isolated evidence. + +The raw ISO and both checksum files passed full public-download hash checks. +The public signed checksum also verifies against the pinned release root. Logs: +`/tmp/archy-190-publish-iso.log` (ISO PASS before the idle upload tunnel closed), +`/tmp/archy-190-publish-iso-checksums.log` (small sidecars retried over HTTPS). +No ISO re-upload or artifact change was needed. A subsequent +follow-up backend suite exposed the pre-existing storage-prefix bug documented in +[known limitations](release-1.9.0-known-limitations.md). Its correction is being +qualified separately. Artifact-byte verification is not a claim that this newly +identified issue has been fixed in the already published release. + +Public assets: [1.9.0-alpha release](https://source.archipelago-foundation.org/lfg2025/archy/releases/tag/v1.9.0-alpha). +The separate follow-up branch now passes1,683 backend tests (four existing ignored) +and all1,222 frontend tests after correcting the storage classifier. These are +source test results, not inclusion in the published artifacts or live acceptance. diff --git a/docs/release-1.9.0-known-limitations.md b/docs/release-1.9.0-known-limitations.md index cf2e5632..4a10eaba 100644 --- a/docs/release-1.9.0-known-limitations.md +++ b/docs/release-1.9.0-known-limitations.md @@ -1,4 +1,6 @@ -# 1.9.0-alpha: Angor historical discovery +# 1.9.0-alpha: known limitations + +## Angor historical discovery Historical project discovery is incomplete. Funding commitments for all35 reference projects were verified, but34 original signed announcements were not @@ -16,3 +18,20 @@ The dev node is still syncing; full-chain evidence comes from Shorty. Evidence and inventory: [client acceptance](angor-client-acceptance-20261001.md), [project recovery inventory](angor-project-recovery-20261001.json), and [release acceptance](release-1.9.0-acceptance.md). + +## Chat/contact storage migration — discovered during follow-up testing + +A subsequent full backend test run exposed an existing random-prefix collision +in `storage_crypto::is_plaintext_json`: an encrypted store whose nonce begins +with `{` or `[` can be mistaken for legacy plaintext. This can prevent chat or +contact state loading correctly, and the message migration path can overwrite +that state. This helper is used for chat messages and mesh contact customizations, +not wallet databases. + +The follow-up branch replaces the prefix-only heuristic with complete JSON +validation and adds deterministic encrypted-prefix regression cases. Qualification +is in progress; the published 1.9.0-alpha artifacts do not include that fix. +Existing release signatures and tags must not be silently replaced. Track a +corrective update and preserve affected state before further node restarts. +The earlier green release run did not detect this probabilistic failure; do not +interpret it as proof that this newly discovered issue is absent. diff --git a/neode-ui/src/components/__tests__/MediaLightboxPip.test.ts b/neode-ui/src/components/__tests__/MediaLightboxPip.test.ts index 45ac2394..ca9e2dd3 100644 --- a/neode-ui/src/components/__tests__/MediaLightboxPip.test.ts +++ b/neode-ui/src/components/__tests__/MediaLightboxPip.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' import MediaLightbox from '../cloud/MediaLightbox.vue' import { usePipSession } from '../../composables/usePipSession' +import { togglePip } from '../../utils/pip' import type { FileBrowserItem } from '../../api/filebrowser-client' // jsdom has no picture-in-picture implementation — stub the pieces the @@ -75,6 +76,18 @@ async function mountLightbox() { } describe('MediaLightbox picture-in-picture handoff', () => { + it('checks PiP support when the action is invoked in a WebView', async () => { + const video = document.createElement('video') + const request = vi.spyOn(video, 'requestPictureInPicture') + Object.defineProperty(document, 'pictureInPictureEnabled', { value: false, configurable: true }) + await togglePip(video) + expect(request).not.toHaveBeenCalled() + + Object.defineProperty(document, 'pictureInPictureEnabled', { value: true, configurable: true }) + await togglePip(video) + expect(request).toHaveBeenCalledOnce() + }) + it('entering PiP emits close exactly once and adopts the video before doing so', async () => { const wrapper = await mountLightbox() const video = findVideo() diff --git a/neode-ui/src/utils/pip.ts b/neode-ui/src/utils/pip.ts index 7399a980..0d1292a6 100644 --- a/neode-ui/src/utils/pip.ts +++ b/neode-ui/src/utils/pip.ts @@ -20,7 +20,10 @@ export function isPipSupported(): boolean { } export async function togglePip(video: HTMLVideoElement | null | undefined): Promise { - if (!video || !pipSupported) return + // Check at call time. Embedded WebViews can expose the document capability + // after the module has been evaluated, and companion navigation can restore + // a page with a different media capability than its first load. + if (!video || !isPipSupported()) return try { if (document.pictureInPictureElement === video) await document.exitPictureInPicture() else await video.requestPictureInPicture()