Skip to content

Development - #17

Merged
56steve merged 8 commits into
mainfrom
development
Sep 16, 2026
Merged

56steve merged 8 commits into
mainfrom
development

Conversation

@56steve

@56steve 56steve commented Sep 16, 2026

Copy link
Copy Markdown
Owner

No description provided.

The FTS5 sync triggers issued the 'delete' command without a rowid, which
SQLite rejects. Every UPDATE and DELETE on `clips` therefore failed, and
because those call sites discarded their Result nothing ever said so:
pinning, paste counts, reminders, OCR write-back and clip deletion were all
silently inert. The triggers now use a plain DELETE, and the callers report
their errors.

Sensitive clips were held in memory for sixty seconds and never written
down, which left a dead row behind once they expired. They are now sealed
and stored: DPAPI on Windows, AES-256-GCM on macOS with the key in an
owner-only file beside the database. Neither platform prompts for a
password. The Keychain was the first choice on macOS and was dropped
because it asks for the login password whenever the binary's signature
changes, and that dialog blocks the capture thread while it waits.

Detection widened to the documented vendor prefixes it was missing
(Stripe, Slack, GitLab, GitHub PAT, Google, SendGrid, PEM private keys)
and narrowed so unseparated hex no longer matches: commit hashes and
checksums are not secrets and masking them only gets in the way.

Also removes the non-Windows DPAPI stubs, which returned the plaintext
unchanged and sat one misplaced cfg away from writing secrets in the clear.
The pin feature was half-built: `is_pinned` in the schema, `toggle_pin` in
Rust, a Pinned filter pill, card styling and a `.pin-btn` rule in the
stylesheet, but no button in the markup and a `togglePin()` nothing called.
This adds the star to the card action bar and wires it up.

`getFilteredClips()` had no case for 'pinned', so it fell through to a
category comparison that can never match and the Pinned pill always showed
an empty list. Favourited clips now also sort to the top immediately,
matching the ordering the database already used.
The README said sensitive clips were encrypted on Windows and stored in
plain text on macOS. Neither was true: the DPAPI helpers existed but were
never called from anywhere. Both platforms now seal their sensitive clips,
and the README says what that does and does not protect against.
MSIX packaging could only be done by hand on one machine: the manifest
lived in msix_stage/, which .gitignore excludes, so CI never saw it. It
also referenced Assets\SplashScreen.png, which exists nowhere in this
repo, and carried a version that had drifted from the app's own.

The manifest now lives in packaging/msix/ with its version filled in from
tauri.conf.json at build time, and CI both packages it and runs the Windows
App Certification Kit against the result. That kit is the same suite Store
certification runs, so rejections surface here instead of in submission
email. The stale msix_stage/ manifest is deleted rather than left as the
copy someone packages by accident.
The Windows leg built the MSI and NSIS installers only to throw them away,
and each bundler downloads its toolchain from GitHub at build time. One of
those fetches returned HTTP 500 and failed the run before the MSIX was ever
packaged. CI needs the executable, nothing more; release.yml still builds
the installers.

Also drops the Win32 process and foreground-window imports left orphaned
when source-app lookup moved to paste_tracker, which were warning on every
Windows build.
The certification kit failed Clipz on "Blocked executables": the binary
referenced powershell, cmd and cmd.exe. Two of those were ours — a
PowerShell one-liner to show a startup error dialog, and `reg.exe` to
delete the autostart value — and std::process::Command drags in the
cmd.exe strings it uses for batch-file handling, so using it at all was
enough to fail. Both now call Win32 directly: MessageBoxW and
RegDeleteKeyValueW. No process is launched on Windows any more.

The CI gate missed this because it read OVERALL_RESULT, which the kit
reports as PASS even with a failing test. It now judges on the tests
themselves and prints each failure's messages.
Every Tauri app fails the certification kit's "Blocked executables" test:
tauri::process::restart uses std::process::Command, which links the Rust
standard library's process module and its cmd.exe strings. That is not
removable without patching Tauri, and the kit marks the test optional.

The gate now allows exactly those five references and fails on anything
else, so the check still catches a process launch we introduce ourselves —
which is how the powershell call was found.
CI built the Windows installers only to discard them, and after a transient
HTTP 500 during NSIS bundling it stopped building them at all. Neither told
us whether the formats users actually download still build.

It now produces all of them — exe, MSI, NSIS setup and MSIX on Windows,
.app and .dmg on macOS — checks each one exists before uploading, and
retries the bundle step so a GitHub outage does not read as a broken build.
@56steve
56steve merged commit 78a4349 into main Sep 16, 2026
4 checks passed
56steve added a commit that referenced this pull request Sep 16, 2026
56steve added a commit that referenced this pull request Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant