docs: document platform layer rationale in ARCHITECTURE

Explain why autostart, file manager, shell, and winproc are OS-specific, where compile-time vs runtime branching applies, and rules for new platform code.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-05 22:46:48 +03:00
parent 5b0e6fe51b
commit 1240297cca
3 changed files with 67 additions and 1 deletions
+2 -1
View File
@@ -8,7 +8,8 @@ application service, scheduler, storage, and command runner in one binary.
- [docs/STANDARDS.md](docs/STANDARDS.md) — **required.** Code-quality rules and - [docs/STANDARDS.md](docs/STANDARDS.md) — **required.** Code-quality rules and
the list of intentional behavior. Do not "fix" anything listed there as the list of intentional behavior. Do not "fix" anything listed there as
intentional; if a change contradicts it, update the document in the same commit. intentional; if a change contradicts it, update the document in the same commit.
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — package contracts and event flow. - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — package contracts, event flow, and
§Platform layer (why and where OS-specific code lives).
- [docs/TESTS.md](docs/TESTS.md) — test layout and conventions. - [docs/TESTS.md](docs/TESTS.md) — test layout and conventions.
- [docs/ROADMAP.md](docs/ROADMAP.md) — deliberately out of scope. - [docs/ROADMAP.md](docs/ROADMAP.md) — deliberately out of scope.
+59
View File
@@ -57,6 +57,65 @@ flowchart LR
svc -->|"Set / Status via Manager"| autostart svc -->|"Set / Status via Manager"| autostart
``` ```
## Platform layer
GoSentry ships one binary per target OS. Platform-specific code is not a
workaround for missing cross-platform support — it **is** the cross-platform
strategy: shared interfaces and call sites, with OS-specific implementations
selected at **compile time** (`*_windows.go`, `//go:build linux`, and similar).
Runtime `runtime.GOOS` checks appear only for small UI details (see below), not
for autostart, file-manager integration, or command invocation.
Callers (`app.Service`, `ui`, `runner`) depend on the shared API; they do not
branch on the operating system.
| Package / file | Windows | Linux | Other (`!windows && !linux`) |
| --- | --- | --- | --- |
| `platform/autostart` | Startup-folder `.lnk` shortcut | XDG `~/.config/autostart/gosentry.desktop` | Stub — `Set` returns an error when enabled |
| `platform/desktop` | no-op | Installs `.desktop` + icon under XDG data home | no-op |
| `platform/filemanager` | `explorer` | `xdg-open` | Unsupported — `Open` returns an error |
| `platform/winproc` | `CREATE_NO_WINDOW` / `HideWindow` on child processes | no-op | no-op |
| `runner/invocation_*` | `cmd.exe /S /C` with Windows-safe quoting | `sh -c` | `sh -c` (same as Linux) |
**Why separate implementations are required**
- **Autostart** — each OS defines its own login startup mechanism (shortcut,
XDG Autostart, LaunchAgents on macOS). There is no portable API in Go, Fyne, or
the standard library; a third-party helper would still wrap the same per-OS
code behind an interface.
- **Opening a folder** — the desktop shell exposes no shared “reveal in file
manager” call; each platform invokes its registered handler (`explorer`,
`xdg-open`, `open` on macOS).
- **Command shell** — users expect OS-native semantics (`cmd.exe` batch files,
`%VAR%`, and path rules on Windows; POSIX `sh` on Linux). A single shell for
all platforms would break commands on one side or the other.
- **Hidden console window** — launching a child process from a GUI app can flash
a console on Windows only; Linux and macOS do not need equivalent flags.
**Deliberate platform choices (not OS API limits)**
- **Window and tray icons** — Fyne accepts icons on every platform, but Windows
renders the notification area and titlebar from multi-size `.ico` resources
(embedded via `packaging/windows/gosentry.rc`), while Linux StatusNotifier
trays scale better from a larger PNG. `ui/run.go` and `ui/tray.go` branch on
`runtime.GOOS` for asset selection only.
- **Sample job commands** in `storage/store.go` — demo `echo` lines differ only
because shell quoting rules differ; real jobs are user-authored per platform.
**Adding new platform code**
- Put OS integration in `src/platform/<name>/` with a small shared API, or use
`*_GOOS.go` files in the owning package when the surface is a single function
(as in `runner/invocation_*`).
- Do not scatter `runtime.GOOS` through `app.Service` or UI business logic.
- Unsupported platforms get an explicit stub (return an error or no-op) rather
than silently doing nothing — see `autostart_other.go` and
`filemanager_other.go`.
macOS autostart and file-manager handlers are not implemented yet; see
[ROADMAP.md](ROADMAP.md) for blocked or deferred cross-platform work (for
example window-maximized detection, which would need per-OS native calls).
## Main Flows ## Main Flows
1. Startup: 1. Startup:
+6
View File
@@ -4,6 +4,12 @@ All notable GoSentry changes are recorded in this file.
## 1.0.1 - 2026-08-04 ## 1.0.1 - 2026-08-04
**Platform layer rationale is documented in ARCHITECTURE.md.**
- **`docs/ARCHITECTURE.md`** — new §Platform layer: why autostart, file manager,
shell, and winproc are OS-specific; compile-time vs runtime branching; rules
for adding platform code.
**KeepRunningInTray is wired to runtime; autostart respects the tray setting.** **KeepRunningInTray is wired to runtime; autostart respects the tray setting.**
**Application:** **Application:**