Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
179 commits
Select commit Hold shift + click to select a range
5e5e890
fix(ai): Resolve issue #1958 - Extract the UI-agnostic local setup en…
Aug 29, 2026
c5b383c
fix(ai): Resolve issue #1959 - Add the desktop-shaped UI mode and ins…
Aug 29, 2026
7ba9aa5
fix(ai): Resolve issue #1954 - Create a shared ProPR API client and i…
Aug 29, 2026
356bfce
fix(ai): Resolve issue #1955 - Add secure desktop pairing tokens and …
Aug 29, 2026
5fc195c
fix(ai): Resolve issue #1956 - Scaffold the secure Electron desktop r…
Aug 29, 2026
b08e5f1
feat(ai): Implemented the follow-up fix without committing.
Aug 29, 2026
56c97eb
feat(ai): Fixed the full-suite failure in [taskInspectCommands.test.t…
Aug 29, 2026
13137ff
Merge pull request #1964 from integry/1959/gpt-5.6-sol-add-the-deskto…
integry Aug 29, 2026
2ee3db9
Merge pull request #1965 from integry/1954/gpt-5.6-sol-create-a-share…
integry Aug 29, 2026
21d0ff3
feat(ai): Implemented the packaging supply-chain follow-up without ch…
Aug 29, 2026
788c4b1
Merge pull request #1966 from integry/1955/gpt-5.6-sol-add-secure-des…
integry Aug 29, 2026
3275d74
feat(ai): Implemented the release-blocking packaging fix.
Aug 29, 2026
f01d661
Merge pull request #1969 from integry/1953-epic-desktop-transport-api
integry Aug 29, 2026
10c0cd7
feat(ai): Implemented the self-contained desktop preparation:
Aug 29, 2026
b20ae26
feat(ai): Implemented the follow-up in [cli-node-compatibility.yml](/…
Aug 29, 2026
6882e61
Merge pull request #1963 from integry/1958/gpt-5.6-sol-extract-the-ui…
integry Aug 29, 2026
c95ad7a
feat(ai): Implemented the Electron entry-format repair and strengthen…
Aug 29, 2026
4606f27
merge: resolve conflicts from 1950-epic-cross-platform-dsk into 1951-…
Aug 29, 2026
79e5111
feat(ai): Fixed the PR build failure in [App.tsx](/tmp/git-processor/…
Aug 29, 2026
c706970
feat(ai): Implemented the Linux space-free package path while preserv…
Aug 29, 2026
d1d4e32
feat(ai): Fixed the full-suite failure in [test/orchestratorConfig.te…
Aug 29, 2026
5b42070
feat(ai): Implemented only F1 and F2.
Aug 29, 2026
9e9cd23
feat(ai): Implemented F1–F3 only.
Aug 29, 2026
c505632
feat(ai): Implemented F3, F4, and F5 only.
Aug 29, 2026
7c39c48
feat(ai): Implemented only F4, F5, and F6.
Aug 29, 2026
944d55e
feat(ai): Implemented F6 only.
Aug 29, 2026
6ed84df
feat(ai): Implemented F7 only.
Aug 29, 2026
7a26a6b
feat(ai): Implemented only F7, F8, and F9.
Aug 29, 2026
1da60f5
feat(ai): Fixed the intermittent notification regression failure in […
Aug 29, 2026
5b73b8f
feat(ai): Fixed the flaky full-suite failure in [webPushDispatcher.te…
Aug 29, 2026
0728353
feat(ai): Implemented the focused PR #1968 follow-up without committing.
Aug 29, 2026
85aee4b
Merge pull request #1967 from integry/1956/gpt-5.6-sol-scaffold-the-s…
integry Aug 29, 2026
a9fde0f
Merge remote-tracking branch 'origin/1950-epic-cross-platform-dsk' in…
Aug 29, 2026
ba2511b
feat(ai): Implemented F9 and S1 follow-up changes.
Aug 29, 2026
42d1fb9
fix(ai): Resolve issue #1957 - Add cross-platform desktop packaging, …
Aug 29, 2026
4c99bb7
feat(ai): Implemented the requested follow-ups on synced head `a9fde0…
Aug 29, 2026
e319d2e
feat(ai): Fixed the CI failure in [App.tsx](/tmp/git-processor/worktr…
Aug 29, 2026
78b2803
merge: resolve conflicts from 1952-epic-electron-runtime-app into 195…
Aug 29, 2026
337f49c
Merge pull request #1968 from integry/1951-epic-desktop-experience-uxs
integry Aug 29, 2026
750e802
feat(ai): Implemented F2 only.
Aug 29, 2026
a9dc441
feat(ai): Implemented the PR follow-ups.
Aug 29, 2026
b3738cf
merge: resolve conflicts from 1950-epic-cross-platform-dsk into 1952-…
Aug 29, 2026
8ef74c1
feat(ai): Fixed the CI blocker in [App.tsx](/tmp/git-processor/worktr…
Aug 29, 2026
7ba9e9b
feat(ai): Implemented F1–F4 without committing.
Aug 29, 2026
a4410ec
feat(ai): Implemented the packaged-renderer CSS fix without changing …
Aug 29, 2026
eef7396
feat(ai): Implemented the runtime download hardening without committi…
Aug 29, 2026
b36984e
feat(ai): Fixed the CI-only shortcut race in [DesktopExperience.tsx](…
Aug 29, 2026
d5465a3
feat(ai): Implemented F3 only; S1 remains untouched.
Aug 29, 2026
872cd99
merge: resolve conflicts from 1952-epic-electron-runtime-app into 195…
Aug 29, 2026
6fe54e8
feat(ai): Fixed the flaky full-suite failure in [DesktopExperience.te…
Aug 29, 2026
c524a9e
feat(ai): Reapplied the canonical deep-link repair on exact head `6fe…
Aug 29, 2026
48f8581
feat(ai): Fixed the full-suite flake in [notificationManagementRoutes…
Aug 29, 2026
f94a38d
Merge remote-tracking branch 'origin/1952-epic-electron-runtime-app' …
Aug 29, 2026
267e6b2
feat(ai): Implemented all requested follow-up blockers on exact head …
Aug 29, 2026
d99f006
feat(ai): Implemented F1 only on base head `48f85811addf4bccfd390961e…
Aug 29, 2026
db3d69a
Merge remote-tracking branch 'origin/1952-epic-electron-runtime-app' …
Aug 29, 2026
fe68d40
feat(ai): Implemented F5–F8 on synchronized head `db3d69a2788ece2273c…
Aug 29, 2026
15e39bc
feat(ai): Implemented all four follow-ups without modifying F5–F8 or …
Aug 29, 2026
ef737aa
feat(ai): Implemented F9–F11 on the exact requested head without comm…
Aug 29, 2026
078eac2
feat(ai): Implemented the exact `ef737aacf73c77e4fa6c8a6d59dc3e5a16bb…
Aug 29, 2026
fb14a29
feat(ai): Implemented the narrow test-only fix in [release-architectu…
Aug 29, 2026
f088817
feat(ai): Implemented the two requested fixes on exact head `fb14a297…
Aug 30, 2026
20fcc8c
feat(ai): Implemented only the aggregate DMG finalization fix on exac…
Aug 30, 2026
4fba922
feat(ai): Implemented the two requested DMG blockers on exact head `2…
Aug 30, 2026
bcc7372
feat(ai): Implemented the exact-head DMG follow-up without merging, s…
Aug 30, 2026
ce7ce35
feat(ai): Implemented the two requested fixes on exact head `bcc73729…
Aug 30, 2026
f4cfdcd
feat(ai): Implemented F12 only.
Aug 30, 2026
fe26f93
feat(ai): Implemented F13 on exact head `f4cfdcd717be70804f435ef3955b…
Aug 30, 2026
a047008
feat(ai): Implemented on exact head `fe26f938c7ea8c2ae276f0abbb5079fd…
Aug 30, 2026
3737d95
feat(ai): Implemented the follow-up changes on exact head `a0470086c6…
Aug 30, 2026
e98a6f3
feat(ai): Implemented the requested follow-up changes, but completion…
Aug 30, 2026
8556ed5
feat(ai): Implemented the requested follow-up changes without committ…
Aug 30, 2026
4852382
feat(ai): Implemented on exact head `8556ed513fc516839e99a6deb04b2632…
Aug 30, 2026
dd08df6
feat(ai): Implemented the follow-up changes without merging, syncing,…
Aug 30, 2026
b6fcd42
feat(ai): Implemented the Windows broker bootstrap follow-up without …
Aug 30, 2026
1969938
feat(ai): Implemented on exact head `b6fcd421a809713157826f736f69bb11…
Aug 30, 2026
5261a6c
feat(ai): Implemented the locally verifiable follow-up changes withou…
Aug 30, 2026
6c62a9e
feat(ai): Implemented the requested follow-up on exact base `5261a6cd…
Aug 30, 2026
9d87bac
feat(ai): Implemented the follow-up on exact head `6c62a9e2eaeb97c8b9…
Aug 30, 2026
6ee11d1
feat(ai): Implemented the six requested blockers on exact head `9d87b…
Aug 30, 2026
62847ea
feat(ai): Implemented the requested follow-up without merging, syncin…
Aug 30, 2026
3efab56
feat(ai): Implemented the requested follow-up on exact head `62847ea2…
Aug 30, 2026
cdad428
feat(ai): Implemented the requested follow-up without committing, mer…
Aug 30, 2026
5059c43
feat(ai): Implemented the requested follow-up without merging, syncin…
Aug 30, 2026
889b8c3
feat(ai): Implemented on exact head `5059c437661362670443983ffa8b173f…
Aug 30, 2026
d8256be
feat(ai): Implemented the exact-head WinTrust fix without merge/runti…
Aug 30, 2026
be54c38
feat(ai): Implemented the two Windows build-boundary fixes without ch…
Aug 30, 2026
bd53d9f
feat(ai): Implemented the two follow-up blockers on base SHA `be54c38…
Aug 30, 2026
4078647
feat(ai): Implemented the Windows staging-launch fix on base SHA `bd5…
Aug 30, 2026
ec12eab
feat(ai): Implemented the narrowly scoped correction on exact base `4…
Aug 30, 2026
4557fa2
feat(ai): Implemented the narrow build-only correction on exact HEAD …
Aug 30, 2026
f3f1a96
feat(ai): Implemented the bounded Windows staging correction on exact…
Aug 30, 2026
44561fa
feat(ai): Implemented the bounded Windows launcher-authentication fix…
Aug 30, 2026
5cd8eb9
feat(ai): Implemented the bounded dynamic catalog pivot on exact head…
Aug 30, 2026
fba219f
feat(ai): Implemented the functional-build pivot on exact `5cd8eb9564…
Aug 30, 2026
47afb77
feat(ai): Implemented the diagnostic-only Windows launch-stage split …
Aug 30, 2026
3e712a2
feat(ai): Implemented the release-functional Windows pivot on exact `…
Aug 30, 2026
0a37ecc
feat(ai): Implemented the Windows pre-spawn fix on exact head `3e712a…
Aug 30, 2026
731e145
feat(ai): Implemented the bounded Windows MVP packaging pivot.
Aug 30, 2026
d8ff447
feat(ai): Implemented only the two requested blockers.
Aug 30, 2026
dc27bcf
feat(ai): Implemented the deterministic packaged-smoke ordering fix o…
Aug 30, 2026
5d5ad38
feat(ai): Implemented the four cross-platform fixture fixes on exact …
Aug 30, 2026
021ff5e
feat(ai): Implemented the deterministic MSI compiler fixes on exact h…
Aug 31, 2026
5295d77
feat(ai): Implemented the exact WiX Light code-page fix:
Aug 31, 2026
57eb4c6
feat(ai): Implemented the exact blocker fix on head `5295d7785…`:
Aug 31, 2026
609d24b
feat(ai): Implemented the production Light timeout fix on exact head …
Aug 31, 2026
520042f
feat(ai): Implemented the exact per-machine Start Menu fix on head `6…
Aug 31, 2026
4381af0
feat(ai): Implemented the requested follow-up on exact head `520042f8…
Aug 31, 2026
306a3ed
feat(ai): Implemented the exact installed-Windows harness fix on head…
Aug 31, 2026
c6f33d9
feat(ai): Implemented the compatible selected findings:
Aug 31, 2026
3b4d69d
feat(ai): Implemented the requested follow-up without committing.
Aug 31, 2026
6595e07
feat(ai): Implemented only the requested Windows smoke boundary fix:
Aug 31, 2026
1894e29
feat(ai): Implemented the exact Windows evidence-reader fix without c…
Aug 31, 2026
3e916db
feat(ai): Implemented the exact evidence-parser fix on head `1894e29c…
Aug 31, 2026
1d7eee0
feat(ai): Implemented the Windows smoke observability fix on unchange…
Aug 31, 2026
5ee275e
feat(ai): Implemented the exact shutdown-order fix.
Aug 31, 2026
ba10a98
feat(ai): Implemented the alternate-credential smoke launch fix witho…
Aug 31, 2026
ad61f50
feat(ai): Implemented the F18 child-environment boundary fix.
Aug 31, 2026
6d12bb7
feat(ai): Implemented the F19 follow-up without touching the installe…
Aug 31, 2026
deee2d8
feat(ai): Implemented the F20 filename fix on head `6d12bb7a00cef1e4c…
Aug 31, 2026
8d716e6
feat(ai): Implemented the F21 portability fix in [packaged-smoke-supp…
Aug 31, 2026
8ddd727
feat(ai): Implemented the F22-only MSI inspection fix on head `8d716e…
Aug 31, 2026
30e94bd
feat(ai): Implemented F16 on exact head `8ddd72727ee72334124e3114bdf6…
Aug 31, 2026
83f1d1c
Merge pull request #1972 from integry/1957/gpt-5.6-sol-add-cross-plat…
integry Aug 31, 2026
d84daba
fix(ai): Resolve issue #2031 - Fix CodeQL ReDoS in Windows smoke root…
Aug 31, 2026
2c35025
fix(ai): Resolve issue #2032 - Make Windows MSI Start Menu shortcut m…
Aug 31, 2026
739319a
Merge pull request #2033 from integry/2031/gpt-5.6-sol-fix-codeql-red…
integry Aug 31, 2026
1aace8c
Merge remote-tracking branch 'origin/1952-epic-electron-runtime-app' …
Aug 31, 2026
e1b318f
feat(ai): Implemented the narrowly scoped fix on exact head `1aace8c1…
Aug 31, 2026
83aecdf
feat(ai): Implemented MSI correction F2 on exact head `e1b318ffa2c139…
Aug 31, 2026
9c6e1d4
feat(ai): Implemented F3 and F1 on exact head `83aecdf4db2ea68c7d6eee…
Aug 31, 2026
33889bd
feat(ai): Implemented diagnostic F4 on exact head `9c6e1d43c30fe296c9…
Aug 31, 2026
f916c79
feat(ai): Implemented functional F5 on exact head `33889bd36bbdb9aae2…
Aug 31, 2026
5ec88c0
feat(ai): Implemented functional F6 on exact head `f916c794e5d3995241…
Aug 31, 2026
1b3a179
feat(ai): Implemented diagnostic F7 on exact head `5ec88c0835c58628b7…
Aug 31, 2026
2a008f7
feat(ai): Implemented F8 on exact head `1b3a179a4f39f45deafe3e487abeb…
Aug 31, 2026
86faa47
feat(ai): Implemented F9 on exact head `2a008f7461250bc514e15118d2ce4…
Aug 31, 2026
62c8c06
feat(ai): Implemented diagnostic F10 on exact head `86faa47925fdaf288…
Aug 31, 2026
fe67899
feat(ai): Implemented F3 only.
Aug 31, 2026
2ecdd60
feat(ai): Implemented F4 only on exact head `fe67899ebe7f1c98b0819a9c…
Aug 31, 2026
30a749b
Merge pull request #2034 from integry/2032/gpt-5.6-sol-make-windows-m…
integry Aug 31, 2026
57bfef6
fix(ai): Resolve issue #2037 - Enforce Windows Installer ProductVersi…
Aug 31, 2026
79dfe9e
fix(ai): Resolve issue #2036 - Clamp desktop window sizing to the act…
Aug 31, 2026
8ab9ae9
feat(ai): Implemented the Windows validation-order fix on exact head …
Sep 1, 2026
f7811aa
Merge pull request #2038 from integry/2037/gpt-5.6-sol-enforce-window…
integry Sep 1, 2026
4775600
Merge pull request #2039 from integry/2036/gpt-5.6-sol-clamp-desktop-…
integry Sep 1, 2026
30b33a8
fix(ai): Resolve issue #2041 - Bound every Windows installed-app harn…
Sep 1, 2026
436cefa
feat(ai): Implemented only F1/F2 on exact head `30b33a80802262d60e7c7…
Sep 1, 2026
9e9f375
feat(ai): Implemented the fixture-only correction on exact HEAD `436c…
Sep 1, 2026
a064d8f
feat(ai): Implemented only F1 and F2.
Sep 1, 2026
b2bfe47
feat(ai): Implemented the complete #2042 follow-up on exact head `a06…
Sep 1, 2026
a966e3a
feat(ai): Implemented the requested #2042 follow-up without committing.
Sep 1, 2026
35acc0e
feat(ai): Implemented the requested PR #2042 follow-ups without commi…
Sep 1, 2026
0a1e94f
feat(ai): Implemented the complete F10–F13 correction on exact head `…
Sep 1, 2026
390a721
feat(ai): Implemented the exact-head F14–F16 follow-up without commit…
Sep 1, 2026
a30d8bf
feat(ai): Implemented the exact-head F17/F18 correction without commi…
Sep 1, 2026
41cd874
feat(ai): Implemented the exact-head F19/F20 correction on `a30d8bf31…
Sep 1, 2026
d2ba71e
feat(ai): Implemented the exact-head F21 correction on `41cd874ada649…
Sep 1, 2026
de947aa
feat(ai): Implemented the exact-head correction on `d2ba71eb795fd0a5d…
Sep 1, 2026
b9415f5
feat(ai): Implemented the exact-head correction on `de947aac8e3f0dd04…
Sep 1, 2026
d0450fa
feat(ai): Implemented the exact-head correction on `b9415f52f8a50288c…
Sep 1, 2026
b2d2b54
feat(ai): Implemented the exact native protocol correction on `d0450f…
Sep 1, 2026
06b8844
feat(ai): Implemented the bounded NO_MARKER correction.
Sep 1, 2026
d4dfd38
feat(ai): Implemented the pre-branch correction on `06b8844…`.
Sep 1, 2026
59893c8
fix(ai): Resolve issue #2048 - Patch runtime desktop packaging browse…
Sep 1, 2026
4eb7dcd
feat(ai): Implemented the fixture-only diagnostic transport:
Sep 1, 2026
ee6eb2f
Merge pull request #2049 from integry/2048/gpt-5.6-sol-patch-runtime-…
integry Sep 1, 2026
3af4800
feat(ai): Implemented the schema-v3 follow-up on exact head `4eb7dcd9`.
Sep 1, 2026
1a40502
feat(ai): Implemented the #2042 follow-up on exact head `3af480032d47…
Sep 1, 2026
faf1d69
feat(ai): Implemented the post-validation NO_MARKER correction on exa…
Sep 1, 2026
4a9d15e
feat(ai): Implemented the PS5.1 receipt replacement correction on exa…
Sep 1, 2026
ccea5c2
feat(ai): Implemented diagnostic-only changes on exact head `4a9d15e9…
Sep 1, 2026
2807860
feat(ai): Implemented the parser-only fix in [test-installed-windows-…
Sep 1, 2026
6747a03
feat(ai): Implemented the diagnostic-only follow-up on exact head `28…
Sep 1, 2026
01b133f
feat(ai): Implemented the exact parser-only fix.
Sep 1, 2026
01373ad
Merge remote-tracking branch 'origin/1952-epic-electron-runtime-app' …
Sep 1, 2026
e3149c2
Merge PR #2042: Windows installed-app harness hardening
integry Sep 1, 2026
4fda554
fix(ai): Resolve issue #2078 - Restore canonical qs and fast-uri runt…
Sep 2, 2026
03821a2
Merge pull request #2080 from integry/2078/gpt-5.6-sol-restore-canoni…
integry 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
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,14 @@ DASHBOARD_API_PORT=4000
# security). Defaults to http://localhost:4000 when unset; set it to the
# https://t-<id>.propr.dev host when the hosted UI tunnel is enabled.
# API_PUBLIC_URL=http://localhost:4000
# Optional lifetime for newly paired desktop instance tokens. When unset,
# tokens remain valid until the owner revokes them. Range: 1-3650 days.
# PROPR_DESKTOP_TOKEN_TTL_DAYS=90
# Optional per-IP desktop discovery/pairing quotas. Defaults are documented in
# docs/docs/operations/desktop-pairing.md.
# PROPR_DISCOVERY_RATE_LIMIT_MAX=60
# PROPR_PAIRING_START_RATE_LIMIT_MAX=10
# PROPR_PAIRING_POLL_RATE_LIMIT_MAX=180
# Session cookie domain. Leave UNSET for v1 — including hosted UI tunnel proxy
# sessions, which run on a single t-<id>.propr.dev host (see the tunnel
# section above). Only set it for a custom multi-subdomain deployment.
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/cli-node-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- '.github/workflows/cli-node-compatibility.yml'
- 'package-lock.json'
- 'packages/cli/**'
- 'packages/local-setup/**'
- 'packages/shared/**'

concurrency:
Expand Down Expand Up @@ -37,8 +38,10 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Build shared dependency
run: npm run build -w @propr/shared
- name: Build workspace dependencies
run: |
npm run build -w @propr/shared
npm run build -w @propr/local-setup

- name: Run project option regressions
run: >-
Expand Down
949 changes: 949 additions & 0 deletions .github/workflows/desktop-release-guard.yml

Large diffs are not rendered by default.

29 changes: 24 additions & 5 deletions .github/workflows/pr-build-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jobs:
- name: Build and test the CLI Agent Skill
run: |
npm run build -w @propr/shared
npm run build -w @propr/local-setup
npm run typecheck -w @propr/cli
npx tsx --experimental-test-module-mocks --test \
packages/cli/src/agentSkill.test.ts \
Expand Down Expand Up @@ -82,6 +83,7 @@ jobs:
runuser --user node -- env HOME=/home/node bash -euo pipefail <<'NON_ROOT'
test "$(node -p 'process.geteuid()')" -ne 0
npm run build -w @propr/shared
npm run build -w @propr/local-setup
npx tsx --experimental-test-module-mocks --test \
packages/cli/src/agentSkill.test.ts \
packages/cli/src/agentSkill.forceRace.test.ts \
Expand Down Expand Up @@ -111,6 +113,7 @@ jobs:
test "$(node -p process.platform)" = darwin
test "$(node -p process.arch)" = arm64
npm run build -w @propr/shared
npm run build -w @propr/local-setup
npm run typecheck -w @propr/cli
npx tsx --experimental-test-module-mocks --test \
packages/cli/src/agentSkill.test.ts \
Expand Down Expand Up @@ -281,10 +284,11 @@ jobs:
echo
echo "--- Hosted tunnel regression tests ---"
echo "Running hosted tunnel regression tests..."
# Build @propr/shared first: the tsx and UI tests below import from it,
# so a stale or missing dist in a clean checkout would fail or use old
# output. Build once, up front, before anything that depends on it.
# Build workspace dependencies first: the tsx and UI tests below import
# from them, so a stale or missing dist in a clean checkout would fail
# or use old output. Build once, up front, before their consumers.
npm run build -w @propr/shared
npm run build -w @propr/local-setup
PROPR_DEMO_MODE=true npx tsx --test \
test/orchestratorConfig.test.mjs \
packages/cli/src/commands/setup/engine.test.ts \
Expand Down Expand Up @@ -328,6 +332,7 @@ jobs:
- 'packages/shared/**'
ui:
- 'propr-ui/**'
- 'packages/client/**'
- 'packages/shared/**'
docs:
- 'docs/**'
Expand Down Expand Up @@ -445,6 +450,18 @@ jobs:
EXIT_CODE=1
fi

if [ $UI_FAILED -eq 0 ]; then
CLIENT_OUTPUT=$(npm run typecheck -w @propr/client 2>&1 && npm test -w @propr/client 2>&1 && npm run build -w @propr/client 2>&1) || {
echo "❌ Client Package Validation FAILED (UI transport dependency)" >> build_log.txt
echo "$CLIENT_OUTPUT" >> build_log.txt
UI_FAILED=1
EXIT_CODE=1
}
if [ $UI_FAILED -eq 0 ]; then
echo "✅ Client Package validation passed" >> build_log.txt
fi
fi

if [ $UI_FAILED -eq 0 ]; then
TYPECHECK_OUTPUT=$(npm run typecheck -w propr-ui 2>&1) || {
echo "❌ UI Typecheck FAILED" >> build_log.txt
Expand Down Expand Up @@ -708,8 +725,10 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Build shared package
run: npm run build --workspace=@propr/shared
- name: Build workspace dependencies
run: |
npm run build --workspace=@propr/shared
npm run build --workspace=@propr/local-setup

- name: Parse init JSON output
run: npx tsx --test packages/cli/src/commands/initCommands.test.ts
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ apps/release-site-videos/

# Standalone publish staging (scripts/build-publish.mjs)
dist-publish/

# Electron Forge build and package output
apps/desktop/.vite/
apps/desktop/out/
190 changes: 190 additions & 0 deletions apps/desktop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# ProPR Desktop

This workspace packages the existing `propr-ui` React source as a sandboxed Electron renderer. The desktop entry is
`propr-ui/src/desktop.tsx`; the normal web entry, service worker, CLI, API, and self-hosted deployment remain unchanged.

## Commands

Run these from the repository root:

```sh
npm run desktop:dev
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:make
npm run desktop:audit
# On Linux hosts with the corresponding native packaging tools installed:
npm run make:deb -w @propr/desktop
npm run make:rpm -w @propr/desktop
# macOS only, after packaging the selected architecture:
npm run make:dmg -w @propr/desktop -- --arch=arm64
```

Desktop development, typecheck, package, and make commands build required renderer workspace dependencies through
`desktop:prepare`, in dependency order (`@propr/shared` then `@propr/client`). They do not depend on previously
generated workspace `dist` directories.

Development renderer URLs are accepted only when Electron Forge supplies an HTTP loopback URL. Packaged builds load
the generated renderer from the application ASAR through an app-owned protocol.

The packaged-binary smoke test verifies the hardened fuse states and launches artifacts without a sandbox-disabling
flag. Its preferred window is 1280x820 with an 880x620 minimum, sourced from one runtime/smoke sizing manifest. The
runtime selects the cursor-relevant display with a primary-display fallback and clamps both sizes to that display's
work area before native construction. Native evidence requires the actual window to equal that clamped size and
derives the viewport from the actual native content bounds. The packaged smoke also constructs a hidden 800x560
reduced-work-area window and verifies its real native bounds and clamped minimums. It retains the real title-bar logo,
connection-card, control containment, sizing, spacing, and footer checks on smaller responsive work areas. The child
receives only fixed smoke triggers, private profile/temp paths, and strictly validated platform launch inputs; it never
inherits the parent CI environment or `PATH`. The smoke
also rejects main-process uncaught exceptions and requires proof that `window.proprDesktop` is exposed before a clean
exit. `desktop:smoke:inspect` performs executable and fuse inspection without launching a window. Release CI launches
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.

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
inspection fails if any deferred authority resource appears.

`desktop:audit` deliberately applies separate policies to the two dependency surfaces: low-or-higher advisories fail
the production-runtime audit, while high and critical advisories fail the desktop development/build-tool audit. Release
CI runs both checks directly from the committed lockfile before installing or executing the packaging toolchain.

## Security boundary

The renderer has no Node.js integration and receives only the typed `window.proprDesktop` bridge. It exposes metadata,
validated external-browser opening, profiles, encrypted credentials, lifecycle placeholders, and validated deep-link
events. It never exposes a shell, command runner, arbitrary IPC call, or filesystem path/API.

Profile metadata is stored in an app-owned, permission-restricted JSON file. Credential values are encrypted with
Electron `safeStorage` before they are written separately. If OS encryption is unavailable—or Linux selects the
`basic_text` backend—the app reports that state and refuses to persist or return credentials; there is no plaintext
fallback. Profiles remain usable because they contain only a display label and validated API endpoint.

`propr://connect` and `propr://open` are the only accepted deep-link actions. A single-instance lock routes later
activations to the existing window. Local lifecycle methods intentionally return `not-implemented`; this scaffold does
not download, install, start, or execute ProPR runtime components.

## Desktop distributables and releases

Desktop releases have their own `desktop-v<major>.<minor>.<patch>` tags. They do not use or require the monorepo's
`v<version>` tag. `PROPR_DESKTOP_VERSION` propagates the tag version into the packaged application, renderer, native
metadata, Linux packages, protected machine MSI, artifact names, and release manifest without changing the monorepo
package versions.

The native GitHub Actions matrix produces these assets for both x64 and arm64:

| Platform | Native runner | Direct-distribution artifacts |
| --- | --- | --- |
| Linux | `ubuntu-24.04`, `ubuntu-24.04-arm` | DEB, RPM, ZIP |
| macOS | `macos-15-intel`, `macos-15` | DMG, ZIP |
| Windows | `windows-2025`, `windows-11-arm` | signed per-machine Program Files MSI |

Every matrix job stages DEB/RPM/ZIP/DMG names as `ProPR-Desktop-<version>-<platform>-<arch>.<format>` and retains
`ProPR-Desktop-<version>-windows-<arch>-Machine-Setup.msi` for Windows. The final job rejects
missing targets or changed fragment checksums, emits `SHA256SUMS` and `desktop-release.json`, and attaches the complete
set to the matching GitHub release. Production publication is triggered only by a new, non-forced
`desktop-v<major>.<minor>.<patch>` tag push; there is no manual dispatch path. A secretless preflight must succeed before
any job can request the protected release environment or receive release secrets. Normal local packages are unsigned
and have updates disabled:

```sh
npm ci
npm run desktop:typecheck
npm run desktop:test
npm run desktop:package
xvfb-run --auto-servernum npm run desktop:smoke # Linux

# Full unsigned Linux release artifacts (requires dpkg-deb and rpmbuild/rpm):
PROPR_DESKTOP_VERSION=1.2.3 \
PROPR_DESKTOP_ENABLE_DEB=1 \
PROPR_DESKTOP_ENABLE_RPM=1 \
npm run make -w @propr/desktop -- --arch="$(node -p process.arch)"
```

### CI preflight, signing, and notarization configuration

Repository-ruleset inspection uses a dedicated GitHub App installed only on this repository. Configure the App with
exactly repository **Administration: read**, **Contents: read**, and **Environments: read** (GitHub adds Metadata: read
implicitly), with no write permission and no Actions, Deployments, Releases, or other repository permission. Store its
private key only in a separate approval-protected `desktop-release-preflight` environment:

- Variable `PROPR_DESKTOP_PREFLIGHT_APP_ID`: the least-privilege preflight App ID.
- Secret `PROPR_DESKTOP_PREFLIGHT_APP_PRIVATE_KEY`: that App's private key.

Configure `desktop-release-preflight` with at least one required reviewer, custom deployment policies enabled,
protected-branch policies disabled, and exactly one deployment policy: the tag pattern `desktop-v*`. The workflow
uses a SHA-pinned token action to mint a short-lived installation token explicitly requesting only Administration read,
Contents read, and Environments read; workflow regression tests pin those exact inputs and reject any write or Actions
permission. The App installation itself must have the same exact least-privilege permission set. Preflight fails closed
when the ruleset API does not return `bypass_actors`. Pull requests do not schedule this job, and a nonmatching or
unreviewed tag cannot enter the environment or obtain the App credential. The preflight environment must contain no
signing, notarization, update-signing, release-publication, or production deployment secret.

Signing material is read only from the distinct approval-protected `desktop-release` GitHub environment and written
to runner-temporary files/keychains. Every value below is mandatory for a production `desktop-v*` tag; unsigned and
partially signed production releases fail before publication. Pull-request package validation and the preflight
environment receive none of these secrets and explicitly check that release-secret environment variables are absent.

GitHub Actions secrets:

- `PROPR_DESKTOP_MAC_CERTIFICATE_P12_BASE64`: base64 of the Developer ID Application `.p12`.
- `PROPR_DESKTOP_MAC_CERTIFICATE_PASSWORD`: password for that `.p12`.
- `PROPR_DESKTOP_APPLE_API_KEY_P8_BASE64`: base64 of the App Store Connect API `.p8` key.
- `PROPR_DESKTOP_APPLE_API_KEY_ID`: App Store Connect API key ID.
- `PROPR_DESKTOP_APPLE_API_ISSUER_ID`: App Store Connect issuer UUID.
- `PROPR_DESKTOP_WINDOWS_CERTIFICATE_PFX_BASE64`: base64 of the Authenticode `.pfx`.
- `PROPR_DESKTOP_WINDOWS_CERTIFICATE_PASSWORD`: password for that `.pfx`.
- `PROPR_DESKTOP_UPDATE_PRIVATE_KEY`: base64 Ed25519 PKCS#8 DER key used only to sign update-channel metadata.

GitHub Actions variables (public configuration, not secrets):

- `PROPR_DESKTOP_MAC_SIGNING_IDENTITY`: exact Developer ID Application identity.
- `PROPR_DESKTOP_MAC_TEAM_ID`: exact Team ID embedded in signed macOS update builds and verified from produced apps.
- `PROPR_DESKTOP_WINDOWS_SIGNING_IDENTITY`: exact Authenticode certificate subject expected by installed builds.
- `PROPR_DESKTOP_WINDOWS_SIGNER_PINS`: sorted, unique comma-separated allowlist of one or more
`certificate-sha256:<64 lowercase hex>` or `spki-sha256:<64 lowercase hex>` fingerprints. Production Windows
packaging fails closed when this public operator pin is absent, malformed, or does not match the signing key.
- `PROPR_DESKTOP_UPDATE_PUBLIC_KEY`: base64 Ed25519 SPKI DER public key matching the update private key.
- `PROPR_DESKTOP_UPDATE_MANIFEST_URL`: stable HTTPS URL from which clients fetch `desktop-release.json`; the detached
signature must be published beside it as `desktop-release.json.sig`.
- `PROPR_DESKTOP_DARWIN_X64_FEED_URL`, `PROPR_DESKTOP_DARWIN_ARM64_FEED_URL`: macOS JSON feed URLs.

Generate the independent update-channel keys once and store only the public output as a repository variable:

```sh
openssl genpkey -algorithm ED25519 -outform DER -out desktop-update-private.der
openssl pkey -inform DER -in desktop-update-private.der -pubout -outform DER -out desktop-update-public.der
base64 < desktop-update-private.der # secret: PROPR_DESKTOP_UPDATE_PRIVATE_KEY
base64 < desktop-update-public.der # variable: PROPR_DESKTOP_UPDATE_PUBLIC_KEY
```

Do not commit either key file. The private key is available only to the approval-protected `desktop-release`
environment. Configure that environment with at least one required reviewer, custom deployment policies enabled,
protected-branch policies disabled, and exactly one deployment policy: the tag pattern `desktop-v*`. The repository's
default branch must be protected `main`. It must also have an active tag-targeting ruleset whose sole include is
`refs/tags/desktop-v*`, whose exclude and bypass-actor lists are empty, and whose rules block both tag updates and tag
deletions.

For each new, non-forced `desktop-v<major>.<minor>.<patch>` tag push, the read-only preflight verifies both protected
environments and the repository prerequisites through the GitHub API, proves the exact tag commit is reachable from
`main`, rejects an existing release, and rechecks the tag and immutability ruleset for changes. The active tag ruleset
must match exactly `refs/tags/desktop-v*`, have no exclusions or bypass actors, and block update and deletion. Pull-
request finalization produces unsigned validation metadata; trusted signing jobs depend on preflight, check out its
immutable SHA, revalidate the tag before publication, and fail closed if any signing, notarization, or signed-update
field is missing. A release operator must publish the exact signed manifest/signature, generated macOS feeds, and
bound macOS packages to their configured HTTPS URLs. The manifest URL must not contain a query, so its companion is
always the documented pathname plus `.sig`.

Linux never checks for native updates. macOS remains a signed, check-only channel: it verifies the Ed25519 manifest,
exact target/version/feed bytes, package URL/size/SHA-256, and actual Team ID/designated requirement. Windows self-update
is explicitly `unsupported` for this release. The Windows build embeds no update URL or key even when update environment
variables are present; its public check and apply boundaries return `unsupported` before any network, cache, artifact,
signer, install-authority, or apply-capability call, and signed release metadata advertises no Windows feed.

Windows still publishes exactly one timestamped Authenticode-signed machine-wide MSI for each x64 and ARM64 target,
with the packaged application's signer and architecture inspected before staging. Per-user Squirrel Setup/NUPKG
artifacts remain unsupported and are never staged, checksummed, advertised, or published. Unsigned developer packages
remain update-disabled. Windows self-update installation work resumes only under issue #2000.
Loading
Loading