From 8e26f405f96800c282f89beb5082acb95161195e Mon Sep 17 00:00:00 2001
From: DivanMe <48186011+Divaaaan@users.noreply.github.com>
Date: Sun, 13 Sep 2026 15:35:55 +0300
Subject: [PATCH] docs: refresh GitHub presentation for Tenebra 0.6.0
---
CHANGELOG.md | 43 +++-
CONTRIBUTING.md | 2 +-
README.md | 384 ++++---------------------------
README.ru.md | 77 +++++++
ROADMAP.md | 6 +-
docs/README.md | 9 +-
docs/assets/README.md | 15 ++
docs/assets/desktop-advanced.png | Bin 0 -> 71360 bytes
docs/assets/desktop-simple.png | Bin 0 -> 38805 bytes
docs/dpi-bypass.md | 39 ++++
docs/installation.md | 68 ++++++
11 files changed, 297 insertions(+), 346 deletions(-)
create mode 100644 README.ru.md
create mode 100644 docs/assets/README.md
create mode 100644 docs/assets/desktop-advanced.png
create mode 100644 docs/assets/desktop-simple.png
create mode 100644 docs/dpi-bypass.md
create mode 100644 docs/installation.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90f85504..16dd2086 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,13 +4,48 @@ All notable changes to Tenebra are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows
[Semantic Versioning](https://semver.org/).
-> **Early days.** Tenebra is at 0.x: the desktop clients (Windows and macOS) are
+> **Early days.** Tenebra is at 0.x: the desktop clients are
> the current focus — see the
-> [project status](README.md#project-status). Expect breaking changes between
+> [project status](README.md#project-status-and-known-limits). Expect breaking changes between
> 0.x releases.
## [Unreleased]
+## [0.6.0] - 2026-09-13
+
+### Changed
+
+- Redesigned the simple and full desktop interfaces, with clearer subscription
+ setup, server selection, connection feedback, settings and diagnostics.
+- Improved keyboard navigation, compact layouts, themes and Russian/English text.
+- Added persistent Windows protection through WFP, with the saved preference,
+ confirmed enforcement and cleanup errors shown separately. Explicit
+ Disconnect releases Tenebra's policy.
+
+### Fixed
+
+- Failed TCP probes no longer prevent manual server selection or claim that
+ the server's VPN protocol cannot connect.
+- Windows service communication verifies the installed service identity and
+ supports ordinary users and administrators, with bounded request waits.
+- System proxy handling tracks the owning user and retains restoration data.
+- Windows installation no longer falsely fails while waiting for service stop
+ in a fresh PowerShell process.
+- Split settings survive routing changes; unusable multihop chains are rejected
+ and repeated engine-crash recovery attempts are bounded.
+
+### Verification scope
+
+This release was published with an explicitly limited acceptance scope.
+Windows installation/upgrade/repair/removal, ordinary-user UI, IPv4 traffic,
+system-proxy restoration and selected engine/service failure cases were checked.
+The complete IPv6, BFE, reboot and other protection matrix remains open.
+The original unavailable-server report and real-world DPI effectiveness have
+not been causally verified. macOS/Linux build checks are not native tunnel
+acceptance. Android and iOS are outside this release.
+
+See the [published release and its verification notice](https://github.com/Divaaaan/tenebra/releases/tag/v0.6.0).
+
## [0.5.11] - 2026-08-31
### Fixed
@@ -1481,7 +1516,9 @@ Initial tagged release.
first run. Updates delivered in-app are minisign-verified against the bundled
key; only the initial download is unsigned.
-[Unreleased]: https://github.com/Divaaaan/tenebra/compare/v0.5.10...HEAD
+[Unreleased]: https://github.com/Divaaaan/tenebra/compare/v0.6.0...HEAD
+[0.6.0]: https://github.com/Divaaaan/tenebra/compare/v0.5.11...v0.6.0
+[0.5.11]: https://github.com/Divaaaan/tenebra/compare/v0.5.10...v0.5.11
[0.5.10]: https://github.com/Divaaaan/tenebra/compare/v0.5.5...v0.5.10
[0.5.5]: https://github.com/Divaaaan/tenebra/compare/v0.5.4...v0.5.5
[0.5.4]: https://github.com/Divaaaan/tenebra/compare/v0.5.3...v0.5.4
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4ef838ad..61060bbc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,7 +18,7 @@ By contributing you agree your work is licensed under the project's license,
- **Triage** — reproducing issues and narrowing them down.
Highest-leverage areas right now (see
-[the status table](README.md#project-status)):
+[the project status](README.md#project-status-and-known-limits)):
1. **Live tunnel bring-up** on Windows (wintun + sing-box, elevated).
2. **New platform adapters** — macOS/Linux (utun), Android (`VpnService`),
diff --git a/README.md b/README.md
index 79ba3eb6..dee8f00c 100644
--- a/README.md
+++ b/README.md
@@ -1,369 +1,77 @@
-

+

-[](https://github.com/Divaaaan/tenebra/actions/workflows/ci.yml)
-[](https://www.gnu.org/licenses/gpl-3.0)
-[](https://github.com/Divaaaan/tenebra/releases/latest)
-[](#project-status)
-
-**A cross-platform VPN client built on [sing-box](https://github.com/SagerNet/sing-box).**
-Desktop first — Windows has an installer-managed service; the current audit candidate still requires native acceptance. macOS and Linux ship for advanced users (see below). The same Go core drives an Android client, in alpha and installed by hand; iOS is a scaffold.
-
-

-
-
-
-> **Project status — early development.** The desktop client is the current
-> focus. Earlier Windows releases have been exercised against real servers;
-> that evidence does not establish native acceptance of the current audit
-> candidate, including its persistent host guard. The required packet, BFE and
-> reboot gates are [documented here](docs/host-protection-acceptance.md).
-> macOS and Linux have had no privileged live-tunnel run signed off.
-> Treat this as pre-release: not yet "production-ready",
-> and expect things to move around. See
-> [Project status](#project-status) for the honest breakdown.
-
-## Why another client
-
-Most clients either lock you into a single protocol or are vague about what they
-do with your traffic. Tenebra:
-
-- speaks the protocols sing-box supports — VLESS/REALITY, Hysteria2, AmneziaWG,
- Shadowsocks, Trojan, VMess;
-- routes Russian destinations directly and sends everything else through the
- tunnel, so latency-sensitive local traffic stays local;
-- falls back between protocols when one gets throttled or blocked, and remembers
- what worked;
-- ships no telemetry, no accounts and no bundled servers — you import your own
- subscription.
-
-## What it does
-
-Everything below is implemented in this repo today (the UI features are desktop):
-
-- **Many protocols, one model.** Import VLESS (incl. REALITY), Hysteria2,
- AmneziaWG, Shadowsocks, Trojan and VMess. A single normalized node model feeds
- a from-scratch sing-box config generator. *(AmneziaWG links import and connect,
- but the bundled stock sing-box applies none of the AWG obfuscation parameters —
- the tunnel runs as plain WireGuard; full AmneziaWG obfuscation is
- [planned](ROADMAP.md#planned) and needs a build that links a fork.)*
-- **Import the way you have it.** Subscription URL, a raw share link, a `.txt`
- file of links, clipboard paste, or a QR code (image file or pasted image).
- Subscription bodies handle a Clash/Mihomo YAML config, base64, or plaintext
- link lists and read the `Subscription-Userinfo` header for traffic used / total
- and expiry.
-- **Smart RU routing.** *Smart* keeps Russian domains and IPs (and your LAN)
- direct and tunnels the rest; *Global* tunnels everything; *Direct* is the
- proxy off. Geodata comes from the official public sing-geoip / sing-geosite
- rule-sets, shipped in the build as local `.srs` binaries and loaded from disk —
- never downloaded while you are connecting. If a build is missing them, *Smart*
- routes like *Global* and says so in the log rather than failing to connect.
-- **DPI bypass that works on the first connect.** Windows only: the client drives
- [zapret](https://github.com/bol-van/zapret) so censored services work at their
- own latency instead of through an exit node. One bundle release is compiled
- into the build so a censored network cannot leave a fresh install with no
- bypass at all; newer releases are downloaded as they are published — see
- [DPI bypass](#dpi-bypass).
-- **Protocol fallback.** A pure state machine walks the last known-good node
- first, then by protocol preference (REALITY → Hysteria2 → AmneziaWG), so a
- blocked or throttled protocol is retried as another. The last good node leads
- the next launch.
-- **Per-app split tunnelling.** *Exclude* sends chosen apps around the tunnel;
- *Include* sends only chosen apps through it. Matched by executable name and
- persisted across restarts.
-- **Honest leak check.** Observes the machine's public IP from redundant echo
- services and runs a best-effort DNS probe, then reports a verdict that never
- fakes a pass — it tells you what it could *not* measure rather than claiming
- "safe". See [docs/control-protocol.md](docs/control-protocol.md#leak-check-leak_check).
-- **Desktop niceties.** System tray that reflects the connection state (with quick
- connect/disconnect), desktop notifications on state changes, `tenebra://` deep
- links (import a subscription or connect a profile), launch at login (optionally
- minimized to the tray), single-instance, live traffic graphs, light/dark themes,
- and English / Russian UI.
-
-The v0.5.11 kill switch was best-effort; its behavior is recorded in the
-[changelog](CHANGELOG.md). The current Windows audit candidate adds persistent
-host protection, with desired settings separate from confirmed policy state.
-Its engine/service-death and reboot guarantees still require
-[native acceptance](docs/host-protection-acceptance.md); they are not established
-by unit tests or prior-release tunnel runs. LAN bypass remains a routing option.
-
-## DPI bypass
-
-Blocking here is done by inspecting traffic, not by address: YouTube can be
-unwatchable on a connection that is otherwise fine, and a tunnel handshake can be
-dropped for looking like a tunnel handshake. **On Windows** Tenebra answers that
-with [zapret](https://github.com/bol-van/zapret) — a separate program that edits
-packets on the way out (splitting the TLS ClientHello, sending decoys, and so on)
-until the filter stops matching them. It runs beside the tunnel rather than
-inside it, so a service the bypass can reach directly stays direct at its own
-latency instead of taking the round trip through an exit node. There is no
-equivalent on macOS or Linux; the tunnel there carries everything.
-
-**Shipped as a floor, downloaded to stay current.** What the bypass needs is the
-[Flowseal/zapret-discord-youtube](https://github.com/Flowseal/zapret-discord-youtube)
-bundle: zapret's Windows build (`winws.exe`), the
-[WinDivert](https://github.com/basil00/WinDivert) packet-interception driver it
-attaches to, the Cygwin runtime that build needs, and the strategy and host lists
-around them. Strategies are a moving target — a set that worked in March is a
-set the filter has since learned — so the current release is fetched from
-upstream. But a client that can only download one is a client with no bypass on
-exactly the networks it exists for, so one release is also compiled into the
-Windows core: the archive upstream published, byte for byte, checked against the
-checksum this build pins for it. It is the floor, never the ceiling — a newer
-release replaces it as soon as one is published and pinned. The macOS and Linux
-binaries carry none of it; there is nothing there that could run a Windows
-packet filter.
-
-**When it happens and where it lands.** On the first connect with no bundle
-present, the core downloads the latest published release and unpacks it into its
-own data directory — `%ProgramData%\Tenebra\data\zapret` under the Windows
-service — then re-checks for a newer one every twelve hours. It is a plain
-download from the upstream release page; nothing about you goes with the request.
-When that download cannot deliver a bundle at all — no network, GitHub blocked,
-a release newer than any checksum this build carries, or an archive that did not
-match the checksum it does — the compiled-in copy is unpacked into the same
-place instead, and the next successful check upgrades past it.
-
-**How to decline the download.** *Settings → Censorship bypass → Update the
-bundle automatically* governs what Tenebra fetches: the first-connect download
-and the twelve-hour re-check alike. Turned off, it asks the release page for
-nothing — press *Update* when you want a newer one, or unpack one into the
-`zapret` directory above yourself. It does not govern the copy compiled into the
-build: those bytes need no
-network and no update, so a first connect with no bundle present still unpacks
-them and a fresh install is never left with the bypass missing. Deleting the
-`zapret` directory removes what is installed; a later connect lays the
-compiled-in copy back down. Running with no bypass at all means the tunnel
-carries every service, censored ones included, through the exit node instead of
-around the filter.
-
-Everything in the bundle, with its license and copyright holder, is listed in
-[THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md#2-components-downloaded-at-runtime).
-
-## Installing
+**A desktop VPN client built on [sing-box](https://github.com/SagerNet/sing-box).**
-**Windows** — from the [Windows Package Manager](https://learn.microsoft.com/windows/package-manager/winget/):
+Bring your own subscription or compatible server link. Tenebra does not include VPN servers or require a Tenebra account.
-```powershell
-winget install Divaaaan.Tenebra
-```
+**English** · [Русский](README.ru.md)
-or grab `Tenebra_x.y.z_x64-setup.exe` from the
-[latest release](https://github.com/Divaaaan/tenebra/releases/latest). Either
-way the installer sets up the background service and the in-app updater keeps
-everything current.
+[](https://github.com/Divaaaan/tenebra/releases/download/v0.6.0/Tenebra_0.6.0_x64-setup.exe)
-**macOS** — download the universal DMG from the
-[latest release](https://github.com/Divaaaan/tenebra/releases/latest), then
-read the [macOS note](#macos-note--read-before-downloading-the-dmg) first —
-the build currently needs a hand-installed root daemon.
+Windows x64 · [All packages](https://github.com/Divaaaan/tenebra/releases/latest) · [What's new in 0.6.0](CHANGELOG.md#060---2026-09-13)
-## Getting a server
-
-Tenebra is a **client** — it ships no servers and hard-codes nothing. You bring
-your own endpoint and import it as a subscription or a share link. Two ways to
-get one:
-
-- **Run your own.** Any [sing-box](https://github.com/SagerNet/sing-box) or Xray
- server works; point Tenebra at its subscription URL.
-- **Use a provider.** Any service that hands you a subscription or a share link
- will do. I run one at **[vpsxd.pro](https://vpsxd.pro)**.
-
-## Project status
-
-| Area | State |
-|------|-------|
-| Go core (parsing, profiles, routing, config gen, fallback, leak logic) | Implemented, unit-tested, no third-party deps |
-| Control protocol (core ↔ UI) | Implemented; covered by Go tests **and** a real-binary e2e |
-| Desktop UI (Tauri 2 + React) | Implemented: all screens, reactive tray, notifications, deep links, autostart, i18n, themes |
-| Windows tunnel (wintun + sing-box) | A background **service** owns the tunnel; installer/update code coordinates app and service. The current audit candidate still needs standard-user installer, live-tunnel and [host-protection acceptance](docs/host-protection-acceptance.md). INC-01 remains open; cause unknown. |
-| macOS tunnel (utun + sing-box) | Builds and runs — universal `.app`/DMG — but see the **macOS note** below: it needs a hand-installed root daemon and is not yet a click-to-run product. No live-tunnel sign-off yet |
-| Linux tunnel (`/dev/net/tun` + sing-box) | Builds and runs — a root **systemd service** owns the tunnel, installed by an Arch package or a `sudo` script; see the **Linux note** below. No live-tunnel sign-off yet |
-| Android (`VpnService` + libbox) | **Alpha, hand-installed** — a Kotlin / Compose client in [`ui-android/`](ui-android/README.md) builds and runs on a device: subscription import, node list with latency badges, an AUTO exit, switching the live exit without a reconnect, connect-on-boot, a Quick Settings tile, in-app logs and crash reports. Routing is *Global* only and there is no DPI bypass. CI builds a debug APK; a tagged release carries a signed one only once the signing key is in CI secrets |
-| iOS (Network Extension) | Scaffold only — none of the Swift under `ui-ios/` has been compiled and no framework has been built; the plan is [docs/porting/ios.md](docs/porting/ios.md) |
-| Release pipeline | Tag-triggered `release` workflow builds the Windows, macOS and Linux bundles plus the Arch package, minisign-signs the in-app updater artifacts, and publishes the GitHub release once every expected asset is on it; Android is a separate workflow on the same tag |
-| Code-signing | Not set up — the Windows installer is Authenticode-unsigned (SmartScreen warns), the macOS build is unsigned/un-notarized (Gatekeeper needs a manual "Open Anyway"), and the Android release APK has no keystore in CI yet |
-
-### macOS note — read before downloading the DMG
-
-The macOS build is **for advanced users right now, not a finished product.** Two
-things are not yet in place, so a plain "download the DMG and drag to
-Applications" will **not** give you a working tunnel:
-
-- **The tunnel needs a privileged helper.** macOS only lets root open the `utun`
- device, so the app talks to a small root **LaunchDaemon** that owns the tunnel.
- That daemon is currently installed **by hand** with a `sudo` script
- ([`scripts/macos/install-daemon.sh`](scripts/macos/install-daemon.sh)) — there
- is no in-app installer for it yet. Without it, the app runs but cannot connect.
-- **The build is unsigned and un-notarized.** First launch needs
- **System Settings → Privacy & Security → Open Anyway**, and updates to the
- daemon are a manual step (the in-app updater refreshes only the app, not the
- root daemon). Since 0.4.4 the app warns with a banner when the daemon has
- fallen behind it; re-run the install script from your checkout to update:
- `sudo bash scripts/macos/install-daemon.sh --from-app /Applications/Tenebra.app --allow-unsigned`.
-
-The click-to-run macOS path — a signed, notarized build with an `SMAppService`
-daemon bundled inside the app (so it installs and updates like the Windows
-service) — needs an Apple Developer ID and is **planned, not done**. Until then,
-use the DMG only if you're comfortable running the install script yourself.
-Windows uses an installer-managed service; the current audit candidate's
-installation and update path still requires [delivery acceptance](docs/delivery-acceptance.md).
-
-### Linux note — the tunnel needs a root service
-
-Linux is the same shape as macOS: only a privileged process may open
-`/dev/net/tun` and install routes, so the app talks to a small root **systemd
-service** that owns the tunnel and serves the control protocol on
-`/run/tenebra.sock`. The app alone cannot connect. Two ways to set it up:
-
-- **Arch Linux — build the package.** [`packaging/arch/PKGBUILD`](packaging/arch/PKGBUILD)
- builds the core, the desktop app and the unit from source and installs them
- with `pacman`:
-
- ```
- cd packaging/arch && makepkg -si
- sudo systemctl enable --now tenebra.service
- ```
-
- Updates come from `pacman`, not the in-app updater — it can only replace an
- AppImage, never files a package manager owns.
-
-- **Any other distribution — the install script.** Fetch the bundled resources,
- then install the daemon from your checkout:
-
- ```
- bash scripts/fetch-resources.sh
- sudo bash scripts/linux/install-daemon.sh --dev
- ```
-
- It is safe to re-run to upgrade, rolls back if an upgrade fails, and
- [`scripts/linux/uninstall-daemon.sh`](scripts/linux/uninstall-daemon.sh)
- removes it. The GUI is a separate `.deb`/AppImage build.
-
-Two limits worth knowing before you install: **system-proxy mode does nothing on
-Linux** (it needs per-desktop settings a root daemon cannot reach, so it stays
-quietly disarmed — tun mode, the default, is unaffected), and the bundled
-sing-box binaries are **glibc-linked**, so musl distributions need their own.
-Full detail, including the systemd sandbox and what is deliberately left out of
-it, is in [docs/porting/linux.md](docs/porting/linux.md).
-
-If you want to help close the gap, the macOS `SMAppService` path and the
-non-desktop adapters are the highest-leverage places — see
-[CONTRIBUTING.md](CONTRIBUTING.md).
+[](https://github.com/Divaaaan/tenebra/actions/workflows/ci.yml)
+[](LICENSE)
-## Repository layout
+
-```
-tenebra/
-├── core/ Go. Platform-agnostic, stdlib-only, fully unit-tested.
-│ ├── model/ Normalized proxy node + config types.
-│ ├── subscription/ Parse vless/hysteria2/ss/trojan/vmess links + sub bodies.
-│ ├── profile/ Named profiles and their atomic on-disk store.
-│ ├── routing/ smart/global/direct + per-app split -> sing-box route/dns.
-│ ├── singbox/ Build a full sing-box config as plain JSON (no sing-box dep).
-│ ├── fallback/ Pure REALITY->Hysteria2->AmneziaWG fallback state machine.
-│ ├── zapret/ Drive the DPI-bypass bundle, embedded + downloaded (Windows).
-│ └── control/ The line-delimited JSON protocol + the daemon.
-├── core-bridge/ The same generator as a mobile-facing library (no sing-box).
-├── mobile/ gomobile wrapper: binds core-bridge + libbox into one artifact.
-├── adapters/
-│ ├── windows/ Spawn & supervise sing-box; traffic via its clash API.
-│ ├── macos/ The same over utun, under the root LaunchDaemon.
-│ └── linux/ The same over /dev/net/tun, under the root systemd service.
-├── cmd/
-│ └── tenebra-core/ The sidecar entry point (talks the protocol on stdin/stdout).
-├── ui-desktop/ Tauri 2 app: Rust shell (src-tauri) + React/TS front end (src).
-├── ui-android/ Kotlin/Compose client: VpnService + libbox (alpha).
-├── ui-ios/ SwiftUI + Network Extension scaffold; never compiled.
-├── deploy/ The privileged daemon's service definitions per platform.
-├── packaging/
-│ └── arch/ PKGBUILD building the whole thing for Arch Linux.
-├── scripts/
-│ ├── fetch-resources.ps1 Download pinned sing-box + wintun (Windows).
-│ ├── fetch-resources.sh The same for macOS and Linux.
-│ ├── build-libbox-android.sh One gomobile bind -> the fused tenebra.aar.
-│ ├── build-libbox.sh The same bind for Apple (xcframework).
-│ ├── macos/ Install/remove the root LaunchDaemon.
-│ └── linux/ Install/remove the root systemd service.
-└── docs/ Architecture, control protocol, the dev guide, porting notes.
-```
+| Platform | Before you install |
+| --- | --- |
+| **Windows** | Installer sets up the background service. The installer is not Authenticode-signed; SmartScreen may warn. |
+| **macOS / Linux** | For advanced users: a privileged helper is required; setup varies by package. No native live-tunnel validation for 0.6.0. [Installation guide](docs/installation.md). |
+| **Android / iOS** | Outside the 0.6.0 release. Android is experimental; iOS is a scaffold. |
-## Building
+
+
+

+
+**VPN-клиент для компьютера на базе [sing-box](https://github.com/SagerNet/sing-box).**
+
+Подключите свою подписку или совместимую ссылку на сервер. В Tenebra нет встроенных VPN-серверов, и аккаунт Tenebra не нужен.
+
+[English](README.md) · **Русский**
+
+[](https://github.com/Divaaaan/tenebra/releases/download/v0.6.0/Tenebra_0.6.0_x64-setup.exe)
+
+Windows x64 · [Все сборки](https://github.com/Divaaaan/tenebra/releases/latest) · [Что нового в 0.6.0](CHANGELOG.md#060---2026-09-13)
+
+[](https://github.com/Divaaaan/tenebra/actions/workflows/ci.yml)
+[](LICENSE)
+
+
+
+| Платформа | Перед установкой |
+| --- | --- |
+| **Windows** | Установщик настраивает фоновую службу. Подписи Authenticode нет; SmartScreen может показать предупреждение. |
+| **macOS / Linux** | Для опытных пользователей: нужна привилегированная служба; способ настройки зависит от пакета. Работа реального туннеля 0.6.0 на этих платформах не подтверждена. [Инструкция](docs/installation.md). |
+| **Android / iOS** | Не входят в релиз 0.6.0. Android — экспериментальный клиент; iOS — заготовка. |
+
+