fix(ime): keystroke-buffer privacy, composing preservation, and source-review hardening - #18
Merged
Merged
Conversation
…e-activation
Three findings from a multi-perspective source review:
- KeyEventTap: log recorded focus-steal characters at %{private} instead of
%{public}, so plaintext keystrokes don't surface in the unified log.
- KeyEventTap: add a hard 0.5s expiry timer for keyBuffer so decoded
characters don't linger in memory after typing stops. The timeout is
aligned with focus-steal's own give-up threshold (first key > 0.5s old),
so keys it would actually replay are never removed.
- InputStateCoordinator.activateApp: on same-app re-activation (no
intervening deactivateServer) honor set_mode's flush contract — capture
the flush result on Korean->English and surface it via StateEffect, so an
in-progress composing syllable isn't silently dropped. The app-switch path
is unchanged (reset() already clears the buffer there).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three new fixes from a multi-perspective source review (Rust correctness · Swift concurrency/lifecycle · FFI boundary · security · architecture), plus two earlier source-review commits.
New in this PR (
3ef0b34)%{private}instead of%{public}, so plaintext keystrokes don't surface in the unified log.keyBufferso decoded characters don't linger in memory after typing stops. The timeout is aligned with focus-steal's own give-up threshold (first key > 0.5s old), so keys it would actually replay are provably never removed — the feature is preserved.activateAppflush contract (InputStateCoordinator.swift): on same-app re-activation (no interveningdeactivateServer), honorset_mode's flush contract — capture the flush result on Korean→English and surface it viaStateEffect, so an in-progress composing syllable isn't silently dropped. The app-switch path is unchanged (reset()already clears the buffer there).Also lands (from PR #17, not yet in
main)3cda49a— refactor(automata): harden engine per source review (jamo/jaso/lib/unicode)ed6fdf5— refactor(ime): stop per-keystroke layout retry; document Control+[ dual-pathReview notes
stop()ordering were refuted as main-run-loop-serialized).keyBufferexpiry was originally proposed as "clear ondeactivateServer," but that would break focus-steal (which relies on the buffer surviving deactivate→activate). The hard-timer approach was chosen specifically to avoid that regression — worth a manual check of focus-steal (Korean replay during app focus changes).Verification
./scripts/build.sh— Swift compile + bundle + sign OKcargo test -p ongeul-automata— all pass🤖 Generated with Claude Code