feat(launcher): harden native caching and telemetry; consolidate documentation
- Implemented SHA-256 integrity checks and stale temp purge in native download logic.\n- Enabled strict hash verification in background sync cycle.\n- Made CPU load gauge dynamic using real-time loadavg metadata.\n- Consolidated native app documentation into single master manual.\n- Marked legacy electron_native.js as deprecated.\n- Updated roadmap with temp cleanup and launch protection tasks.
This commit is contained in:
166
documentation/history/NATIVE_APP_V3_REWRITE_PLAN.md
Normal file
166
documentation/history/NATIVE_APP_V3_REWRITE_PLAN.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# Project Plan: Aether Native V3 Rewrite
|
||||
|
||||
**Target:** Electron 33+
|
||||
**Primary Platform:** macOS (Production)
|
||||
**Development Platform:** Arch Linux
|
||||
**API Version:** Aether V3 (REST + JWT)
|
||||
|
||||
## 0. Project Purpose
|
||||
The sole purpose of this Native App is to serve as the **AE Events Launcher**. It provides the SvelteKit frontend with the ability to:
|
||||
- Persistently cache files in the local filesystem.
|
||||
- Execute OS-level shell commands and scripts (e.g., launching presentation software).
|
||||
- Provide a "Zero-Config" experience for onsite event laptops.
|
||||
|
||||
### 0.1 Application Modes
|
||||
The system must support three distinct operational modes:
|
||||
|
||||
| Mode | Refresh Logic | File Handling |
|
||||
| --- | --- | --- |
|
||||
| **Default** | Slower auto-refresh timers. | Standard browser downloads. No local caching. |
|
||||
| **Onsite** | Faster auto-refresh timers. | Downloads files with modified extensions (e.g., .pptxwin). |
|
||||
| **Native** | Fastest auto-refresh timers. | Full background pre-caching. Launching from local temp directory with original names. |
|
||||
|
||||
---
|
||||
|
||||
## 1. Minimalist Configuration Strategy
|
||||
To simplify laptop deployment, we will move away from large local JSON files.
|
||||
|
||||
### 1.1 The "Seed" Config
|
||||
Each laptop will contain a `seed.json`. For development, this is located at `~/seed.json`. In production, it will move to standard OS config paths (e.g., `~/.config/aether/seed.json` or `~/Library/Application Support/Aether/`).
|
||||
|
||||
```json
|
||||
{
|
||||
"event_device_id": "dbgMWS3KEHE",
|
||||
"primary_api_base_url": "https://dev-api.oneskyit.com",
|
||||
"backup_api_base_url": null,
|
||||
"onsite_api_base_url": null,
|
||||
"aether_api_key": "INSdG85ANwsEIru3nUttMw"
|
||||
}
|
||||
```
|
||||
*Note: only `event_device_id` is strictly required for the bootstrapper to start.*
|
||||
|
||||
### 1.2 The Bootstrap Flow
|
||||
1. **Launch:** Electron reads the `seed.json`.
|
||||
2. **Identity:** App calls `GET /v3/crud/event_device/{id}`.
|
||||
3. **Hydrate:** App uses `app_base_url` from the device record to search for the corresponding `site_domain`.
|
||||
4. **Target URL:** Electron constructs the launcher URL:
|
||||
`http://[app_base_url]/events/[event_id]/launcher/[event_location_id]`
|
||||
5. **Inject:** Config and JWT are injected into the SvelteKit frontend via the Preload script.
|
||||
|
||||
### 1.3 Technical Flow: Startup & Background Caching
|
||||
The system utilizes a multi-layered hydration and synchronization strategy to ensure files are available instantly.
|
||||
|
||||
#### Step 1: Zero-Config Initialization (Main Process)
|
||||
- **Seed Discovery:** Main process reads `seed.json`.
|
||||
- **Identity Exchange:** Main process authenticates with the API using the `aether_api_key`.
|
||||
- **Global Injections:** Once hydrated, the Main process provides the SvelteKit frontend with:
|
||||
- `native_device`: Full record from `event_device` table (contains timers).
|
||||
- `aether_api_key`: For authorized background downloads.
|
||||
- `local_file_cache_path`: Root for the permanent hashed cache.
|
||||
- `host_file_temp_path`: Root for the operational launch directory.
|
||||
|
||||
#### Step 2: Session-Driven Caching (Renderer Process)
|
||||
- **View Trigger:** When a user navigates to a session or location, the SvelteKit frontend populates the `event_file_obj_li` store.
|
||||
- **Sync Cycle:** The `LauncherBackgroundSync` component detects the new file list and:
|
||||
1. Extracts all `event_file_id` values.
|
||||
2. Fetches full metadata (hashes) from the local Dexie IndexedDB.
|
||||
3. Asynchronously checks the Native Cache for each hash.
|
||||
- **Background Download:** Missing files are downloaded directly to the hashed cache using the authorized Native API Key.
|
||||
- **Timer Loop:** A background loop runs every `check_event_loop_period` (configurable via API) to ensure the cache stays in sync with server-side changes.
|
||||
|
||||
#### Step 3: Hashed Cache Pattern (Filesystem)
|
||||
To prevent filename collisions and handle versioning, the permanent cache follows the server's structure:
|
||||
- **Root:** `[local_file_cache_path]`
|
||||
- **Subdirectory:** First 2 characters of SHA256 (e.g., `ab/`)
|
||||
- **Filename:** Full SHA256 with `.file` extension (e.g., `abc123...file`)
|
||||
|
||||
#### Step 4: Safe Handover (Launch Sequence)
|
||||
When a user clicks "Open", the system follows a non-destructive handover:
|
||||
1. **Verify:** Confirm hash exists in `local_file_cache_path`.
|
||||
2. **Prepare:** Copy the hashed file to `host_file_temp_path`.
|
||||
3. **Restore:** Rename the copy back to its original filename (e.g., `Presentation.pptx`).
|
||||
4. **Execute:** Trigger OS-level `shell.openPath()` on the temp file.
|
||||
*This ensures the permanent cache remains clean while the third-party app (PowerPoint, etc.) can operate on a file with a familiar name.*
|
||||
|
||||
### 1.3 Technical Flow: Startup & Background Caching
|
||||
The system utilizes a multi-layered hydration and synchronization strategy to ensure files are available instantly.
|
||||
|
||||
#### Step 1: Zero-Config Initialization (Main Process)
|
||||
- **Seed Discovery:** Main process reads `seed.json`.
|
||||
- **Identity Exchange:** Main process authenticates with the API using the `aether_api_key`.
|
||||
- **Global Injections:** Once hydrated, the Main process provides the SvelteKit frontend with:
|
||||
- `native_device`: Full record from `event_device` table (contains timers).
|
||||
- `aether_api_key`: For authorized background downloads.
|
||||
- `local_file_cache_path`: Root for the permanent hashed cache.
|
||||
- `host_file_temp_path`: Root for the operational launch directory.
|
||||
|
||||
#### Step 2: Session-Driven Caching (Renderer Process)
|
||||
- **View Trigger:** When a user navigates to a session or location, the SvelteKit frontend populates the `event_file_obj_li` store.
|
||||
- **Sync Cycle:** The `LauncherBackgroundSync` component detects the new file list and:
|
||||
1. Extracts all `event_file_id` values.
|
||||
2. Fetches full metadata (hashes) from the local Dexie IndexedDB.
|
||||
3. Asynchronously checks the Native Cache for each hash.
|
||||
- **Background Download:** Missing files are downloaded directly to the hashed cache using the authorized Native API Key.
|
||||
- **Timer Loop:** A background loop runs every `check_event_loop_period` (configurable via API) to ensure the cache stays in sync with server-side changes.
|
||||
|
||||
#### Step 3: Hashed Cache Pattern (Filesystem)
|
||||
To prevent filename collisions and handle versioning, the permanent cache follows the server's structure:
|
||||
- **Root:** `[local_file_cache_path]`
|
||||
- **Subdirectory:** First 2 characters of SHA256 (e.g., `ab/`)
|
||||
- **Filename:** Full SHA256 with `.file` extension (e.g., `abc123...file`)
|
||||
|
||||
#### Step 4: Safe Handover (Launch Sequence)
|
||||
When a user clicks "Open", the system follows a non-destructive handover:
|
||||
1. **Verify:** Confirm hash exists in `local_file_cache_path`.
|
||||
2. **Prepare:** Copy the hashed file to `host_file_temp_path`.
|
||||
3. **Restore:** Rename the copy back to its original filename (e.g., `Presentation.pptx`).
|
||||
4. **Execute:** Trigger OS-level `shell.openPath()` on the temp file.
|
||||
*This ensures the permanent cache remains clean while the third-party app (PowerPoint, etc.) can operate on a file with a familiar name.*
|
||||
|
||||
## 2. macOS Hardening (Permissions)
|
||||
...
|
||||
macOS requires explicit user consent for several features. The new app will handle these during the "Splash Screen" phase.
|
||||
|
||||
- **AV Access:** Use `systemPreferences.askForMediaAccess('camera')` and `microphone`.
|
||||
- **Accessibility:** For remote control/automation, check `systemPreferences.isTrustedAccessibilityClient(true)`.
|
||||
- **Screen Recording:** Required for the presentation tracker. We will use a "Check and Prompt" loop.
|
||||
|
||||
## 3. Cross-Platform Handling
|
||||
| Feature | macOS (Production) | Linux/Windows (Dev/Comp) |
|
||||
| --- | --- | --- |
|
||||
| **Process Kill** | `killall -INT "PowerPoint"` | `pkill -f "powerpnt.exe"` |
|
||||
| **Automation** | AppleScript (`osascript`) | Mocked via logs or Shell commands. |
|
||||
| **Paths** | `~/Library/Caches/Aether` | `~/.cache/aether` |
|
||||
| **Window** | Frameless, Transparent support. | Standard decorated window. |
|
||||
|
||||
## 4. Proposed Directory Structure
|
||||
```text
|
||||
aether_app_native_v3/
|
||||
├── src/
|
||||
│ ├── main/
|
||||
│ │ ├── index.ts # Window lifecycle
|
||||
│ │ ├── ipc_handlers.ts # Whitelisted OS commands
|
||||
│ │ ├── macos_perms.ts # Mic/Cam/Accessibility logic
|
||||
│ │ └── api_client.ts # V3 Auth & Config sync
|
||||
│ ├── preload/
|
||||
│ │ └── index.ts # Secure ContextBridge
|
||||
│ └── shared/
|
||||
│ └── types.ts # TS Interfaces for the bridge
|
||||
├── resources/ # Icons and splash screens
|
||||
└── electron-builder.yml # Multi-platform build config
|
||||
```
|
||||
|
||||
## 5. Security Upgrades
|
||||
1. **JWT Storage:** Store the session token in Electron's `safeStorage` (OS-level encryption) rather than simple `localStorage`.
|
||||
2. **Navigation Lock:** Prevent the SvelteKit UI from navigating away from the Aether domain.
|
||||
3. **Command Whitelisting:** Instead of a generic `run_cmd`, implement specific handlers like `native:launch-presentation` which only accepts a file hash.
|
||||
|
||||
## 6. Deployment & Self-Update
|
||||
To support onsite deployment via Syncthing:
|
||||
1. **Version Watcher:** Main process monitors `admin_share/binaries/native_app/version.json`.
|
||||
2. **Atomic Swap:** Use a dedicated `update_helper.sh` to swap the `.app` bundle while the app is closed.
|
||||
3. **Zero-Touch Provisioning:** Auto-copy `seed_[hostname].json` from the sync share if local config is missing.
|
||||
|
||||
## 7. Development Tools (Arch Linux)
|
||||
- Use `fakeroot` and `binutils` to package for macOS on Linux.
|
||||
- Use `Xvfb` for headless testing of Electron windows in CI/CD.
|
||||
Reference in New Issue
Block a user