Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
acca2f2
fix(ai): Resolve issue #2044 - Add packaged desktop visual and access…
Sep 1, 2026
5162698
feat(ai): Implemented the Ultrafix follow-up on exact HEAD `acca2f2f1…
Sep 1, 2026
29f6191
feat(ai): Implemented the four exact-head corrections without committ…
Sep 1, 2026
b9cb86a
feat(ai): Implemented the exact-head correction without committing.
Sep 1, 2026
7dc9ae4
feat(ai): Implemented the packaged accessibility correction on exact …
Sep 1, 2026
82087e0
feat(ai): Implemented the axe cleanup correction on exact head `7dc9a…
Sep 1, 2026
f8ee684
feat(ai): Implemented on exact head `82087e0221c2b90c7bf5fabe9c2f8906…
Sep 1, 2026
2d95ded
feat(ai): Implemented the zoom-200 metric correction on exact head `f…
Sep 1, 2026
791012e
feat(ai): Implemented the narrowly scoped real-Chromium gate on exact…
Sep 1, 2026
af182d7
feat(ai): Implemented the exact-head Electron zoom correction without…
Sep 1, 2026
8128f26
feat(ai): Implemented the packaged Electron authorization fix.
Sep 1, 2026
529699a
feat(ai): Implemented the narrow acceptance evidence correction on un…
Sep 2, 2026
101c3d7
feat(ai): Implemented the exact correction on head `529699a81f3b0ef8c…
Sep 2, 2026
f43f222
feat(ai): Implemented the acceptance-only clock correction on exact h…
Sep 2, 2026
e0a2b8f
feat(ai): Implemented the narrow packaged WebSocket correction.
Sep 2, 2026
912cfdb
feat(ai): Implemented the narrow completeness-counter correction.
Sep 2, 2026
25f5b68
feat(ai): Implemented the narrow two-blocker correction on head `912c…
Sep 2, 2026
6cadbc3
feat(ai): Implemented the narrow stale-socket acceptance correction o…
Sep 2, 2026
b9d02a1
feat(ai): Implemented the narrow renderer lifecycle correction on hea…
Sep 2, 2026
481c453
feat(ai): Implemented the narrow lifecycle correction on head `b9d02a…
Sep 2, 2026
c2c069d
feat(ai): Implemented the scoped current-user boundary fix on PR #204…
Sep 2, 2026
71be668
feat(ai): Implemented the narrow correction on exact head `c2c069ddfb…
Sep 2, 2026
6e5b150
feat(ai): Implemented the narrow bootstrap ownership correction on ex…
Sep 2, 2026
bb33495
feat(ai): Implemented the minimal lockfile-only correction based on e…
Sep 2, 2026
074d09b
feat(ai): Implemented the narrowly scoped four-file fix on exact head…
Sep 2, 2026
a81addd
feat(ai): Implemented the follow-up on exact HEAD `074d09bf1481eeb8c4…
Sep 2, 2026
cb822b4
feat(ai): Updated only [package-lock.json](/tmp/git-processor/worktre…
Sep 2, 2026
520d03d
feat(ai): Implemented the narrow current-user CORS fix on exact head …
Sep 2, 2026
1af99a3
feat(ai): Implemented the follow-up on exact head `520d03d34860a1adf0…
Sep 2, 2026
bd81253
feat(ai): Implemented the hosted-gate follow-up on exact head `1af99a…
Sep 2, 2026
4f8f367
feat(ai): Implemented the narrow packaged renderer correction, uncomm…
Sep 2, 2026
255645c
feat(ai): Implemented the Linux-first acceptance correction without w…
Sep 2, 2026
4c5b1fe
feat(ai): Implemented the production-boundary correction.
Sep 2, 2026
bab3480
feat(ai): Applied PR #2082’s exact 20-line test-only patch to [creden…
Sep 2, 2026
d733ee3
feat(ai): The existing session test already exercises the real permis…
Sep 2, 2026
17a0947
feat(ai): Implemented the requested follow-up without committing or m…
Sep 2, 2026
5338087
feat(ai): Implemented the narrow packaged-smoke sequencing fix on exa…
Sep 2, 2026
449e074
feat(ai): Implemented the narrow renderer-ownership correction on exa…
Sep 2, 2026
82b2837
feat(ai): Implemented the harness-only sequencing correction on exact…
Sep 2, 2026
f2d0d21
feat(ai): Implemented the harness-only correction on exact head `82b2…
Sep 2, 2026
96194d6
feat(ai): Implemented the narrow CSP parity correction on exact head …
Sep 2, 2026
8df95da
feat(ai): Implemented the diagnostic-only strict acceptance correction.
Sep 2, 2026
952411f
feat(ai): Implemented the diagnostic-only correction on exact head `8…
Sep 2, 2026
2dcf1bf
feat(ai): Implemented the narrow stats fixture correction without pro…
Sep 2, 2026
7f7b76b
feat(ai): Implemented the narrow Socket.IO synchronization correction…
Sep 2, 2026
2611822
feat(ai): Fixed the changed-area validation failure in [desktopPairin…
Sep 2, 2026
9862a4e
feat(ai): Implemented the narrow binary-safe scanner correction.
Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 80 additions & 3 deletions .github/workflows/desktop-release-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,37 @@ jobs:
node -e 'if (!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(process.argv[1])) process.exit(1)' "$version"
echo "version=$version" >> "$GITHUB_OUTPUT"

renderer-axe-boundary:
name: Prove stock Chromium existing-target axe boundary
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout pull-request validation source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Set up Node.js
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version-file: '.nvmrc'
cache: npm
cache-dependency-path: package-lock.json

- name: Install locked dependencies and real Chromium
run: |
npm ci
npx playwright install --with-deps chromium

- name: Run focused stock Chromium existing-target axe regressions
# This required predecessor step exclusively owns the real-browser opt-in.
env:
PROPR_DESKTOP_REAL_CHROMIUM_BOUNDARY: '1'
run: node --test --test-name-pattern='packaged acceptance renderer variants' apps/desktop/scripts/packaged-acceptance-renderer.test.mjs

package:
name: Validate unsigned ${{ matrix.platform }}-${{ matrix.arch }} package
if: github.event_name == 'pull_request'
needs: validation-version
needs: [validation-version, renderer-axe-boundary]
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
Expand Down Expand Up @@ -142,7 +169,7 @@ jobs:
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install --yes cpio dbus-x11 fakeroot gnome-keyring libsecret-1-0 rpm zip
sudo apt-get install --yes cpio dbus-x11 fakeroot fonts-liberation gnome-keyring libsecret-1-0 rpm tesseract-ocr zip

- name: Package desktop app from clean checkout
shell: bash
Expand Down Expand Up @@ -207,6 +234,31 @@ jobs:
xvfb-run --auto-servernum npm run desktop:smoke
' bash "$keyring_root"

- name: Capture packaged Linux x64 visual and accessibility acceptance evidence
if: matrix.platform == 'linux' && matrix.arch == 'x64'
shell: bash
env:
PROPR_DESKTOP_ACCEPTANCE_OUTPUT: ${{ github.workspace }}/desktop-acceptance-artifacts
run: |
keyring_root="$(mktemp -d)"
trap 'rm -rf -- "$keyring_root"' EXIT
dbus-run-session -- bash -euo pipefail -c '
export PROPR_DESKTOP_SMOKE_KEYRING_ROOT="$1"
export XDG_DATA_HOME="$1"
eval "$(printf "%s\n" "propr-packaged-acceptance" | gnome-keyring-daemon --unlock --components=secrets)"
xvfb-run --auto-servernum npm run desktop:acceptance
' bash "$keyring_root"
npm run desktop:acceptance:verify

- name: Publish mandatory packaged desktop acceptance evidence
if: matrix.platform == 'linux' && matrix.arch == 'x64'
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: propr-desktop-acceptance-linux-x64-${{ github.run_id }}-${{ github.run_attempt }}
path: desktop-acceptance-artifacts
if-no-files-found: error
retention-days: 14

- name: Launch packaged Windows application and exercise MVP desktop flows
if: matrix.platform == 'win32'
shell: bash
Expand Down Expand Up @@ -474,7 +526,7 @@ jobs:
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install --yes cpio dbus-x11 fakeroot gnome-keyring libsecret-1-0 rpm zip
sudo apt-get install --yes cpio dbus-x11 fakeroot fonts-liberation gnome-keyring libsecret-1-0 rpm tesseract-ocr zip

- name: Configure required macOS signing and notarization
if: matrix.platform == 'darwin'
Expand Down Expand Up @@ -653,6 +705,31 @@ jobs:
xvfb-run --auto-servernum npm run desktop:smoke
' bash "$keyring_root"

- name: Capture signed packaged Linux x64 visual and accessibility acceptance evidence
if: matrix.platform == 'linux' && matrix.arch == 'x64'
shell: bash
env:
PROPR_DESKTOP_ACCEPTANCE_OUTPUT: ${{ github.workspace }}/desktop-acceptance-artifacts
run: |
keyring_root="$(mktemp -d)"
trap 'rm -rf -- "$keyring_root"' EXIT
dbus-run-session -- bash -euo pipefail -c '
export PROPR_DESKTOP_SMOKE_KEYRING_ROOT="$1"
export XDG_DATA_HOME="$1"
eval "$(printf "%s\n" "propr-packaged-acceptance" | gnome-keyring-daemon --unlock --components=secrets)"
xvfb-run --auto-servernum npm run desktop:acceptance
' bash "$keyring_root"
npm run desktop:acceptance:verify

- name: Publish mandatory signed packaged desktop acceptance evidence
if: matrix.platform == 'linux' && matrix.arch == 'x64'
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: propr-desktop-production-acceptance-linux-x64-${{ github.run_id }}-${{ github.run_attempt }}
path: desktop-acceptance-artifacts
if-no-files-found: error
retention-days: 30

- name: Launch signed packaged Windows application and exercise MVP desktop flows
if: matrix.platform == 'win32'
shell: bash
Expand Down
25 changes: 25 additions & 0 deletions apps/desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ npm run desktop:typecheck
npm run desktop:test
npm run desktop:package
npm run desktop:smoke # Run under xvfb-run on a headless Linux host.
npm run desktop:acceptance # Linux x64 package; run under Xvfb in a D-Bus/keyring session.
npm run desktop:make
npm run desktop:audit
# On Linux hosts with the corresponding native packaging tools installed:
Expand Down Expand Up @@ -43,6 +44,30 @@ exit. `desktop:smoke:inspect` performs executable and fuse inspection without la
both Linux architectures under Xvfb, inspects macOS and Windows packages on their native runners, validates
DMG/ZIP/DEB/RPM/MSI packages, and validates configured OS signatures.

## Packaged visual and accessibility acceptance

Linux x64 is the canonical visual runtime. `desktop:acceptance` launches the real packaged executable with a fresh
private Electron profile and drives it over Chromium's debugging protocol with Playwright. A separately authorized
acceptance mode supplies deterministic local API, Socket.IO, browser-pairing, ProPR Connect, and local-setup fixtures
while preserving the production main/preload/renderer boundary, renderer sandbox, context isolation, navigation
policy, and credential service. It requires independent command-line and environment triggers, accepts only a
packaged Linux binary, and refuses the default Electron profile.

The mandatory artifact contains screenshots for first run, endpoint and Connect confirmation, pairing, local setup
prerequisites/progress/recovery/completion, dashboard profile management, offline, revoked, and incompatible states.
Every state is captured at standard, narrow, high-DPI, 200% zoom, and reduced-motion configurations. The manifest
records fixed locale/time/theme inputs, dimensions, hashes, and native coverage. The 200% variant uses an
acceptance-only, main-authorized preload bridge to Electron `webFrame` zoom and records its read-back alongside raw
CDP/renderer viewports, independently measured geometry, DPR, and physical PNG dimensions. Accessibility evidence
fails for any serious or critical axe finding or missing keyboard order, visible focus, dialog trap/restore,
accessible name, or live announcement proof. Finalization rejects missing, duplicate, unexpected, incorrectly sized, or secret-bearing
output. Sentinel coverage includes renderer DOM, process output, URLs, local/session storage, persisted profile/config
data, screenshots and metadata, and every decompressed Playwright trace entry.

The existing six-target package matrix is unchanged. Linux x64 produces the visual/accessibility runtime evidence.
Linux arm64, macOS x64/arm64, and Windows x64/arm64 retain native package inspection and platform runtime smoke
coverage; their acceptance classification is structural/runtime-only.

The first-release Windows MVP packages only the normal desktop application. Native self-update installation authority
is deferred to issue #2000: no broker, bootstrap, launcher, service, or authority custom action is built, copied into
`resources`, or installed by the MSI. Both Windows architectures remain mandatory release targets, and package/MSI
Expand Down
6 changes: 5 additions & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"package": "electron-forge package",
"smoke:package": "node scripts/smoke-packaged.mjs",
"smoke:inspect": "node scripts/smoke-packaged.mjs --inspect-only",
"acceptance:package": "node scripts/run-packaged-acceptance.mjs",
"acceptance:verify": "node -e \"import('./scripts/acceptance-artifacts.mjs').then(m => m.verifyAcceptanceArtifacts(process.env.PROPR_DESKTOP_ACCEPTANCE_OUTPUT || m.defaultAcceptanceOutputDirectory()))\"",
"premake": "npm run prepare:renderer",
"make": "electron-forge make",
"make:dmg": "node scripts/make-dmg.mjs",
Expand All @@ -46,11 +48,13 @@
"@electron-forge/maker-zip": "8.0.0-alpha.10",
"@electron-forge/plugin-vite": "8.0.0-alpha.10",
"@electron-forge/shared-types": "8.0.0-alpha.10",
"@electron/windows-sign": "2.0.6",
"@electron/fuses": "^2.1.3",
"@electron/windows-sign": "2.0.6",
"@types/node": "^22.10.0",
"@vitejs/plugin-react": "^4.6.0",
"axe-core": "4.10.3",
"electron": "^44.0.0",
"playwright": "^1.62.1",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vite": "^7.3.5"
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/renderer.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; connect-src 'self' https: http://127.0.0.1:* http://[::1]:* http://localhost:* ws://127.0.0.1:* ws://[::1]:* ws://localhost:* wss:; object-src 'none'; base-uri 'none'; form-action 'none'; frame-src 'none'"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; connect-src 'self' https: http: ws: wss:; object-src 'none'; base-uri 'none'; form-action 'none'; frame-src 'none'"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#f8fafc" />
Expand Down
Loading
Loading