Skip to content

[2051 by GPT-5.6 Sol] Make packaged Windows Connect smoke lifecycle bounded and path-redacted - #2054

Merged
integry merged 5 commits into
1953-epic-desktop-transport-apifrom
2051/gpt-5.6-sol-make-packaged-windows-con-20260901-2205-5rn
Sep 2, 2026
Merged

[2051 by GPT-5.6 Sol] Make packaged Windows Connect smoke lifecycle bounded and path-redacted#2054
integry merged 5 commits into
1953-epic-desktop-transport-apifrom
2051/gpt-5.6-sol-make-packaged-windows-con-20260901-2205-5rn

Conversation

@propr-dev

@propr-dev propr-dev Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

AI Implementation Summary

Closes #2051

Branch: 2051/gpt-5.6-sol-make-packaged-windows-con-20260901-2205-5rn
Commits: ✅ Changes committed (678e573)


AI Processing Completed

Execution Details:

Summary:
Implemented the bounded, path-redacted packaged Connect lifecycle.

Key changes:

  • Added incremental bounded JSON parsing with exact ready-proof validation.
  • Added single-settlement handling for spawn, readiness, exit, timeout, shutdown, and races.
  • Added bounded Windows taskkill /PID <pid> /T /F termination with stream draining and fallback handling.
  • Added canonical fixture authorization, Windows EBUSY retries, and primary-error preservation.
  • Emits only fixed, allowlisted, path-free diagnostics.
  • Added deterministic coverage for all requested lifecycle, cleanup, truncation, redaction, and race scenarios.

Files:

Validation:

  • New lifecycle suite: 14/14 passed.
  • Related smoke-support tests passed.
  • ESLint and git diff --check passed.
  • Full desktop suite reached 320 passes; three failures reproduce independently in untouched existing source-order/window-option tests.

Detailed Logs:

  • Conversation: 91 messages
  • Session: 01a05f02-7023-7080-8e5e-864df8a2f97c

Log files stored at:

  • conversation: /tmp/claude-logs/issue-2051-2026-09-01T22-20-33-567Z-conversation.json
  • output: /tmp/claude-logs/issue-2051-2026-09-01T22-20-33-567Z-output.txt
Latest Conversation Messages

This PR was created automatically by ProPR after processing issue #2051.


💡 Need changes?

Comment on this PR to request refinements — the AI agent monitors comments and will update the implementation based on your feedback. Keep iterating until you're satisfied!

…fecycle boun

Implemented by ProPR AI using gpt-5.6-sol model.

Implementation completed successfully.
@integry

integry commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Ultrafix follow-up on exact head 678e573. Preserve the current lifecycle design and scope, but correct two independently reproduced blockers:

  1. Path/secret leakage through JSON escaping. The raw sensitive-needle scan misses Windows backslashes once JSON.stringify escapes them, and a parsed non-allowlisted record containing a private path is discarded before inspection. Inspect bounded parsed record string content recursively (or an equivalent canonical decoded representation) for every sensitive needle before accepting readiness, while retaining raw scanning for non-JSON output. Add deterministic tests for a Windows backslash path in a JSON field both before and after the ready record. Neither case may succeed and no raw secret/path may reach diagnostics.

  2. The cleanup deadline is not a real bound because rm/lstat/realpath promises can remain pending forever. Put every cleanup authorization and removal attempt behind an actual phase deadline. A never-settling filesystem promise must settle the harness with the fixed fixture-cleanup-failed secondary category within the configured bound, while preserving any primary result/error. Prefer a cancellable or isolated Windows operation if needed so the pending request cannot keep the harness alive. Add deterministic never-settling rm and authorization-call tests plus the existing retry scenarios.

Keep taskkill absolute-path authority, shell:false, exact PID /T /F arguments, bounded close/drain, exact ready-key validation, canonical generated-leaf authorization, fixed sanitized diagnostics, and primary-error preservation unchanged. Run focused tests and typecheck, and report the exact new head.

@propr-dev

propr-dev Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Applied the requested follow-up changes in commit 0c4ffa6

Summary of Changes

Implemented the two requested follow-up fixes in:

Changes include recursive decoded-JSON sensitive-string inspection, real cleanup phase deadlines, and isolated default Windows filesystem cleanup so stuck native requests cannot hold the harness open. Existing taskkill, readiness, sanitization, retry, and primary-result behavior remains intact.

Validation:

  • Lifecycle/cleanup tests: 19/19 passed
  • Related smoke-support tests: 11/11 passed
  • ESLint: passed
  • git diff --check: passed
  • Desktop typecheck: blocked by the pre-existing untouched src/window-options.test.ts:15 string/Rectangle error

Per instruction, I did not commit. The exact checked-out head remains 678e573b005f9623cbb6380622ca4216e3b3a431; the automation-generated post-commit head is therefore not yet available.


🤖 Implementation Details

  • Model: GPT-5.6 Sol (high)
  • Requested By: @integry
  • Time: 8m 5s
  • Tokens: 936,669 (917,634 in / 19,035 out)
  • Cost: $1.32
  • Subscription usage: Weekly +1%

Undo ChangesView Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Implement fixes for issues found by /review /fix or /fix address the null check issue
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment ID: 5501251882✓

@integry integry removed the AI label Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Full Test Suite Results

Validation failed during: Full test suite.

  • Dependency install: success
  • Workspace build: success
  • Docs validation: success
  • Redis startup: success
  • Full test suite: failure
View Test Output

> propr@0.8.15 test:full:prepared
> npm run test:server


> propr@0.8.15 test:server
> node scripts/run-test-suite.mjs


[1/360] apps/desktop/scripts/assert-windows-mvp-package.test.mjs
TAP version 13
# Subtest: Windows MVP ASAR main entry
    # Subtest: uses the rooted listPackage representation accepted by extractFile
    ok 1 - uses the rooted listPackage representation accepted by extractFile
      ---
      duration_ms: 28.181474
      type: 'test'
      ...
    # Subtest: preserves the Windows separator after removing the one archive root
    ok 2 - preserves the Windows separator after removing the one archive root
      ---
      duration_ms: 0.251662
      type: 'test'
      ...
    # Subtest: rejects traversal, duplicate entries, and case-colliding main paths
    ok 3 - rejects traversal, duplicate entries, and case-colliding main paths
      ---
      duration_ms: 0.761768
      type: 'test'
      ...
    1..3
ok 1 - Windows MVP ASAR main entry
  ---
  duration_ms: 30.316536
  type: 'suite'
  ...
1..1
# tests 3
# suites 1
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 278.370626

[2/360] apps/desktop/scripts/build-windows-machine-installer.test.mjs
TAP version 13
# Subtest: sets explicit Windows-1252 MSI and summary code pages in probe and production WXS
ok 1 - sets explicit Windows-1252 MSI and summary code pages in probe and production WXS
  ---
  duration_ms: 1.998446
  type: 'test'
  ...
# Subtest: accepts the exact MSI ProductVersion boundary and retains version and upgrade identity in WXS
ok 2 - accepts the exact MSI ProductVersion boundary and retains version and upgrade identity in WXS
  ---
  duration_ms: 0.524623
  type: 'test'
  ...
# Subtest: rejects every unsupported ProductVersion at the direct installer builder entry point
ok 3 - rejects every unsupported ProductVersion at the direct installer builder entry point
  ---
  duration_ms: 2.138168
  type: 'test'
  ...
# Subtest: uses per-machine scope without explicitly authoring the derived ALLUSERS property
ok 4 - uses per-machine scope without explicitly authoring the derived ALLUSERS property
  ---
  duration_ms: 0.561913
  type: 'test'
  ...
# Subtest: authors the complete per-machine Start Menu contract for x64 and ARM64
ok 5 - authors the complete per-machine Start Menu contract for x64 and ARM64
  ---
  duration_ms: 1.166747
  type: 'test'
  ...
# Subtest: selects only the installed x64 WiX directory or an explicit ARM64 build directory
ok 6 - selects only the installed x64 WiX directory or an explicit ARM64 build directory
  ---
  duration_ms: 0.718276
  type: 'test'
  ...
# Subtest: uses a ten-minute timeout only for production Light
ok 7 - uses a ten-minute timeout only for production Light
  ---
  duration_ms: 0.331722
  type: 'test'
  ...
# Subtest: keeps WiX processes and their emitted diagnostics bounded
ok 8 - keeps WiX processes and their emitted diagnostics bounded
  ---
  duration_ms: 0.215504
  type: 'test'
  ...
# Subtest: emits WiX v3 default registry values without empty Name attributes
ok 9 - emits WiX v3 default registry values without empty Name attributes
  ---
  duration_ms: 0.51235
  type: 'test'
  ...
1..9
# tests 9
# suites 0
# pass 9
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 254.481709

[3/360] apps/desktop/scripts/packaged-connect-lifecycle.test.mjs
TAP version 13
# Subtest: packaged Connect bounded child lifecycle
    # Subtest: accepts an exact ready proof followed by a clean exit
    ok 1 - accepts an exact ready proof followed by a clean exit
      ---
      duration_ms: 5.39886
      type: 'test'
      ...
    # Subtest: forces a ready app with a hung descendant through an exact bounded taskkill invocation
    ok 2 - forces a ready app with a hung descendant through an exact bounded taskkill invocation
      ---
      duration_ms: 5.618522
      type: 'test'
      ...
    # Subtest: keeps timeout-before-ready primary while terminating and draining the tree
    ok 3 - keeps timeout-before-ready primary while terminating and draining the tree
      ---
      duration_ms: 17.009021
      type: 'test'
      ...
    # Subtest: classifies asynchronous spawn errors without exposing their message
    ok 4 - classifies asynchronous spawn errors without exposing their message
      ---
      duration_ms: 6.091789
      type: 'test'
      ...
    # Subtest: settles close/timeout races once and never upgrades an early exit to success
    ok 5 - settles close/timeout races once and never upgrades an early exit to success
      ---
      duration_ms: 0.891822
      type: 'test'
      ...
    # Subtest: accepts a clean post-proof close racing a taskkill no-process result
    ok 6 - accepts a clean post-proof close racing a taskkill no-process result
      ---
      duration_ms: 7.540644
      type: 'test'
      ...
    # Subtest: rejects malformed, partial, truncated, and extra-field ready records
    ok 7 - rejects malformed, partial, truncated, and extra-field ready records
      ---
      duration_ms: 9.816721
      type: 'test'
      ...
    # Subtest: terminates an exact-event record whose platform proof is invalid
    ok 8 - terminates an exact-event record whose platform proof is invalid
      ---
      duration_ms: 1.313021
      type: 'test'
      ...
    # Subtest: fails after proof when Windows tree termination cannot be proven
    ok 9 - fails after proof when Windows tree termination cannot be proven
      ---
      duration_ms: 8.153123
      type: 'test'
      ...
    # Subtest: never returns secret-bearing raw output or non-allowlisted record fields
    ok 10 - never returns secret-bearing raw output or non-allowlisted record fields
      ---
      duration_ms: 1.597384
      type: 'test'
      ...
    # Subtest: revokes success when sensitive output arrives after the exact ready proof
    ok 11 - revokes success when sensitive output arrives after the exact ready proof
      ---
      duration_ms: 0.905377
      type: 'test'
      ...
    1..11
ok 1 - packaged Connect bounded child lifecycle
  ---
  duration_ms: 66.433475
  type: 'suite'
  ...
# Subtest: packaged Connect fixture cleanup
    # Subtest: retries a transient Windows EBUSY only inside the authorized fixture
    ok 1 - retries a transient Windows EBUSY only inside the authorized fixture
      ---
      duration_ms: 2.695052
      type: 'test'
      ...
    # Subtest: redacts cleanup failure and preserves the primary lifecycle outcome
    ok 2 - redacts cleanup failure and preserves the primary lifecycle outcome
      ---
      duration_ms: 0.657753
      type: 'test'
      ...
    # Subtest: refuses a link, renamed leaf, or fixture outside the canonical temporary parent
    ok 3 - refuses a link, renamed leaf, or fixture outside the canonical temporary parent
      ---
      duration_ms: 0.418404
      type: 'test'
      ...
    1..3
ok 2 - packaged Connect fixture cleanup
  ---
  duration_ms: 4.034002
  type: 'suite'
  ...
1..2
# tests 14
# suites 2
# pass 14
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 301.338697

[4/360] apps/desktop/scripts/packaged-layout.test.mjs
TAP version 13
# Subtest: packaged desktop layout assertions
    # Subtest: retains the exact 1280x820 Linux Xvfb proof
    ok 1 - retains the exact 1280x820 Linux Xvfb proof
      ---
      duration_ms: 2.229569
      type: 'test'
      ...
    # Subtest: accepts a safe 1024x720 Windows display clamp with intact contained content
    ok 2 - accepts a safe 1024x720 Windows display clamp with intact contained content
      ---
      duration_ms: 0.319449
      type: 'test'
      ...
    # Subtest: rejects unsafe Windows clamps and content outside the visible work area
    ok 3 - rejects unsafe Windows clamps and content outside the visible work area
      ---
      duration_ms: 0.381535
      type: 'test'
      ...
    1..3
ok 1 - packaged desktop layout assertions
  ---
  duration_ms: 4.755164
  type: 'suite'
  ...
1..1
# tests 3
# suites 1
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 240.303115

[5/360] apps/desktop/scripts/packaged-smoke-support.test.mjs
TAP version 13
# Subtest: packaged smoke native window layout
    # Subtest: accepts the preferred size while retaining responsive containment
    ok 1 - accepts the preferred size while retaining responsive containment
      ---
      duration_ms: 1.346143
      type: 'test'
      ...
    # Subtest: accepts the 1024x720-clamped size while retaining responsive containment
    ok 2 - accepts the 1024x720-clamped size while retaining responsive containment
      ---
      duration_ms: 0.156984
      type: 'test'
      ...
    # Subtest: accepts the configured minimum size while retaining responsive containment
    ok 3 - accepts the configured minimum size while retaining responsive containment
      ---
      duration_ms: 0.124935
      type: 'test'
      ...
    # Subtest: accepts the undersized work area while retaining responsive containment
    ok 4 - accepts the undersized work area while retaining responsive containment
      ---
      duration_ms: 0.148519
      type: 'test'
      ...
    # Subtest: rejects an unclamped window or a viewport inconsistent with native content chrome
    ok 5 - rejects an unclamped window or a viewport inconsistent with native content chrome
      ---
      duration_ms: 0.494868
      type: 'test'
      ...
    # Subtest: accepts actual reduced native sizing only when both minimum constraints are exercised
    ok 6 - accepts actual reduced native sizing only when both minimum constraints are exercised
      ---
      duration_ms: 0.241292
      type: 'test'
      ...
    1..6
ok 1 - packaged smoke native window layout
  ---
  duration_ms: 3.68657
  type: 'suite'
  ...
# Subtest: packaged smoke child environment
    # Subtest: passes only platform launch inputs and private profile paths from a hostile parent
    ok 1 - passes only platform launch inputs and private profile paths from a hostile parent
      ---
      duration_ms: 25.656761
      type: 'test'
      ...
    # Subtest: keeps cleanup bounded to the generated profile root
    ok 2 - keeps cleanup bounded to the generated profile root
      ---
      duration_ms: 11.213208
      type: 'test'
      ...
    # Subtest: accepts only a normalized absolute Windows SystemRoot directory
    ok 3 - accepts only a normalized absolute Windows SystemRoot directory
      ---
      duration_ms: 2.281737
      type: 'test'
      ...
    # Subtest: contains no parent environment spread, enumeration, denylist, PATH, or shell launch
    ok 4 - contains no parent environment spread, enumeration, denylist, PATH, or shell launch
      ---
      duration_ms: 4.293288
      type: 'test'
      ...
    # Subtest: requires the adjacent packaged spawn options with LF or CRLF source
    ok 5 - requires the adjacent packaged spawn options with LF or CRLF source
      ---
      duration_ms: 2.252553
      type: 'test'
      ...
    1..5
ok 2 - packaged smoke child environment
  ---
  duration_ms: 46.283606
  type: 'suite'
  ...
1..2
# tests 11
# suites 2
# pass 11
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 279.773984

[6/360] apps/desktop/scripts/release-architecture.test.mjs
TAP version 13
# Subtest: machine-wide Windows artifacts require a real MSI compound file
ok 1 - machine-wide Windows artifacts require a real MSI compound file
  ---
  duration_ms: 8.936182
  type: 'test'
  ...
# Subtest: administrative MSI payload inspection
    # Subtest: uses exact fixed native extractor argv and minimal environments
    ok 1 - uses exact fixed native extractor argv and minimal environments
      ---
      duration_ms: 1.550557
      type: 'test'
      ...
    # Subtest: accepts only the canonical application with the one administrative root prefix
    ok 2 - accepts only the canonical application with the one administrative root prefix
      ---
      duration_ms: 10.415984
      type: 'test'
      ...
    # Subtest: rejects path escapes and case collisions from the Linux listing before extraction
    ok 3 - rejects path escapes and case collisions from the Linux listing before extraction
      ---
      duration_ms: 0.74162
      type: 'test'
      ...
    # Subtest: uses fixed missing and duplicate canonical-app codes with bounded counts
    ok 4 - uses fixed missing and duplicate canonical-app codes with bounded counts
      ---
      duration_ms: 8.809941
      type: 'test'
      ...
    # Subtest: distinguishes authority resources, unsafe trees, and architecture mismatch without path data
    ok 5 - distinguishes authority resources, unsafe trees, and architecture mismatch without path data
      ---
      duration_ms: 9.467065
      type: 'test'
      ...
    # Subtest: maps extractor failures to one redacted tool code
    ok 6 - maps extractor failures to one redacted tool code
      ---
      duration_ms: 2.316132
      type: 'test'
      ...
    # Subtest: retains compound-file, per-machine scope, and canonical PE evidence across extraction
    ok 7 - retains compound-file, per-machine scope, and canonical PE evidence across extraction
      ---
      duration_ms: 5.60045
      type: 'test'
      ...
    # Subtest: fails closed on extractor nonzero, stderr, output overflow, and timeout
    ok 8 - fails closed on extractor nonzero, stderr, output overflow, and timeout
      ---
      duration_ms: 140.262328
      type: 'test'
      ...
    1..8
ok 2 - administrative MSI payload inspection
  ---
  duration_ms: 180.201272
  type: 'suite'
  ...
# Subtest: DEB and RPM executable layouts
    # Subtest: accept only the canonical regular ELF payload and documented launcher symlink
    ok 1 - accept only the canonical regular ELF payload and documented launcher symlink
      ---
      duration_ms: 17.454808
      type: 'test'
      ...
    # Subtest: reject missing and extra payload names for both package formats
    ok 2 - reject missing and extra payload names for both package formats
      ---
      duration_ms: 16.217179
      type: 'test'
      ...
    # Subtest: reject unexpected same-name file types and non-ELF or cross-architecture payloads
    ok 3 - reject unexpected same-name file types and non-ELF or cross-architecture payloads
      ---
      duration_ms: 18.790448
      type: 'test'
      ...
    # Subtest: reject launcher escapes, cycles, and targets other than the canonical payload
    ok 4 - reject launcher escapes, cycles, and targets other than the canonical payload
      ---
      duration_ms: 15.703867
      type: 'test'
      ...
    # Subtest: reject special files with the executable name
    ok 5 - reject special files with the executable name
      ---
      duration_ms: 11.933094
      type: 'test'
      ...
    1..5
ok 3 - DEB and RPM executable layouts
  ---
  duration_ms: 80.456755
  type: 'suite'
  ...
# Subtest: DMG application layout
    # Subtest: accepts the real Forge tree with its install link and nested Electron helper bundles
    ok 1 - accepts the real Forge tree with its install link and nested Electron helper bundles
      ---
      duration_ms: 17.618944
      type: 'test'
      ...
    # Subtest: rejects a symbolic-link canonical helper bundle
    ok 2 - rejects a symbolic-link canonical helper bundle
      ---
      duration_ms: 8.7173
      type: 'test'
      ...
    # Subtest: rejects a symbolic-link canonical helper executable ancestor
    ok 3 - rejects a symbolic-link canonical helper executable ancestor
      ---
      duration_ms: 8.570293
      type: 'test'
      ...
    # Subtest: rejects every symbolic link outside canonical framework internals
    ok 4 - rejects every symbolic link outside canonical framework internals
      ---
      duration_ms: 13.29996
      type: 'test'
      ...
    # Subtest: rejects escaping, cyclic, missing, and case-mismatched framework symbolic links
    ok 5 - rejects escaping, cyclic, missing, and case-mismatched framework symbolic links
      ---
      duration_ms: 46.092506
      type: 'test'
      ...
    # Subtest: never treats Linux 7z sanitized install-link output as native layout evidence
    ok 6 - never treats Linux 7z sanitized install-link output as native layout evidence
      ---
      duration_ms: 11.579238
      type: 'test'
      ...
    # Subtest: rejects wrong bundles, alternate same-name executables, and canonical symlink escapes
    ok 7 - rejects wrong bundles, alternate same-name executables, and canonical symlink escapes
      ---
      duration_ms: 17.315137
      type: 'test'
      ...
    # Subtest: rejects alternate top-level application bundles
    ok 8 - rejects alternate top-level application bundles
      ---
      duration_ms: 7.903426
      type: 'test'
      ...
    # Subtest: rejects unsafe links inside the canonical application bundle
    ok 9 - rejects unsafe links inside the canonical application bundle
      ---
      duration_ms: 11.52284
      type: 'test'
      ...
    # Subtest: rejects non-helper nested application bundles
    ok 10 - rejects non-helper nested application bundles
      ---
      duration_ms: 14.970116
      type: 'test'
      ...
    # Subtest: rejects case-colliding top-level entries when the filesystem permits them
    ok 11 - rejects case-colliding top-level entries when the filesystem permits them
      ---
      duration_ms: 8.113151
      type: 'test'
      ...
    # Subtest: rejects special files inside the canonical application bundle
    ok 12 - rejects special files inside the canonical application bundle
      ---
      duration_ms: 15.583368
      type: 'test'
      ...
    1..12
ok 4 - DMG application layout
  ---
  duration_ms: 181.925609
  type: 'suite'
  ...
1..4
# tests 26
# suites 3
# pass 26
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 670.305877

[7/360] apps/desktop/scripts/release-artifacts.test.mjs
TAP version 13
# Subtest: desktop release artifacts
    # Subtest: stages named artifacts and finalizes unsigned validation metadata
    ok 1 - stages named artifacts and finalizes unsigned validation metadata
      ---
      duration_ms: 98.243083
      type: 'test'
      ...
    # Subtest: rejects extensionless, doubled-extension, case-conflicting, duplicate, wrong-kind, stale, and mixed-target names
    ok 2 - rejects extensionless, doubled-extension, case-conflicting, duplicate, wrong-kind, stale, and mixed-target names
      ---
      duration_ms: 276.392099
      type: 'test'
      ...
    # Subtest: rejects altered DMG bytes even when fragment artifact metadata is rewritten
    ok 3 - rejects altered DMG bytes even when fragment artifact metadata is rewritten
      ---
      duration_ms: 31.946785
      type: 'test'
      ...
    # Subtest: rejects permanent DMG replacement or in-place mutation during held inspection without emitting evidence
    ok 4 - rejects permanent DMG replacement or in-place mutation during held inspection without emitting evidence
      ---
      duration_ms: 11.789059
      type: 'test'
      ...
    # Subtest: keeps held A bytes, evidence, and publication stable when original and public pathnames change during inspection
    ok 5 - keeps held A bytes, evidence, and publication stable when original and public pathnames change during inspection
      ---
      duration_ms: 15.017818
      type: 'test'
      ...
    # Subtest: continues to reject a mutable pathname passed directly to DMG inspection
    ok 6 - continues to reject a mutable pathname passed directly to DMG inspection
      ---
      duration_ms: 0.284353
      type: 'test'
      ...
    # Subtest: requires explicit fixture authority for Windows-hosted DMG evidence tests
    ok 7 - requires explicit fixture authority for Windows-hosted DMG evidence tests # SKIP
      ---
      duration_ms: 0.071063
      type: 'test'
      ...
    # Subtest: accepts real Darwin mode-0700 directory and mode-0600 single-link file authority
    ok 8 - accepts real Darwin mode-0700 directory and mode-0600 single-link file authority # SKIP
      ---
      duration_ms: 0.060734
      type: 'test'
      ...
    # Subtest: rejects native Darwin broad mode, foreign owner, extra link, replacement type, and symlink with fixed authority codes
    ok 9 - rejects native Darwin broad mode, foreign owner, extra link, replacement type, and symlink with fixed authority codes # SKIP
      ---
      duration_ms: 0.093475
      type: 'test'
      ...
    # Subtest: accepts native xattr/ctime-only change when held bytes and identity are unchanged
    ok 10 - accepts native xattr/ctime-only change when held bytes and identity are unchanged # SKIP
      ---
      duration_ms: 0.271529
      type: 'test'
      ...
    # Subtest: does not emit claimed DMG layout evidence without the native-validation marker
    ok 11 - does not emit claimed DMG layout evidence without the native-validation marker
      ---
      duration_ms: 10.0126
      type: 'test'
      ...
    # Subtest: strictly rejects missing, mixed, stale, malformed, or fabricated native DMG evidence
    ok 12 - strictly rejects missing, mixed, stale, malformed, or fabricated native DMG evidence
      ---
      duration_ms: 357.838044
      type: 'test'
      ...
    # Subtest: rejects native DMG evidence copied between x64 and arm64 fragments
    ok 13 - rejects native DMG evidence copied between x64 and arm64 fragments
      ---
      duration_ms: 28.315845
      type: 'test'
      ...
    # Subtest: rejects duplicate target fragments before aggregation
    ok 14 - rejects duplicate target fragments before aggregation
      ---
      duration_ms: 22.175119
      type: 'test'
      ...
    # Subtest: rejects either Windows fragment when the installed ordinary-user application gate was skipped
    ok 15 - rejects either Windows fragment when the installed ordinary-user application gate was skipped
      ---
      duration_ms: 94.440969
      type: 'test'
      ...
    # Subtest: fails closed when trusted update signing configuration is incomplete
    ok 16 - fails closed when trusted update signing configuration is incomplete
      ---
      duration_ms: 67.481389
      type: 'test'
      ...
    # Subtest: signs cryptographically bound feeds only in the trusted release phase
    ok 17 - signs cryptographically bound feeds only in the trusted release phase
      ---
      duration_ms: 62.218336
      type: 'test'
      ...
    # Subtest: refuses to sign a renamed extensionless distributable
    ok 18 - refuses to sign a renamed extensionless distributable
      ---
      duration_ms: 42.716308
      type: 'test'
      ...
    # Subtest: refuses to sign when artifact bytes changed after unsigned finalization
    ok 19 - refuses to sign when artifact bytes changed after unsigned finalization
      ---
      duration_ms: 47.049675
      type: 'test'
      ...
    # Subtest: rejects unsigned production metadata and actual signer mismatches
    ok 20 - rejects unsigned production metadata and actual signer mismatches
      ---
      duration_ms: 102.268197
      type: 'test'
      ...
    # Subtest: rejects mixed Windows signers and tampered fingerprint evidence
    ok 21 - rejects mixed Windows signers and tampered fingerprint evidence
      ---
      duration_ms: 49.252486
      type: 'test'
      ...
    # Subtest: parses x64 and arm64 ELF, PE, and Mach-O executable fixtures
    ok 22 - parses x64 and arm64 ELF, PE, and Mach-O executable fixtures
      ---
      duration_ms: 2.132627
      type: 'test'
      ...
    # Subtest: derives Windows target architecture from the full NUPKG independently of its supported bootstrapper
    ok 23 - derives Windows target architecture from the full NUPKG independently of its supported bootstrapper
      ---
      duration_ms: 13.929628
      type: 'test'
      ...
    # Subtest: binds ZIP and NUPKG executables to exact maker-specific canonical paths
    ok 24 - binds ZIP and NUPKG executables to exact maker-specific canonical paths
      ---
      duration_ms: 4.014401
      type: 'test'
      ...
    # Subtest: rejects missing, corrupt, mismatched, and ambiguous packaged Windows authority helpers
    ok 25 - rejects missing, corrupt, mismatched, and ambiguous packaged Windows authority helpers
      ---
      duration_ms: 6.306671
      type: 'test'
      ...
    # Subtest: accepts only the real Forge macOS framework-internal symbolic-link layout
    ok 26 - accepts only the real Forge macOS framework-internal symbolic-link layout
      ---
      duration_ms: 4.688898
      type: 'test'
      ...
    # Subtest: rejects hostile macOS ZIP symbolic links before trusting their payloads
    ok 27 - rejects hostile macOS ZIP symbolic links before trusting their payloads
      ---
      duration_ms: 19.015631
      type: 'test'
      ...
    # Subtest: rejects unsafe, duplicate, shadowed, forged, alternate, and noncanonical archive layouts
    ok 28 - rejects unsafe, duplicate, shadowed, forged, alternate, and noncanonical archive layouts
      ---
      duration_ms: 5.861716
      type: 'test'
      ...
    # Subtest: rejects cross-labeled package architectures at staging and finalization
    ok 29 - rejects cross-labeled package architectures at staging and finalization
      ---
      duration_ms: 42.046999
      type: 'test'
      ...
    1..29
ok 1 - desktop release artifacts
  ---
  duration_ms: 1419.234212
  type: 'suite'
  ...
1..1
# tests 29
# suites 1
# pass 25
# fail 0
# cancelled 0
# skipped 4
# todo 0
# duration_ms 1644.431546

[8/360] apps/desktop/scripts/release-preflight.test.mjs
TAP version 13
# Subtest: desktop release preflight
    # Subtest: accepts only a new immutable tag reachable from protected main and a protected environment
    ok 1 - accepts only a new immutable tag reachable from protected main and a protected environment
      ---
      duration_ms: 3.388691
      type: 'test'
      ...
    # Subtest: accepts an authorization-visible bypass list and fails closed for hidden or denied ruleset details
    ok 2 - accepts an authorization-visible bypass list and fails closed for hidden or denied ruleset details
      ---
      duration_ms: 1.38204
      type: 'test'
      ...
    # Subtest: paginates repository rulesets and reads every full rule definition
    ok 3 - paginates repository rulesets and reads every full rule definition
      ---
      duration_ms: 3.506362
      type: 'test'
      ...
    # Subtest: requires an exact active bypass-free update and deletion tag ruleset
    ok 4 - requires an exact active bypass-free update and deletion tag ruleset
      ---
      duration_ms: 2.041897
      type: 'test'
      ...
    # Subtest: rejects ruleset mutation or deletion during preflight
    ok 5 - rejects ruleset mutation or deletion during preflight
      ---
      duration_ms: 1.697712
      type: 'test'
      ...
    # Subtest: requires the complete effective environment policy set to be exactly desktop-v* tags
    ok 6 - requires the complete effective environment policy set to be exactly desktop-v* tags
      ---
      duration_ms: 4.19358
      type: 'test'
      ...
    # Subtest: requires the separately protected preflight credential environment
    ok 7 - requires the separately protected preflight credential environment
      ---
      duration_ms: 1.096465
      type: 'test'
      ...
    # Subtest: paginates all environment policies and rejects a permissive policy on a later page
    ok 8 - paginates all environment policies and rejects a permissive policy on a later page
      ---
      duration_ms: 1.057612
      type: 'test'
      ...
    # Subtest: rejects missing or ambiguous environment protection and explicit API denial
    ok 9 - rejects missing or ambiguous environment protection and explicit API denial
      ---
      duration_ms: 1.281482
      type: 'test'
      ...
    # Subtest: rejects tags not created by this push, tags off main, and moved or existing releases
    ok 10 - rejects tags not created by this push, tags off main, and moved or existing releases
      ---
      duration_ms: 2.175146
      type: 'test'
      ...
    1..10
ok 1 - desktop release preflight
  ---
  duration_ms: 23.407572
  type: 'suite'
  ...
1..1
# tests 10
# suites 1
# pass 10
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 292.781713

[9/360] apps/desktop/scripts/release-publish.test.mjs
TAP version 13
# Subtest: atomic desktop release publication
    # Subtest: creates a draft, paginates and verifies the exact final assets, then publishes
    ok 1 - creates a draft, paginates and verifies the exact final assets, then publishes
      ---
      duration_ms: 186.885108
      type: 'test'
      ...
    # Subtest: leaves a partial upload as a recoverable draft and resumes only matching assets
    ok 2 - leaves a partial upload as a recoverable draft and resumes only matching assets
      ---
      duration_ms: 11.459495
      type: 'test'
      ...
    # Subtest: rejects unexpected, duplicate, size, and content-digest asset mismatches without publishing
    ok 3 - rejects unexpected, duplicate, size, and content-digest asset mismatches without publishing
      ---
      duration_ms: 11.090257
      type: 'test'
      ...
    # Subtest: rejects tag drift before publishing the verified draft
    ok 4 - rejects tag drift before publishing the verified draft
      ---
      duration_ms: 6.136226
      type: 'test'
      ...
    # Subtest: rejects local files outside or missing from finalized checksums
    ok 5 - rejects local files outside or missing from finalized checksums
      ---
      duration_ms: 3.663366
      type: 'test'
      ...
    1..5
ok 1 - atomic desktop release publication
  ---
  duration_ms: 220.6848
  type: 'suite'
  ...
1..1
# tests 5
# suites 1
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 435.003201

[10/360] apps/desktop/scripts/verify-darwin-image.test.mjs
TAP version 13
# Subtest: Darwin image verification retries only bounded documented resource states
ok 1 - Darwin image verification retries only bounded documented resource states
  ---
  duration_ms: 13.775509
  type: 'test'
  ...
# Subtest: Darwin image verification does not retry malformed/truncated images or accept mutation
ok 2 - Darwin image verification does not retry malformed/truncated images or accept mutation
  ---
  duration_ms: 10.44165
  type: 'test'
  ...
# Subtest: Darwin image verification holds a fixed hdiutil image behind a real mutation and replacement barrier
ok 3 - Darwin image verification holds a fixed hdiutil image behind a real mutation and replacement barrier # SKIP
  ---
  duration_ms: 0.242966
  type: 'test'
  ...
1..3
# tests 3
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 1
# todo 0
# duration_ms 252.491563

[11/360] apps/desktop/scripts/windows-fixture-acl.test.mjs
TAP version 13
# Subtest: keeps the encoded Windows PowerShell 5.1 ACL helper fail-closed and byte-empty
ok 1 - keeps the encoded Windows PowerShell 5.1 ACL helper fail-closed and byte-empty # SKIP
  ---
  duration_ms: 0.671098
  type: 'test'
  ...
1..1
# tests 1
# suites 0
# pass 0
# fail 0
# cancelled 0
# skipped 1
# todo 0
# duration_ms 225.335824

[12/360] apps/desktop/src/connect-discovery.test.ts
TAP version 13
# Subtest: desktop fixed-root Connect discovery
    # Subtest: projects only a stable opaque profile and canonical endpoint
    ok 1 - projects only a stable opaque profile and canonical endpoint
      ---
      duration_ms: 2.236432
      type: 'test'
      ...
    # Subtest: fences rediscovery to an existing managed profile and preserves its id and label
    ok 2 - fences rediscovery to an existing managed profile and preserves its id and label
      ---
      duration_ms: 0.701895
      type: 'test'
      ...
    # Subtest: discards rediscovery when the exact saved profile changes while native discovery awaits
    ok 3 - discards rediscovery when the exact saved profile changes while native discovery awaits
      ---
      duration_ms: 0.64066
      type: 'test'
      ...
    # Subtest: fails closed for unsupported hosts and malformed native results
    ok 4 - fails closed for unsupported hosts and malformed native results
      ---
      duration_ms: 0.76819
      type: 'test'
      ...
    1..4
ok 1 - desktop fixed-root Connect discovery
  ---
  duration_ms: 5.896571
  type: 'suite'
  ...
1..1
# tests 4
# suites 1
# pass 4
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 328.878794

[13/360] apps/desktop/src/credential-service.pairing-browser.test.ts
TAP version 13
# Subtest: DesktopCredentialService pairing browser sink
    # Subtest: binds the API base, pairing id, and response URL through the final shell validator
    ok 1 - binds the API base, pairing id, and response URL through the final shell validator
      ---
      duration_ms: 69.172997
      type: 'test'
      ...
    # Subtest: rejects a URL replaced after the credential service receives the API response
    ok 2 - rejects a URL replaced after the credential service receives the API response
      ---
      duration_ms: 20.191716
      type: 'test'
      ...
    1..2
ok 1 - DesktopCredentialService pairing browser sink
  ---
  duration_ms: 90.362613
  type: 'suite'
  ...
1..1
# tests 2
# suites 1
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 520.375825

[14/360] apps/desktop/src/credential-service.test.ts
TAP version 13
# Subtest: main-process desktop credential service
    # Subtest: injects the active bearer only for its bound profile origin and strips renderer identity
    ok 1 - injects the active bearer only for its bound profile origin and strips renderer identity
      ---
      duration_ms: 104.538345
      type: 'test'
      ...
    # Subtest: uses only the active bearer when profiles share an origin and never a cookie identity
    ok 2 - uses only the active bearer when profiles share an origin and never a cookie identity
      ---
      duration_ms: 72.565213
      type: 'test'
      ...
    # Subtest: detaches profile B credential A without sending any bearer request to A or minting a ticket
    ok 3 - detaches profile B credential A without sending any bearer request to A or minting a ticket
      ---
      duration_ms: 50.087491
      type: 'test'
      ...
    # Subtest: does not mint a ticket when a delayed B probe observes credential replacement with origin A
    ok 4 - does not mint a ticket when a delayed B probe observes credential replacement with origin A
      ---
      duration_ms: 38.55352
      type: 'test'
      ...
    # Subtest: atomically rejects a ticket when delayed activation races with profile B credential A
    ok 5 - atomically rejects a ticket when delayed activation races with profile B credential A
      ---
      duration_ms: 45.729801
      type: 'test'
      ...
    # Subtest: keeps a slow successful same-origin A probe status-only after fast B activates
    ok 6 - keeps a slow successful same-origin A probe status-only after fast B activates
      ---
      duration_ms: 68.552829
      type: 'test'
      ...
    # Subtest: keeps A active while B is only probed and if B selection persistence fails
    ok 7 - keeps A active while B is only probed and if B selection persistence fails
      ---
      duration_ms: 87.075103
      type: 'test'
      ...
    # Subtest: keeps B active during a direct same-origin A probe and rejects replayed activation tickets
    ok 8 - keeps B active during a direct same-origin A probe and rejects replayed activation tickets
      ---
      duration_ms: 68.511108
      type: 'test'
      ...
    # Subtest: rejects activation after candidate removal, selection drift, or exact credential replacement
    ok 9 - rejects activation after candidate removal, selection drift, or exact credential replacement
      ---
      duration_ms: 234.481701
      type: 'test'
      ...
    # Subtest: binds REST and Socket.IO work to one fresh scope and rejects stale or malformed markers
    ok 10 - binds REST and Socket.IO work to one fresh scope and rejects stale or malformed markers
      ---
      duration_ms: 73.069758
      type: 'test'
      ...
    # Subtest: passes through a realistic packaged-origin CORS preflight without renderer identity or bearer injection
    ok 11 - passes through a realistic packaged-origin CORS preflight without renderer identity or bearer injection
      ---
      duration_ms: 0.411441
      type: 'test'
      ...
    # Subtest: rotates scope on every same-profile reprobe and rejects a cold reconnect from the old activation
    ok 12 - rotates scope on every same-profile reprobe and rejects a cold reconnect from the old activation
      ---
      duration_ms: 54.250887
      type: 'test'
      ...
    # Subtest: never sends an A-origin bearer after the profile URL is edited to an attacker origin
    ok 13 - never sends an A-origin bearer after the profile URL is edited to an attacker origin
      ---
      duration_ms: 33.551312
      type: 'test'
      ...
    # Subtest: preserves a re-paired credential and current connection after a stale definitive probe response
    ok 14 - preserves a re-paired credential and current connection after a stale definitive probe response
      ---
      duration_ms: 96.14829
      type: 'test'
      ...
    # Subtest: preserves a replacement credential at a changed origin after a stale definitive probe response
    ok 15 - preserves a replacement credential at a changed origin after a stale definitive probe response
      ---
      duration_ms: 81.778417
      type: 'test'
      ...
    # Subtest: preserves the active profile and credential when an origin edit fails during browser-launch
    ok 16 - preserves the active profile and credential when an origin edit fails during browser-launch
      ---
      duration_ms: 50.342589
      type: 'test'
      ...
    # Subtest: preserves the active profile and credential when an origin edit fails during cancellation
    ok 17 - preserves the active profile and credential when an origin edit fails during cancellation
      ---
      duration_ms: 61.306892
      type: 'test'
      ...
    # Subtest: preserves the active profile and credential when an origin edit fails during expiry
    ok 18 - preserves the active profile and credential when an origin edit fails during expiry
      ---
      duration_ms: 56.508178
      type: 'test'
      ...
    # Subtest: preserves the active profile and credential when an origin edit fails during polling
    ok 19 - preserves the active profile and credential when an origin edit fails during polling
      ---
      duration_ms: 57.089733
      type: 'test'
      ...
    # Subtest: preserves the active profile and credential when an origin edit fails during secure-storage
    ok 20 - preserves the active profile and credential when an origin edit fails during secure-storage
      ---
      duration_ms: 59.843554
      type: 'test'
      ...
    # Subtest: commits an edited profile and replacement credential before revoking the old token
    ok 21 - commits an edited profile and replacement credential before revoking the old token
      ---
      duration_ms: 74.249003
      type: 'test'
      ...
# NATIVE_SCENARIO delivery
    # Subtest: durably journals a provisional delivery before server activation and local publication
    ok 22 - durably journals a provisional delivery before server activation and local publication
      ---
      duration_ms: 36.176255
      type: 'test'
      ...
    # Subtest: retries an encrypted pending A revocation across failure, restart, remote success, and local cleanup failure
    ok 23 - retries an encrypted pending A revocation across failure, restart, remote success, and local cleanup failure
      ---
      duration_ms: 174.702031
      type: 'test'
      ...
# NATIVE_SCENARIO revocation-crash
    # Subtest: recovers B and retries idempotently after a real process crash during-revoke
    ok 24 - recovers B and retries idempotently after a real process crash during-revoke
      ---
      duration_ms: 428.423148
      type: 'test'
      ...
# NATIVE_SCENARIO revocation-crash
    # Subtest: recovers B and retries idempotently after a real process crash after-remote-success
    ok 25 - recovers B and retries idempotently after a real process crash after-remote-success
      ---
      duration_ms: 409.524039
      type: 'test'
      ...
    # Subtest: cleans durable retry material only for endpoint-bound terminal 204 success
    ok 26 - cleans durable retry material only for endpoint-bound terminal 204 success
      ---
      duration_ms: 39.344588
      type: 'test'
      ...
    # Subtest: cleans durable retry material only for endpoint-bound terminal 404 TOKEN_NOT_FOUND
    ok 27 - cleans durable retry material only for endpoint-bound terminal 404 TOKEN_NOT_FOUND
      ---
      duration_ms: 32.001019
      type: 'test'
      ...
    # Subtest: cleans durable retry material only for endpoint-bound terminal 401 INSTANCE_TOKEN_REVOKED
    ok 28 - cleans durable retry material only for endpoint-bound terminal 401 INSTANCE_TOKEN_REVOKED
      ---
      duration_ms: 47.384525
      type: 'test'
      ...
    # Subtest: cleans durable retry material only for endpoint-bound terminal 401 INSTANCE_TOKEN_EXPIRED
    ok 29 - cleans durable retry material only for endpoint-bound terminal 401 INSTANCE_TOKEN_EXPIRED
      ---
      duration_ms: 38.70866
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for empty 401
    ok 30 - retains encrypted retry material for empty 401
      ---
      duration_ms: 27.628434
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for empty 404
    ok 31 - retains encrypted retry material for empty 404
      ---
      duration_ms: 32.041748
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for HTML route 404
    ok 32 - retains encrypted retry material for HTML route 404
      ---
      duration_ms: 27.225157
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for malformed JSON
    ok 33 - retains encrypted retry material for malformed JSON
      ---
      duration_ms: 35.622605
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for wrong content type
    ok 34 - retains encrypted retry material for wrong content type
      ---
      duration_ms: 29.876578
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for wrong schema version
    ok 35 - retains encrypted retry material for wrong schema version
      ---
      duration_ms: 30.090989
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for wrong credential generation
    ok 36 - retains encrypted retry material for wrong credential generation
      ---
      duration_ms: 39.302274
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for unknown terminal code
    ok 37 - retains encrypted retry material for unknown terminal code
      ---
      duration_ms: 33.458632
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for status/code mismatch
    ok 38 - retains encrypted retry material for status/code mismatch
      ---
      duration_ms: 32.670664
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for redirect
    ok 39 - retains encrypted retry material for redirect
      ---
      duration_ms: 28.316625
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for redirected 204
    ok 40 - retains encrypted retry material for redirected 204
      ---
      duration_ms: 32.662726
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for wrong endpoint 204
    ok 41 - retains encrypted retry material for wrong endpoint 204
      ---
      duration_ms: 30.66788
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for server failure
    ok 42 - retains encrypted retry material for server failure
      ---
      duration_ms: 30.175898
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for oversized JSON
    ok 43 - retains encrypted retry material for oversized JSON
      ---
      duration_ms: 28.600325
      type: 'test'
      ...
    # Subtest: accepts encrypted retry material for chunked 2048-byte terminal JSON
    ok 44 - accepts encrypted retry material for chunked 2048-byte terminal JSON
      ---
      duration_ms: 56.773259
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for chunked 2049-byte terminal JSON
    ok 45 - retains encrypted retry material for chunked 2049-byte terminal JSON
      ---
      duration_ms: 30.437539
      type: 'test'
      ...
    # Subtest: accepts encrypted retry material for terminal JSON without Content-Length
    ok 46 - accepts encrypted retry material for terminal JSON without Content-Length
      ---
      duration_ms: 36.093019
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for deceptive short Content-Length
    ok 47 - retains encrypted retry material for deceptive short Content-Length
      ---
      duration_ms: 31.662665
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for extra chunk after declared Content-Length
    ok 48 - retains encrypted retry material for extra chunk after declared Content-Length
      ---
      duration_ms: 39.590934
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for malformed UTF-8
    ok 49 - retains encrypted retry material for malformed UTF-8
      ---
      duration_ms: 29.356445
      type: 'test'
      ...
    # Subtest: retains encrypted retry material for premature body error
    ok 50 - retains encrypted retry material for premature body error
      ---
      duration_ms: 28.057463
      type: 'test'
      ...
    # Subtest: bounds a one-byte slowloris body and retains its encrypted retry material
    ok 51 - bounds a one-byte slowloris body and retains its encrypted retry material
      ---
      duration_ms: 53.668053
      type: 'test'
      ...
    # Subtest: dispose aborts a stalled header fetch, deduplicates its generation, and leaves no later activity
    ok 52 - dispose aborts a stalled header fetch, deduplicates its generation, and leaves no later activity
      ---
      duration_ms: 54.024928
      type: 'test'
      ...
    # Subtest: dispose cancels a headers-then-stall body and retains exact encrypted material
    ok 53 - dispose cancels a headers-then-stall body and retains exact encrypted material
      ---
      duration_ms: 47.820186
      type: 'test'
      ...
# NATIVE_SCENARIO dispose
    # Subtest: dispose waits for terminal journal cleanup and no file operation runs afterward
    ok 54 - dispose waits for terminal journal cleanup and no file operation runs afterward
      ---
      duration_ms: 59.026255
      type: 'test'
      ...
    # Subtest: bounds aggregate startup across stalled records and recovers all encrypted records later
    ok 55 - bounds aggregate startup across stalled records and recovers all encrypted records later
      ---
      duration_ms: 282.558217
      type: 'test'
      ...
# NATIVE_SCENARIO transient-revocation
# NATIVE_SCENARIO provisional
    # Subtest: retries a crash-left provisional pairing credential on startup
    ok 56 - retries a crash-left provisional pairing credential on startup
      ---
      duration_ms: 27.311007
      type: 'test'
      ...
    # Subtest: ignores delayed A invalidation after B connects and preserves tokens for authorization/transient codes
    ok 57 - ignores delayed A invalidation after B connects and preserves tokens for authorization/transient codes
      ---
      duration_ms: 125.606533
      type: 'test'
      ...
    # Subtest: preserves a replacement written while an old transient token revocation is pending
    ok 58 - preserves a replacement written while an old transient token revocation is pending
      ---
      duration_ms: 66.56517
      type: 'test'
      ...
# NATIVE_SCENARIO transient-revocation
    # Subtest: keeps an exactly persisted cancelled pairing token pending when revocation fails
    ok 59 - keeps an exactly persisted cancelled pairing token pending when revocation fails
      ---
      duration_ms: 32.119572
      type: 'test'
      ...
    # Subtest: detaches a removed profile locally before deferred revoke and preserves a later replacement
    ok 60 - detaches a removed profile locally before deferred revoke and preserves a later replacement
      ---
      duration_ms: 153.428829
      type: 'test'
      ...
    # Subtest: never lets a delayed A-to-B revoke overwrite a later C save, pairing, selection, or credential
    ok 61 - never lets a delayed A-to-B revoke overwrite a later C save, pairing, selection, or credential
      ---
      duration_ms: 100.935358
      type: 'test'
      ...
    # Subtest: returns connection-changed and preserves a re-paired credential for an old ready invalidation
    ok 62 - returns connection-changed and preserves a re-paired credential for an old ready invalidation
      ---
      duration_ms: 66.783648
      type: 'test'
      ...
# NATIVE_SCENARIO transient-revocation
    # Subtest: revokes a transient completion instead of persisting when pairing races with delete
    ok 63 - revokes a transient completion instead of persisting when pairing races with delete
      ---
      duration_ms: 58.282123
      type: 'test'
      ...
# NATIVE_SCENARIO transient-revocation
    # Subtest: revokes a transient completion instead of persisting when pairing races with switch
    ok 64 - revokes a transient completion instead of persisting when pairing races with switch
      ---
      duration_ms: 53.809369
      type: 'test'
      ...
# NATIVE_SCENARIO cancellation-switch
    # Subtest: keeps durable A when cancel linearizes at paired state-written before publish
    ok 65 - keeps durable A when cancel linearizes at paired state-written before publish
      ---
      duration_ms: 57.698011
      type: 'test'
      ...
# NATIVE_SCENARIO cancellation-switch
    # Subtest: keeps durable A when switch linearizes at paired state-written before publish
    ok 66 - keeps durable A when switch linearizes at paired state-written before publish
      ---
      duration_ms: 72.103046
      type: 'test'
      ...
# NATIVE_SCENARIO cancellation-switch
    # Subtest: keeps durable A when cancel linearizes at paired state-fsynced before publish
    ok 67 - keeps durable A when cancel linearizes at paired state-fsynced before publish
      ---
      duration_ms: 63.197247
      type: 'test'
      ...
# NATIVE_SCENARIO cancellation-switch
    # Subtest: keeps durable A when switch linearizes at paired state-fsynced before publish
    ok 68 - keeps durable A when switch linearizes at paired state-fsynced before publish
      ---
      duration_ms: 78.636455
      type: 'test'
      ...
    1..68
ok 1 - main-process desktop credential service
  ---
  duration_ms: 4823.7745
  type: 'suite'
  ...
1..1
# tests 68
# suites 1
# pass 68
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 5293.305498

[15/360] apps/desktop/src/deep-link-delivery.test.ts
TAP version 13
# Subtest: desktop deep-link delivery
    # Subtest: queues links received after did-finish-load until the ready window is registered
    ok 1 - queues links received after did-finish-load until the ready window is registered
      ---
      duration_ms: 1.468202
      type: 'test'
      ...
    # Subtest: delivers a queued initial Connect URL before packaged smoke asserts it and only once
    not ok 2 - delivers a queued initial Connect URL before packaged smoke asserts it and only once
      ---
      duration_ms: 2.192951
      type: 'test'
      location: '/home/runner/work/propr/propr/apps/desktop/src/deep-link-delivery.test.ts:1:1040'
      failureType: 'testCodeFailure'
      error: |-
        Expected values to be strictly equal:
        
        2 !== 1
        
      code: 'ERR_ASSERTION'
      name: 'AssertionError'
      expected: 1
      actual: 2
      operator: 'strictEqual'
      stack: |-
        TestContext.<anonymous> (/home/runner/work/propr/propr/apps/desktop/src/deep-link-delivery.test.ts:40:12)
        Test.runInAsyncScope (node:async_hooks:214:14)
        Test.run (node:internal/test_runner/test:1047:25)
        Suite.processPendingSubtests (node:internal/test_runner/test:744:18)
        Test.postRun (node:internal/test_runner/test:1173:19)
        Test.run (node:internal/test_runner/test:1101:12)
        async Promise.all (index 0)
        async Suite.run (node:internal/test_runner/test:1442:7)
        async startSubtestAfterBootstrap (node:internal/test_runner/harness:296:3)
      ...
    1..2
not ok 1 - desktop deep-link delivery
  ---
  duration_ms: 4.827368
  type: 'suite'
  location: '/home/runner/work/propr/propr/apps/desktop/src/deep-link-delivery.test.ts:1:274'
  failureType: 'subtestsFailed'
  error: '1 subtest failed'
  code: 'ERR_TEST_FAILURE'
  ...
1..1
# tests 2
# suites 1
# pass 1
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 233.412023

[16/360] apps/desktop/src/discovery-ipc.test.ts
TAP version 13
# Subtest: main-to-preload Connect discovery IPC
    # Subtest: returns only typed candidates and redacts underlying discovery failures
    ok 1 - returns only typed candidates and redacts underlying discovery failures
      ---
      duration_ms: 2.720088
      type: 'test'
      ...
    1..1
ok 1 - main-to-preload Connect discovery IPC
  ---
  duration_ms: 3.610027
  type: 'suite'
  ...
1..1
# tests 1
# suites 1
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 282.294676

[17/360] apps/desktop/src/ipc-lifecycle.test.ts
TAP version 13
# Subtest: desktop IPC shutdown gate
    # Subtest: clears old and new origin storage through the real save IPC before a same-ID URL commit
    ok 1 - clears old and new origin storage through the real save IPC before a same-ID URL commit
      ---
      duration_ms: 3.977365
      type: 'test'
      ...
    # Subtest: clears both origins when activation edits the active profile URL without changing its ID
    ok 2 - clears both origins when activation edits the active profile URL without changing its ID
      ---
      duration_ms: 1.890934
      type: 'test'
      ...
    # Subtest: rejects activation and discards its exact scope when origin storage clearing fails
    ok 3 - rejects activation and discards its exact scope when origin storage clearing fails
      ---
      duration_ms: 0.947296
      type: 'test'
      ...
    # Subtest: discards the exact activation when the post-commit profile read fails
    ok 4 - discards the exact activation when the post-commit profile read fails
      ---
      duration_ms: 0.450665
      type: 'test'
      ...
    # Subtest: clears a profile origin before committing removal and retains it when cleanup fails
    ok 5 - clears a profile origin before committing removal and retains it when cleanup fails
      ---
      duration_ms: 0.57075
      type: 'test'
      ...
    # Subtest: replaces every handler with a fixed closing failure and drains admitted work before disposal
    ok 6 - replaces every handler with a fixed closing failure and drains admitted work before disposal
      ---
      duration_ms: 0.621716
      type: 'test'
      ...
    # Subtest: runs an admitted profile handler through the production before-quit drain
    ok 7 - runs an admitted profile handler through the production before-quit drain
      ---
      duration_ms: 1.286822
      type: 'test'
      ...
    # Subtest: runs an admitted pairing handler through the production before-quit drain
    ok 8 - runs an admitted pairing handler through the production before-quit drain
      ---
      duration_ms: 0.43731
      type: 'test'
      ...
    # Subtest: runs an admitted session handler through the production before-quit drain
    ok 9 - runs an admitted session handler through the production before-quit drain
      ---
      duration_ms: 24.424417
      type: 'test'
      ...
    1..9
ok 1 - desktop IPC shutdown gate
  ---
  duration_ms: 36.262888
  type: 'suite'
  ...
1..1
# tests 9
# suites 1
# pass 9
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 322.747411

[18/360] apps/desktop/src/ipc.test.ts
TAP version 13
# Subtest: desktop session IPC operations
    # Subtest: logs out through the active Electron session with credentials and without following redirects
    ok 1 - logs out through the active Electron session with credentials and without following redirects
      ---
      duration_ms: 26.065347
      type: 'test'
      ...
    # Subtest: rejects untrusted logout endpoints before making a session request
    ok 2 - rejects untrusted logout endpoints before making a session request
      ---
      duration_ms: 1.003311
      type: 'test'
      ...
    # Subtest: clears browser identity and origin storage for normalized profile origins when profiles switch
    ok 3 - clears browser identity and origin storage for normalized profile origins when profiles switch
      ---
      duration_ms: 1.10444
      type: 'test'
      ...
    1..3
ok 1 - desktop session IPC operations
  ---
  duration_ms: 29.669573
  type: 'suite'
  ...
1..1
# tests 3
# suites 1
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 309.762412

[19/360] apps/desktop/src/logger.test.ts
TAP version 13
# Subtest: desktop logger field schemas
    # Subtest: preserves only bounded numeric and boolean packaged layout measurements
    ok 1 - preserves only bounded numeric and boolean packaged layout measurements
      ---
      duration_ms: 1.375658
      type: 'test'
      ...
    # Subtest: does not weaken object, secret, path, error, or malformed-layout redaction
    ok 2 - does not weaken object, secret, path, error, or malformed-layout redaction
      ---
      duration_ms: 0.347502
      type: 'test'
      ...
    1..2
ok 1 - desktop logger field schemas
  ---
  duration_ms: 2.750575
  type: 'suite'
  ...
1..1
# tests 2
# suites 1
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 239.713628

[20/360] apps/desktop/src/pairing-browser.test.ts
TAP version 13
# Subtest: desktop pairing browser final sink
    # Subtest: opens only the exact canonical API browser route
    ok 1 - opens only the exact canonical API browser route
      ---
      duration_ms: 2.597369
      type: 'test'
      ...
    # Subtest: opens the exact hosted Connect approval bound to the verified tunnel
    ok 2 - opens the exact hosted Connect approval bound to the verified tunnel
      ---
      duration_ms: 0.695143
      type: 'test'
      ...
    # Subtest: rejects replacement, mutation, noncanonical, and reserved-host values without opening
    ok 3 - rejects replacement, mutation, noncanonical, and reserved-host values without opening
      ---
      duration_ms: 1.305277
      type: 'test'
      ...
    1..3
ok 1 - desktop pairing browser final sink
  ---
  duration_ms: 5.847611
  type: 'suite'
  ...
1..1
# tests 3
# suites 1
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 273.513533

[21/360] apps/desktop/src/pairing-response-lifecycle.test.ts
TAP version 13
# NATIVE_PAIRING_SHUTDOWN start-header
# Subtest: desktop pairing service IPC native shutdown lifecycle
    # Subtest: start-header drains through the real service, IPC gate, and before-quit order
    ok 1 - start-header drains through the real service, IPC gate, and before-quit order
      ---
      duration_ms: 59.181373
      type: 'test'
      ...
# NATIVE_PAIRING_SHUTDOWN start-body
    # Subtest: start-body drains through the real service, IPC gate, and before-quit order
    ok 2 - start-body drains through the real service, IPC gate, and before-quit order
      ---
      duration_ms: 52.066184
      type: 'test'
      ...
# NATIVE_PAIRING_SHUTDOWN poll-header
    # Subtest: poll-header drains through the real service, IPC gate, and before-quit orde

...(truncated)

View Workflow

Implemented the two requested follow-up fixes in:

- [packaged-connect-lifecycle.mjs](/tmp/git-processor/worktrees/integry/propr/pr-2054-followup-2026-09-01T22-25-29/apps/desktop/scripts/packaged-connect-lifecycle.mjs:120)
- [packaged-connect-lifecycle.test.mjs](/tmp/git-processor/worktrees/integry/propr/pr-2054-followup-2026-09-01T22-25-29/apps/desktop/scripts/packaged-connect-lifecycle.test.mjs:251)

Changes include recursive decoded-JSON sensitive-string inspection, real cleanup phase deadlines, and isolated default Windows filesystem cleanup so stuck native requests cannot hold the harness open. Existing taskkill, readiness, sanitization, retry, and primary-result behavior remains intact.

Validation:

- Lifecycle/cleanup tests: 19/19 passed
- Related smoke-support tests: 11/11 passed
- ESLint: passed
- `git diff --check`: passed
- Desktop typecheck: blocked by the pre-existing untouched `src/window-options.test.ts:15` `string`/`Rectangle` error

Per instruction, I did not commit. The exact checked-out head remains `678e573b005f9623cbb6380622ca4216e3b3a431`; the automation-generated post-commit head is therefore not yet available.

PR: #2054
Comment by: @integry (ID: 5501251882)
Model: gpt-5.6-sol
@integry integry added the AI label Sep 1, 2026
@integry

integry commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Final narrow lifecycle correction on exact head 0c4ffa6. Preserve the audited killable Windows cleanup child, real authorization/removal deadlines, primary-result preservation, and decoded JSON sensitive-value scanning, but close one remaining bounded-capture bypass.

createRecordCapture stops structured JSON parsing after recordCount reaches 128 and after the 64 KiB capture budget. Raw scanning cannot detect JSON-escaped Windows backslashes, and a previously observed ready record can still produce success when capture is marked truncated. Therefore ready + enough benign records/bytes + a later JSON-escaped sensitive path + clean exit can be accepted.

Fail closed: any record-count or byte-budget truncation must revoke/preclude ready success with one fixed sanitized category, or equivalently continue a separate bounded streaming sensitive scan that cannot be bypassed by JSON escaping. Do not expose raw content or paths. Add deterministic post-ready tests for both exceeding the record-count cap and exceeding the byte cap followed by a JSON-escaped Windows sensitive path and clean exit; neither may succeed. Retain the existing before/after-ready Windows path tests and never-settling cleanup tests. Run focused tests/typecheck and report the exact new head. Base synchronization with transport head 1c02016 will be requested separately after this correction lands.

@propr-dev

propr-dev Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Applied the requested follow-up changes in commit 657374d

Summary of Changes

Implemented the fail-closed capture correction.

Validation:

  • Focused lifecycle/cleanup suite: 21/21 passed
  • ESLint: passed
  • git diff --check: passed
  • Desktop typecheck: blocked by the existing untouched src/window-options.test.ts:15 string/Rectangle error

Per instruction, changes are uncommitted. Exact checked-out head remains 0c4ffa6dd916b0947bb0e10e2be8bcf7d1301606; the system-generated commit will establish the new head.


🤖 Implementation Details

  • Model: GPT-5.6 Sol (high)
  • Requested By: @integry
  • Time: 3m 43s
  • Tokens: 548,609 (542,121 in / 6,488 out)
  • Cost: $0.68

Undo ChangesView Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Implement fixes for issues found by /review /fix or /fix address the null check issue
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment ID: 5501363330✓

@integry integry removed the AI label Sep 1, 2026
Implemented the fail-closed capture correction.

- Any truncated capture now converts ready success to fixed sanitized category `output-rejected`: [packaged-connect-lifecycle.mjs](/tmp/git-processor/worktrees/integry/propr/pr-2054-followup-2026-09-01T22-37-25/apps/desktop/scripts/packaged-connect-lifecycle.mjs:457)
- Added deterministic post-ready record-count and byte-budget bypass tests: [packaged-connect-lifecycle.test.mjs](/tmp/git-processor/worktrees/integry/propr/pr-2054-followup-2026-09-01T22-37-25/apps/desktop/scripts/packaged-connect-lifecycle.test.mjs:287)

Validation:

- Focused lifecycle/cleanup suite: 21/21 passed
- ESLint: passed
- `git diff --check`: passed
- Desktop typecheck: blocked by the existing untouched `src/window-options.test.ts:15` `string`/`Rectangle` error

Per instruction, changes are uncommitted. Exact checked-out head remains `0c4ffa6dd916b0947bb0e10e2be8bcf7d1301606`; the system-generated commit will establish the new head.

PR: #2054
Comment by: @integry (ID: 5501363330)
Model: gpt-5.6-sol
@integry integry added the AI label Sep 1, 2026
@integry

integry commented Sep 1, 2026

Copy link
Copy Markdown
Owner

/merge

@propr-dev

propr-dev Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

🔀 Auto-merged 1953-epic-desktop-transport-api into 2051/gpt-5.6-sol-make-packaged-windows-con-20260901-2205-5rn (clean merge) in commit b5b5c3b

No conflicts were found — the merge was verified by an AI agent.


🤖 Verification Details

  • Model: gpt-5.6-sol
  • Time: 1m 34s

View Task Execution


System-triggered merge conflict resolution

… into 2051/gpt-5.6-sol-make-packaged-windows-con-20260901-2205-5rn
@integry integry added AI and removed AI labels Sep 1, 2026
@integry

integry commented Sep 2, 2026

Copy link
Copy Markdown
Owner

/merge

@propr-dev

propr-dev Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

🔀 Auto-merged 1953-epic-desktop-transport-api into 2051/gpt-5.6-sol-make-packaged-windows-con-20260901-2205-5rn (clean merge) in commit 366bb50

No conflicts were found — the merge was verified by an AI agent.


🤖 Verification Details

  • Model: gpt-5.6-sol
  • Time: 1m 59s

View Task Execution


System-triggered merge conflict resolution

… into 2051/gpt-5.6-sol-make-packaged-windows-con-20260901-2205-5rn
@integry integry removed the AI label Sep 2, 2026
@integry
integry merged commit 7bcfcff into 1953-epic-desktop-transport-api Sep 2, 2026
20 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant