Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
195 commits
Select commit Hold shift + click to select a range
b19af68
feat: workspace proxy toggle + target allowlist config roundtrip (#52)
joshooaj Oct 30, 2026
ed01d98
fix: review follow-ups for proxy config roundtrip (#52)
joshooaj Oct 30, 2026
794bcf8
feat: Event Server proxy fetcher over MIP messaging with chunked HTTP…
joshooaj Oct 30, 2026
35c4d62
fix: proxy-test harness resumed off the UI thread after await, crashi…
joshooaj Oct 30, 2026
c496091
feat: per-workspace loopback forwarding proxy pinned to WebView2, ser…
joshooaj Oct 31, 2026
5a7a7c0
fix(proxy): carry fetch payloads as JSON strings; plugin types never …
joshooaj Oct 31, 2026
9cff27c
docs,test: code-review fixes for #54 - contract prose matches JSON-st…
joshooaj Oct 31, 2026
8c7d709
feat(proxy): forward POST/PUT/DELETE/OPTIONS with method, headers, an…
joshooaj Oct 31, 2026
7c42d9e
fix(proxy): review follow-ups for #55 - transport property setters ca…
joshooaj Oct 31, 2026
dd5dcad
test(proxy): SC-2 probe harness - XHR endpoints serve raw text/plain …
joshooaj Oct 31, 2026
2d35b75
test(proxy): SC-2 probe harness hardening - wait for the dashboard XH…
joshooaj Oct 31, 2026
bda0cac
test(harness): Management Client tree navigation without keyboard wal…
joshooaj Oct 31, 2026
46dbd7f
docs: SC-2 live-host record - vendor login POST+cookie+XHR round-trip…
joshooaj Oct 31, 2026
65cb045
feat(proxy): #56 fetcher TLS decision - full chain validation by defa…
joshooaj Oct 31, 2026
220c21c
feat(proxy): #56 allowlist carries the per-target accept-untrusted-ce…
joshooaj Oct 31, 2026
8efde53
feat(proxy): #56 config plumbing - proxy-target lines carry the accep…
joshooaj Oct 31, 2026
8cfb2ba
feat(proxy): #56 forward policy allowlist-gates CONNECT - allowlisted…
joshooaj Oct 31, 2026
485641d
feat(proxy): #56 codec and policy accept origin-form in-tunnel reques…
joshooaj Oct 31, 2026
1a7f1ef
feat(proxy): #56 connection flow terminates allowlisted CONNECT tunne…
joshooaj Oct 31, 2026
5ec872f
feat(proxy): #56 loopback TLS manager mints session CA + per-host lea…
joshooaj Oct 31, 2026
b88dd35
feat(proxy): #56 listener wires tunnel TLS termination end to end - P…
joshooaj Oct 31, 2026
539620c
docs(adr): #56 ADR-0003 supersedes the per-session CU-root trust - fi…
joshooaj Oct 31, 2026
da51633
feat(proxy): #56 leaf-mint contract (ADR-0003) - LeafRequest carries …
joshooaj Oct 31, 2026
171d04c
feat(proxy): #56 Event Server answers LeafRequest over the shared mes…
joshooaj Oct 31, 2026
d4c671b
feat(proxy): #56 client half of ADR-0003 - ProxyLoopbackClientKey gen…
joshooaj Oct 31, 2026
56030ba
test(ux): #56 SC-2 TLS rows - LoginTestServer gains a self-signed HTT…
joshooaj Oct 31, 2026
7c4b54f
docs: #56 operator runbook (one-time CA export/Import-Certificate int…
joshooaj Oct 31, 2026
3239376
fix(ux): #56 harness survives the Management Client save-confirmation…
joshooaj Oct 31, 2026
2e84c1c
Add elevated Event Server CA provisioning runbook and script
joshooaj Oct 31, 2026
ba99906
Load the deployment CA read-only when the service account cannot writ…
joshooaj Oct 31, 2026
7a62547
Retry Save when MC disables the button between lookup and UIA Invoke
joshooaj Oct 31, 2026
06615bc
Terminate tunnel responses inside the TLS stream, not the raw socket
joshooaj Oct 31, 2026
e6c20e2
Detect the MC save-confirmation modal by structure, not title
joshooaj Oct 31, 2026
55bb718
Classify the fail-closed document correctly: Playwright throws on sel…
joshooaj Oct 31, 2026
30b8206
Catch the timeout Playwright actually throws; record the SC-3 live rows
joshooaj Oct 31, 2026
f76dcb5
Verify keyboard focus before typing the Smart Client password
joshooaj Oct 31, 2026
715db8f
Enter client login passwords by clipboard paste, not keystrokes
joshooaj Nov 1, 2026
584912e
Gate login entry on foreground+focus together, log the entry path, re…
joshooaj Nov 1, 2026
453bef6
Route login focus/foreground checks by process id and dump the login …
joshooaj Nov 1, 2026
4234775
Tolerate client Auto-login: never fight the connecting login dialog
joshooaj Nov 1, 2026
974984e
Treat a login dialog that dies mid-entry as auto-login winning
joshooaj Nov 1, 2026
b717d5f
Never mistake the MC login window for a session window
joshooaj Nov 1, 2026
df6f2a7
Auto-login shortcut only on Smart Client's unique main-window id
joshooaj Nov 1, 2026
4f8a73b
Maximize MC's main window before any tree geometry work
joshooaj Nov 1, 2026
45a7181
Probe the shell Save affordance broadly; never fight an auto-login di…
joshooaj Nov 1, 2026
20b1530
Edit proxy targets via keyboard paste, not ValuePattern.SetValue
joshooaj Nov 1, 2026
237f026
Record why SelectWorkspace saw no tabs
joshooaj Nov 1, 2026
3a22cee
Gate every pane keystroke on verified focus; repair the renamed item
joshooaj Nov 1, 2026
73e9720
Dump the realized tree rows when the workspace child cannot be found
joshooaj Nov 1, 2026
1821d10
Recreate a destroyed workspace item through the shell New menu
joshooaj Nov 1, 2026
f610ef3
Create the workspace via the menu bar 'Add New ...' entry
joshooaj Nov 1, 2026
4aa8dca
Share the Management Client provisioning across proxied probes
joshooaj Nov 1, 2026
93c5211
Record the #56 full-suite green run in the verification matrix
joshooaj Nov 1, 2026
7943bc9
Tunnel websocket upgrades through the proxy decision and forward flow…
joshooaj Nov 1, 2026
0e304e1
Add the Event Server websocket tunnel server (#57)
joshooaj Nov 1, 2026
891fe37
chore: Add and apply PSScriptAnalyzer formatting rules
joshooaj Nov 1, 2026
d0bf98c
Wire websocket tunnels through both messaging hosts (#57)
joshooaj Nov 1, 2026
6d6227c
Pin the #57 tunnel seams and add the SC-4 live row to the verificatio…
joshooaj Nov 1, 2026
167a8ef
Close the two #57 review findings
joshooaj Nov 1, 2026
cd0b0ea
Accept CONNECT-carried ws:// upgrades at the loopback listener (#57)
joshooaj Nov 1, 2026
04a60ff
Record the SC-4 live pass and the CONNECT-carry live repro (#57)
joshooaj Nov 1, 2026
87cbdad
Render explicit per-failure proxy error pages, never a silent wait (#58)
joshooaj Nov 1, 2026
b458382
Add the Event Server machine plugin deployment script with hash verif…
joshooaj Nov 1, 2026
6dbc035
Compare remote service status as strings; WinRM deserializes the enum…
joshooaj Nov 1, 2026
fd0a123
Document the proxied rollout: ES-not-Mgmt-Server, deploy script, log …
joshooaj Nov 1, 2026
6799d2a
Record the live ES deployment and the human handoff steps for the SC-…
joshooaj Nov 1, 2026
9a4ae38
Record the SC-5 deployment prerequisite and stage the byte-identical …
joshooaj Nov 1, 2026
6a12ed5
Harden the probe login for a desktop with no focus and record the SC-…
joshooaj Nov 1, 2026
4e2157a
SC-5 outage row live PASS + the SC drop deployed on BEAST (#58, #59)
joshooaj Nov 1, 2026
541710d
SC-5 live-complete: 403 start-URL row PASS closes the #58 demo matrix
joshooaj Nov 1, 2026
930e777
DP-1 fresh-both-machine smoke PASS on the deployed drop; hosts contro…
joshooaj Nov 1, 2026
3416665
Record the passed fresh-both-machine blocked-egress smoke (SC-1 row o…
joshooaj Nov 1, 2026
7c62e10
Keep the proxy test pins warning-clean: async correlation outcomes, A…
joshooaj Nov 1, 2026
4f5a317
Assert SC-5 recovery in the outage row and record the live PASS (#58)
joshooaj Nov 1, 2026
a3dc6f7
build: convert plugin csproj to SDK-style net472 so dotnet builds eve…
joshooaj Nov 1, 2026
8739460
chore: update workspace dictionary and editor settings
joshooaj Nov 1, 2026
d981ef6
feat(proxy): tunnel wss:// upgrades through terminated TLS tunnels wi…
joshooaj Nov 1, 2026
640a0aa
test(ux): live wss tunnel probes - trusted-target echo and fail-close…
joshooaj Nov 1, 2026
1a124e1
docs: add the SC-6 wss tunnel row and probe procedure; lift the stale…
joshooaj Nov 1, 2026
0de91d3
fix(proxy): name the open exception on the in-tunnel 502 page; classi…
joshooaj Nov 1, 2026
053e22e
fix(scripts): retry the drop copy while the stopped service still hol…
joshooaj Nov 1, 2026
c5803e6
docs: record the Event Server deployment of the #60 drop and the copy…
joshooaj Nov 1, 2026
7813b73
fix(ux): WssTargetTrust host resolution matches EventServerControl (b…
joshooaj Nov 2, 2026
92ac647
docs: SC-6 both live rows PASSED - wss echo round-trip and fail-close…
joshooaj Nov 2, 2026
a94239b
refactor(proxy): one TLS failure classifier, one in-tunnel 502 tail, …
joshooaj Nov 2, 2026
e2f9917
build(psake): task-runner psakefile with unelevated local and remote …
joshooaj Nov 2, 2026
d50d587
chore: run dotnet format
joshooaj Nov 2, 2026
266a4ac
test(psake): Test and TestUI tasks, and docs aligned to the psake ent…
joshooaj Nov 2, 2026
eb00bd9
docs(agents): Lint is green after the dotnet format commit
joshooaj Nov 2, 2026
8865f34
feat(mc): tabbed workspace config page shell - Settings | Proxy | Dia…
joshooaj Nov 2, 2026
481c52a
docs: MC-11 tab shell live row PASSED - four tabs, Save never dirty, …
joshooaj Nov 2, 2026
9a4646b
feat(proxy): diagnostics substrate - block reports, session lifecycle…
joshooaj Nov 2, 2026
315565f
feat(proxy): Event Server logs the diagnostics ingress it records (#69)
joshooaj Nov 2, 2026
c424b5a
docs: verification matrix row + ES-2 host check for the proxy diagnos…
joshooaj Nov 2, 2026
218a640
feat(proxy): a local request-size refusal reports TooLarge like every…
joshooaj Nov 2, 2026
590fd6f
feat(mc): Status tab pulls live proxy sessions, polling tied to tab s…
joshooaj Nov 2, 2026
95bd0a6
test(ux): MC status probe - polling trace, live session row, no-polli…
joshooaj Nov 2, 2026
245e28e
docs: verification matrix row + MC-12 host check for the MC status ta…
joshooaj Nov 2, 2026
ad75f25
feat(proxy): per-view block tally in front of the ES block reporter (…
joshooaj Nov 2, 2026
6d92925
feat(sc): setup-mode blocked-resources indicator and per-view list (#83)
joshooaj Nov 2, 2026
80ba0d9
test: ProxyBlockTally pins - counts, reset, bound, dead forwarder, co…
joshooaj Nov 2, 2026
4261ad0
test(ux): SC-7 blocked-indicator probe + page-pair harness; no-input …
joshooaj Nov 2, 2026
944975c
docs: SC-7 verification matrix row + pinned regression, live rows pen…
joshooaj Nov 2, 2026
d0b854d
feat(proxy): one shared allowlist matcher - leftmost-label wildcards,…
joshooaj Nov 2, 2026
7651057
test: wildcard grammar pins, seeded matcher invariants, gate-agreemen…
joshooaj Nov 2, 2026
a84a3a8
test(ux): MC wildcard/hatch probe - live ES gate admission, apex refu…
joshooaj Nov 2, 2026
f142514
fix(mc): dgStatusSessions carried tri-state 'Disabled' on a WPF-bool …
joshooaj Nov 2, 2026
7963668
docs: MC-13 live rows PASSED - wildcard/hatch/floor verdicts on the l…
joshooaj Nov 2, 2026
4426bc3
docs: MC-12 live rows PASSED on the fixed drop; ES-2 round-trip note …
joshooaj Nov 2, 2026
992846d
fix(sc): toolbar commands refused admission without a CoreWebView2 - …
joshooaj Nov 2, 2026
5af836b
feat(mc): structured allowlist grid on the Proxy tab - live-editor ro…
joshooaj Nov 2, 2026
92a300d
test: ProxyAllowlistEditor pins - row validation IS the shared gramma…
joshooaj Nov 2, 2026
51d2831
test(ux): MC grid probe - Win32 notice capture, MIP.log refusal/audit…
joshooaj Nov 2, 2026
eebb247
docs: MC-14 live row PASSED (run 20261102-105226, three live-found de…
joshooaj Nov 2, 2026
a6a82a9
feat(es): wss tunnel leg honours the per-target accept-untrusted over…
joshooaj Nov 2, 2026
605860c
test: tunnel TLS pins - callback factory null for every unflagged pos…
joshooaj Nov 2, 2026
fa92b12
docs: #61 matrix row + SC-6 prose - accept-untrusted now reaches the …
joshooaj Nov 2, 2026
76ce945
docs: SC-6 #61 live rows PASSED - override admits self-signed wss (ru…
joshooaj Nov 2, 2026
90625f3
chore(ux): retry grid-cell FindAll and wait for row realization (UIA …
joshooaj Nov 2, 2026
d3d9b7d
docs: SC-6 override row re-passed with the MC checkbox roundtrip (run…
joshooaj Nov 2, 2026
d45a734
docs: SC-6 override row second live pass on the hardened harness (run…
joshooaj Nov 2, 2026
942c69b
feat: per-workspace rule-trigger grammar and matcher store - url glob…
joshooaj Nov 2, 2026
f8d04eb
feat(es): a matching proxied fetch raises the fixed WebContent proxy …
joshooaj Nov 2, 2026
1079048
fix(es): raise trigger events through EnvironmentManager.SendMessage …
joshooaj Nov 2, 2026
beae519
docs: rule triggers - README grammar + event-definition admin flow, E…
joshooaj Nov 2, 2026
788f96e
feat: deployment CA public-certificate export over MIP messaging - pr…
joshooaj Nov 2, 2026
b3d72ab
test(ux): MC-15 live probe - Management Client exports the deployment…
joshooaj Nov 2, 2026
621e0f9
chore: apply updated .editorconfig formatting
joshooaj Nov 3, 2026
99886d1
chore: add PSScriptAnalyzer to lint task
joshooaj Nov 3, 2026
66eeef5
feat: MC Diagnostics tab - live recently-blocked list with one-click …
joshooaj Nov 3, 2026
4e07156
test(ux): MC-16 live probe - the Diagnostics tab lists a live Smart C…
joshooaj Nov 3, 2026
a8e7824
test(ux): MC-16 probe hardened against the failures its own live rows…
joshooaj Nov 3, 2026
948b4e7
Merge branch 'feat/mc-diagnostics-tab-84' into feat/proxy - #84 MC Di…
joshooaj Nov 3, 2026
7c77412
feat: per-workspace max-response-bytes cap (5 MB default, 20 MB ceili…
joshooaj Nov 3, 2026
fdcbb3d
test(ux): MC-17 live probe for the per-workspace response cap - defau…
joshooaj Nov 3, 2026
c9811dc
test(ux): MC-17 probe green end to end (run 20261102-210935, drop 362…
joshooaj Nov 3, 2026
0ac1b90
Merge branch 'feat/proxy-response-cap-85' into feat/proxy - #85 per-w…
joshooaj Nov 3, 2026
6521f53
wip(#86): server-side per-workspace proxy header policy - canonical f…
joshooaj Nov 3, 2026
90b884b
feat(#86): MC Proxy tab 'Advanced: headers' - two name/value/strip gr…
joshooaj Nov 3, 2026
1317b0c
test(#86): unit + guard coverage for the per-workspace proxy header p…
joshooaj Nov 3, 2026
eea547e
test(#86): MC-18 live probe for the per-workspace proxy header policy…
joshooaj Nov 3, 2026
1d06545
docs(#86): verification-matrix row + MC-18 section - green live run 2…
joshooaj Nov 3, 2026
529b7a6
feat(#66): proxy error pages carry an explicit cause category instead…
joshooaj Nov 3, 2026
bd8f532
docs(#66): verification-matrix SC-5 row + record 6 - friendly refusal…
joshooaj Nov 3, 2026
60e8c52
docs(#66): README error-page section rewritten around the cause categ…
joshooaj Nov 3, 2026
9d80302
Merge branch 'feat/proxy-error-pages-66' into feat/proxy - #66 friend…
joshooaj Nov 3, 2026
d0119f2
feat(#70): installer force-closes running Milestone clients so upgrad…
joshooaj Nov 3, 2026
f07d5f1
docs(#70): README install section states the installer closes running…
joshooaj Nov 3, 2026
9b84734
feat(#88): off-allowlist https refusals render the friendly proxy err…
joshooaj Nov 3, 2026
929a3bb
test(#88): unit + probe coverage for the view-layer https refusal - P…
joshooaj Nov 3, 2026
8ad8516
docs(#88): README error-page section names the https posture (the vie…
joshooaj Nov 3, 2026
4d85ec0
Merge branch 'fix/https-view-refusal-88' into feat/proxy - #88 off-al…
joshooaj Nov 3, 2026
4934ae0
feat(#78): Rule triggers grid on the MC Proxy tab
joshooaj Nov 3, 2026
570366c
test(#78): fix MC-19 combo driving after live runs
joshooaj Nov 3, 2026
266dc19
docs(#78): verification matrix row + MC-19 live run record
joshooaj Nov 3, 2026
a3ed098
Merge branch 'feat/mc-proxy-triggers-78' into feat/proxy - #78 Rule t…
joshooaj Nov 3, 2026
a977129
test(#67): OS (WinINET) proxy inheritance probes - WinInetProxyHarnes…
joshooaj Nov 3, 2026
eec0b3b
Merge branch 'feat/os-proxy-wininet-67': OS (WinINET) proxy inheritan…
joshooaj Nov 3, 2026
79c0768
feat(#71): managed workspaces lock the security-relevant view setting…
joshooaj Nov 3, 2026
2669bd3
test(#71): unit + guard + live-probe coverage - WorkspaceSettingLocks…
joshooaj Nov 3, 2026
c2c3fd5
docs(#71): README Configuration gains the managed-workspace paragraph…
joshooaj Nov 3, 2026
c27b35b
Merge branch 'feat/managed-view-locks-71' into feat/proxy - #71 Manag…
joshooaj Nov 3, 2026
ee5405c
feat(#72): untrusted-proxy-CA banner for every user + setup-mode elev…
joshooaj Nov 3, 2026
8bac5c2
test+docs(#72): live trust probes + matrix/README coverage - ScProxyT…
joshooaj Nov 3, 2026
1ecc533
feat(#80): untrusted-CA reports ride the block channel; ES aggregates…
joshooaj Nov 3, 2026
2b63cda
test(#80): unit + wiring-guard coverage for the untrusted-CA machine …
joshooaj Nov 3, 2026
ac73a81
test(ux), docs: MC-20 untrusted-CA machine-aggregate probes + records…
joshooaj Nov 3, 2026
b995814
Merge branch 'feat/mc-ca-aggregate-80' into feat/proxy - #80 MC: aggr…
joshooaj Nov 3, 2026
59bb637
feat(#82): Event Server service stop/wait/restart flow in the MSI - n…
joshooaj Nov 3, 2026
2e712bc
docs+scripts(#82): README Event Server restart-choice section, verifi…
joshooaj Nov 3, 2026
0c0d367
feat+test+docs(#83): first live SC-7 run exposed and fixed the unrend…
joshooaj Nov 3, 2026
5fb5c27
docs(#83): SC-7 live record drop-hash honesty - run-time drop 972A01E…
joshooaj Nov 3, 2026
28cfe4e
docs: IN-2 full-UI walkthrough row - choice page clicked through live…
joshooaj Nov 3, 2026
37dd625
docs(#63): verification-matrix epic-integration records - MC-13/MC-14…
joshooaj Nov 3, 2026
ce974e8
docs(#68): MSI on the Event Server machine is THE supported deploymen…
joshooaj Nov 3, 2026
7fa8b16
feat+test+docs(#77): the MSI creates the deployment proxy CA at insta…
joshooaj Nov 3, 2026
29c4995
docs(#77): IN-4 live records - four PASSED rows on the live Event Ser…
joshooaj Nov 3, 2026
af2ed46
test(ux), docs(#64): epic-64 integration pass - one default-option MS…
joshooaj Nov 4, 2026
d98a1ed
docs(#87): triage-recorded domain language + ADR-0004 - CONTEXT.md na…
joshooaj Nov 4, 2026
e45a967
test+spike(#90): WebView2 browser-process lifetime probe - standalone…
joshooaj Nov 4, 2026
0f8cfc5
docs(#90,#91): ADR-0004 point 5 settled by the #90 measurements - bro…
joshooaj Nov 4, 2026
b2b5a65
feat+test+docs(#92): proxied profile keyed to the FULL proxied bounda…
joshooaj Nov 4, 2026
f1c2ed8
chore: run dotnet format - the #77 commit left WebContentProxyCa/Prog…
joshooaj Nov 4, 2026
87675b1
feat+test(#93): listener-claim core - the ADR-0004 point-3 claim as p…
joshooaj Nov 4, 2026
57ce0f6
feat+test+docs(#94): startup sweep of orphaned proxied profiles and s…
joshooaj Nov 4, 2026
5d75765
fix+test(#89): version-stamp WebContentTrustHelper.exe so MSI upgrade…
joshooaj Nov 4, 2026
7838eed
test(#89): Event Server upgrade harness for the stamped-helper row - …
joshooaj Nov 4, 2026
28f000a
docs(#89): IN-6 live row - version-stamped helper self-heals over a C…
joshooaj Nov 4, 2026
2c3fdb9
feat+test+docs(#87): failed PROXIED CoreWebView2 initialization prese…
joshooaj Nov 4, 2026
e497c5f
feat+test+docs(#95): a second Smart Client JOINS the boundary owner's…
joshooaj Nov 4, 2026
41926b9
feat+test(#96): owner death mid-session HEALS itself - claim epoch + …
joshooaj Nov 4, 2026
451c82c
fix(#96): IsViewLive hops through the WebView2 control's dispatcher w…
joshooaj Nov 4, 2026
1ef2ebb
docs+test(#96): SC-15 live probes + matrix rows for the owner-death h…
joshooaj Nov 4, 2026
e574f8e
chore: bump copyright from 2024 to 2026
joshooaj Nov 5, 2026
15e46f2
fix(#82): build.ps1 StopEventServerService guard uses if/else, not th…
joshooaj Nov 6, 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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ indent_size = 4
tab_width = 4

# New line preferences
insert_final_newline = false
insert_final_newline = true

#### .NET Coding Conventions ####
[*.{cs,vb}]
Expand Down
187 changes: 187 additions & 0 deletions .es-upgrade-89.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# Ticket #89 row: MSI upgrade over a Copy-Item-strayed trust helper on the Event Server
# machine. Mirrors the IN-3 row-1 scenario WITH the fix: the helper now carries the build's
# nbgv stamp, so seeding it with an OLDER stamped build's helper (Copy-Item stray) and
# upgrading to a NEWER build must end with every drop file hash-identical to the local drop
# (the IN-3 original ended 12/13 because the unstamped 1.0.0.0 helper shadowed the upgrade).
# Sequence: pre-state -> seed stray helper from .cache\seed89 -> stage+run the new MSI
# (default options) -> post-state + full local-vs-remote drop hash table.
$ErrorActionPreference = 'Stop'
$root = 'C:\repos\WebContentPlugin'
. (Join-Path $root 'scripts\helpers.ps1')
Import-Environment (Join-Path $root '.env')
Unlock-SecretStore -Password (Import-Clixml (Join-Path $root '.secretstore'))
$cred = Get-Secret -Name $env:VMS_CREDENTIAL

$msi = Get-ChildItem (Join-Path $root 'output\Setup\en-US\*.msi') | Sort-Object LastWriteTime | Select-Object -Last 1
$localMsiHash = (Get-FileHash $msi.FullName -Algorithm SHA256).Hash
Write-Host "LOCAL MSI: $($msi.Name) SHA256=$localMsiHash"

$seedHelper = Join-Path $root '.cache\seed89\WebContentTrustHelper.exe'
$seedHash = (Get-FileHash $seedHelper -Algorithm SHA256).Hash
$seedVer = (Get-Item $seedHelper).VersionInfo
Write-Host ('SEED HELPER: {0}.{1}.{2}.{3} SHA256={4}' -f $seedVer.FileMajorPart, $seedVer.FileMinorPart, $seedVer.FileBuildPart, $seedVer.FilePrivatePart, $seedHash)

$s = New-PSSession -ComputerName $env:VMS_ADDRESS -Credential $cred
$s2 = New-PSSession -ComputerName $env:VMS_ADDRESS -Credential $cred

# --- pre-state (read-only) ---
$stateBlock = {
$drop = 'C:\Program Files\VideoOS\MIPPlugins\CascadiaWebContentPlugin'
$svc = Get-Service -Name MilestoneEventServerService
$regs = Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like '*Web Content*' } |
ForEach-Object { [pscustomobject]@{ Name = $_.DisplayName; Version = $_.DisplayVersion; Code = $_.PSChildName } }
$cas = @()
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store('My', 'LocalMachine')
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly -bor [System.Security.Cryptography.X509Certificates.OpenFlags]::OpenExistingOnly)
try {
$found = @($store.Certificates.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindBySubjectName, 'XProtect WebContent Plugin Loopback Proxy', $false))
foreach ($cert in $found) {
$container = $null
try { if ($cert.PrivateKey -and $cert.PrivateKey.CspKeyContainerInfo) { $container = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName } } catch { $container = 'READ-REFUSED' }
$cas += [pscustomobject]@{ Thumb = $cert.Thumbprint; NotAfter = $cert.NotAfter.ToString('o'); Container = $container }
}
} finally { $store.Close() }
$cacl = 'n/a'
if ($cas.Count -ge 1 -and $cas[0].Container -and $cas[0].Container -ne 'READ-REFUSED') {
$keyFile = Get-ChildItem 'C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys' -Filter $cas[0].Container -ErrorAction SilentlyContinue | Select-Object -First 1
if ($keyFile) {
$cacl = (@(Get-Acl -LiteralPath $keyFile.FullName).Access | ForEach-Object { "$($_.IdentityReference) $($_.FileSystemRights) $($_.AccessControlType)" }) -join ' | '
} else { $cacl = 'KEYFILE-NOT-FOUND' }
}
$files = @()
if (Test-Path -LiteralPath $drop) {
$trim = $drop.TrimEnd('\').Length + 1
$files = @(Get-ChildItem -LiteralPath $drop -File -Recurse | ForEach-Object {
$v = $_.VersionInfo
[pscustomobject]@{
File = $_.FullName.Substring($trim)
Sha = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash
Ver = "$($v.FileMajorPart).$($v.FileMinorPart).$($v.FileBuildPart).$($v.FilePrivatePart)"
}
})
}
$mipTail = @()
$mipLog = 'C:\ProgramData\Milestone\XProtect Event Server\logs\MIP.log'
if (Test-Path -LiteralPath $mipLog) { $mipTail = @(Get-Content -LiteralPath $mipLog -Tail 400 -ErrorAction SilentlyContinue | Where-Object { $_ -match 'Proxy fetcher ready|Loaded deployment proxy CA|Minted loopback proxy leaf' }) }
[pscustomobject]@{
Service = $svc.Status
Regs = $regs
Cas = $cas
Dacl = $cacl
Files = $files
Mip = $mipTail
}
}
$pre = Invoke-Command -Session $s -ScriptBlock $stateBlock
Write-Host "PRE service=$($pre.Service)"
$pre.Regs | ForEach-Object { Write-Host "PRE reg: $($_.Version) [$($_.Code)]" }
$pre.Cas | ForEach-Object { Write-Host "PRE CA: $($_.Thumb) notAfter=$($_.NotAfter) container=$($_.Container)" }
Write-Host "PRE key DACL: $($pre.Dacl)"
Write-Host "PRE drop files=$($pre.Files.Count)"

# --- seed the Copy-Item stray: older stamped helper over the installed one ---
$remoteDrop = Invoke-Command -Session $s { 'C:\Program Files\VideoOS\MIPPlugins\CascadiaWebContentPlugin' }
Copy-Item -ToSession $s -Path $seedHelper -Destination (Join-Path $remoteDrop 'WebContentTrustHelper.exe') -Force
$seeded = Invoke-Command -Session $s {
param($drop)
$h = Join-Path $drop 'WebContentTrustHelper.exe'
$v = (Get-Item -LiteralPath $h).VersionInfo
[pscustomobject]@{ Ver = "$($v.FileMajorPart).$($v.FileMinorPart).$($v.FileBuildPart).$($v.FilePrivatePart)"; Sha = (Get-FileHash -LiteralPath $h -Algorithm SHA256).Hash }
} -ArgumentList $remoteDrop
Write-Host "SEEDED helper on server: Ver=$($seeded.Ver) Sha=$($seeded.Sha)"
if ($seeded.Sha -ne $seedHash) { throw "seed copy hash mismatch on the server: $($seeded.Sha) != $seedHash" }

# --- stage the MSI ---
$remoteTempRoot = Invoke-Command -Session $s { [IO.Path]::GetTempPath() }
if ([string]::IsNullOrWhiteSpace($remoteTempRoot)) { throw 'remote GetTempPath returned nothing' }
$temp = Join-Path $remoteTempRoot 'wces89'
$null = Invoke-Command -Session $s -ArgumentList $temp { param($t) $null = New-Item -ItemType Directory -Path $t -Force; $t }
if ([string]::IsNullOrWhiteSpace($temp)) { throw 'remote temp folder creation failed' }
Copy-Item -ToSession $s -Path $msi.FullName -Destination $temp
$remoteMsi = Join-Path $temp $msi.Name
$remoteHash = Invoke-Command -Session $s -ArgumentList $remoteMsi { param($p) (Get-FileHash -LiteralPath $p -Algorithm SHA256).Hash }
if ($remoteHash -ne $localMsiHash) { throw "remote MSI hash $remoteHash != local $localMsiHash" }
Write-Host "staged + hash-verified: $remoteMsi"

# --- service journal from the second session ---
$journalFile = Join-Path $temp 'service-journal.txt'
$journal = Invoke-Command -Session $s2 -AsJob -ArgumentList $journalFile {
param($f)
$lines = @()
$end = (Get-Date).AddMinutes(6)
while ((Get-Date) -lt $end) {
$lines += ('{0:HH:mm:ss.fff} {1}' -f (Get-Date), (Get-Service -Name MilestoneEventServerService -ErrorAction SilentlyContinue).Status)
Start-Sleep -Milliseconds 500
}
Set-Content -LiteralPath $f -Value $lines
}

# --- the upgrade itself: defaults (RESTART_EVENT_SERVER=1, PROXY_SUPPORT=1) ---
$log = Join-Path $temp 'upgrade.log'
$exit = Invoke-Command -Session $s -ArgumentList @($remoteMsi, $log) {
param($m, $l)
$p = Start-Process msiexec.exe -ArgumentList "/i `"$m`" /qn /l*v `"$l`"" -Wait -PassThru
$p.ExitCode
}
Write-Host "MSIEXEC EXIT=$exit"
if ($exit -notin 0, 3010, 1641) { throw "msiexec exit $exit - upgrade failed" }

Wait-Job -Job $journal -Timeout 420 | Out-Null
Receive-Job -Job $journal | Out-Null

# --- post-state ---
$post = Invoke-Command -Session $s -ScriptBlock $stateBlock
Write-Host "POST service=$($post.Service)"
$post.Regs | ForEach-Object { Write-Host "POST reg: $($_.Version) [$($_.Code)]" }
$post.Cas | ForEach-Object { Write-Host "POST CA: $($_.Thumb) notAfter=$($_.NotAfter) container=$($_.Container)" }
Write-Host "POST key DACL: $($post.Dacl)"
$post.Mip | ForEach-Object { Write-Host "MIP: $_" }

$journalText = Invoke-Command -Session $s -ArgumentList $journalFile { param($f) Get-Content -LiteralPath $f }
Write-Host '--- journal transitions ---'
$prev = ''
foreach ($line in $journalText) {
$st = ($line -split ' ')[-1]
if ($st -ne $prev) { Write-Host $line; $prev = $st }
}

Write-Host '--- MSI log action evidence ---'
Invoke-Command -Session $s -ArgumentList $log {
param($l)
Get-Content -LiteralPath $l | Where-Object {
$_ -match 'CustomActionSchedule|Skipping action: (StopEventServerService|RestartEventServerService|CreateProxyAuthority)|Doing action: (StopEventServerService|RestartEventServerService|CreateProxyAuthority)|MainEngineThread is returning|Wix4CloseApplications|Shutting down application:|ExitCode'
} | Select-Object -First 60
}

# --- the #89 verdict: local drop vs remote drop, every file, hash + version ---
Write-Host '--- local drop (output\WebContent) ---'
$localDrop = Join-Path $root 'output\WebContent'
$trim = $localDrop.TrimEnd('\').Length + 1
$localFiles = @(Get-ChildItem -LiteralPath $localDrop -File -Recurse | ForEach-Object {
$v = $_.VersionInfo
[pscustomobject]@{
File = $_.FullName.Substring($trim)
Sha = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash
Ver = "$($v.FileMajorPart).$($v.FileMinorPart).$($v.FileBuildPart).$($v.FilePrivatePart)"
}
})
Write-Host '--- local-vs-remote file comparison ---'
$remoteByFile = @{}
foreach ($f in $post.Files) { $remoteByFile[$f.File] = $f }
$mismatch = 0
foreach ($lf in $localFiles) {
$rf = $remoteByFile[$lf.File]
if ($null -eq $rf) { Write-Host "MISSING-REMOTE $($lf.File)"; $mismatch++; continue }
$tag = if ($rf.Sha -eq $lf.Sha) { 'IDENTICAL' } else { $mismatch++; 'DIFFERS' }
Write-Host ('{0,-9} {1} local={2} {3} remote={4} {5}' -f $tag, $lf.File, $lf.Ver, $lf.Sha.Substring(0, 8), $rf.Ver, $rf.Sha.Substring(0, 8))
}
foreach ($rf in $post.Files) {
if (-not ($localFiles.File -contains $rf.File)) { Write-Host "EXTRA-REMOTE $($rf.File) $($rf.Ver) $($rf.Sha.Substring(0,8))"; $mismatch++ }
}
Write-Host "COMPARISON: local=$($localFiles.Count) remote=$($post.Files.Count) mismatches=$mismatch"

# --- cleanup ---
Invoke-Command -Session $s -ArgumentList $temp { param($t) Remove-Item -LiteralPath $t -Recurse -Force -ErrorAction SilentlyContinue }
Remove-PSSession $s, $s2
Write-Host 'DONE'
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ jobs:
path: .\.cache
key: ${{ runner.os }}-webview

- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3

- name: Build
id: build
shell: powershell
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ jobs:
path: .\.cache
key: ${{ runner.os }}-webview

- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3

- name: Restore .NET tools
shell: pwsh
run: dotnet tool restore
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,5 @@ FodyWeavers.xsd
.env
tests/ux/uxconfig.json
artifacts/

.secretstore
45 changes: 44 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,46 @@
{
"dotnet.preferCSharpExtension": true
"powershell.codeFormatting.preset": "OTBS",
"powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1",
"files.encoding": "utf8",
"[powershell]": {
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.formatOnSave": true
},
"[csharp]": {
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.formatOnSave": true
},
"[json]": {
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.formatOnSave": true
},
"[xaml]": {
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.formatOnSave": true
},
"[xml]": {
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.formatOnSave": true
},
"cSpell.words": [
"Cascadia",
"correlator",
"FQID",
"LASTEXITCODE",
"mintable",
"nbgv",
"nologo",
"Spki",
"unicasted",
"unicasts",
"vdproj",
"WEBCONTENT",
"wixproj",
"xunit"
]
}
Loading