enBoxer/CHANGELOG.md
en cece41d2ee Tighten IPC socket permissions (chmod 0o700/0o600)
fix(security): the daemon's IPC socket was world-accessible. Any local
user could speak the IPC protocol and type arbitrary text into game
windows via Command::Type.

- src/profile.rs: add chmod_runtime_dir() and chmod_socket(path) helpers
- src/session.rs: call chmod_runtime_dir() after create_dir_all, and
  chmod_socket() right after UnixListener::bind succeeds
- Tests: chmod_socket_sets_0o600, chmod_runtime_dir_sets_0o700 (saved/
  restored live dir perms to avoid clobbering a real session)
- CHANGELOG.md: security note

cargo test 96+/0; clippy clean.
2026-09-16 05:45:48 +02:00

60 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Changelog
## 0.1.0 — unreleased
- Rust CLI daemon: `enboxer run|press|status|macros|doctor`
- YAML profile: maps, targets (`current` / `others` / `all` / groups), `game_binds`
- Configurable `passthrough` (empty by default; example profile uses ESDF)
- Hyprland 0.56 Lua binds installed only while a managed game or VFX overlay is focused
- Key delivery via `hl.dsp.send_shortcut` / `send_key_state` (no game injection)
- Stock loot map: assist → CTM on → Interact with Target once → delay → CTM off
- Video FX: `grim` region capture, overlay viewer, hover pass-through to source slot
- Unit tests for hotkey parse, passthrough, targets, loot sequence, example profile load
- Bind IPC line no longer duplicated `ipc` (Hyprland hotkeys actually reach the daemon)
- Video FX overlay is `mpv` (`--wayland-app-id=enboxer-vfx`) with JSON reload; `grim` capture
- `enboxer run` clears binds on ctrl-c; empty `window_match` matches nothing
- Live check: `send_shortcut` to an unfocused XWayland window; overlay window class `enboxer-vfx`
- Per-character `assist_key` / `follow_key`; map steps using `bind: assist|follow` resolve to the current main's keys
- Layout wizard `borderless` toggle installs a Hyprland `window_rule` (rounding 0, border_size 0) on `run`
- Layout page: drag canvas over the monitor rectangle; tile moves clamp to the monitor bounds
- T8: clipboard IPC verb `clipboard` reads `wl-paste` / `xclip` and delivers Ctrl+V to every non-leader captured slot; GUI button on Session page; routing plan unit-tested
- T11: named-profiles list in File menu (`Load named…` submenu) with Refresh; listing helper unit-tested against a tempdir
- T12: unit test for `type_to_others` routing (`others_clients` helper, excludes leader, per-char × per-slot plan) and for `apply_layout` short-circuiting when `ENBOXER_ALLOW_LAYOUT` is unset
- T9 (real): `src/wayland_layer.rs``zwlr_layer_shell_v1` Wayland client with shm-backed buffers, 3×5 bitmap digit glyphs, `wl_pointer` click routing; per-slot `OverlayHandle` via `OverlayHub` in `session::run`. Live path gated behind `ENBOXER_ENABLE_OVERLAY=1`; `cargo test` does not connect to Wayland
- T10 (real): `src/toplevel_export.rs``zwlr_export_dmabuf_unstable_v1` Wayland client; per-frame format negotiation (ARGB8888 / XRGB8888), synthetic-PNG fallback for tests. Live path gated behind `ENBOXER_ENABLE_TOPLEVEL=1`; `gbm_bo_map` is documented as the upgrade step for actual pixel reads
- T13: mirror-mode mouse click broadcast — `hypr::deliver_click` posts compositor pointer events to every non-leader captured slot; press-and-hold guard deferred
- T14: round-robin bind target (`round_robin` / `rr`) — rotates through ALL slots including the leader, in slot-number order, wrapping; per-map cursor
- T15: Teams + Lutris launcher. `src/team.rs` (Team, list_teams, teams_dir, current_team), `src/lutris.rs` (LutrisGame parser, `load_all` with bad-YAML tolerance), `src/launcher.rs` (SpawnPlan merging Lutris config with per-character wine-prefix override). GUI: Teams menu (New / Switch / Refresh / Show / Delete) and Launch menu (per-character + Launch all); Lutris picker visible only in the New-team flow. Direct Wine spawn — never calls `lutris` CLI
- `game_binds.interact` example uses **Alt+J** (Master's request). Interact with Target is a built-in WoW keybind; enBoxer just routes the keystroke.
- `docs/MACROS.md` rewritten for current retail (The War Within era, 2026): rename "CTM" → Auto-Interact (the CVar), document Alt+J for Interact with Target, document per-character Assist / Follow macro override, add optional Pet Attack / Target Last Target keybinds.
## Unreleased — Interact chain (ISBoxer-style mapped key)
- **Smart interact shortcut.** A step with `bind: interact` now expands at
compile time into the full CTM-on → Interact-with-Target → sleep
`walk_delay_ms` → CTM-off chain, driven by `profile.interact` (`style`
+ `walk_delay_ms`). One user keypress, four keystrokes dispatched to
every captured slot. Styles:
- `standard` (default): chain runs, CTM ends off.
- `auto`: chain runs, CTM stays on (toggle via `ctm_off` later).
- `hold`: press fires CTM-on + Alt+J; put `bind: ctm_off` in
`release_steps` to fire it on hotkey release.
- The example `loot` map (Alt+G) and `interact` map (Alt+I) now use the
shortcut. A `loot_manual` map (Ctrl+Alt+G) exercises the explicit
chain for users who want per-step control.
- New tests: `interact_smart_shortcut_standard_emits_full_sequence`,
`interact_smart_shortcut_auto_emits_two_no_tail`,
`interact_smart_shortcut_hold_emits_press_only`. 92/92 unit tests pass;
clippy clean.
- Docs: `docs/MACROS.md` "Smart interact shortcut" section, `docs/NOTES.md`
callout, `examples/profile.yaml` updated with comments.
> Note: After this change, `bind: "interact"` is a single Alt+J send (game_binds.interact).
> The full chain trigger is now `bind: "smart_interact"`. Examples and tests updated.
- **Security:** IPC runtime dir is now `chmod 0o700` and the Unix socket is
`chmod 0o600` immediately after `UnixListener::bind`. Any local user with
read access could speak our IPC protocol (`Command::Type` etc.); this is
the cheapest defense. Helpers: `profile::chmod_runtime_dir()` and
`profile::chmod_socket(path)`.