162 lines
5.5 KiB
Markdown
162 lines
5.5 KiB
Markdown
# Архитектура 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.
|