* craft-update: a Windows MSI copy updates itself in its own context, wherever it is installed Self-update only recognised an MSI copy by the launcher's per-user folder (the HKCU InstallDir key, or %LOCALAPPDATA%\Programs\<App>). Every app installed for everyone, in Program Files\ArtCraft\<App> or the older Program Files\<App>, was treated as a loose folder and updated by unpacking the portable zip over Program Files without permission. - msi_context moves here from the launcher (craft-launcher crates/native/src/msi_context.rs at b827fed, unchanged apart from visibility, MsiScope and scope_arguments). Windows Installer's own registration decides a copy's context, for the launcher and the apps alike, so the launcher can drop its copy and both routes follow one rule. - New msi_copy module: a copy is an MSI copy when an App Paths entry names its exe (a registry read, cheap enough for status checks). Its update asks Windows Installer for the context; the App Paths hive is only the fallback when that lookup cannot run. - The update stops, before the app exits, when the copy is registered in both hives, the lookup is unclear, or Windows lists the app more than once. - After the update the helper starts the exe the registrations name now, since the package may have moved an exact old default folder. - A failed self-update now names the Windows Installer log, as the launcher's installs do. - The launcher's own per-user package is recognised and updated exactly as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * craft-update: a copy only takes the Windows Installer context of its own hive Review follow-up (CodeRabbit on #419). The product code for the context lookup came from the app's only uninstall record, which was not proven to own the running exe. A package writes App Paths under HKMU, always the hive of its own context, so a registration whose Windows Installer context differs from the hive that named this exe belongs to another copy. The update now stops then, instead of taking the other copy's context. Also documents the remaining helpers the diff touches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * craft-update: an app in the old per-user folder is judged by its registration first Review follow-up (CodeRabbit on #419). The folder rule for the launcher's per-user package also matched an app installed in %LOCALAPPDATA%\Programs\<App>, and it ran before the App Paths check, so such a copy skipped the product-count, conflict and context checks. Now an app is judged by its registration first; the folder rule only covers an app copy no registration names. The launcher in its own folder still keeps its old path whatever is registered: on a real PC it has an App Paths entry and a stale second uninstall record, and registration-first would have stopped its self-update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * craft-update: when the Windows Installer lookup cannot run, the uninstall records decide Review follow-up (CodeRabbit on #419). The fallback trusted the App Paths hive, so a stale entry or a product registered in both scopes could run the update in the wrong context. The fallback now follows the launcher's rule: the context every uninstall record of the product agrees on (msi_context::single_scope over HKLM in both views and HKCU). Missing or mixed records stop the update, and an agreed context that differs from the App Paths hive still stops it as another copy's registration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Craft App Libraries
This repo contains libraries used by the various Craft Apps. It's a Rust monorepo workspace, and the libraries can be included by any Craft Apps that need them.
In the future this may grow to include non-Rust library code.
If any libraries grow beyond Craft App usage, eg. RAW format support, they may be promoted out and into their own libraries for the broader ecosystem to take advantage of.
Layout
A Cargo workspace (edition 2024, resolver 3). Each library is a crate under crates/<name>, named
craft-<name>, with version, edition, license and repository inherited from the workspace
(license.workspace = true, and so on) and [lints] workspace = true. Register each crate in
[workspace.dependencies] in the root Cargo.toml.
Apps depend on a crate by git:
craft-<name> = { git = "https://github.com/storytold/craft-libs", rev = "<commit>" }
Libraries
-
craft-platform: optional native dialog lifecycle, Linux/BSD desktop appearance observation and browser download ownership; application policy stays in the apps. -
craft-ai-core: the data model and contract for AI in the Craft Apps (connections, models, tools, requests, jobs, consent, history, route spec). Pure, no I/O, wasm-safe. Contract in docs/ai-shared-layer.md. -
craft-pdf: independently optional PDF parsing, interpretation, rasterization and guarded authoring. Apps retain layout, fonts, editing and export policy; writer-only consumers do not enable the shared reader. -
craft-atomic: Crash-safe atomic file writing and replacement with same-directory staging, directory fsync, AppleF_FULLFSYNCfallback, transient lock backoff, and fault injection for the Craft suite. -
craft-cms: pure-Rust ICC v2/v4 colour management: profile parsing and writing, transforms, rendering intents, black point compensation, soft proofing, gamut checks, 3D LUTs and built-in profiles (sRGB, Display P3, synthetic coated CMYK and others). -
craft-dialogs: native file and message dialogs that never block the event loop: queued requests shown at the end of the frame and answered on a later frame, free-standing Open and Folder panels and Save sheets on macOS, case-insensitive filters. What to do with the answer stays in each app. -
craft-docpath: decides whether a path orfile:URL stored in a document may be opened. Paths stored in documents are followed only when they are local or on the document's own network share; other network paths, device paths and non-file URLs are refused. -
craft-font-catalog: the installed fonts on every platform (font folders, fontconfig and Flatpak host folders, CoreText, DirectWrite, the font store), lookup by family, style, localized, legacy, full and PostScript names, family loads shared between threads, and rescans when fonts are installed or removed. -
craft-font-manager: Craft Font Manager as a library: search and filters over the Google Fonts index, installed fonts by family, the font store interface, and (eguifeature)FontsPanel, the whole interface as one panel for the launcher's Fonts tab and the standalone app. -
craft-font-store: the suite's font store: the pinned Google Fonts and Noto indexes plus indexes the user adds (never curated), exact lookup by family and style or PostScript name, and installs from each source's URLs (jsDelivr, then raw GitHub) checked by size, sha256 and parsing, with the licence, a manifest, and removal. Off until the user turns downloading on; agents can't. -
craft-fonts-build: embeds the optional craft-fonts faces from an app'sbuild.rs(CRAFT_FONTS_DIR,CRAFT_FONTS_REQUIRED, script filters) as a table ofEmbeddedFaces. No dependencies; the app picks the faces. -
craft-i18n: translations over the embedded craft-i18n catalogs: lookup with fallback (pt-br→pt→ English), plurals, language names, the system locale and a pseudo locale. The catalogs stay a fully optional build input; apps keeptl!and their language setting. -
craft-jpeg: clean-room decoder for 12-bit and arithmetic-coded JPEG (T.81 SOF0/SOF1 at 12 bits, SOF9, SOF10), from PhotoCraft, and a frame probe for routing. Metadata stays in each app. -
craft-keymap: keyboard bindings: chords and their text forms, scopes, conflicts, user overrides stored through craft-settings and import of other applications' shortcut sets. Command catalogs, file readers and the shortcut editor UI stay in each app. -
craft-media: bit-level I/O (bitstream), clean-room MP4/MOV (isobmff) and Matroska/WebM (matroska) demuxers and muxers, from FilmCraft, and an ISO BMFF box reader. Containers only; codecs stay in each app. -
craft-menu: an app's menus as a macOS menu bar: the Mac layout (app menu, Window, Help, system-key clashes), a platform backend trait, and key equivalents fed back to egui as the input egui-winit would have made. Commands and their enabled state stay in each app. -
craft-print: PDF submission to CUPS and Windows, printer discovery, duplex/copies/colour and driver preferences. PDF generation stays in each app. -
craft-quit: native macOS quit, egui close handling and an optional app menu. Unsaved-document decisions and save prompts stay in each app. -
craft-settings:config.tomlsettings storage for every app: platform folders, portable mode and overrides, atomic saves while running, backup, damaged-file recovery and schema migrations. Policy in docs/settings-storage.md. -
craft-text: text processing below the composer. Itshyphenmodule finds hyphenation points, with a bundled US English dictionary and patterns and optional hypher patterns for 47 more languages (one cargo feature each). -
craft-ui: SVG catalogs, icon buttons, tabs, pane controls, transactional docking, print settings and theme helpers for egui frontends; assets, themes, localization and command handling stay in each app. Requires Rust 1.95 or later. -
Shared UI component audit: source inventory, extraction priorities and compatibility boundaries across the Craft suite.
-
Theme infrastructure: eight-app comparison and the small shared widget-state styling boundary.
-
Panel docking: validated panel moves, floating groups, workspace adapters and an optional egui docking surface.
License and credits
craft-libs is dual-licensed under MIT or Apache-2.0, at your option. Copyright (c) 2026 ArtCraft Team and the craft-libs contributors. Required notices are in NOTICE.
Bundled fonts, icons, images and other assets keep their own open licenses; each one is listed with its author, source and license in ATTRIBUTION.md.