Commit Graph

3 Commits

Author SHA1 Message Date
xah30 dbee9d8b93 fix(aura-gui): rename product to 'Aura' + uppercase SETENV in sudoers
Two bugs visible after user's first Install-admin-access click:

1) `visudo -c` rejected the fragment because sudoers tags must be UPPERCASE.
   We wrote `setenv:` (lowercase) which sudoers does not recognise as a tag
   and treats as a command path, producing a syntax error at column 29 of
   /etc/sudoers.d/aura-gui:2 — and worse, the broken file stayed on disk
   so every subsequent `sudo` complained about the syntax error too (sudo
   still functions but the warning is noise).

   Fix: drop the `setenv:` tag entirely. We never needed it — the GUI only
   passes RUST_LOG to the child via env(), which `sudo -E` would forward
   but we deliberately chose not to (smaller surface). Removing the tag
   also removes the failure mode.

2) Product rename per user feedback ("переименуй пакет на просто Aura"):
   - tauri.conf.json `productName` and window title: `aura-gui` -> `Aura`
   - bundle now produces /Applications/Aura.app and Aura_0.1.0_aarch64.dmg
   - identifier `ru.undergr0und.aura` was already correct, no change
   - sudoers file is now /etc/sudoers.d/aura (was aura-gui), so the success
     message and revert hint are updated accordingly

The internal MacOS/ binary is still named `aura-gui` (Tauri uses the Cargo
crate name there) — not user-visible, only the dev internals see it.

Manual cleanup also performed on the dev host:
- /Applications/aura-gui.app removed
- /etc/sudoers.d/aura-gui (the broken fragment from the first failed
  install attempt) removed via `osascript ... with administrator
  privileges` so sudo is no longer logging syntax errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 19:39:04 +03:00
xah30 1635190797 feat(aura-gui): privilege escalation via sudo + one-click NOPASSWD installer
The v0.1 GUI's Connect button was broken in practice: the Tauri app launched
from /Applications runs as the desktop user, so `Command::new(aura).spawn()`
started aura without root. aura died in ms with EPERM at TUN creation, faster
than the 1.5 s status poller could catch — the UI just silently flipped back
to "disconnected" with no clue.

## Fix

* `cli_proc::spawn_client` now prepends `sudo -n` on Unix. After spawn it
  blocks for 1.5 s and checks `try_wait`; if the child already exited, it
  reads the stderr ring's last 20 lines and returns an anyhow Error with
  that tail + a hint list of common causes. The Tauri command surfaces it
  to the frontend's `error` state where the UI renders it as a multi-line
  `<pre>` block instead of the previous single-line text.
* `ClientHandle::kill` no longer uses `Child::kill` (SIGKILL) on its sudo
  parent — that would have left aura orphaned with the TUN lingering.
  Sends SIGTERM to sudo, which sudo forwards to aura, giving the inner
  `OsRouteGuard::Drop` 2 s to run cleanup. Falls back to SIGKILL only after
  the grace period.

## One-click NOPASSWD installer

Two new Tauri commands plus a UI banner:

* `check_admin_access` — runs `sudo -n aura --help` and returns whether the
  sudoers entry is in place. Used by the React side to decide whether to
  show the banner.
* `install_sudoers_admin` — runs `osascript ... with administrator
  privileges` which surfaces the native macOS auth dialog, then writes
  `/etc/sudoers.d/aura-gui` scoped to `<aura> client *` only (not arbitrary
  aura invocations), runs `visudo -c` for syntax validation, and reports
  success or the syntax error.

The frontend shows a yellow "One-time setup needed" banner above the
profile list whenever `adminReady === false`. Clicking the button pops the
Mac password dialog once; from then on Connect is a single click with no
prompt.

## UI feedback

* "Connecting…" disabled state on the Connect button while spawn_client's
  1.5 s wait is in progress
* Errors render as monospace `<pre>` so the multi-line stderr tail is
  readable
* `.error` and `.admin-banner` CSS classes added to App.css

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 19:32:38 +03:00
xah30 40b38beb11 feat(aura-gui): v0.1 Tauri-based desktop client — system tray + profile manager + admin status
New crate (kept out of the cargo workspace so the protocol-side check/test cycle stays fast):
a Tauri 2 + React 19 + TypeScript desktop app that runs in the system tray and manages
`aura client` for the user. The clash-verge replacement we settled on instead of trying to
shoehorn AuraVPN's L3 IP-tunnel into a clash-verge L4 outbound.

## What's wired

- **Profile manager** — `aura-gui/src-tauri/src/profiles.rs`. App-data layout
  (`~/Library/Application Support/ru.undergr0und.aura/profiles/<id>/` on macOS, the
  equivalent on Linux + Windows). `import_profile_from_tgz` accepts the same bundle shape
  `aura provision-client` emits, detects flat vs single-dir layouts, and refuses overwrites
  unless the operator deletes first. `delete_profile` refuses symlinks.

- **Connection control** — `cli_proc.rs`. Spawns `aura client --config <profile>/client.toml
  --admin-socket /tmp/aura-admin-<uid>-<profile>.sock`, captures stderr into a bounded
  in-memory ring (200 lines) for the UI to tail, kills via `Child::kill` on disconnect.
  Per-profile / per-uid socket paths so two GUIs (or two profiles) don't collide.

- **Live status** — `admin.rs`. Tiny JSON-line client for the v3.3 admin socket. Polled by
  the React app every 1.5 s: peer id, rx/tx packets, default action, rule count. Falls back
  gracefully (admin_error in the response) when the handshake hasn't completed yet.

- **System tray** — `lib.rs` `setup` callback. Three-item menu (Open AuraVPN / Disconnect /
  Quit). The window's close button hides to the tray instead of exiting — the app keeps
  running so the VPN stays connected; the user explicitly chooses Quit.

- **Frontend** — `src/App.tsx`. Single-page layout: profile list (with badge for missing
  files), connect/disconnect button per profile, status table, collapsible logs panel,
  binary-path picker at the bottom. Dark-mode CSS by default; the same look as a typical
  WireGuard / Tailscale-style tray app.

## What's deferred for v0.2

- Auto-start at login (launchd plist / systemd user unit / Windows Run key)
- Code signing + notarization
- Persisting the aura binary path between sessions
- Per-profile route overrides editor
- Live log streaming (today the frontend polls the ring buffer)
- Admin status query on Windows (today's `admin.rs` Unix-only; Windows path returns a clear
  "not supported yet" error)
- Polkit / authorization-services prompt for the TUN-needs-root step (today the operator
  has to launch the GUI from a privileged context, e.g. `sudo open -a aura-gui` on macOS)

## Workspace hygiene

Cargo workspace at the repo root now has `exclude = ["aura-gui"]` so the protocol crates'
`cargo check --workspace` / `cargo test --workspace` don't pull in the tauri + wry + webview
dep graph. The GUI builds standalone from `aura-gui/` via `npm run tauri build`.

## Validation

- `cd aura-gui/src-tauri && cargo check` — green
- `cd aura-gui/src-tauri && cargo clippy -- -D warnings` — clean
- `cd aura-gui/src-tauri && cargo fmt --check` — clean
- `cd aura-gui && npm run build` — frontend tsc + vite build succeeds
- Full `npm run tauri dev` not exercised in this session (would open a real window) — should
  work; if it breaks the surface area is small enough that next session fixes it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 17:47:51 +03:00