Commit Graph
220 Commits
Author SHA1 Message Date
aiongg f0ed593d9f keymap: update Cargo.lock for the egui dev-dependency with serde 2026-10-23 08:14:06 +00:00
aiongg 135981286f keymap: a layout switch forgets what letter positions typed, and Layout::forget_letters does so on request 2026-10-23 08:03:27 +00:00
aiongg 5050d5dead Merge remote-tracking branch 'ao/craft-keymap' into keymap-layout-rule 2026-10-23 08:02:46 +00:00
aiongg 3f5f57642a Merge remote-tracking branch 'upstream/main' into keymap-layout-rule
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	README.md
2026-10-23 08:02:46 +00:00
aiongg 457da42c5f keymap: pin the workflow's toolchain and cache actions to main's commits, and keep the token out of .git/config after checkout 2026-10-23 05:28:19 +00:00
aiongg af6eb6ae1e Revert "keymap: leave the token out of .git/config after checkout in the keymap workflow"
This reverts commit e6b54fa8aa.
2026-10-23 05:16:16 +00:00
aiongg e6b54fa8aa keymap: leave the token out of .git/config after checkout in the keymap workflow 2026-10-23 05:03:07 +00:00
aiongg b94e7d8b87 Merge remote-tracking branch 'upstream/main' into craft-keymap
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	README.md
2026-10-23 05:02:48 +00:00
Dylan M. Taylor 4919088427 Merge pull request #238 from dylanmtaylor/security/media-allocation-bounds
security: bound craft-media metadata, sample reservation, header stripping and cue bookkeeping (CodeRabbit)
2026-10-22 22:42:59 -04:00
Dylan M. Taylor c67b1e16b8 Merge pull request #236 from dylanmtaylor/security/docking-group-move-permission
security: require every floating-group member to be movable for MoveFloating (CodeRabbit)
2026-10-22 22:42:36 -04:00
Dylan M. Taylor f0d9c32e67 Merge pull request #237 from dylanmtaylor/security/print-parsing-bounds
security: bound print dialog names, PPD labels, lpstat merge and inherited page geometry (CodeRabbit)
2026-10-22 22:26:23 -04:00
Dylan M. Taylor f721e1b969 Merge pull request #234 from dylanmtaylor/security/cms-eval-work
security: bound cms CLUT interpolation and inverse-curve table work (CodeRabbit)
2026-10-22 22:26:18 -04:00
Dylan M. Taylor c0a3d4c08c media: charge metadata at its converted length, before converting
Lossy UTF-8 conversion can triple invalid bytes, and a fallback key such as ©nam is five
bytes, not four. The budget now charges the length the text will be stored at, computed
without allocating, before the value is converted (CodeRabbit review).
2026-10-22 22:25:45 -04:00
Dylan M. Taylor fd9cf54c48 ui: test that a protected member blocks the floating group's resize grip
Drags the resize grip of sample()'s floating group: a movable group emits MoveFloating,
one with a protected member emits none. Fails without the surface.rs check (CodeRabbit
review nitpick).
2026-10-22 22:23:27 -04:00
Dylan M. Taylor bc8fe0eb53 cms: keep NaN propagation in multilinear interpolation
A NaN input gives a NaN fraction, which the active-dimension check dropped, returning a
finite node value. Keep any nonzero fraction, NaN included (CodeRabbit review).
2026-10-22 22:22:39 -04:00
Dylan M. Taylor 4d30617bcf Merge pull request #235 from dylanmtaylor/security/settings-section-merge
security: validate settings sections against the defaults alone (CodeRabbit)
2026-10-22 22:22:11 -04:00
Dylan M. Taylor b7d92278fe Merge pull request #233 from dylanmtaylor/security/ai-core-bounds
security: bound ai-core redaction and template rendering; consent for params-only requests (CodeRabbit)
2026-10-22 22:22:06 -04:00
Dylan M. Taylor ecf0ad47ad security: bound craft-media metadata, sample reservation, header stripping and cue bookkeeping
Follow-up to the hostile-input fixes in #196, covering findings that PR does not:

- ISO BMFF metadata: all udta/meta entries share a 4 MiB budget charged before a keys name
  is copied, so many ilst items naming one long key cannot multiply it (CodeRabbit CWE-400,
  isobmff/demux.rs:939)
- ISO BMFF stbl: reserve only the samples the chunk map can place, fallibly, instead of the
  declared stsz count (CodeRabbit CWE-789, isobmff/demux.rs:767)
- Matroska: a header-stripping prefix over 256 bytes is treated as unsupported compression
  rather than copied in front of every frame; Track::sample_size no longer allocates the
  prefix (CodeRabbit CWE-409, matroska/track.rs:257)
- Matroska muxer: per-track cue flags use a cluster number, so starting a cluster no longer
  clears every declared track (CodeRabbit CWE-407, matroska/mux.rs:402)
2026-10-22 21:53:10 -04:00
Dylan M. Taylor 4f85efb2b9 security: bound print dialog name resolution, PPD labels, lpstat merge and inherited geometry
- craft-ui shown_names resolves label collisions with hash-map counts and a worklist, so a
  crafted cascade is linear instead of cubic (CodeRabbit CWE-407, ui/src/printing.rs:32)
- parse_ppd caps group, option and choice labels at 256 characters before each option copies
  its group (CodeRabbit CWE-400, print/src/lib.rs:232)
- printers_parsed tracks seen destinations in a HashSet (CodeRabbit CWE-407, lib.rs:417)
- sheets::Reader::rect checks an inline array's length before reading it and borrows direct
  objects instead of deep-cloning the inherited MediaBox/CropBox/Rotate for every page
  (CodeRabbit CWE-400, print/src/sheets.rs:774)
2026-10-22 21:49:46 -04:00
Dylan M. Taylor d66e345cc7 security: require every floating-group member to be movable for MoveFloating
MoveFloating checked only the panel it named, but changes the rectangle shared by that
panel's whole floating group, so naming a movable sibling moved a panel whose policy forbids
it. The model now refuses the action unless every member is movable, and the floating
window's resize grip no longer emits it for such a group.

CodeRabbit CWE-863, crates/ui/src/docking/model.rs:392
2026-10-22 21:46:25 -04:00
Dylan M. Taylor 08109be362 security: validate settings sections against the defaults alone
deserialize_sections tried each top-level key against a document holding every key accepted
before it, cloning and deserializing the growing document per key. A config.toml with many
unknown keys took quadratic time (20k keys: >2 minutes, now <1 s). Each key is now checked
against the defaults plus that key, and accepted keys are merged once.

CodeRabbit CWE-407, crates/settings/src/document.rs:47
2026-10-22 21:42:13 -04:00
Dylan M. Taylor c900c69553 security: bound cms CLUT interpolation and inverse-curve table construction
- Clut::multilinear enumerates corners only for dimensions between two grid points, so
  singleton dimensions no longer multiply per-pixel work (CodeRabbit CWE-407, clut.rs:238)
- Transform::from_pipeline finds a sampled curve's flat ends once per curve via
  Curve::inverse64_many instead of rescanning the table for each of the 4096 output entries
  (CodeRabbit CWE-407, curve.rs:276)
2026-10-22 21:39:20 -04:00
Dylan M. Taylor a719521c13 security: bound ai-core redaction, template rendering and model checks; consent for params-only requests
- redact matches secrets in the original text only, so markers are never searched again
  (CodeRabbit CWE-400, secret.rs:47)
- render_text/render_value share one MAX_RENDERED_BYTES budget across repeated slots
  (CodeRabbit CWE-400, spec/template.rs:122)
- Connection::validate checks model-ID uniqueness with a set instead of a pairwise scan
  (CodeRabbit CWE-407, connection.rs:205)
- Disclosure::kinds counts parameters as text, so a request carrying only params still needs
  an agreement (CodeRabbit CWE-863, consent.rs:123)
2026-10-22 21:37:34 -04:00
Dylan M. Taylor 514db92b77 Merge pull request #229 from storytold/sonar-fix/path-cmd-hardening
security: validate CLI paths/args in dev tools (SonarCloud S2083/S8707/S8705)
2026-10-22 19:33:13 -04:00
Dylan M. Taylor 7a6d60a285 security: enforce HTTPS redirects and atomic write in fetch-pdf-test-fonts.py 2026-10-22 19:28:55 -04:00
skylar taylor-barrick b1401e33b1 Share browser download resource ownership (#226)
Add opt-in browser download helpers that own detached links and object URLs, clean up failed or abandoned preparation, and register delayed URL cleanup before issuing a click. Applications retain filename, MIME type, pacing, and user-activation policy.

Include browser lifecycle and failure-path tests, public API documentation, and Sonar test-source classification. All 32 PR checks passed; targeted WASM Clippy and formatting passed in local validation.
2026-10-22 20:49:41 +02:00
James ChapmanandClaude Code f20f364d55 hayro-jbig2: cap long-form referred-to segment count (#176)
* hayro-jbig2: cap long-form referred-to-segment count

A crafted JBIG2 segment header can claim a 29-bit referred-to-segment count;
Vec::with_capacity reserved ~2 GiB from that field before a single
referred-to number was read, and the resulting allocation failure aborts
the process in a way catch_unwind cannot contain (fatal on wasm32, where
memory is capped well below 2 GiB). A ~100 KB Flate-compressed PDF was
enough to reach it inside the 256 MiB stream budget.

Real files refer to a handful of segments, so the count is now capped at
u16::MAX; larger claims fail as InvalidReferredCount before any
retention-flag bytes are consumed. Regression test included.

Updates SOURCE.json's local hash for src/segment.rs and records the patch
in vendor/README.craft-reader.md, following the vendored tree's provenance
practice.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* hayro-jbig2: record git-blob sha256 for patched segment.rs

The previous entry hashed the Windows working-tree checkout (CRLF) of
src/segment.rs instead of the LF content git stores, so every other
manifest entry's convention (git-blob content hash) was broken by this
one file. Re-hash against `git show HEAD:vendor/hayro-jbig2/src/segment.rs`
as the vendored manifests' other 30 entries do.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-10-22 13:10:36 -04:00
skylar taylor-barrickandskylartaylor ffe7f8fce8 Share Linux and BSD desktop appearance observation (#225)
* platform: share desktop appearance observation

* Align appearance target guards and document watcher contracts

* Replace appearance wildcard imports with explicit dependencies

---------

Co-authored-by: skylartaylor <skylartaylor@users.noreply.github.com>
2026-10-22 10:13:09 -04:00
skylar taylor-barrickandskylartaylor b9c1a1105e Add craft-platform with shared native dialog lifecycle helpers (#224)
* platform: add native dialog lifecycle services

* Document dialog outcomes and lifecycle contracts

---------

Co-authored-by: skylartaylor <skylartaylor@users.noreply.github.com>
2026-10-22 10:13:08 -04:00
Dylan M. Taylor 1b9cf1973a ci: pin GitHub Actions to full commit SHA (SonarCloud githubactions:S7637) (#228)
Pin third-party actions to full-length commit SHAs (with version comments)
instead of mutable tags/branches to prevent supply-chain tampering via
retagged releases. Resolves SonarCloud rule githubactions:S7637.
2026-10-21 20:14:01 -04:00
Dylan M. Taylor e25b6ec6e6 security: validate CLI paths/args in dev tools (SonarCloud S2083/S8707/S8705/S7044)
Resolve and validate command-line path arguments before use, enforce HTTPS at
download sinks, and confirm path containment. Hardens local codegen/fetch tools
against path-traversal and command-argument-injection findings.
2026-10-21 17:12:54 -04:00
Dylan M. Taylor ce89625521 ci: add sonar-project.properties for CI-based analysis
Marks the project ineligible for SonarCloud Automatic Analysis, resolving the
CI-vs-automatic-analysis conflict so the SonarCloud workflow succeeds.
2026-10-21 16:00:28 -04:00
Dylan M. Taylor 20b2c1a1eb ci: add SonarCloud scan via shared reusable workflow
Calls storytold/craft-common-actions/.github/workflows/sonarcloud.yml@main
with secrets: inherit. Adds SonarCloud badge to README where missing and
removes the redundant sonar-project.properties (config now passed by the
reusable workflow).
2026-10-21 15:46:51 -04:00
aiongg 8ce872938f keymap: a failed import change keeps its shortcuts when a later change frees room
The cleanup after an import could remove a chord from a command whose own change had failed, once a later change freed an overrides entry. That command now keeps its bindings, and the change that would have taken its chord is dropped and reported, as when the removal itself fails.
2026-10-21 18:14:21 +00:00
aiongg 315af428c7 keymap: a key whose Latin layout character is no letter runs no letter binding
The suite's egui reports, per key pressed, the character it types on the
Latin layout shortcuts follow (InputState::latin_layout_char). A letter
makes the press that letter; any other character means the key has no
Latin letter, so egui's position fallback no longer turns it into one: on
Dvorak + Russian the key that types й is Dvorak's ', not Ctrl+Q. Without a
report (crates.io egui) the key's position still decides.
2026-10-21 18:05:18 +00:00
aiongg cec769a889 keymap: on layouts that are not Latin, take the letter the toolkit reports
The suite's egui-winit reports a letter key on a layout that is not Latin
as the Latin layout's letter, so on Dvorak + Russian the с key is
Dvorak's J. resolve takes that letter before the key's position; with
crates.io egui the letter is the position, as before.
2026-10-21 17:23:16 +00:00
Dylan M. Taylor 1f805378d4 feat(window): shared craft-window crate for consistent window decorations (#217)
* feat(window): shared crate deciding who draws the window frame

Add craft-window, which decides whether the desktop or the app draws the
window frame (titlebar, borders, window buttons) and applies it to an
egui ViewportBuilder. This fixes the drift where some Craft apps drew
their own titlebar on KDE while others kept KWin's.

The rule: macOS, Windows and X11 keep the desktop frame; a Wayland
compositor with zxdg_decoration_manager_v1 (KDE, Sway, Hyprland, COSMIC)
keeps its frame; one without it (GNOME) leaves the frame to the app.
<PREFIX>_TITLEBAR=app|system|desktop overrides. When the app draws the
frame, the decision carries the window-button Layout from GNOME's
button-layout so the app's header bar matches the desktop's order.

Decision logic only; drawing the buttons stays in each app. Extracted and
generalized from pdfcraft's decorations.rs. forbid(unsafe_code); default
build has no egui dependency (egui feature adds decorate()).

* style(window): rustfmt the Wayland probe and Dispatch impl

cargo fmt --check failed CI: collapse the thread-spawn builder chain and
the Dispatch::event signature onto the lines rustfmt wants (verified with
rustfmt 1.98 against the workspace rustfmt.toml).

* fix(window): address review — WAYLAND_SOCKET, bounded gsettings, checkout creds

- Skip the Wayland probe when WAYLAND_SOCKET is set: connect_to_env would
  take ownership of the inherited fd and unset the variable, closing the
  descriptor winit needs. Keep the desktop frame instead.
- Run the gsettings button-layout lookup behind the same 500 ms bounded
  worker as the Wayland probe, so a stalled gsettings can't block startup.
  Factored the worker into a shared bounded() helper.
- window.yml: set persist-credentials: false on checkout so the token
  isn't left in .git/config while cargo runs dependency build scripts.
- README: document the socket guard and the bounded gsettings lookup.

Verified with rustfmt 1.98 and clippy -D warnings (both feature sets).

* fix(window): reap the gsettings child on timeout; document probe tradeoffs

Follow-up to review: the button-layout lookup now spawns gsettings with
piped output, reads it on a worker, and kills+reaps the child whether it
finishes or times out — so a stalled gsettings leaves neither a blocked
process nor a parked worker (it is a one-shot startup call).

Also document, on the Wayland probe, that an inherited WAYLAND_SOCKET
(rare; normal launches get WAYLAND_DISPLAY) deliberately falls back to the
desktop frame to protect winit's connection — the same frame an app that
doesn't probe would get, a safe default rather than a regression.

Verified: rustfmt 1.98 clean, clippy -D warnings clean (default + egui),
tests pass.
2026-10-21 05:35:20 -04:00
aiongg cdc3b45496 keymap: take whether the layout is Latin from egui when it reports it
The suite's egui reports it from egui-winit on Linux. A report sets the
layout's Latin-ness; frames without one keep learning from typing. On
crates.io egui a private fallback trait reports nothing.
2026-10-21 06:57:03 +00:00
aiongg 1a0e7e7bbf keymap: learn nothing from presses while right Alt is held
egui-winit reports AltGr with neither Ctrl nor Alt, so AltGr text read as plain
typing: German AltGr+M (µ) marked the layout as not Latin and Ctrl+Z resolved
by position as Ctrl+Y. µ, ª and º no longer count as a sign of another script.
2026-10-21 06:08:30 +00:00
aiongg 9c75eda598 keymap: block the position fallback only at positions seen typing something else
AZERTY's Ctrl+Shift+E works before an e has been typed.
2026-10-21 05:49:41 +00:00
aiongg d0acf36588 keymap: Shift presses egui reports as their position run nothing on moved layouts
Dvorak's ⇧, types <, which egui has no key for, so egui reports the
press as W and Ctrl+Shift+, ran Ctrl+Shift+W. Once typing shows the
layout's letters are not on QWERTY positions, such a press resolves to
nothing unless the position is known to type its own letter.
2026-10-21 05:47:51 +00:00
aiongg 86248331bb keymap: read presses by the keyboard layout
Matching, the recorder and labels share one rule (craft-libs#198, track 4):
letters by the layout's Latin letter, or by position on layouts that are not
Latin; digits as typed, else by position; punctuation as typed, without the
Shift the layout needs for it. Layout holds whether the layout is Latin and
its characters at punctuation positions, reported by the platform or learned
from typing. KeyInput holds what the toolkit reports for one press, so a
toolkit that knows the virtual-key code, the macOS command table or the
Shift level can pass it on.
2026-10-21 04:57:06 +00:00
aiongg 9aaf9dfd38 keymap: format, and keep the dispatcher's Default clear of clippy's derive lint 2026-10-20 15:46:00 +00:00
Brandon ThomasandClaude Opus 5.5 e36f189018 Skip CodeRabbit reviews on Dependabot PRs (#195)
Adds .coderabbit.yaml so CodeRabbit no longer reviews or comments on PRs opened by dependabot[bot].

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:41:43 -04:00
aiongg 6d96b4f684 keymap: mark public enums and report structs that will grow non_exhaustive 2026-10-20 15:29:50 +00:00
aiongg 501e2cf1fc keymap: while typing, text-editing chords go to the text field unless an active context binds them 2026-10-20 15:21:54 +00:00
aiongg 423524c1bc keymap: clipboard chords with more modifiers run their bindings with clipboard events off 2026-10-20 15:18:05 +00:00
aiongg 5160611bad keymap: while typing, a Ctrl+Alt press runs unless it typed text in the frame 2026-10-20 15:11:46 +00:00
aiongg 79747aeaae keymap: remove the Text event a bound press typed, also when the web build sends it first 2026-10-20 15:11:21 +00:00
aiongg f4b04e4ad1 keymap: a double press needs both presses in the same panel 2026-10-20 15:09:01 +00:00