- Implemented Default, Onsite, and Native launcher modes in launcher_file_cont.svelte. - Restored background pre-caching logic with configurable timers in new LauncherBackgroundSync component. - Fixed standard browser download regression for regular website mode. - Modernized electron_relay to TypeScript and standardized bridge detection in layout. - Detailed startup and background sync technical flow in documentation.
9.2 KiB
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/).
{
"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
- Launch: Electron reads the
seed.json. - Identity: App calls
GET /v3/crud/event_device/{id}. - Hydrate: App uses
app_base_urlfrom the device record to search for the correspondingsite_domain. - Target URL: Electron constructs the launcher URL:
http://[app_base_url]/events/[event_id]/launcher/[event_location_id] - 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 fromevent_devicetable (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_listore. - Sync Cycle: The
LauncherBackgroundSynccomponent detects the new file list and:- Extracts all
event_file_idvalues. - Fetches full metadata (hashes) from the local Dexie IndexedDB.
- Asynchronously checks the Native Cache for each hash.
- Extracts all
- 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
.fileextension (e.g.,abc123...file)
Step 4: Safe Handover (Launch Sequence)
When a user clicks "Open", the system follows a non-destructive handover:
- Verify: Confirm hash exists in
local_file_cache_path. - Prepare: Copy the hashed file to
host_file_temp_path. - Restore: Rename the copy back to its original filename (e.g.,
Presentation.pptx). - 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 fromevent_devicetable (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_listore. - Sync Cycle: The
LauncherBackgroundSynccomponent detects the new file list and:- Extracts all
event_file_idvalues. - Fetches full metadata (hashes) from the local Dexie IndexedDB.
- Asynchronously checks the Native Cache for each hash.
- Extracts all
- 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
.fileextension (e.g.,abc123...file)
Step 4: Safe Handover (Launch Sequence)
When a user clicks "Open", the system follows a non-destructive handover:
- Verify: Confirm hash exists in
local_file_cache_path. - Prepare: Copy the hashed file to
host_file_temp_path. - Restore: Rename the copy back to its original filename (e.g.,
Presentation.pptx). - 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')andmicrophone. - 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
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
- JWT Storage: Store the session token in Electron's
safeStorage(OS-level encryption) rather than simplelocalStorage. - Navigation Lock: Prevent the SvelteKit UI from navigating away from the Aether domain.
- Command Whitelisting: Instead of a generic
run_cmd, implement specific handlers likenative:launch-presentationwhich only accepts a file hash.
6. Deployment & Self-Update
To support onsite deployment via Syncthing:
- Version Watcher: Main process monitors
admin_share/binaries/native_app/version.json. - Atomic Swap: Use a dedicated
update_helper.shto swap the.appbundle while the app is closed. - Zero-Touch Provisioning: Auto-copy
seed_[hostname].jsonfrom the sync share if local config is missing.
7. Development Tools (Arch Linux)
- Use
fakerootandbinutilsto package for macOS on Linux. - Use
Xvfbfor headless testing of Electron windows in CI/CD.