- Remove tmp_shell_handlers.ts from SvelteKit repo — this was a draft of the
Electron main-process shell handler that was placed in the wrong repo. It used
ipcMain (Electron main-process only) and could never run in SvelteKit. Was not
imported anywhere but was misleading.
- Fix src/lib/electron/README.md:
- Correct broken doc link (was AE_EVENTS_LAUNCHER_NATIVE_INTEGRATION.md,
actual filename is PROJECT__AE_Events_Launcher_Native_integration.md)
- Mark electron_native.js as DEPRECATED — do not import (was described as
active "Bridge Logic", which was incorrect and confusion-causing)
- Add clear bridge architecture diagram showing the three-layer flow
- Note that aether_app_native_electron/ is the active Electron repo
- Update PROJECT__AE_Events_Launcher_Native_integration.md:
- Fix Layer 1 file path: aether_app_native/ → aether_app_native_electron/
- Section 5.3: Phase 5 actuators are all implemented, not "planned" — update
recording, display layout, power control, window control, wallpaper to reflect
actual implementation status; note update_app is a stub
- Section 7: Expand IPC whitelist to cover all relay functions including new
cleanup_tmp_files, system handlers, and full parameter signatures
- Document get_seed_config / get_jwt as intentionally not relayed to UI
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
9.7 KiB
Aether Events Launcher: Native Electron Integration
Status: Operational / Phase 5 Implementation Last Updated: 2026-03-11 Primary Platform: macOS (Darwin) Fallback Platform: Linux / Windows
1. Overview
The Aether Events Launcher utilizes an Electron-based "Native Shell" to provide OS-level capabilities that are normally restricted by browser sandboxing. This enables persistent file caching, direct control of presentation software (Keynote, PowerPoint), and hardware telemetry.
Operational Modes
| Mode | Purpose | File Handling |
|---|---|---|
| Default | Standard web browser access. | Direct downloads; no local caching. |
| Onsite | Web access on event networks. | Faster polling; browser-based file management. |
| Native | Dedicated Podium Kiosk (Electron). | Full background pre-caching; atomic safe-handover. |
2. Architecture: The Three-Layer Bridge
The integration is built on a decoupled three-layer communication model to ensure security and cross-platform flexibility.
2.1 Layer 1: The Engine (Main Process)
- Repo:
~/OSIT_dev/aether_app_native_electron/(separate git repo) - File:
aether_app_native_electron/src/main/*.ts - Role: Performs the heavy lifting (Filesystem, Shell, AppleScript).
- Responsibilities:
- Managing the Hashed Cache directory.
- Executing
osascriptintents for presentation control. - Spawn/Kill process management.
2.2 Layer 2: The Gatekeeper (Preload Script)
- Namespace:
window.aetherNative - Role: Securely exposes whitelisted IPC channels to the Renderer.
- Standards: Uses
contextBridge.exposeInMainWorldto prevent arbitrary code execution.
2.3 Layer 3: The Messenger (SvelteKit Relay)
- File:
src/lib/electron/electron_relay.ts - Role: Provides a clean, typed API for Svelte components.
- Responsibilities:
- Mapping
camelCaseUI triggers tosnake_caseIPC calls. - Implementing "Smart Fallbacks" (e.g., resolving
[home]placeholders if the bridge is partially hydrated).
- Mapping
3. The "Zero-Config" Lifecycle
To support rapid onsite deployment, the native app requires zero manual setup.
- Seed: On launch, the Main process reads a local
seed.json(Device ID + API Key). - Identity: Calls
GET /v3/data_store/code/{device_code}orGET /v3/crud/event_device/{id}to pull operational context. - Hydrate: Authenticates with the Aether V3 API and injects the JWT and Device Config into the UI environment.
- Launch: Navigates the SvelteKit frontend directly to the assigned Event Launcher route.
4. Podium Reliability Protocol
The system is designed to ensure that a presentation never fails due to network instability.
4.1 Hashed Cache Pattern
Files are stored persistently using their SHA-256 hash to prevent filename collisions and handle versioning.
- Root:
~/Library/Caches/OSIT/file_cache/ - Subdirectory: First 2 characters of hash (e.g.,
ab/) - Filename:
{hash}.file
4.2 Background Sync (File Warming)
When a user navigates to a session in the Launcher UI, the LauncherBackgroundSync component:
- Extracts all
event_file_idvalues for that session. - Checks the native cache via
aetherNative.check_cache. - Triggers background downloads for missing files via
aetherNative.download_to_cache.
4.3 Safe Handover (Launch Sequence)
When a user clicks "Open", the system follows a non-destructive sequence:
- Verify: Confirm hash exists in the permanent cache.
- Copy: Create an atomic copy in the system
[tmp]directory. - Restore: Rename the copy to its original filename (e.g.,
Abstract_101.pptx). - Execute: Launch the file via the OS.
5. Automation & Actuators (Phase 5)
The native shell provides specialized handlers for controlling the "Podium Experience."
5.1 Presentation Acts
| Action | Handler | Actuator (macOS) |
|---|---|---|
| Launch | launch_presentation |
open or osascript (slideshow start) |
| Control | control_presentation |
osascript (next/prev slide) |
| Clean Up | kill_processes |
killall -INT (graceful exit) |
5.2 System Management
- Telemetry: Pushes
cpu_usage,memory_free_gb, andforeground_appvia heartbeats using theget_device_inforelay. - Self-Update (Roadmap): Plan to monitor Syncthing
admin_sharefor newer.appversions and perform atomic swaps.
5.3 Implemented Actuators (Phase 5 Complete)
- Recording:
manage_recording({action})— Aperture session capture (start,stop,status). macOS only. - Display Layouts:
set_display_layout({mode})— Mirror / Extend viadisplayplacer. macOS only. - Power Control:
power_control({action})— Shutdown, reboot, sleep. macOS + Linux. - Window Control:
window_control({action})— Maximize, minimize, fullscreen, kiosk mode. - Wallpaper:
set_wallpaper({path})— macOS (AppleScript) + Linux (gsettings).
Note:
update_appis implemented as a stub — downloads but does not install. Not yet functional for end users.
6. Launcher Configuration & Management
The Launcher features a standardized, responsive configuration interface designed for onsite technical management.
6.1 UI Architecture
- Tabbed Navigation: Categorized into System, Sync, and General settings.
- Section Wrapper (
Launcher_Cfg_Section): A shared component providing a consistent header, icon, and responsive grid container.
6.2 3-Way State Logic
To manage screen real estate on varying laptop resolutions, all configuration sections utilize a 3-way visibility state:
collapsed: Content is hidden.auto: Expanded by default, but automatically closes if another "auto" section is opened.pinned: Expanded and remains open regardless of other section interactions.
6.3 Technical Mode (edit_mode)
The UI dynamically filters fields based on the user's focus. Enabling Technical Mode ($ae_loc.edit_mode) reveals advanced diagnostic and writeable fields.
| Category | Standard View (Read-Only) | Technical Mode (Read/Write) |
|---|---|---|
| Health | Heartbeat, RAM Usage, Sync Stats | Hostname, IP List, Raw Device JSON |
| OS Bridge | Folder Buttons, Recording Toggle | Manual Terminal Commands, Reset Wallpaper |
| Sync | Sync Completion Status | Millisecond Timers, Cache Prefix Logic |
| Update | Current Version Status | Manual Update Paths, URL Overrides |
7. Implementation Reference (IPC Whitelist)
All functions below are exported from src/lib/electron/electron_relay.ts and safely
no-op when window.aetherNative is not present (i.e., in browser/non-native mode).
Config & Info
get_device_config()— Returns hydrated device settings injected by the native shell on startup.get_device_info()— Returns OS metadata, IP list, hostname, and path placeholders ([home],[tmp]).
File Cache
check_hash_file_cache({cache_root, hash, hash_prefix_length?})— Verifies a file exists in the local hashed cache.download_to_cache({url, cache_root, hash, api_key, account_id, hash_prefix_length?})— Streams a file download to the hashed cache with SHA-256 integrity check.launch_from_cache({cache_root, hash, temp_root, filename, hash_prefix_length?})— Atomic "Safe Handover": copy from cache → tmp → rename → execute.cleanup_tmp_files({cache_root, max_age_minutes?})— Removes stale*.tmpdownload artifacts. Default: 1440 min (24h). Called at launcher startup.
hash_prefix_lengthdefaults to2throughout. Do not change without coordinating all devices — mismatched values create orphaned cache subdirectories.
Shell & OS
open_folder(path)— Opens a path in the OS file manager.run_cmd({cmd, timeout?, return_stdout?})— Async shell command execution.run_cmd_sync({cmd, return_stdout?})— Synchronous shell command execution.run_osascript(script)— Executes an AppleScript string. macOS only.kill_processes({process_name_li})— Gracefully terminates processes by name.open_local_file_v2(path)— Opens a file with its default OS application.
Presentations (Phase 5)
launch_presentation({path, app?, os?})— Platform-aware launcher. macOS: PowerPoint/Keynote via AppleScript. Linux: LibreOffice Impress. Resolves[home]/[tmp]placeholders.control_presentation({app, action})— Slide navigation (next/prev/start/stop) for PowerPoint or Keynote via AppleScript.
System Management (Phase 5)
set_wallpaper({path})— Sets desktop wallpaper. macOS (AppleScript) + Linux (gsettings).window_control({action, value?})— Electron window management: maximize, minimize, fullscreen, kiosk.set_display_layout({mode, configStr?})— Mirror or extend displays via displayplacer. macOS only.power_control({action})— Shutdown, reboot, or sleep the host machine. macOS + Linux.manage_recording({action, options?})— Aperture capture control (start/stop/status). macOS only.open_external({url, app?})— Opens a URL in Chrome, Firefox, or the default browser.update_app(args)— Stub only. Downloads but does not install. Not yet functional.list_tools()— Returns a self-documenting manifest of all available native bridge functions.
Path Placeholders
All paths passed to native handlers should use tokens rather than hardcoded OS paths:
[home]— Resolved to the user's home directory by the native bridge.[tmp]— Resolved to the system temporary directory.
Not Exposed via Relay (intentional)
get_seed_config/get_jwt— Exposed in the preload but not relayed to the UI. The JWT and seed are injected into the environment at startup; components should not call these directly.