Skip to content

Latest commit

 

History

History
155 lines (120 loc) · 6.89 KB

File metadata and controls

155 lines (120 loc) · 6.89 KB

Devolutions Terminal packaging

The packaging area produces both an MSIX package and a per-machine MSI. The MSI is the replacement distribution path for the former wt-distro installer: it installs the NativeAOT host and dt.exe under C:\Program Files\Devolutions\Terminal, creates a Devolutions Terminal Start Menu shortcut, and registers dt.exe through Windows App Paths. It does not install wt.exe or claim Windows Terminal drop-in compatibility.

Build the NuGet distribution packages, which contain the same self-contained payloads used by the native platform packages:

.\src\Devolutions.Terminal.Package\Scripts\Build-NuGet.ps1

Build the MSI:

.\src\Devolutions.Terminal.Package\Scripts\Build-Msi.ps1

This project owns the development package identity and the scripts that turn the win-x64 and win-arm64 NativeAOT publishes into per-architecture MSIX packages. Direct dotnet run and dotnet publish remain unpackaged and do not require registration.

Identity

Field Value
NuGet distribution package Devolutions.Terminal.App
Development publisher CN=Devolutions Inc.
Application ID Terminal
Execution aliases dt.exe, Devolutions.Terminal.exe
Protocol dterm:
Minimum Windows Windows 10, version 2004 (10.0.19041.0)

The checked-in identity is stable for development and unsigned CI builds. Signed releases override the generated manifest's publisher with the complete Artifact Signing certificate subject: CN=Devolutions Inc, O=Devolutions Inc, L=Lavaltrie, S=Québec, C=CA. The workflow's optional TRUSTED_SIGNING_PUBLISHER GitHub configuration variable supports profiles with a different subject. The source manifest and development certificate generation remain unchanged.

A different publisher produces a different package family and is not an in-place upgrade of the development package; package-scoped data is separate. This distinction does not affect the unpackaged host or MSI.

The package is a medium-integrity, full-trust desktop package. It declares only runFullTrust; it does not request broad file-system or network capabilities. The checked-in visual assets live with the package project.

The effective packaged AUMID is Devolutions.Terminal_<publisher-id>!Terminal; code derives the publisher-id with GetCurrentPackageFamilyName and never guesses it.

Build unsigned packages

Install winapp CLI 0.6.0 or newer, then run:

.\src\Devolutions.Terminal.Package\Scripts\Build-Packages.ps1
.\src\Devolutions.Terminal.Package\Scripts\Test-Packages.ps1 `
  -PackagePath .\artifacts\msix\packages\*.msix

Unsigned packages are the default so CI can publish artifacts for a trusted release-signing stage. They cannot be installed until signed.

To package NativeAOT outputs produced elsewhere, place them in artifacts\msix\layout\win-x64 and artifacts\msix\layout\win-arm64, then pass -SkipPublish. Build-Packages.ps1 still cross-builds the x64/ARM64 shell helpers. -SkipNativeBuild is only valid when matching helper outputs already exist under artifacts\msix\native-shell\<architecture>.

For an external signing profile, pass its exact certificate subject through Build-Packages.ps1 -Publisher before packaging, and use the same value with Test-Packages.ps1 -ExpectedPublisher. Do not modify a built MSIX manifest: that would invalidate its block map. Omitting these parameters retains the development identity and its validation.

Development signing and installation

Private keys and generated package artifacts live under dotnet\artifacts, which is ignored by Git. Never commit a .pfx or its password.

$password = Read-Host "Certificate password" -AsSecureString

.\src\Devolutions.Terminal.Package\Scripts\New-DevelopmentCertificate.ps1 `
  -Password $password

.\src\Devolutions.Terminal.Package\Scripts\Sign-Packages.ps1 `
  -PackageDirectory .\artifacts\msix\packages `
  -CertificatePath .\artifacts\msix\certificates\Devolutions.Terminal.pfx `
  -Password $password `
  -Version 2026.3.0.0

Trust only the exported public certificate from an elevated Administrator terminal:

.\src\Devolutions.Terminal.Package\Scripts\Trust-DevelopmentCertificate.ps1 `
  -CertificatePath .\artifacts\msix\certificates\Devolutions.Terminal.cer

Install, launch, validate, and uninstall:

$package = ".\artifacts\msix\packages\Devolutions.Terminal_2026.3.0.0_x64.msix"
.\src\Devolutions.Terminal.Package\Scripts\Test-Packages.ps1 -PackagePath $package -RequireSignature
.\src\Devolutions.Terminal.Package\Scripts\Install-Package.ps1 -PackagePath $package -Launch
dt.exe
Start-Process "dterm:"
.\src\Devolutions.Terminal.Package\Scripts\Uninstall-Package.ps1

Use -ReplaceExisting for an in-place update or downgrade of the development package while preserving package data. Before the certificate is trusted, signature integrity and publisher matching can still be checked with -RequireSignature -AllowUntrustedRoot; installation continues to require a trusted certificate.

Capability boundary

PackageEnvironment.DetectCurrent() uses NativeAOT-safe generated P/Invoke. The package includes architecture-matched Devolutions.Terminal.ShellExt.dll and dt-shell-integration.exe. The DLL implements the package-registered IExplorerCommand directory/background verbs. The helper implements protocol-1 jump-list refresh and toast publication; requests are bounded, versioned, and authenticated with a random token passed only through standard input and the child process environment.

Visible profile name/GUID/icon data produces jump-list tasks. The app refreshes them after startup and every settings-editor or snippet save. Toast launch data contains only a version, random notification id, validated use-any/positive window target, and focus action. Activation is validated before it is routed through the authenticated broker; no broker token, command line, environment data, or other secret is embedded in the toast.

Packaged jump lists/toasts use the package family AUMID. Supported unpackaged toast use requires both:

  • WT_DOTNET_AUMID set to an AUMID registered on a Start-menu shortcut.
  • WT_DOTNET_TOAST_SHORTCUT set to that existing .lnk path.
  • The shortcut's toast activator property and COM/sparse-package registration point to a3aeb121-45d9-4cd9-a278-4b43d19b95b1.

Unpackaged jump lists require the same registered AUMID. The helper reports an explicit unsupported/failed diagnostic when these identity requirements are not met; the accessible in-app notification remains independent.

Default-terminal delegation is intentionally not advertised in the manifest. The versioned default-terminal-delegation.v1 boundary reports unsupported until the OpenConsole handoff v3 proxy/stub and host are built and package registered. BuiltInComInteropSupport=false remains set on the NativeAOT host.