From a6dd567c0a29cfa08bfb0da3735de1b515a96a0d Mon Sep 17 00:00:00 2001 From: marcusH Date: Wed, 22 Jul 2026 09:56:08 +0200 Subject: [PATCH] =?UTF-8?q?README:=20Architektur=C3=BCbersicht,=20CSP-Zeil?= =?UTF-8?q?e=20nachgezogen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer Abschnitt Architecture: die drei Prozessrollen des einen Binaries (aus Project layout hierher gezogen, dort steht jetzt ein Verweis), der gemeinsame Look über die Plattformen und der Anchor-Kontrakt als Tabelle — ein Codepfad show_popup, drei Herkünfte der Platzierung. Dazu der ehrliche Linux-Absatz: Desktop x Sessiontyp x Tray-Host ist eine breite Matrix, die kein Release ganz testet; auf einer ungetesteten Kombination läuft das Popup, kann aber beim ersten Mal woanders landen als am Icon. Die CSP-Zeile im Sicherheitsmodell nennt jetzt style-src ohne unsafe-inline und den Grund, warum die Fenster-Styles in eigenen CSS-Dateien liegen. An tauri.conf.json gegengelesen: unsafe-inline gibt es nur in der devCsp. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a2ec54b..496dffe 100644 --- a/README.md +++ b/README.md @@ -87,9 +87,33 @@ The installers are hand-tested per release. Current state: Fedora 44 via rpm on Follows. +## Architecture + +One binary, three process roles: + +- **Main app** (`ai-control`) — tray, main window, management, session watcher. +- **Terminal process** (`ai-control --terminal `) — one window with its own PTY; launches Claude Code in the project directory with the assigned pool's config directory. On macOS it carries its own Dock icon and Cmd-Tab entry, on Linux its own app id and `.desktop` file. +- **MCP server** (`ai-control --mcp-panel`) — stdio server started by Claude Code itself; no GUI. + +Running projects are recognised by their terminal processes (`pgrep` for `--terminal `) — there is no state file that could go stale. + +**One look, every platform.** Windows are frameless and draw their own header as the title bar, styled from theme variables: macOS keeps the traffic lights as an overlay, Linux gets its own window buttons. The tray popup is the same HTML window everywhere — what differs is only how the click arrives and who places the window. + +**Placement follows a contract.** `show_popup` is a single code path; where the popup lands is decided by the anchor the tray integration hands it: + +| Anchor | Where it comes from | Placement | +|---|---|---| +| `IconRect` | native tray (macOS, Windows) | popup's right edge at the tray icon — below the menu bar, above the taskbar | +| `Click` | StatusNotifierItem (KDE, XFCE, Cinnamon) | at the activate coordinates when the host supplies usable ones, otherwise at the pointer, clamped into the monitor | +| `Managed` | GNOME shell extension, KWin script, Cinnamon extension | the compositor places the window itself | + +GNOME has no tray at all, so the bundled shell extension provides the icon and relays the click over D-Bus. On Wayland a window cannot position itself, which is why KDE and Cinnamon get a small script/extension for that job. + +**Linux, honestly:** desktop × session type (X11/Wayland) × tray host is a wide matrix, and no release can test all of it. What was tested is listed under [Installer tests](#installer-tests). On an untested combination the popup works, but its first placement may sit somewhere other than at the tray icon. + ## Security model -- **CSP** — the WebViews run under `default-src 'self'`; scripts and connections are limited to the app itself and the Tauri IPC endpoint (dev mode additionally allows the Vite dev server). +- **CSP** — the WebViews run under `default-src 'self'`; scripts, styles, and connections are limited to the app itself and the Tauri IPC endpoint (dev mode additionally allows the Vite dev server and inline styles for hot reload). `style-src` carries no `unsafe-inline`: the window styles live in their own CSS files rather than in the HTML heads, so the policy holds without an exception. - **Per-window capabilities, deny-by-default** — four capability files, one per window group: `main` (management, broadest command set), `popup` (list/start projects only), `term-*` (PTY plus docked panel), `panel-*` (panel/archive channels only — no PTY, no management). A backend command is callable only from windows whose capability lists it. - **Pools separate configuration, not access** — keychain entries are deliberately readable without a prompt; any process running as your user can read any pool key. No isolation promise is made or implied. @@ -131,13 +155,7 @@ Deleting a project is scoped in three stages, each preceded by a preview of the └── deploy-windows.ps1 run the freshest NSIS installer ``` -Process roles from one binary: - -- **Main app** (`ai-control`) — tray, main window, management, watcher. -- **Terminal process** (`ai-control --terminal `) — one window with its own PTY; launches Claude Code in the project directory with the assigned pool's `CLAUDE_CONFIG_DIR`. -- **MCP server** (`ai-control --mcp-panel`) — stdio server started by Claude Code itself; no GUI. - -Running projects are detected through their terminal processes (`pgrep` for `--terminal `), without a state file. +The three process roles that binary takes are described under [Architecture](#architecture). ## Tooling