diff --git a/.github/workflows/connector-windows.yml b/.github/workflows/connector-windows.yml
index 28e4100..d44c34b 100644
--- a/.github/workflows/connector-windows.yml
+++ b/.github/workflows/connector-windows.yml
@@ -31,12 +31,17 @@ jobs:
npm run typecheck
npm run test -- --ci --runInBand tests/bridge/bridge-service.test.ts tests/auth/computer-bridge.test.ts tests/lib/connector-version.test.ts
- - name: Build unsigned Windows installer verification artifacts
- run: npm run connector:build:windows
+ - name: Build Windows verification artifacts and Microsoft Store MSIX
+ run: npm run connector:build:windows:store
- name: Verify installer lifecycle, package, pinned runtime, and DPAPI
run: npm run connector:verify:windows
+ - name: Verify Microsoft Store identity and MSIX contents
+ env:
+ DEVINX_REQUIRE_MSIX_ARTIFACT: '1'
+ run: npm run connector:verify:windows:store
+
- name: Audit JavaScript dependencies
run: npm run audit
@@ -51,3 +56,12 @@ jobs:
artifacts/connector/windows/DevinX-Connector-Setup-0.1.0-windows-x64.exe.sha256
artifacts/connector/windows/verification-audit.json
if-no-files-found: error
+
+ - name: Upload Microsoft Store submission package
+ uses: actions/upload-artifact@v6
+ with:
+ name: devinx-connector-windows-x64-MICROSOFT-STORE-UPLOAD
+ path: |
+ artifacts/connector/windows/DevinX-Connector-*-windows-x64.msix
+ artifacts/connector/windows/DevinX-Connector-*-windows-x64.msix.sha256
+ if-no-files-found: error
diff --git a/README.md b/README.md
index 496b68d..2afb4d2 100644
--- a/README.md
+++ b/README.md
@@ -148,9 +148,12 @@ controls. Cognition's separate
[Windows cloud-session environments](https://docs.devin.ai/onboard-devin/environment/windows-support)
are not the Connector runtime.
-The unsigned artifact produced by ordinary CI is deliberately marked **NOT FOR RELEASE**. DevinX
-will offer Windows as a supported download only after an Authenticode-signed candidate passes the
-clean Windows 11 x64 physical matrix in [spec 037](specs/037-windows-connector.md), including
+The unsigned EXE and ZIP artifacts produced by ordinary CI are deliberately marked **NOT FOR
+RELEASE**. The public Windows distribution is the reserved
+[Microsoft Store listing](https://apps.microsoft.com/detail/9N52Z3FVMFH8), whose accepted MSIX is
+signed and delivered by Microsoft. DevinX will offer it as a supported download only after the
+Store package passes certification and the clean Windows 11 x64 physical matrix in
+[spec 037](specs/037-windows-connector.md), including
official Devin ACP discovery, Tailscale routing, pairing, read/send/create grants,
AskUserQuestion, sleep/reconnect, update, and uninstall. This prevents an unfinished or unsigned
package from being presented as trustworthy.
@@ -267,6 +270,8 @@ or TestFlight build. Expo Go is not the release test environment.
| `npm run connector:verify:macos` | Verify the packaged Connector artifact |
| `npm run connector:build:windows` | Build the Windows x64 app, installer, and checksums |
| `npm run connector:verify:windows` | Verify installer lifecycle, package, and DPAPI storage |
+| `npm run connector:build:windows:store` | Build the exact-identity Microsoft Store MSIX |
+| `npm run connector:verify:windows:store` | Verify Store identity, manifest, assets, and MSIX |
No package may be added until it is verified in the official registry, including its publication
history, download history, and source repository. Dependencies are lockfile-enforced; never use a
diff --git a/connector/windows-msix/AppxManifest.xml.template b/connector/windows-msix/AppxManifest.xml.template
new file mode 100644
index 0000000..fafdfc4
--- /dev/null
+++ b/connector/windows-msix/AppxManifest.xml.template
@@ -0,0 +1,56 @@
+
+
+
+
+ DevinX Connector
+ {{PUBLISHER_DISPLAY_NAME}}
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/connector/windows-msix/Assets/Square150x150Logo.png b/connector/windows-msix/Assets/Square150x150Logo.png
new file mode 100644
index 0000000..bb6eef5
Binary files /dev/null and b/connector/windows-msix/Assets/Square150x150Logo.png differ
diff --git a/connector/windows-msix/Assets/Square44x44Logo.png b/connector/windows-msix/Assets/Square44x44Logo.png
new file mode 100644
index 0000000..6a313b6
Binary files /dev/null and b/connector/windows-msix/Assets/Square44x44Logo.png differ
diff --git a/connector/windows-msix/Assets/StoreLogo.png b/connector/windows-msix/Assets/StoreLogo.png
new file mode 100644
index 0000000..284a92f
Binary files /dev/null and b/connector/windows-msix/Assets/StoreLogo.png differ
diff --git a/connector/windows-msix/store-identity.json b/connector/windows-msix/store-identity.json
new file mode 100644
index 0000000..5e9e04c
--- /dev/null
+++ b/connector/windows-msix/store-identity.json
@@ -0,0 +1,13 @@
+{
+ "storeId": "9N52Z3FVMFH8",
+ "identityName": "DevinXTools.DevinXConnector",
+ "publisher": "CN=43D84E24-857C-4C40-9DAA-1A6983913CD9",
+ "publisherDisplayName": "DevinX Tools",
+ "packageFamilyName": "DevinXTools.DevinXConnector_ydtgrt4yd5wrc",
+ "msaAppId": "7d1237e7-6265-48ab-adf5-2a12f5d81101",
+ "version": "0.1.1.0",
+ "architecture": "x64",
+ "defaultLanguage": "en-US",
+ "minimumWindowsVersion": "10.0.22000.0",
+ "maximumWindowsVersionTested": "10.0.26100.0"
+}
diff --git a/connector/windows/DevinXConnector.csproj b/connector/windows/DevinXConnector.csproj
index cab7ba4..6ad442e 100644
--- a/connector/windows/DevinXConnector.csproj
+++ b/connector/windows/DevinXConnector.csproj
@@ -1,7 +1,7 @@
WinExe
- net10.0-windows
+ net10.0-windows10.0.22000.0
true
enable
enable
diff --git a/connector/windows/Program.cs b/connector/windows/Program.cs
index f9e363e..4dcab19 100644
--- a/connector/windows/Program.cs
+++ b/connector/windows/Program.cs
@@ -21,8 +21,9 @@ private static void Main()
internal sealed class ConnectorForm : Form
{
private const int MaximumIpcLineCharacters = 16_384;
+ private const string StartupTaskId = "DevinXConnectorStartup";
private const string StartupValueName = "DevinX Connector";
- private const string ReleasePage = "https://github.com/fenner888/Devinx/releases/latest";
+ private const string ReleasePage = "https://apps.microsoft.com/detail/9N52Z3FVMFH8";
private const string SetupGuide =
"https://github.com/fenner888/Devinx/blob/main/docs/devinx-connector.md";
private readonly Label statusLabel = new() { AutoSize = true, Font = new Font("Segoe UI", 18, FontStyle.Bold) };
@@ -42,12 +43,13 @@ internal sealed class ConnectorForm : Form
};
private readonly Button savePermissionsButton = new() { Text = "Save permissions", AutoSize = true };
private readonly Button revokeButton = new() { Text = "Revoke selected iPhone", AutoSize = true };
- private readonly Button releasesButton = new() { Text = "Check official releases", AutoSize = true };
+ private readonly Button releasesButton = new() { Text = "Open Microsoft Store", AutoSize = true };
private readonly Button helpButton = new() { Text = "Setup and uninstall help", AutoSize = true };
private readonly NotifyIcon trayIcon = new() { Text = "DevinX Connector", Visible = true };
private readonly SemaphoreSlim writeLock = new(1, 1);
private Process? runtime;
private bool exiting;
+ private bool launchAtLoginInitializing = true;
public ConnectorForm()
{
@@ -124,9 +126,13 @@ public ConnectorForm()
revokeButton.Click += async (_, _) => await RevokeSelectedDeviceAsync();
releasesButton.Click += (_, _) => OpenOfficialPage(ReleasePage);
helpButton.Click += (_, _) => OpenOfficialPage(SetupGuide);
- launchAtLogin.CheckedChanged += (_, _) => SetLaunchAtLogin(launchAtLogin.Checked);
+ launchAtLogin.CheckedChanged += async (_, _) => await HandleLaunchAtLoginChangedAsync();
FormClosing += HandleFormClosing;
- Shown += async (_, _) => await StartRuntimeAsync();
+ Shown += async (_, _) =>
+ {
+ await InitializeLaunchAtLoginAsync();
+ await StartRuntimeAsync();
+ };
var menu = new ContextMenuStrip();
menu.Items.Add("Open DevinX Connector", null, (_, _) => RestoreWindow());
@@ -134,7 +140,6 @@ public ConnectorForm()
trayIcon.ContextMenuStrip = menu;
trayIcon.Icon = SystemIcons.Application;
trayIcon.DoubleClick += (_, _) => RestoreWindow();
- launchAtLogin.Checked = IsLaunchAtLoginEnabled();
SetStatus("Starting…", "Checking Tailscale and Devin for Terminal");
}
@@ -372,13 +377,103 @@ private async Task ExitAsync()
Application.Exit();
}
- private static bool IsLaunchAtLoginEnabled()
+ private async Task InitializeLaunchAtLoginAsync()
+ {
+ launchAtLoginInitializing = true;
+ try
+ {
+ if (!IsPackaged())
+ {
+ launchAtLogin.Checked = IsRegistryLaunchAtLoginEnabled();
+ return;
+ }
+
+ var startupTask = await global::Windows.ApplicationModel.StartupTask.GetAsync(StartupTaskId);
+ launchAtLogin.Checked =
+ startupTask.State == global::Windows.ApplicationModel.StartupTaskState.Enabled;
+ }
+ catch
+ {
+ launchAtLogin.Checked = false;
+ launchAtLogin.Enabled = false;
+ launchAtLogin.Text = "Open at sign in is unavailable for this installation";
+ }
+ finally
+ {
+ launchAtLoginInitializing = false;
+ }
+ }
+
+ private async Task HandleLaunchAtLoginChangedAsync()
+ {
+ if (launchAtLoginInitializing) return;
+ if (!IsPackaged())
+ {
+ SetRegistryLaunchAtLogin(launchAtLogin.Checked);
+ return;
+ }
+
+ launchAtLoginInitializing = true;
+ try
+ {
+ var startupTask = await global::Windows.ApplicationModel.StartupTask.GetAsync(StartupTaskId);
+ if (!launchAtLogin.Checked)
+ {
+ startupTask.Disable();
+ return;
+ }
+
+ var state = await startupTask.RequestEnableAsync();
+ if (state == global::Windows.ApplicationModel.StartupTaskState.Enabled) return;
+
+ launchAtLogin.Checked = false;
+ var detail =
+ state == global::Windows.ApplicationModel.StartupTaskState.DisabledByUser
+ ? "Windows has disabled this startup task. Re-enable DevinX Connector in Settings > Apps > Startup."
+ : "Windows could not enable DevinX Connector at sign in on this PC.";
+ MessageBox.Show(
+ this,
+ detail,
+ "Open at sign in",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Information);
+ }
+ catch
+ {
+ launchAtLogin.Checked = false;
+ MessageBox.Show(
+ this,
+ "Windows could not update the startup setting. Reopen DevinX Connector and try again.",
+ "Open at sign in",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Warning);
+ }
+ finally
+ {
+ launchAtLoginInitializing = false;
+ }
+ }
+
+ private static bool IsPackaged()
+ {
+ try
+ {
+ return !string.IsNullOrWhiteSpace(
+ global::Windows.ApplicationModel.Package.Current.Id.Name);
+ }
+ catch (InvalidOperationException)
+ {
+ return false;
+ }
+ }
+
+ private static bool IsRegistryLaunchAtLoginEnabled()
{
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", writable: false);
return key?.GetValue(StartupValueName) is string;
}
- private static void SetLaunchAtLogin(bool enabled)
+ private static void SetRegistryLaunchAtLogin(bool enabled)
{
using var key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", writable: true);
if (enabled) key.SetValue(StartupValueName, $"\"{Application.ExecutablePath}\"");
diff --git a/connector/windows/packages.lock.json b/connector/windows/packages.lock.json
index 3ec9e0b..d076576 100644
--- a/connector/windows/packages.lock.json
+++ b/connector/windows/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 1,
"dependencies": {
- "net10.0-windows7.0": {
+ "net10.0-windows10.0.22000": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.10, )",
@@ -15,6 +15,6 @@
"contentHash": "RuvX3PEXU6pbY/I5ItAk800jm62r+YnoPLgyS2WTgwxkOnGkOfU9ORiipHUF0LkLyqM8rlroUCA319JjRYfRFQ=="
}
},
- "net10.0-windows7.0/win-x64": {}
+ "net10.0-windows10.0.22000/win-x64": {}
}
-}
\ No newline at end of file
+}
diff --git a/docs/connector-platform-roadmap.md b/docs/connector-platform-roadmap.md
index ace9f29..878f674 100644
--- a/docs/connector-platform-roadmap.md
+++ b/docs/connector-platform-roadmap.md
@@ -16,21 +16,22 @@ Platform code may implement only secure storage, executable discovery, lifecycle
## Windows x64 implementation checkpoint
The shared Windows adapter, current-user DPAPI helper, native WinForms control surface,
-notification-area lifecycle, pinned-runtime builder, per-user installer/uninstaller, Authenticode
-signing hook, and Windows CI verifier are implemented under `bridge/`, `connector/windows/`,
-`connector/windows-installer/`, and `scripts/connector/`. Ordinary CI remains explicitly unsigned
-and not for release. A protected manual workflow produces a signed verification candidate once a
-publisher-controlled Authenticode identity is configured. Windows becomes a supported download
-only after that candidate passes the physical matrix in `specs/037-windows-connector.md`.
+notification-area lifecycle, pinned-runtime builder, per-user installer/uninstaller, Microsoft
+Store MSIX builder, and Windows CI verifier are implemented under `bridge/`, `connector/windows/`,
+`connector/windows-installer/`, `connector/windows-msix/`, and `scripts/connector/`. Ordinary EXE
+and ZIP CI artifacts remain explicitly unsigned and not for release. The public path is the exact
+Partner Center identity `DevinXTools.DevinXConnector`; Microsoft signs and delivers the accepted
+MSIX. Windows becomes a supported download only after Store certification and that exact package
+passes the physical matrix in `specs/037-windows-connector.md`.
Remaining public-release gates:
1. Physically verify the exact ACP methods advertised by the installed official Windows Devin CLI.
Cognition now documents native Windows x64 and arm64 CLI installers plus `devin acp`; runtime
negotiation remains authoritative for the exact methods available on the test PC.
-2. Configure a stable Authenticode code-signing identity, run the protected signed-candidate
- workflow, and publish its checksum and provenance only after the physical matrix passes. Do not
- distribute the unsigned CI artifact.
+2. Upload the exact-identity MSIX to Partner Center, pass certification, and publish only through
+ Store ID `9N52Z3FVMFH8` after the physical matrix passes. Do not distribute the unsigned CI EXE,
+ ZIP, or pre-certification MSIX directly.
3. Validate Windows Firewall behavior while binding only to the active `100.64.0.0/10` Tailscale
interface.
4. Test pairing, denial, expiry, read/send/create permission separation, endpoint refresh,
diff --git a/docs/devinx-connector-setup-prompt.md b/docs/devinx-connector-setup-prompt.md
index 309b199..29f7401 100644
--- a/docs/devinx-connector-setup-prompt.md
+++ b/docs/devinx-connector-setup-prompt.md
@@ -1,6 +1,6 @@
# AI-assisted DevinX Connector setup prompt
-This is the primary assisted installation guide presented by DevinX after a user chooses **Local** or **Cloud + Local**. The official release page is . The prompt must stop safely unless that page contains a signed Connector package for the detected operating system and an adjacent SHA-256 file.
+This is the primary assisted installation guide presented by DevinX after a user chooses **Local** or **Cloud + Local**. macOS uses the notarized release at . Windows 11 x64 uses the reserved Microsoft Store listing at . The prompt must stop safely unless the platform's official distribution and trust checks are available.
Cloud-only users do not need Connector. For Local access, Tailscale provides only the private network route; Connector is the required trusted local service that communicates with a supported local Devin ACP capability and authenticates each iPhone. A Tailscale IP or password is not a replacement for a compatible service running on the local device.
@@ -8,15 +8,19 @@ Cloud-only users do not need Connector. For Local access, Tailscale provides onl
>
> Before downloading anything, explain that Tailscale supplies only the private network route. DevinX Connector is the trusted local service that communicates with Devin for Terminal, authenticates this iPhone, and enforces its permissions. A Tailscale IP, server URL, or password cannot replace a compatible service running on this computer. Cloud-only DevinX use does not require Connector.
>
-> Detect whether this computer is macOS or Windows. Open the official DevinX release page at https://github.com/fenner888/Devinx/releases/latest. Download DevinX Connector only when that official release provides a signed package for this operating system and architecture plus an adjacent SHA-256 checksum file. If no signed release is available for this platform, stop and tell me that DevinX Connector has not been published for it yet. Do not clone or build the source, install a guessed package, use an unsigned CI artifact, use an unofficial repository or mirror, or substitute a similarly named application.
+> Detect whether this computer is macOS or Windows.
>
-> Verify the downloaded package against the published SHA-256 value. On macOS, require a Developer ID Application signature, Apple notarization, and Gatekeeper acceptance. On Windows, require a valid DevinX Authenticode signature and a supported x64 Windows release. Stop if any verification is missing or fails.
+> On macOS, open https://github.com/fenner888/Devinx/releases/latest. Download Connector only when that page provides the signed Apple-silicon DMG plus its adjacent SHA-256 checksum. Verify the checksum, require a Developer ID Application signature, Apple notarization, and Gatekeeper acceptance.
+>
+> On Windows 11 x64, open https://apps.microsoft.com/detail/9N52Z3FVMFH8. Install only the Microsoft Store package named DevinX Connector, published by DevinX Tools, with Store ID 9N52Z3FVMFH8. After installation, confirm that Get-AppxPackage reports identity DevinXTools.DevinXConnector, publisher CN=43D84E24-857C-4C40-9DAA-1A6983913CD9, and package family DevinXTools.DevinXConnector_ydtgrt4yd5wrc. Do not download, sideload, or execute an unsigned CI MSIX, EXE, or ZIP.
+>
+> If the required official distribution is unavailable, or any applicable identity, signature, checksum, notarization, or Gatekeeper check fails, stop and tell me that DevinX Connector cannot be safely installed. Do not clone or build the source, install a guessed package, use an unofficial repository or mirror, or substitute a similarly named application.
>
> Confirm that an official local Devin installation exposes the ACP capability required by Connector. You may locate its executable, but do not read, copy, print, log, or modify its credentials. If the required ACP capability is unavailable on this operating system, stop instead of claiming Local sessions will work.
>
> Confirm that Tailscale is installed and connected on this computer. If authentication is required, open the official interactive login and let me complete it. Never request, generate, print, or persist a reusable Tailscale authentication key.
>
-> Install DevinX Connector for the signed-in user and open it. On macOS, install it in /Applications. On Windows, use the signed per-user package and do not create an administrator service. Do not run it as root or Administrator, bind it to `0.0.0.0`, expose a public listener, install a public tunnel, or weaken its QR pairing and per-device authorization. Do not enable launch at login without showing me the Connector's visible setting and receiving my approval.
+> Install DevinX Connector for the signed-in user and open it. On macOS, install it in /Applications. On Windows, use only the Microsoft Store package and do not create an administrator service. Do not run it as root or Administrator, bind it to `0.0.0.0`, expose a public listener, install a public tunnel, or weaken its QR pairing and per-device authorization. Do not enable launch at login without showing me the Connector's visible setting and receiving my approval.
>
> Verify that the connector reports a private Tailscale connection and detects a supported local Devin ACP capability. Then tell me to open DevinX on my iPhone and choose **Settings → Local devices → Add local device → Scan pairing code**.
>
diff --git a/docs/devinx-connector.md b/docs/devinx-connector.md
index 3a82938..4acb7cc 100644
--- a/docs/devinx-connector.md
+++ b/docs/devinx-connector.md
@@ -15,7 +15,14 @@ The separate Connector application is the current supported way to install and o
## User experience
-1. Download the supported signed connector from the official DevinX release page. Connector 0.1.4 currently supports Apple-silicon Macs. Windows 11 x64 is an active release implementation; its public download activates only after the signed installer and physical test matrix pass. Linux and Intel Mac packages remain unavailable.
+1. Choose the trusted package for the computer:
+ - Apple-silicon macOS: download the signed DMG and checksum from the
+ [official DevinX release page](https://github.com/fenner888/Devinx/releases/latest).
+ - Windows 11 x64: install only
+ [DevinX Connector from Microsoft Store](https://apps.microsoft.com/detail/9N52Z3FVMFH8).
+ The package must be published by **DevinX Tools** with Store ID
+ `9N52Z3FVMFH8`.
+ Linux and Intel Mac packages remain unavailable.
2. Install and open **DevinX Connector**.
3. Connect the computer and iPhone to the same Tailscale network, then confirm that the connector shows Tailscale and Devin for Terminal.
4. In the iPhone app, open **Settings → Local devices → Add local device → Scan pairing code**.
@@ -102,12 +109,13 @@ The app bundle and DMG root both include `LICENSE.txt`, byte-for-byte matching t
## Windows 11 x64 active release track
-On a Windows 11 x64 development machine with Node 24 and .NET 10 installed:
+On a Windows 11 x64 development machine with Node 24, .NET 10, and the Windows 11 SDK installed:
```powershell
npm ci --legacy-peer-deps
-npm run connector:build:windows
+npm run connector:build:windows:store
npm run connector:verify:windows
+npm run connector:verify:windows:store
```
The build compiles a native per-user Windows control surface, a current-user DPAPI helper, and a
@@ -120,21 +128,27 @@ The signed native helper also creates the Connector's bounded self-signed TLS id
with .NET cryptography. Windows does not need OpenSSL, and the resulting identity is retained only
inside the current user's DPAPI-protected Connector state.
-Ordinary CI uploads only an explicitly named **UNSIGNED-NOT-FOR-RELEASE** artifact. The manual
-**Windows Connector Signed Candidate** workflow fails closed unless the protected
-`windows-connector-release` environment supplies:
+Ordinary CI uploads two deliberately separate artifacts:
-- `WINDOWS_SIGNING_PFX_BASE64` and `WINDOWS_SIGNING_PFX_PASSWORD` secrets for the publisher's
- Authenticode identity; and
-- a `WINDOWS_TIMESTAMP_URL` variable for an RFC 3161 timestamp service.
+- an EXE/ZIP verification artifact explicitly named **UNSIGNED-NOT-FOR-RELEASE**; and
+- an unsigned MSIX explicitly named **MICROSOFT-STORE-UPLOAD** whose manifest uses the exact
+ Partner Center identity.
-Repository administrators must restrict that environment to the protected `main` branch, require a
-human reviewer, and prevent self-review where the GitHub plan supports it. The signing identity must
-not be exposed to pull-request workflows or ordinary branch builds.
+The MSIX is uploaded only to Partner Center. Microsoft signs the accepted Store package; the
+unsigned upload MSIX must never be sideloaded or offered as a direct download. The identity is:
-That workflow signs and verifies every DevinX-owned EXE, verifies the signed installer lifecycle,
-and uploads a candidate for physical testing. It does not publish a GitHub release. Public
-distribution still requires clean-account install/update/uninstall, SmartScreen/signature
+- package identity: `DevinXTools.DevinXConnector`
+- publisher: `CN=43D84E24-857C-4C40-9DAA-1A6983913CD9`
+- publisher display name: `DevinX Tools`
+- Store ID: `9N52Z3FVMFH8`
+- package family: `DevinXTools.DevinXConnector_ydtgrt4yd5wrc`
+
+The Store package declares an opt-in Windows startup task. Connector uses the packaged
+`Windows.ApplicationModel.StartupTask` API and respects a task disabled by the user in Windows
+Settings or Task Manager. A separately distributed direct-download installer remains a distinct
+future gate and would require Authenticode signing for every owned executable and installer.
+
+Public distribution still requires clean-account install/update/uninstall, Store signature
inspection, Windows Firewall validation, official Devin ACP validation, and the complete physical
matrix in `specs/037-windows-connector.md`.
@@ -149,7 +163,8 @@ matrix in `specs/037-windows-connector.md`.
- The Devin CLI is discovered from an allowlisted application PATH and launched only through the fixed ACP subcommand.
- Bridge identity, TLS material, and paired-device records stay in macOS Keychain or Windows current-user DPAPI storage.
- The QR payload crosses only the inherited connector process pipe and the native in-memory renderer.
-- Launch at login is an explicit user toggle and uses the per-user macOS login-item API.
+- Launch at login is an explicit user toggle. macOS uses the per-user login-item API; the Windows
+ Store package uses its manifest-declared startup task and Windows' packaged startup API.
## Release gates
diff --git a/docs/physical-release-checklist.md b/docs/physical-release-checklist.md
index 6314cf6..25c3873 100644
--- a/docs/physical-release-checklist.md
+++ b/docs/physical-release-checklist.md
@@ -48,7 +48,7 @@ installed Build 67 for every remaining check below.
button can scroll above the keyboard, the typed name remains visible, dragging and Done dismiss the
keyboard, and neither path clears the name.
- Starting from the Computer or Cloud + Computer onboarding choice, confirm **Send assisted setup
- prompt** opens the iOS share sheet with the guarded prompt, **Open official releases** resolves only
+ prompt** opens the iOS share sheet with the guarded prompt, **Mac release** resolves only
to `github.com/fenner888/Devinx/releases/latest`, and **Already installed? Continue below** reaches
pairing without claiming that the Connector was installed automatically.
- With the Mac available, confirm **Disconnect** completes signed Mac-side revocation before local
diff --git a/docs/release-readiness.md b/docs/release-readiness.md
index 7a8f6fb..b9c9061 100644
--- a/docs/release-readiness.md
+++ b/docs/release-readiness.md
@@ -281,11 +281,11 @@ official release link.
## Platform scope
macOS is the first Connector release. Windows 11 x64 is an active implementation using the same
-protocol and authorization contract, with native DPAPI storage, process supervision, per-user
-packaging, signing hooks, Tailscale discovery, and update guidance now implemented. Authenticode
-configuration and the physical Windows matrix remain release gates. Linux remains a later
-platform. Neither platform is a supported download until its own threat model and physical tests
-pass.
+protocol and authorization contract, with native DPAPI storage, process supervision, exact-identity
+Microsoft Store packaging, an opt-in packaged startup task, Tailscale discovery, and update
+guidance. The Microsoft Store listing is public under **DevinX Tools** with Store ID
+`9N52Z3FVMFH8`; Store certification and signing cover the published MSIX. Authenticode applies only
+to any separately released direct-download package. Linux remains a later platform.
## Connector 0.1.4 release evidence
diff --git a/package.json b/package.json
index 414b7e7..065deab 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,8 @@
"connector:open:macos": "npm run connector:build:macos && open 'artifacts/connector/DevinX Connector.app'",
"connector:build:windows": "node scripts/connector/build-windows.mjs",
"connector:verify:windows": "node scripts/connector/verify-windows-artifact.mjs",
+ "connector:build:windows:store": "npm run connector:build:windows && node scripts/connector/build-windows-msix.mjs",
+ "connector:verify:windows:store": "node scripts/connector/verify-windows-msix.mjs",
"build": "echo 'EAS build is invoked via eas build; CI validates both app and bridge TypeScript' && tsc --noEmit && npm run bridge:build",
"audit": "node scripts/security/npm-audit-gate.mjs",
"ci": "npm run lint && npm run typecheck && npm run test && npm run build && npm run audit"
diff --git a/scripts/connector/build-windows-msix.mjs b/scripts/connector/build-windows-msix.mjs
new file mode 100644
index 0000000..8fa71f3
--- /dev/null
+++ b/scripts/connector/build-windows-msix.mjs
@@ -0,0 +1,86 @@
+import { createHash } from 'node:crypto';
+import {
+ copyFileSync,
+ cpSync,
+ existsSync,
+ mkdirSync,
+ readFileSync,
+ renameSync,
+ rmSync,
+ writeFileSync,
+} from 'node:fs';
+import { basename, resolve } from 'node:path';
+import { spawnSync } from 'node:child_process';
+
+import {
+ findMakeAppx,
+ loadStoreIdentity,
+ renderStoreManifest,
+ repositoryRoot,
+ storeArtifactName,
+ storePackagingRoot,
+} from './windows-store-identity.mjs';
+
+function run(executable, args) {
+ const result = spawnSync(executable, args, {
+ cwd: repositoryRoot,
+ encoding: 'utf8',
+ shell: false,
+ });
+ if (result.error || result.status !== 0) {
+ const detail = `${result.stderr ?? ''}${result.stdout ?? ''}`.trim();
+ throw new Error(`${basename(executable)} failed${detail ? `: ${detail}` : ''}`);
+ }
+ return `${result.stdout ?? ''}${result.stderr ?? ''}`;
+}
+
+function sha256(path) {
+ return createHash('sha256').update(readFileSync(path)).digest('hex');
+}
+
+if (process.platform !== 'win32') {
+ throw new Error('The Microsoft Store MSIX can only be built on Windows');
+}
+
+const identity = loadStoreIdentity();
+const outputRoot = resolve(repositoryRoot, 'artifacts', 'connector', 'windows');
+const unpackagedRoot = resolve(
+ outputRoot,
+ `DevinX-Connector-0.1.0-windows-${identity.architecture}`,
+);
+if (!existsSync(resolve(unpackagedRoot, 'DevinX Connector.exe'))) {
+ throw new Error('Build the Windows Connector payload before creating the Store MSIX');
+}
+
+const stagingRoot = resolve(outputRoot, 'store-msix-staging');
+const msixPath = resolve(outputRoot, storeArtifactName(identity));
+rmSync(stagingRoot, { recursive: true, force: true });
+rmSync(msixPath, { force: true });
+rmSync(`${msixPath}.sha256`, { force: true });
+mkdirSync(stagingRoot, { recursive: true });
+cpSync(unpackagedRoot, stagingRoot, { recursive: true });
+renameSync(
+ resolve(stagingRoot, 'DevinX Connector.exe'),
+ resolve(stagingRoot, 'DevinXConnector.exe'),
+);
+mkdirSync(resolve(stagingRoot, 'Assets'), { recursive: true });
+for (const asset of ['Square44x44Logo.png', 'Square150x150Logo.png', 'StoreLogo.png']) {
+ copyFileSync(resolve(storePackagingRoot, 'Assets', asset), resolve(stagingRoot, 'Assets', asset));
+}
+writeFileSync(resolve(stagingRoot, 'AppxManifest.xml'), renderStoreManifest(identity), 'utf8');
+
+const makeAppx = findMakeAppx();
+run(makeAppx, ['pack', '/d', stagingRoot, '/p', msixPath, '/o']);
+if (!existsSync(msixPath)) throw new Error('MakeAppx did not produce the Store MSIX');
+
+const digest = sha256(msixPath);
+writeFileSync(`${msixPath}.sha256`, `${digest} ${basename(msixPath)}\n`, {
+ encoding: 'utf8',
+ mode: 0o644,
+});
+process.stdout.write(
+ `Built Microsoft Store upload package ${msixPath}\n` +
+ `Store ID ${identity.storeId}\n` +
+ `MSIX SHA-256 ${digest}\n` +
+ 'The package is unsigned for Partner Center upload; Microsoft Store signs it after acceptance.\n',
+);
diff --git a/scripts/connector/verify-windows-msix.mjs b/scripts/connector/verify-windows-msix.mjs
new file mode 100644
index 0000000..18b960c
--- /dev/null
+++ b/scripts/connector/verify-windows-msix.mjs
@@ -0,0 +1,134 @@
+import { createHash } from 'node:crypto';
+import {
+ existsSync,
+ mkdtempSync,
+ readFileSync,
+ rmSync,
+} from 'node:fs';
+import { tmpdir } from 'node:os';
+import { basename, resolve } from 'node:path';
+import { spawnSync } from 'node:child_process';
+
+import {
+ findMakeAppx,
+ loadStoreIdentity,
+ renderStoreManifest,
+ repositoryRoot,
+ storeArtifactName,
+ storePackagingRoot,
+} from './windows-store-identity.mjs';
+
+function requireText(value, expected, label) {
+ if (!value.includes(expected)) throw new Error(`Store manifest is missing ${label}`);
+}
+
+function pngDimensions(path) {
+ const contents = readFileSync(path);
+ const signature = contents.subarray(0, 8).toString('hex');
+ if (signature !== '89504e470d0a1a0a' || contents.subarray(12, 16).toString('ascii') !== 'IHDR') {
+ throw new Error(`${basename(path)} is not a valid PNG`);
+ }
+ return {
+ width: contents.readUInt32BE(16),
+ height: contents.readUInt32BE(20),
+ };
+}
+
+function sha256(path) {
+ return createHash('sha256').update(readFileSync(path)).digest('hex');
+}
+
+function run(executable, args) {
+ const result = spawnSync(executable, args, {
+ cwd: repositoryRoot,
+ encoding: 'utf8',
+ shell: false,
+ });
+ if (result.error || result.status !== 0) {
+ const detail = `${result.stderr ?? ''}${result.stdout ?? ''}`.trim();
+ throw new Error(`${basename(executable)} failed${detail ? `: ${detail}` : ''}`);
+ }
+}
+
+const identity = loadStoreIdentity();
+const manifest = renderStoreManifest(identity);
+for (const [expected, label] of [
+ [`Name="${identity.identityName}"`, 'Partner Center identity name'],
+ [`Publisher="${identity.publisher}"`, 'Partner Center publisher'],
+ [`Version="${identity.version}"`, 'four-part package version'],
+ [`ProcessorArchitecture="${identity.architecture}"`, 'x64 architecture'],
+ [`${identity.publisherDisplayName}`, 'publisher name'],
+ [``, 'default package language'],
+ ['Name="Windows.Desktop"', 'Windows Desktop target'],
+ ['Executable="DevinXConnector.exe"', 'normalized packaged executable'],
+ [`MinVersion="${identity.minimumWindowsVersion}"`, 'Windows 11 minimum'],
+ ['', 'runFullTrust capability'],
+ ['Category="windows.startupTask"', 'packaged startup task'],
+ ['TaskId="DevinXConnectorStartup"', 'startup task identifier'],
+ ['Enabled="false"', 'opt-in startup behavior'],
+]) {
+ requireText(manifest, expected, label);
+}
+if (manifest.includes('internetClient') || manifest.includes('broadFileSystemAccess')) {
+ throw new Error('Store manifest requests an unsupported broad capability');
+}
+
+for (const [name, width, height] of [
+ ['Square44x44Logo.png', 44, 44],
+ ['Square150x150Logo.png', 150, 150],
+ ['StoreLogo.png', 50, 50],
+]) {
+ const actual = pngDimensions(resolve(storePackagingRoot, 'Assets', name));
+ if (actual.width !== width || actual.height !== height) {
+ throw new Error(`${name} must be ${width}x${height}`);
+ }
+}
+
+const outputRoot = resolve(repositoryRoot, 'artifacts', 'connector', 'windows');
+const msixPath = resolve(outputRoot, storeArtifactName(identity));
+const checksumPath = `${msixPath}.sha256`;
+if (process.env.DEVINX_REQUIRE_MSIX_ARTIFACT === '1' || existsSync(msixPath)) {
+ if (process.platform !== 'win32') {
+ throw new Error('A generated MSIX must be verified on Windows');
+ }
+ if (!existsSync(msixPath) || !existsSync(checksumPath)) {
+ throw new Error('Store MSIX or checksum is missing');
+ }
+ const expectedDigest = readFileSync(checksumPath, 'utf8').trim().split(/\s+/)[0];
+ if (expectedDigest !== sha256(msixPath)) throw new Error('Store MSIX checksum mismatch');
+
+ const makeAppx = findMakeAppx();
+ const unpackRoot = mkdtempSync(resolve(tmpdir(), 'devinx-store-msix-'));
+ try {
+ run(makeAppx, ['unpack', '/p', msixPath, '/d', unpackRoot, '/o']);
+ const packagedManifest = readFileSync(resolve(unpackRoot, 'AppxManifest.xml'), 'utf8');
+ if (packagedManifest !== manifest) throw new Error('Packaged manifest differs from source');
+ for (const required of [
+ 'DevinXConnector.exe',
+ 'LICENSE.txt',
+ 'Resources/connector-runtime.cjs',
+ 'Resources/runtime/node.exe',
+ 'Resources/windows-dpapi-helper.exe',
+ 'Assets/StoreLogo.png',
+ 'Assets/Square44x44Logo.png',
+ 'Assets/Square150x150Logo.png',
+ ]) {
+ if (!existsSync(resolve(unpackRoot, required))) {
+ throw new Error(`Store MSIX is missing ${required}`);
+ }
+ }
+ if (existsSync(resolve(unpackRoot, 'DevinX Connector.exe'))) {
+ throw new Error('Store MSIX contains the ambiguous spaced executable name');
+ }
+ } finally {
+ rmSync(unpackRoot, { recursive: true, force: true });
+ }
+}
+
+process.stdout.write(
+ `Verified Microsoft Store identity ${identity.identityName}\n` +
+ `Verified Store ID ${identity.storeId}\n` +
+ `Verified package family ${identity.packageFamilyName}\n`,
+);
diff --git a/scripts/connector/windows-store-identity.mjs b/scripts/connector/windows-store-identity.mjs
new file mode 100644
index 0000000..e309a15
--- /dev/null
+++ b/scripts/connector/windows-store-identity.mjs
@@ -0,0 +1,105 @@
+import { existsSync, readFileSync, readdirSync } from 'node:fs';
+import { dirname, resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { spawnSync } from 'node:child_process';
+
+const scriptDirectory = dirname(fileURLToPath(import.meta.url));
+export const repositoryRoot = resolve(scriptDirectory, '..', '..');
+export const storePackagingRoot = resolve(repositoryRoot, 'connector', 'windows-msix');
+export const storeIdentityPath = resolve(storePackagingRoot, 'store-identity.json');
+export const storeManifestTemplatePath = resolve(
+ storePackagingRoot,
+ 'AppxManifest.xml.template',
+);
+
+const expectedIdentity = Object.freeze({
+ storeId: '9N52Z3FVMFH8',
+ identityName: 'DevinXTools.DevinXConnector',
+ publisher: 'CN=43D84E24-857C-4C40-9DAA-1A6983913CD9',
+ publisherDisplayName: 'DevinX Tools',
+ packageFamilyName: 'DevinXTools.DevinXConnector_ydtgrt4yd5wrc',
+ msaAppId: '7d1237e7-6265-48ab-adf5-2a12f5d81101',
+ version: '0.1.1.0',
+ architecture: 'x64',
+ defaultLanguage: 'en-US',
+ minimumWindowsVersion: '10.0.22000.0',
+ maximumWindowsVersionTested: '10.0.26100.0',
+});
+
+export function loadStoreIdentity() {
+ const value = JSON.parse(readFileSync(storeIdentityPath, 'utf8'));
+ for (const [key, expected] of Object.entries(expectedIdentity)) {
+ if (value[key] !== expected) {
+ throw new Error(`Microsoft Store identity mismatch for ${key}`);
+ }
+ }
+ if (Object.keys(value).length !== Object.keys(expectedIdentity).length) {
+ throw new Error('Microsoft Store identity contains an unsupported field');
+ }
+ return Object.freeze(value);
+}
+
+function xmlEscape(value) {
+ return value
+ .replaceAll('&', '&')
+ .replaceAll('"', '"')
+ .replaceAll('<', '<')
+ .replaceAll('>', '>');
+}
+
+export function renderStoreManifest(identity = loadStoreIdentity()) {
+ const replacements = {
+ IDENTITY_NAME: identity.identityName,
+ PUBLISHER: identity.publisher,
+ VERSION: identity.version,
+ ARCHITECTURE: identity.architecture,
+ PUBLISHER_DISPLAY_NAME: identity.publisherDisplayName,
+ DEFAULT_LANGUAGE: identity.defaultLanguage,
+ MINIMUM_WINDOWS_VERSION: identity.minimumWindowsVersion,
+ MAXIMUM_WINDOWS_VERSION_TESTED: identity.maximumWindowsVersionTested,
+ };
+ let manifest = readFileSync(storeManifestTemplatePath, 'utf8');
+ for (const [token, value] of Object.entries(replacements)) {
+ manifest = manifest.replaceAll(`{{${token}}}`, xmlEscape(value));
+ }
+ if (manifest.includes('{{')) {
+ throw new Error('Microsoft Store manifest contains an unresolved template token');
+ }
+ return manifest;
+}
+
+export function storeArtifactName(identity = loadStoreIdentity()) {
+ return `DevinX-Connector-${identity.version}-windows-${identity.architecture}.msix`;
+}
+
+export function findMakeAppx() {
+ const explicit = process.env.DEVINX_MAKEAPPX_PATH;
+ if (explicit && existsSync(explicit)) return explicit;
+
+ const located = spawnSync('where.exe', ['MakeAppx.exe'], {
+ encoding: 'utf8',
+ shell: false,
+ });
+ if (located.status === 0) {
+ const first = located.stdout
+ .split(/\r?\n/)
+ .map((value) => value.trim())
+ .find(Boolean);
+ if (first && existsSync(first)) return first;
+ }
+
+ const programFilesX86 = process.env['ProgramFiles(x86)'];
+ if (programFilesX86) {
+ const kitsBin = resolve(programFilesX86, 'Windows Kits', '10', 'bin');
+ if (existsSync(kitsBin)) {
+ const versions = readdirSync(kitsBin)
+ .filter((entry) => /^\d+\.\d+\.\d+\.\d+$/.test(entry))
+ .sort((left, right) => right.localeCompare(left, undefined, { numeric: true }));
+ for (const version of versions) {
+ const candidate = resolve(kitsBin, version, 'x64', 'MakeAppx.exe');
+ if (existsSync(candidate)) return candidate;
+ }
+ }
+ }
+ throw new Error('MakeAppx.exe was not found. Install the Windows 11 SDK.');
+}
diff --git a/specs/021-devinx-connector.md b/specs/021-devinx-connector.md
index ace93fa..0ef6707 100644
--- a/specs/021-devinx-connector.md
+++ b/specs/021-devinx-connector.md
@@ -1,6 +1,6 @@
# 021 — DevinX Connector distribution and cross-platform boundary
-Status: macOS Connector 0.1.4 is the supported public release with reliable direct CLI model-catalog refresh. Windows implementation is tracked by spec 037 and remains unavailable to end users until its existing Microsoft Store submission passes certification and the physical test matrix. Linux and Intel Mac packages remain roadmap targets.
+Status: macOS Connector 0.1.4 is the supported public release with reliable direct CLI model-catalog refresh. Windows 11 x64 is publicly distributed through Microsoft Store under Store ID `9N52Z3FVMFH8`; its implementation and release gates are tracked by spec 037. Linux and Intel Mac packages remain roadmap targets.
## Product decision
@@ -21,8 +21,16 @@ DevinX Connector is not an official Cognition component. It uses the supported D
Before presenting a Connector download or assisted-install action, DevinX and its public documentation must explain that cloud-only use needs no Connector, while computer access needs both Tailscale for private transport and Connector for authorized local Devin session access. The explanation must not imply that Tailscale alone exposes a computer service or that an IP address/password is sufficient without a compatible service listening on the computer.
1. After choosing **Local** or **Cloud + Local**, the user receives an assisted setup prompt as the primary path. The iPhone share sheet lets them send or copy it to an AI assistant running on the local device. **Official releases** and **Already installed** remain visible alternatives.
-2. The assisted prompt references only the official DevinX GitHub Releases page. It tells the computer-side assistant to stop when no signed, notarized release and adjacent checksum are available; it never substitutes a source checkout, guessed package, unsigned artifact, or third-party mirror.
-3. The user downloads and explicitly approves the signed connector for the computer's operating system. iPhone never claims it can silently install or remotely launch an unpaired computer application.
+2. The assisted prompt uses only the official platform distribution: the DevinX GitHub Releases
+ page for the notarized macOS DMG and adjacent checksum, or Microsoft Store ID
+ `9N52Z3FVMFH8` for Windows 11 x64. It tells the computer-side assistant to stop when the
+ platform distribution or required trust checks are unavailable; it never substitutes a source
+ checkout, guessed package, unsigned artifact, or third-party mirror.
+3. The user downloads and explicitly approves the trusted connector for the computer's operating
+ system. The Windows Store package must report identity `DevinXTools.DevinXConnector`,
+ publisher `CN=43D84E24-857C-4C40-9DAA-1A6983913CD9`, and package family
+ `DevinXTools.DevinXConnector_ydtgrt4yd5wrc`. iPhone never claims it can silently install or
+ remotely launch an unpaired computer application.
4. The connector detects Devin for Terminal and an active Tailscale IPv4 address without reading Devin credentials.
5. Tailscale is the only v1 connection path. The connector fails closed when no active `100.64.0.0/10` address exists and never falls back to LAN.
6. On macOS, the bridge binds only to the selected active `100.64.0.0/10` tailnet interface. The connector never binds to a LAN, wildcard, or public interface and reports a bounded health status.
@@ -101,7 +109,8 @@ When a QR identifies a computer already paired on the iPhone, DevinX may update
- Same shared bridge protocol and mobile pairing contract.
- Credential Manager/DPAPI-backed secrets.
-- Signed per-user application and appropriate background lifecycle.
+- Microsoft Store-signed per-user application with exact Partner Center identity and appropriate
+ background lifecycle.
- Tailscale and Devin CLI discovery validated on supported Windows versions.
### Linux — required follow-up
diff --git a/specs/037-windows-connector.md b/specs/037-windows-connector.md
index c821272..26a2125 100644
--- a/specs/037-windows-connector.md
+++ b/specs/037-windows-connector.md
@@ -44,8 +44,10 @@ The Windows adapter owns only:
- current-user DPAPI protection and the user-owned encrypted state file;
- Windows `Path` executable discovery;
- a native per-user control window and notification-area lifecycle;
-- explicit launch-at-sign-in registration;
-- packaging, Authenticode signing, update awareness, diagnostics, and uninstall; and
+- explicit launch-at-sign-in registration through the packaged Windows startup-task API, with a
+ current-user registry fallback only for separately gated unpackaged development builds;
+- Store packaging, update awareness, diagnostics, and uninstall, plus Authenticode signing only
+ for any separately released direct-download package; and
- Windows Firewall guidance for the exact active Tailscale interface.
The Windows shell launches the bundled, checksum-verified Node runtime as a child with redirected standard input/output. The existing bounded newline-delimited IPC protocol is the only native-to-runtime channel. QR payloads stay in memory and are rendered only in the native window.
@@ -66,7 +68,10 @@ Connector state is encrypted with Windows DPAPI using `CRYPTPROTECT_UI_FORBIDDEN
- Normal operation is per-user and requires no administrator privilege or Windows service.
- Closing the control window keeps Connector available through a visible notification-area icon.
- **Quit DevinX Connector** explicitly stops the child runtime and listener.
-- Launch at sign-in is opt-in and visible. It may use an allowlisted current-user startup registration; it may not create a system service or machine-wide task.
+- Launch at sign-in is opt-in and visible. The Store package uses the manifest-declared
+ `DevinXConnectorStartup` task and `Windows.ApplicationModel.StartupTask`; unpackaged development
+ builds may use an allowlisted current-user startup registration. Neither path may create a
+ system service or machine-wide task, and Connector must respect a user-disabled startup task.
- The window presents connection health, short-lived QR, pending phone approval, separate read/send/create grants, paired-device revocation, code regeneration, update awareness, and reset/uninstall guidance.
- Paired devices are ordered with the most recently paired device first.
@@ -74,22 +79,42 @@ Connector state is encrypted with Windows DPAPI using `CRYPTPROTECT_UI_FORBIDDEN
The first supported package is Windows 11 x64. Windows 10 and Windows arm64 remain unsupported until separately tested and named in the compatibility matrix. The app and helper are self-contained. A public artifact requires:
-- an Authenticode code-signing certificate controlled by the DevinX publisher;
-- signature verification on every owned executable and installer;
+- a Microsoft Store MSIX whose package identity exactly matches the Partner Center reservation;
+- Microsoft Store signing and delivery for the public Store package;
- a published adjacent SHA-256 checksum and provenance record;
- the MIT license in both the installed application and distribution artifact;
-- explicit user-approved update/replacement with no silent installer; and
-- deterministic per-user uninstall that stops Connector and deletes only DevinX Connector state.
-
-Unsigned CI artifacts are verification artifacts only. The mobile assisted setup prompt must ignore them and must stop when no signed Windows release exists. Product copy must describe Windows as an active release target without offering an unsigned artifact or promising that an unavailable package works.
+- Store-managed updates and deterministic per-user uninstall that deletes only DevinX Connector
+ state; and
+- a separately gated direct-download installer only when every owned executable and installer has
+ a verified Authenticode signature controlled by the DevinX publisher.
+
+The Store identity is public packaging metadata, not a secret:
+
+- identity name: `DevinXTools.DevinXConnector`
+- publisher: `CN=43D84E24-857C-4C40-9DAA-1A6983913CD9`
+- publisher display name: `DevinX Tools`
+- Store ID: `9N52Z3FVMFH8`
+- package family: `DevinXTools.DevinXConnector_ydtgrt4yd5wrc`
+- default package language: `en-US`
+
+The committed Store identity file is the source of truth for manifest rendering. CI must reject any
+manifest or artifact whose name, publisher, architecture, version, language, logo assets, normalized
+packaged executable name (`DevinXConnector.exe`), or startup-task declaration drifts from it. The
+MSIX submitted to Partner Center is intentionally unsigned before upload;
+Microsoft signs the accepted Store package. It must never be offered as a direct-download build.
+
+Unsigned EXE/ZIP CI artifacts remain verification artifacts only. The mobile assisted setup prompt
+must ignore them and must stop when no Store-signed or Authenticode-signed Windows release exists.
+Product copy must describe Windows as an active release target without offering an unsigned artifact
+or promising that an unavailable package works.
## Acceptance gates
Automated:
- strict TypeScript and Windows native builds on a pinned Windows CI image;
-- fail-closed Authenticode signing and verification for the application, DPAPI helper, and
- per-user installer;
+- fail-closed Authenticode signing and verification for any separately released direct-download
+ application, DPAPI helper, and per-user installer; ordinary CI artifacts remain non-release;
- DPAPI set/get/delete, not-found, size-limit, malformed-input, and wrong-user failure tests;
- in-memory .NET TLS identity generation, cryptographic key/certificate matching, bounded helper
output, and encrypted persistence without an OpenSSL installation;
@@ -97,6 +122,8 @@ Automated:
- shared pairing, authorization, rate-limit, replay, grant, revoke, endpoint-refresh, and generic-404 suites;
- package contents, installer registration/uninstall lifecycle, MIT license, pinned runtime
checksum, secret scan, dependency audit, and artifact checksum verification; and
+- exact Partner Center identity rendering, MSIX schema validation, Store asset dimensions,
+ `runFullTrust`, Windows 11 targeting, and an opt-in packaged startup task; and
- mobile copy tests proving **Local** does not change persisted `computer` identifiers.
Physical Windows 11 x64:
diff --git a/src/app/(onboarding)/computer.tsx b/src/app/(onboarding)/computer.tsx
index 96538aa..736697f 100644
--- a/src/app/(onboarding)/computer.tsx
+++ b/src/app/(onboarding)/computer.tsx
@@ -33,7 +33,11 @@ import {
requestQrScannerPermission,
} from '@auth/deviceSigning';
import { DevinXQrScanner } from '@components/connections/DevinXQrScanner';
-import { CONNECTOR_RELEASE_PAGE, CONNECTOR_SETUP_PROMPT } from '@lib/connectorSetup';
+import {
+ CONNECTOR_RELEASE_PAGE,
+ CONNECTOR_SETUP_PROMPT,
+ WINDOWS_CONNECTOR_STORE_PAGE,
+} from '@lib/connectorSetup';
import {
isConnectorUpdateRequired,
MINIMUM_SUPPORTED_CONNECTOR_VERSION,
@@ -426,16 +430,28 @@ export default function ComputerConnectionScreen() {
- Linking.openURL(CONNECTOR_RELEASE_PAGE).catch(() => {})}
- accessibilityRole="link"
- accessibilityLabel="Open official DevinX Connector releases"
- >
-
- Open official releases
-
-
+
+ Linking.openURL(CONNECTOR_RELEASE_PAGE).catch(() => {})}
+ accessibilityRole="link"
+ accessibilityLabel="Open official DevinX Connector release for Mac"
+ >
+
+ Mac release
+
+
+ Linking.openURL(WINDOWS_CONNECTOR_STORE_PAGE).catch(() => {})}
+ accessibilityRole="link"
+ accessibilityLabel="Open DevinX Connector in Microsoft Store"
+ >
+
+ Windows Store
+
+
+
Already installed? Continue below to name this device and scan its pairing code.
@@ -489,16 +505,27 @@ export default function ComputerConnectionScreen() {
Install DevinX Connector {MINIMUM_SUPPORTED_CONNECTOR_VERSION} or later to
keep local sessions compatible.
- Linking.openURL(CONNECTOR_RELEASE_PAGE).catch(() => {})}
- accessibilityRole="link"
- accessibilityLabel="Open official DevinX Connector update"
- >
-
- Open official release
-
-
+
+ Linking.openURL(CONNECTOR_RELEASE_PAGE).catch(() => {})}
+ accessibilityRole="link"
+ accessibilityLabel="Open official DevinX Connector update for Mac"
+ >
+ Mac update
+
+
+ Linking.openURL(WINDOWS_CONNECTOR_STORE_PAGE).catch(() => {})
+ }
+ accessibilityRole="link"
+ accessibilityLabel="Open DevinX Connector update in Microsoft Store"
+ >
+
+ Windows update
+
+
+
diff --git a/src/lib/branding.ts b/src/lib/branding.ts
index e4e5740..303d4b0 100644
--- a/src/lib/branding.ts
+++ b/src/lib/branding.ts
@@ -44,6 +44,7 @@ export const branding = {
devinApp: 'https://app.devin.ai',
createServiceUser: 'https://docs.devin.ai/api-reference/authentication',
connectorReleases: 'https://github.com/fenner888/Devinx/releases/latest',
+ windowsConnectorStore: 'https://apps.microsoft.com/detail/9N52Z3FVMFH8',
},
} as const;
diff --git a/src/lib/connectorSetup.ts b/src/lib/connectorSetup.ts
index bd566e6..8f1adca 100644
--- a/src/lib/connectorSetup.ts
+++ b/src/lib/connectorSetup.ts
@@ -1,20 +1,25 @@
import { branding } from './branding';
export const CONNECTOR_RELEASE_PAGE = branding.links.connectorReleases;
+export const WINDOWS_CONNECTOR_STORE_PAGE = branding.links.windowsConnectorStore;
export const CONNECTOR_SETUP_PROMPT = `Set up DevinX Connector on this local device so I can securely connect the DevinX iPhone app to supported local Devin sessions through Tailscale.
Before downloading anything, explain that Tailscale supplies only the private network route. DevinX Connector is the trusted local service that communicates with a supported local Devin ACP capability, authenticates this iPhone, and enforces its permissions. A Tailscale IP, server URL, or password cannot replace a compatible service running on this local device. Cloud-only DevinX use does not require Connector.
-Detect whether this local device is running macOS or Windows. Open the official DevinX release page at ${CONNECTOR_RELEASE_PAGE}. Download DevinX Connector only when that official release provides a signed package for this operating system and architecture plus an adjacent SHA-256 checksum file. If no signed release is available for this platform, stop and tell me that DevinX Connector has not been published for it yet. Do not clone or build the source, install a guessed package, use an unsigned CI artifact, use an unofficial repository or mirror, or substitute a similarly named application.
+Detect whether this local device is running macOS or Windows.
-Verify the downloaded package against the published SHA-256 value. On macOS, require a Developer ID Application signature, confirm the app is notarized by Apple, and require Gatekeeper acceptance. On Windows, require a valid DevinX Authenticode signature and a supported x64 Windows release. Stop if any verification is missing or fails.
+On macOS, open the official DevinX release page at ${CONNECTOR_RELEASE_PAGE}. Download Connector only when that page provides the signed Apple-silicon DMG plus its adjacent SHA-256 checksum. Verify the checksum, require a Developer ID Application signature, confirm Apple notarization, and require Gatekeeper acceptance.
+
+On Windows 11 x64, open the official Microsoft Store listing at ${WINDOWS_CONNECTOR_STORE_PAGE}. Install only the Store package named DevinX Connector, published by DevinX Tools, with Store ID 9N52Z3FVMFH8. After installation, confirm that Get-AppxPackage reports package identity DevinXTools.DevinXConnector, publisher CN=43D84E24-857C-4C40-9DAA-1A6983913CD9, and package family DevinXTools.DevinXConnector_ydtgrt4yd5wrc. Do not download, sideload, or execute an unsigned CI MSIX, EXE, or ZIP.
+
+If the required official distribution is unavailable for this platform, or any identity, signature, checksum, notarization, or Gatekeeper check applicable to it fails, stop and tell me that DevinX Connector cannot be safely installed. Do not clone or build the source, install a guessed package, use an unofficial repository or mirror, or substitute a similarly named application.
Confirm that an official local Devin installation exposes the ACP capability required by Connector. You may locate its executable, but do not read, copy, print, log, or modify its credentials. If the required ACP capability is unavailable on this operating system, stop instead of claiming local sessions will work.
Confirm that Tailscale is installed and connected on this local device. If it is missing, use only Tailscale's official installation guidance for the detected operating system. If authentication is required, open the official interactive login and let me complete it. Never request, generate, print, or persist a reusable Tailscale authentication key.
-Install DevinX Connector for the signed-in user and open it. On macOS, install it in /Applications. On Windows, use only the signed per-user package and do not create an administrator service. Do not run it as root or Administrator, bind it to 0.0.0.0, expose a public listener, install a public tunnel, or weaken its QR pairing and per-device authorization. Do not enable launch at login without showing me the Connector's visible setting and receiving my approval.
+Install DevinX Connector for the signed-in user and open it. On macOS, install it in /Applications. On Windows, use only the Microsoft Store package and do not create an administrator service. Do not run it as root or Administrator, bind it to 0.0.0.0, expose a public listener, install a public tunnel, or weaken its QR pairing and per-device authorization. Do not enable launch at login without showing me the Connector's visible setting and receiving my approval.
Verify that Connector reports an active private Tailscale connection and detects a supported local Devin ACP capability. Then tell me to return to DevinX on my iPhone, name this local device, and tap Scan pairing code.
diff --git a/tests/components/ComputerConnectionScreen.test.tsx b/tests/components/ComputerConnectionScreen.test.tsx
index a56092e..dd098a6 100644
--- a/tests/components/ComputerConnectionScreen.test.tsx
+++ b/tests/components/ComputerConnectionScreen.test.tsx
@@ -120,7 +120,8 @@ describe('Computer connection onboarding', () => {
expect(screen.getByText('Open Tailscale setup guide')).toBeTruthy();
expect(screen.getByText('Set up DevinX Connector')).toBeTruthy();
expect(screen.getByText('Send assisted setup prompt')).toBeTruthy();
- expect(screen.getByText('Open official releases')).toBeTruthy();
+ expect(screen.getByText('Mac release')).toBeTruthy();
+ expect(screen.getByText('Windows Store')).toBeTruthy();
expect(
screen.getByText(/Tailscale alone does not expose Devin sessions/),
).toBeTruthy();
@@ -170,7 +171,12 @@ describe('Computer connection onboarding', () => {
const screen = render();
await waitFor(() => expect(screen.getByText('Connector update required')).toBeTruthy());
- expect(screen.getByLabelText('Open official DevinX Connector update')).toBeTruthy();
+ expect(
+ screen.getByLabelText('Open official DevinX Connector update for Mac'),
+ ).toBeTruthy();
+ expect(
+ screen.getByLabelText('Open DevinX Connector update in Microsoft Store'),
+ ).toBeTruthy();
expect(screen.getByText(/0.1.2 or later/)).toBeTruthy();
});
diff --git a/tests/lib/connector-setup.test.ts b/tests/lib/connector-setup.test.ts
index 6ec924d..1f8af23 100644
--- a/tests/lib/connector-setup.test.ts
+++ b/tests/lib/connector-setup.test.ts
@@ -1,14 +1,28 @@
-import { CONNECTOR_RELEASE_PAGE, CONNECTOR_SETUP_PROMPT } from '../../src/lib/connectorSetup';
+import {
+ CONNECTOR_RELEASE_PAGE,
+ CONNECTOR_SETUP_PROMPT,
+ WINDOWS_CONNECTOR_STORE_PAGE,
+} from '../../src/lib/connectorSetup';
describe('Connector assisted setup', () => {
it('uses only the official guarded release path', () => {
expect(CONNECTOR_RELEASE_PAGE).toBe('https://github.com/fenner888/Devinx/releases/latest');
expect(CONNECTOR_SETUP_PROMPT).toContain(CONNECTOR_RELEASE_PAGE);
+ expect(WINDOWS_CONNECTOR_STORE_PAGE).toBe(
+ 'https://apps.microsoft.com/detail/9N52Z3FVMFH8',
+ );
+ expect(CONNECTOR_SETUP_PROMPT).toContain(WINDOWS_CONNECTOR_STORE_PAGE);
expect(CONNECTOR_SETUP_PROMPT).toContain('Developer ID Application');
- expect(CONNECTOR_SETUP_PROMPT).toContain('notarized');
- expect(CONNECTOR_SETUP_PROMPT).toContain('Authenticode');
- expect(CONNECTOR_SETUP_PROMPT).toContain('signed per-user package');
- expect(CONNECTOR_SETUP_PROMPT).toContain('unsigned CI artifact');
+ expect(CONNECTOR_SETUP_PROMPT).toContain('notarization');
+ expect(CONNECTOR_SETUP_PROMPT).toContain('DevinXTools.DevinXConnector');
+ expect(CONNECTOR_SETUP_PROMPT).toContain(
+ 'CN=43D84E24-857C-4C40-9DAA-1A6983913CD9',
+ );
+ expect(CONNECTOR_SETUP_PROMPT).toContain(
+ 'DevinXTools.DevinXConnector_ydtgrt4yd5wrc',
+ );
+ expect(CONNECTOR_SETUP_PROMPT).toContain('Microsoft Store package');
+ expect(CONNECTOR_SETUP_PROMPT).toContain('unsigned CI');
expect(CONNECTOR_SETUP_PROMPT).toContain('SHA-256');
expect(CONNECTOR_SETUP_PROMPT).toContain('stop and tell me');
expect(CONNECTOR_SETUP_PROMPT).toContain('Do not clone or build the source');