Skip to content

fix(ime): keystroke-buffer privacy, composing preservation, and source-review hardening - #18

Merged
hiking90 merged 1 commit into
mainfrom
refactor/source-review-cleanup
Jun 9, 2026
Merged

hiking90 merged 1 commit into
mainfrom
refactor/source-review-cleanup

Conversation

@hiking90

@hiking90 hiking90 commented Jun 9, 2026

Copy link
Copy Markdown
Owner

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.

⚠️ Branch note: PR #17 is marked merged, but its two commits (ed6fdf5, 3cda49a) are not actually in origin/main (git cherry origin/main HEAD reports both as +). This PR re-includes them so the source-review work lands in main.

New in this PR (3ef0b34)

  • Privacy — keystroke logging (KeyEventTap.swift): log recorded focus-steal characters at %{private} instead of %{public}, so plaintext keystrokes don't surface in the unified log.
  • Memory hygiene — keyBuffer expiry (KeyEventTap.swift): 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 provably never removed — the feature is preserved.
  • Correctness — activateApp flush contract (InputStateCoordinator.swift): 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).

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-path

Review notes

  • Other findings from the review were verified and dropped as overstated or refuted (e.g. a claimed 세벌식 ssang-consonant backspace "bug" turned out to be intended, consistent keystroke-reversal; distributed-notification threading and HID stop() ordering were refuted as main-run-loop-serialized).
  • The keyBuffer expiry was originally proposed as "clear on deactivateServer," 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 OK
  • cargo test -p ongeul-automata — all pass

🤖 Generated with Claude Code

…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>
@hiking90
hiking90 merged commit 3284a28 into main Jun 9, 2026
2 checks passed
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