From efa2b204f5c668fde4b13246a5133699f6dab737 Mon Sep 17 00:00:00 2001 From: tsouth89 Date: Sat, 1 Aug 2026 01:36:22 -0400 Subject: [PATCH] Prepare Ceiling 1.5.21 --- ...otes-1.5.20.md => release-notes-1.5.21.md} | 8 +-- CHANGELOG.md | 3 +- Cargo.lock | 4 +- apps/desktop-tauri/package.json | 2 +- apps/desktop-tauri/src-tauri/Cargo.toml | 2 +- apps/desktop-tauri/src-tauri/tauri.conf.json | 2 +- rust/Cargo.toml | 2 +- scripts/windows-smoke-install.ps1 | 60 +++++-------------- version.env | 4 +- 9 files changed, 28 insertions(+), 59 deletions(-) rename .github/{release-notes-1.5.20.md => release-notes-1.5.21.md} (89%) diff --git a/.github/release-notes-1.5.20.md b/.github/release-notes-1.5.21.md similarity index 89% rename from .github/release-notes-1.5.20.md rename to .github/release-notes-1.5.21.md index bf87ca9e..82535233 100644 --- a/.github/release-notes-1.5.20.md +++ b/.github/release-notes-1.5.21.md @@ -20,12 +20,12 @@ Claude now reports HTTP client setup failures instead of panicking a background ## Installers -- **Ceiling-1.5.20-Setup.exe** - standard installer -- **Ceiling-1.5.20-portable.exe** - portable -- **Ceiling-1.5.20-Store-Setup.exe** - Microsoft Store package (WebView2 bundled) +- **Ceiling-1.5.21-Setup.exe** - standard installer +- **Ceiling-1.5.21-portable.exe** - portable +- **Ceiling-1.5.21-Store-Setup.exe** - Microsoft Store package (WebView2 bundled) Portable builds show alerts as banners but do not keep them in the notification center. That requires the Start Menu shortcut installed by the standard or Store build. --- -**Full Changelog**: https://github.com/tsouth89/ceiling/compare/v1.5.19...v1.5.20 +**Full Changelog**: https://github.com/tsouth89/ceiling/compare/v1.5.19...v1.5.21 diff --git a/CHANGELOG.md b/CHANGELOG.md index d6539796..b648e3bc 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -## [Ceiling] 1.5.20 - 2026-08-01 +## [Ceiling] 1.5.21 - 2026-08-01 Patch release for duplicate scheduled-reset notifications and reliability hardening around local state and account-scoped history. @@ -14,6 +14,7 @@ Patch release for duplicate scheduled-reset notifications and reliability harden ### Internal - The release smoke test now asserts that the installed Start Menu shortcut carries Ceiling's AppUserModelID. That property is what lets Windows keep a notification, and 1.5.17 shipped without it: every gate checked source, while the one step that inspects the installed build never looked at it. +- Shortcut identity validation now asks the Windows Shell for `System.AppUserModel.ID`. The custom property marshaller misread a correctly packaged shortcut as empty and blocked the unpublished 1.5.20 release. ## [Ceiling] 1.5.19 - 2026-07-29 diff --git a/Cargo.lock b/Cargo.lock index a9d45824..d261de38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -664,7 +664,7 @@ checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "codexbar" -version = "1.5.20" +version = "1.5.21" dependencies = [ "aes-gcm", "anyhow", @@ -706,7 +706,7 @@ dependencies = [ [[package]] name = "codexbar-desktop-tauri" -version = "1.5.20" +version = "1.5.21" dependencies = [ "chrono", "chrono-tz", diff --git a/apps/desktop-tauri/package.json b/apps/desktop-tauri/package.json index 9c76a568..32eae3bb 100644 --- a/apps/desktop-tauri/package.json +++ b/apps/desktop-tauri/package.json @@ -1,7 +1,7 @@ { "name": "desktop-tauri", "private": true, - "version": "1.5.20", + "version": "1.5.21", "packageManager": "pnpm@10.18.1", "type": "module", "scripts": { diff --git a/apps/desktop-tauri/src-tauri/Cargo.toml b/apps/desktop-tauri/src-tauri/Cargo.toml index c318b0e8..43b15040 100644 --- a/apps/desktop-tauri/src-tauri/Cargo.toml +++ b/apps/desktop-tauri/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codexbar-desktop-tauri" -version = "1.5.20" +version = "1.5.21" edition = "2024" publish = false diff --git a/apps/desktop-tauri/src-tauri/tauri.conf.json b/apps/desktop-tauri/src-tauri/tauri.conf.json index 4561e2d3..aa348648 100644 --- a/apps/desktop-tauri/src-tauri/tauri.conf.json +++ b/apps/desktop-tauri/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Ceiling", - "version": "1.5.20", + "version": "1.5.21", "identifier": "io.github.tsouth89.ceiling", "build": { "beforeDevCommand": "pnpm run dev", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 25d9b57f..189c89bf 100755 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codexbar" -version = "1.5.20" +version = "1.5.21" edition = "2024" authors = ["Ceiling Contributors"] description = "Local-first Windows companion for monitoring AI capacity and reset times" diff --git a/scripts/windows-smoke-install.ps1 b/scripts/windows-smoke-install.ps1 index 184b0e1f..c174250e 100644 --- a/scripts/windows-smoke-install.ps1 +++ b/scripts/windows-smoke-install.ps1 @@ -183,52 +183,20 @@ Write-Step "Start Menu shortcut: $shortcut" # with the installer setting no such property: every alert drew a banner and was # then discarded. Nothing caught it, because every other gate checks source # while this is the only step that inspects what was actually installed. -# -TypeDefinition, not -MemberDefinition: this declares types, which the -# member form cannot host. -if (-not ('Ceiling.Lnk' -as [type])) { - Add-Type -Language CSharp -TypeDefinition @' -using System; -using System.Runtime.InteropServices; -namespace Ceiling { - [ComImport, Guid("00021401-0000-0000-C000-000000000046")] internal class ShellLink {} - [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - internal interface IPersistFile { - void GetClassID(out Guid pClassID); [PreserveSig] int IsDirty(); - void Load([MarshalAs(UnmanagedType.LPWStr)] string fileName, int mode); - void Save([MarshalAs(UnmanagedType.LPWStr)] string fileName, [MarshalAs(UnmanagedType.Bool)] bool remember); - void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] string fileName); - void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out string fileName); } - [StructLayout(LayoutKind.Sequential)] internal struct PropertyKey { public Guid fmtid; public uint pid; } - [ComImport, Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - internal interface IPropertyStore { - void GetCount(out uint count); void GetAt(uint index, out PropertyKey key); - void GetValue(ref PropertyKey key, [In, Out] PropVariant value); - void SetValue(ref PropertyKey key, PropVariant value); void Commit(); } - [StructLayout(LayoutKind.Explicit)] internal class PropVariant : IDisposable { - private const ushort VT_EMPTY = 0; - private const ushort VT_LPWSTR = 31; - [FieldOffset(0)] ushort valueType; [FieldOffset(8)] IntPtr pointer; - public string AsString() { - return valueType == VT_LPWSTR && pointer != IntPtr.Zero ? Marshal.PtrToStringUni(pointer) : ""; } - // Free only what is actually a CoTaskMem string. The field at offset 8 - // overlaps a union, so a non-string variant can leave arbitrary non-zero - // bits there, and handing those to FreeCoTaskMem corrupts the heap. - // Anything else is left alone: leaking a few bytes in a short-lived check - // is strictly better than freeing memory that was never allocated. - public void Dispose() { - if (valueType == VT_LPWSTR && pointer != IntPtr.Zero) { Marshal.FreeCoTaskMem(pointer); } - valueType = VT_EMPTY; pointer = IntPtr.Zero; } } - public static class Lnk { - public static string ReadAppUserModelId(string path) { - var key = new PropertyKey { fmtid = new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), pid = 5 }; - var link = new ShellLink(); - ((IPersistFile)link).Load(path, 0); - using (var value = new PropVariant()) { - ((IPropertyStore)link).GetValue(ref key, value); - return value.AsString(); } } } } -'@ -} -$shortcutAumid = [Ceiling.Lnk]::ReadAppUserModelId($shortcut) +# Ask the Windows Shell for the canonical property value. The previous custom +# PROPVARIANT marshaller assumed VT_LPWSTR, but Shell links can surface the +# value through another string variant; that made a correct installer look +# broken and blocked the 1.5.20 release after signing and packaging succeeded. +$shell = New-Object -ComObject Shell.Application +$shortcutFolder = $shell.Namespace((Split-Path -Parent $shortcut)) +if (-not $shortcutFolder) { + throw "Could not open the Start Menu shortcut folder: $(Split-Path -Parent $shortcut)" +} +$shortcutItem = $shortcutFolder.ParseName((Split-Path -Leaf $shortcut)) +if (-not $shortcutItem) { + throw "Could not inspect the Start Menu shortcut: $shortcut" +} +$shortcutAumid = [string]$shortcutItem.ExtendedProperty("System.AppUserModel.ID") if ($shortcutAumid -ne $ExpectedAppUserModelId) { throw "Start Menu shortcut publishes AppUserModelID '$shortcutAumid' but Ceiling toasts under '$ExpectedAppUserModelId'. Windows will show alerts as banners and then discard them instead of keeping them in the notification center. Check AppUserModelID on the [Icons] entries in rust/installer/codexbar.iss." } diff --git a/version.env b/version.env index acf91c2f..7bd43028 100755 --- a/version.env +++ b/version.env @@ -1,2 +1,2 @@ -MARKETING_VERSION=1.5.20 -BUILD_NUMBER=122 +MARKETING_VERSION=1.5.21 +BUILD_NUMBER=123