update docs with app management and sandbox system documentation
This commit is contained in:
262
CLAUDE.md
262
CLAUDE.md
@@ -21,6 +21,8 @@ Mosis is a **virtual smartphone OS** for VR games and applications. It provides
|
|||||||
| Component | Status | Notes |
|
| Component | Status | Notes |
|
||||||
|-----------|--------|-------|
|
|-----------|--------|-------|
|
||||||
| MosisService | ✅ Working | RmlUi rendering, touch input, navigation |
|
| MosisService | ✅ Working | RmlUi rendering, touch input, navigation |
|
||||||
|
| App Management | ✅ Working | Install/uninstall apps, sandbox integration |
|
||||||
|
| Lua Sandbox | ✅ Working | 149 security tests passing |
|
||||||
| Desktop Designer | ✅ Working | Hot-reload, hierarchy dump, recording |
|
| Desktop Designer | ✅ Working | Hot-reload, hierarchy dump, recording |
|
||||||
| Designer Tests | ✅ 5/5 Passing | Navigation tests automated |
|
| Designer Tests | ✅ 5/5 Passing | Navigation tests automated |
|
||||||
| MosisVR (Unity) | ✅ Building | OpenGL backend working, Vulkan in progress |
|
| MosisVR (Unity) | ✅ Building | OpenGL backend working, Vulkan in progress |
|
||||||
@@ -31,10 +33,11 @@ Mosis is a **virtual smartphone OS** for VR games and applications. It provides
|
|||||||
| Component | Location | Purpose |
|
| Component | Location | Purpose |
|
||||||
|-----------|----------|---------|
|
|-----------|----------|---------|
|
||||||
| Android Service | `src/main/` | Native service running RmlUi renderer |
|
| Android Service | `src/main/` | Native service running RmlUi renderer |
|
||||||
|
| App Management | `src/main/cpp/apps/` | App install/uninstall/launch with sandbox |
|
||||||
|
| Lua Sandbox | `src/main/cpp/sandbox/` | Per-app Lua isolation (22 modules) |
|
||||||
| Desktop Designer | `designer/` | UI development with hot-reload |
|
| Desktop Designer | `designer/` | UI development with hot-reload |
|
||||||
| Designer Tests | `designer-test/` | Automated UI testing framework |
|
| Designer Tests | `designer-test/` | Automated UI testing framework |
|
||||||
| Sandbox Tests | `sandbox-test/` | Lua sandbox security tests |
|
| Sandbox Tests | `sandbox-test/` | Lua sandbox security tests (149 tests) |
|
||||||
| Lua Sandbox | `src/main/cpp/sandbox/` | Per-app Lua isolation |
|
|
||||||
| UI Assets | `src/main/assets/` | Shared RML/RCSS/Lua assets |
|
| UI Assets | `src/main/assets/` | Shared RML/RCSS/Lua assets |
|
||||||
|
|
||||||
## Build Commands
|
## Build Commands
|
||||||
@@ -159,6 +162,7 @@ Kotlin NativeService → JNI → mosis-service (IMosisService)
|
|||||||
|
|
||||||
### Native Code Structure (src/main/cpp/)
|
### Native Code Structure (src/main/cpp/)
|
||||||
|
|
||||||
|
**Core:**
|
||||||
- `kernel.cpp` - Core rendering engine, RmlUi integration, event processing
|
- `kernel.cpp` - Core rendering engine, RmlUi integration, event processing
|
||||||
- `mosis-service.cpp` - Binder service implementation, JNI entry points
|
- `mosis-service.cpp` - Binder service implementation, JNI entry points
|
||||||
- `mosis-test.cpp` - Test client implementation
|
- `mosis-test.cpp` - Test client implementation
|
||||||
@@ -167,6 +171,31 @@ Kotlin NativeService → JNI → mosis-service (IMosisService)
|
|||||||
- `RmlUi_Renderer_GL3.cpp` - RmlUi OpenGL renderer backend
|
- `RmlUi_Renderer_GL3.cpp` - RmlUi OpenGL renderer backend
|
||||||
- `assets_manager.cpp` - Android AssetManager integration
|
- `assets_manager.cpp` - Android AssetManager integration
|
||||||
|
|
||||||
|
**App Management (`apps/`):**
|
||||||
|
- `app_manager.cpp` - App install/uninstall/launch lifecycle
|
||||||
|
- `app_api.cpp` - Lua API bindings for app management
|
||||||
|
- `update_service.cpp` - Background update checking
|
||||||
|
|
||||||
|
**Lua Sandbox (`sandbox/`):**
|
||||||
|
- `sandbox_manager.cpp` - Multi-app sandbox orchestrator
|
||||||
|
- `lua_sandbox.cpp` - Core Lua sandbox with resource limits
|
||||||
|
- `permission_gate.cpp` - Permission system (normal/dangerous/signature)
|
||||||
|
- `virtual_fs.cpp` - Per-app virtual filesystem with quotas
|
||||||
|
- `database_manager.cpp` - SQLite database per app
|
||||||
|
- `network_manager.cpp` - HTTP request validation
|
||||||
|
- `websocket_manager.cpp` - WebSocket connections
|
||||||
|
- `timer_manager.cpp` - setTimeout/setInterval implementation
|
||||||
|
- `json_api.cpp` - Safe JSON encode/decode
|
||||||
|
- `crypto_api.cpp` - Cryptographic functions (SHA256, HMAC)
|
||||||
|
- `camera_interface.cpp` - Camera access with indicators
|
||||||
|
- `microphone_interface.cpp` - Microphone access with indicators
|
||||||
|
- `audio_output.cpp` - Audio playback
|
||||||
|
- `location_interface.cpp` - GPS with precision reduction
|
||||||
|
- `sensor_interface.cpp` - Accelerometer, gyroscope, etc.
|
||||||
|
- `bluetooth_interface.cpp` - Bluetooth device access
|
||||||
|
- `contacts_interface.cpp` - Contacts read/write
|
||||||
|
- `message_bus.cpp` - Inter-app communication
|
||||||
|
|
||||||
## Code Style
|
## Code Style
|
||||||
|
|
||||||
- C++23 standard with modern features (std::span, std::format)
|
- C++23 standard with modern features (std::span, std::format)
|
||||||
@@ -176,7 +205,7 @@ Kotlin NativeService → JNI → mosis-service (IMosisService)
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- vcpkg manages native dependencies (RmlUi, GLFW, Freetype, Lua, libpng, nlohmann-json)
|
- vcpkg manages native dependencies (RmlUi, GLFW, Freetype, Lua, libpng, nlohmann-json, minizip, sqlite3)
|
||||||
- CMake build system with vcpkg toolchain integration
|
- CMake build system with vcpkg toolchain integration
|
||||||
- Android target architecture: arm64-v8a only
|
- Android target architecture: arm64-v8a only
|
||||||
- Desktop target: Windows x64 (MSVC)
|
- Desktop target: Windows x64 (MSVC)
|
||||||
@@ -996,3 +1025,230 @@ Self-hosted on Synology NAS via Docker:
|
|||||||
3. **Pure Go** - `modernc.org/sqlite` (no CGO required)
|
3. **Pure Go** - `modernc.org/sqlite` (no CGO required)
|
||||||
4. **Server-rendered** - htmx for interactivity, no SPA framework
|
4. **Server-rendered** - htmx for interactivity, no SPA framework
|
||||||
5. **Background workers** - Go goroutines for aggregation/cleanup jobs
|
5. **Background workers** - Go goroutines for aggregation/cleanup jobs
|
||||||
|
|
||||||
|
## App Management System (M10)
|
||||||
|
|
||||||
|
The device-side app management system handles installation, updates, and launching of third-party apps.
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ AppManager │
|
||||||
|
│ - Install/Uninstall apps from .mosis packages │
|
||||||
|
│ - Track installed apps in JSON registry │
|
||||||
|
│ - Manage app data/cache directories │
|
||||||
|
└─────────────────────────┬───────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ LuaSandboxManager │
|
||||||
|
│ - StartApp/StopApp lifecycle │
|
||||||
|
│ - Per-app isolated Lua environments │
|
||||||
|
│ - Resource limits (memory, CPU, timers) │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### App Package Format (.mosis)
|
||||||
|
|
||||||
|
Apps are distributed as ZIP files with `.mosis` extension:
|
||||||
|
|
||||||
|
```
|
||||||
|
myapp.mosis
|
||||||
|
├── manifest.json # Required: app metadata
|
||||||
|
├── main.rml # Entry point (RmlUi document)
|
||||||
|
├── styles.rcss # Stylesheets
|
||||||
|
├── scripts/ # Lua scripts
|
||||||
|
│ └── app.lua
|
||||||
|
└── assets/ # Icons, images, etc.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manifest Format
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "com.example.myapp",
|
||||||
|
"name": "My App",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"version_code": 1,
|
||||||
|
"entry": "main.rml",
|
||||||
|
"icon": "icon.tga",
|
||||||
|
"description": "App description",
|
||||||
|
"developer": {
|
||||||
|
"name": "Developer Name",
|
||||||
|
"email": "dev@example.com"
|
||||||
|
},
|
||||||
|
"permissions": [
|
||||||
|
"network",
|
||||||
|
"storage",
|
||||||
|
"camera"
|
||||||
|
],
|
||||||
|
"min_api_version": 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### App Lifecycle
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Install from local file
|
||||||
|
app_manager->InstallFromFile("/path/to/app.mosis", [](auto progress) {
|
||||||
|
LOG_INFO("Install progress: %s %.0f%%",
|
||||||
|
InstallProgress::StageName(progress.stage),
|
||||||
|
progress.progress * 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Launch app (starts sandbox)
|
||||||
|
app_manager->LaunchApp("com.example.myapp");
|
||||||
|
|
||||||
|
// Check if running
|
||||||
|
bool running = app_manager->IsAppRunning("com.example.myapp");
|
||||||
|
|
||||||
|
// Stop app (cleanup sandbox)
|
||||||
|
app_manager->StopApp("com.example.myapp");
|
||||||
|
|
||||||
|
// Uninstall (stops if running, removes files)
|
||||||
|
app_manager->Uninstall("com.example.myapp", false); // keep_data=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
/data/data/com.omixlab.mosis/files/
|
||||||
|
├── apps/
|
||||||
|
│ └── com.example.myapp/
|
||||||
|
│ ├── package/ # Extracted app files
|
||||||
|
│ ├── data/ # App persistent data (VirtualFS)
|
||||||
|
│ ├── cache/ # App cache (clearable)
|
||||||
|
│ └── db/ # SQLite databases
|
||||||
|
├── downloads/ # Temporary download location
|
||||||
|
├── backups/ # App data backups
|
||||||
|
└── config/
|
||||||
|
└── apps.json # Installed apps registry
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lua Sandbox System
|
||||||
|
|
||||||
|
The sandbox provides secure, isolated Lua environments for third-party apps.
|
||||||
|
|
||||||
|
### Security Features
|
||||||
|
|
||||||
|
| Feature | Implementation |
|
||||||
|
|---------|----------------|
|
||||||
|
| Dangerous globals removed | `os`, `io`, `loadfile`, `dofile`, `debug` |
|
||||||
|
| Memory limits | Configurable per-app (default 10MB) |
|
||||||
|
| CPU limits | Instruction counting with timeout |
|
||||||
|
| Bytecode rejected | Only source code allowed |
|
||||||
|
| Metatables protected | Cannot modify string/table metatables |
|
||||||
|
| Path traversal blocked | `../` and absolute paths rejected |
|
||||||
|
|
||||||
|
### Permission Categories
|
||||||
|
|
||||||
|
| Category | Auto-Grant | Examples |
|
||||||
|
|----------|------------|----------|
|
||||||
|
| Normal | Yes | `storage`, `network` |
|
||||||
|
| Dangerous | User consent | `camera`, `microphone`, `location`, `contacts` |
|
||||||
|
| Signature | System apps only | `system_settings`, `install_packages` |
|
||||||
|
|
||||||
|
### Available APIs
|
||||||
|
|
||||||
|
**Core APIs** (always available):
|
||||||
|
```lua
|
||||||
|
-- Timers
|
||||||
|
local id = setTimeout(function() end, 1000)
|
||||||
|
clearTimeout(id)
|
||||||
|
local id = setInterval(function() end, 500)
|
||||||
|
clearInterval(id)
|
||||||
|
|
||||||
|
-- JSON
|
||||||
|
local obj = json.decode('{"key": "value"}')
|
||||||
|
local str = json.encode({key = "value"})
|
||||||
|
|
||||||
|
-- Crypto
|
||||||
|
local bytes = crypto.randomBytes(16)
|
||||||
|
local hash = crypto.sha256("data")
|
||||||
|
local hmac = crypto.hmac("sha256", "key", "data")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Storage APIs** (requires `storage` permission):
|
||||||
|
```lua
|
||||||
|
-- Virtual filesystem (sandboxed to app directory)
|
||||||
|
fs.write("data.txt", "content")
|
||||||
|
local content = fs.read("data.txt")
|
||||||
|
local files = fs.list("/")
|
||||||
|
local stat = fs.stat("data.txt")
|
||||||
|
fs.delete("data.txt")
|
||||||
|
|
||||||
|
-- SQLite database
|
||||||
|
local db = database.open("mydb")
|
||||||
|
db:execute("CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)")
|
||||||
|
db:execute("INSERT INTO items (name) VALUES (?)", {"item1"})
|
||||||
|
local rows = db:query("SELECT * FROM items WHERE id = ?", {1})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Network APIs** (requires `network` permission):
|
||||||
|
```lua
|
||||||
|
-- HTTP (HTTPS only, private IPs blocked)
|
||||||
|
local response = http.get("https://api.example.com/data")
|
||||||
|
local response = http.post("https://api.example.com/data", {
|
||||||
|
headers = {["Content-Type"] = "application/json"},
|
||||||
|
body = json.encode({key = "value"})
|
||||||
|
})
|
||||||
|
|
||||||
|
-- WebSocket
|
||||||
|
local ws = websocket.connect("wss://example.com/ws")
|
||||||
|
ws:send("message")
|
||||||
|
ws:onMessage(function(data) end)
|
||||||
|
ws:close()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hardware APIs** (requires dangerous permissions + user gesture):
|
||||||
|
```lua
|
||||||
|
-- Camera (requires camera permission)
|
||||||
|
camera.start(function(frame) end)
|
||||||
|
camera.stop()
|
||||||
|
|
||||||
|
-- Microphone (requires microphone permission)
|
||||||
|
microphone.start(function(samples) end)
|
||||||
|
microphone.stop()
|
||||||
|
|
||||||
|
-- Location (requires location permission)
|
||||||
|
location.getCurrentPosition(function(pos)
|
||||||
|
print(pos.latitude, pos.longitude)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Sensors (requires sensors permission)
|
||||||
|
sensors.subscribe("accelerometer", function(data)
|
||||||
|
print(data.x, data.y, data.z)
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Sandbox Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd sandbox-test
|
||||||
|
cmake -B build -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake
|
||||||
|
cmake --build build --config Debug
|
||||||
|
./build/Debug/sandbox-test.exe
|
||||||
|
|
||||||
|
# Output: 149 tests, all passing
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Categories
|
||||||
|
|
||||||
|
| Category | Tests | Description |
|
||||||
|
|----------|-------|-------------|
|
||||||
|
| Security | 11 | Globals removal, bytecode, metatables |
|
||||||
|
| Resources | 8 | Memory, CPU limits, instruction counting |
|
||||||
|
| Permissions | 7 | Normal/dangerous/signature grants |
|
||||||
|
| Rate Limiting | 6 | API call throttling |
|
||||||
|
| Timers | 7 | setTimeout/setInterval behavior |
|
||||||
|
| JSON | 5 | Encode/decode, depth limits |
|
||||||
|
| Crypto | 4 | Random, SHA256, HMAC |
|
||||||
|
| VirtualFS | 8 | Read/write, quotas, traversal |
|
||||||
|
| Database | 8 | SQLite operations, injection prevention |
|
||||||
|
| Network | 8 | URL validation, private IP blocking |
|
||||||
|
| WebSocket | 7 | Connection limits, message size |
|
||||||
|
| Hardware | 42 | Camera, mic, location, sensors, bluetooth |
|
||||||
|
| IPC | 7 | Message bus between apps |
|
||||||
|
| Integration | 9 | Full app lifecycle |
|
||||||
|
| Fuzzing | 3 | Random input crash testing |
|
||||||
|
|||||||
Reference in New Issue
Block a user