RKNnoVPN/RKNNOVPN_ARCHITECTURE.md
loop-uh 5260d4f31a Recover uncommitted working tree from user-supplied archive
Preserved on a recovery branch; stable main remains at v2.4.1.
2026-08-07 00:32:07 +03:00

162 lines
5.5 KiB
Markdown
Raw Permalink 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.

# Архитектура RKNnoVPN
RKNnoVPN - прозрачный прокси-стек для rooted Android без Android `VpnService`,
TUN-интерфейса и системной VPN-индикации. Архитектура v2 является local-first:
APK полностью usable без root/module, а root runtime является опциональным
исполнителем сетевой конфигурации.
## Ownership
### APK
APK owns:
- user profile;
- nodes and subscriptions;
- subscription fetch/parse/merge;
- update check and artifact download;
- UI state and user-visible settings;
- rendering the root runtime config passed to the module.
APK can run without root/module. Missing, old, denied or malformed runtime must
disable only runtime actions such as start/stop/reset/logs/module staging. It
must not block profile editing, subscription management, update checks, or app
startup.
### Runtime/module
Runtime/module owns:
- applying rendered runtime config;
- starting, stopping and resetting root networking;
- `sing-box`/Xray process lifecycle;
- iptables/DNS/policy-routing scripts;
- minimal status/logs/version responses.
Runtime/module is optional. Every runtime action must exact-match the APK
release version and wire epoch. Negotiation, startup remediation loops and
generated method surfaces are not supported architecture.
## Removed Old Paths
Do not restore:
- APK startup -> root runtime status probe -> generated surface parse ->
blocked UI;
- runtime-owned user profile files;
- root-required subscriptions;
- root-required update check/download;
- generated method-surface parsing or method capability gates in APK startup;
- embedded panel/config fallbacks or profile carry-forward for old installs;
- socket/JSON-RPC control plane.
Unsupported old state should fail clearly or be replaced by current canonical
state. It should not be carried forward silently.
## Current Control Flow
```text
APK profile/subscriptions/settings
-> APK renders runtime config JSON
-> su -c /data/adb/modules/rknnovpn/bin/rknnovpn-runtime apply <config>
-> rknnovpn-runtime validates/saves module config
-> rknnovpn-runtime renders sing-box/Xray runtime files
-> start/stop/reset operate only on root networking
```
`rknnovpn-runtime version` returns release version, version code and wire epoch.
The APK compares those values against its own release before runtime actions.
`rknnovpn-runtime status` returns only runtime state needed by the UI: connection
state, minimal health booleans, uptime and traffic when available.
It must not return APK-owned profile, subscription, update check or update
download state.
`rknnovpn-runtime start`, `stop`, `restart` and `reset` return an explicit
runtime action result envelope, not a bare status snapshot. The action result
contains:
```text
accepted, status, stage, runtimeCode, userMessage, debug, rollbackApplied
```
This lets the APK distinguish a valid runtime response whose action was rejected
or degraded from a missing runtime, root denial, timeout, non-zero shell failure
or malformed protocol response. A rejected action still publishes the returned
runtime status as a reachable runtime result; only transport/protocol failures
mark the root runtime unavailable.
`rknnovpn-runtime logs` returns bounded runtime logs. It must not expose raw APK
profile storage.
Runtime CLI contract checks are fixture-based, not generated. The APK test
resources under `app/app/src/test/resources/runtime/` and Go fixtures under
`runtime/testdata/` must stay byte-equivalent for minimal `version`, `status`,
runtime action, `ping`, and `test-node` envelopes. These fixtures are exact-version
protocol smoke tests only; do not add codegen, method negotiation, capability
discovery or a generated daemon contract back into this path.
## Storage
APK profile storage:
```text
<APK private files>/rknnovpn/profile.json
```
This is the only user profile source of truth.
Runtime config storage:
```text
/data/adb/modules/rknnovpn/config/config.json
```
This is a rendered runtime config owned by the apply path. It may contain a
`profile` projection needed by the renderer, but that projection is not a user
profile database and must not be treated as runtime-owned user intent.
Rendered core config:
```text
/data/adb/modules/rknnovpn/config/rendered/singbox.json
```
Root runtime cleanup is owned by:
```text
/data/adb/modules/rknnovpn/scripts/rescue_reset.sh
```
Shared module paths, marker semantics and permission helpers live in:
```text
/data/adb/modules/rknnovpn/scripts/lib/rknnovpn_env.sh
```
## Update Flow
APK checks GitHub releases, downloads module/APK artifacts, and verifies
checksums. Module staging is a runtime action because it writes to root-owned
module storage, so it requires exact APK/runtime version match. Update
check/download themselves must not require runtime.
Runtime module staging must build the root-manager pending update layout:
```text
/data/adb/modules_update/rknnovpn
/data/adb/ksu/modules_update/rknnovpn
/data/adb/ap/modules_update/rknnovpn
```
The staged directory is an already-materialized module layout with `bin/`,
`scripts/`, `config/`, `run/`, `logs/`, the installed release catalog
(`releases/<version>/install-manifest.json` plus `current`), and module
entrypoint files. It must not be a raw downloaded module zip stored under the
active module's `releases/` catalog.
## Verification Surface
GitHub Actions is the authoritative broad verification and release surface.
Local checks should stay focused on the edited slice unless explicitly requested
or needed to debug a CI failure.