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:
146
documentation/AE_EVENTS_LAUNCHER_NATIVE_INTEGRATION.md
Normal file
146
documentation/AE_EVENTS_LAUNCHER_NATIVE_INTEGRATION.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Aether Events Launcher: Native Electron Integration
|
||||
|
||||
> **Status:** Operational / Phase 5 Implementation
|
||||
> **Last Updated:** February 10, 2026
|
||||
> **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)
|
||||
- **File:** `aether_app_native/src/main/*.ts`
|
||||
- **Role:** Performs the heavy lifting (Filesystem, Shell, AppleScript).
|
||||
- **Responsibilities:**
|
||||
- Managing the **Hashed Cache** directory.
|
||||
- Executing `osascript` intents 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.exposeInMainWorld` to 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 `camelCase` UI triggers to `snake_case` IPC calls.
|
||||
- Implementing "Smart Fallbacks" (e.g., resolving `[home]` placeholders if the bridge is partially hydrated).
|
||||
|
||||
---
|
||||
|
||||
## 3. The "Zero-Config" Lifecycle
|
||||
|
||||
To support rapid onsite deployment, the native app requires zero manual setup.
|
||||
|
||||
1. **Seed:** On launch, the Main process reads a local `seed.json` (Device ID + API Key).
|
||||
2. **Identity:** Calls `GET /v3/data_store/code/{device_code}` or `GET /v3/crud/event_device/{id}` to pull operational context.
|
||||
3. **Hydrate:** Authenticates with the Aether V3 API and injects the **JWT** and **Device Config** into the UI environment.
|
||||
4. **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:
|
||||
1. Extracts all `event_file_id` values for that session.
|
||||
2. Checks the native cache via `aetherNative.check_cache`.
|
||||
3. 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:
|
||||
1. **Verify:** Confirm hash exists in the permanent cache.
|
||||
2. **Copy:** Create an atomic copy in the system `[tmp]` directory.
|
||||
3. **Restore:** Rename the copy to its original filename (e.g., `Abstract_101.pptx`).
|
||||
4. **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`, and `foreground_app` via heartbeats using the `get_device_info` relay.
|
||||
- **Self-Update (Roadmap):** Plan to monitor Syncthing `admin_share` for newer `.app` versions and perform atomic swaps.
|
||||
|
||||
### 5.3 Planned Actuators (Future Phases)
|
||||
- **Recording:** Control for `aperture` session capture (`start`, `stop`).
|
||||
- **Display Layouts:** Toggling between Mirror and Extended modes via `displayplacer`.
|
||||
|
||||
---
|
||||
|
||||
## 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)
|
||||
|
||||
### Core Functions (`electron_relay.ts`)
|
||||
- `get_device_config()`: Returns hydrated device settings from the native shell.
|
||||
- `get_device_info()`: Returns OS metadata, IP list, and path placeholders (`[home]`, `[tmp]`).
|
||||
- `check_hash_file_cache({cache_root, hash})`: Local filesystem hash check.
|
||||
- `download_to_cache({url, cache_root, hash, ...})`: Authorized background download to the hashed cache.
|
||||
- `launch_from_cache({cache_root, hash, temp_root, filename})`: Atomic "Safe Handover" trigger.
|
||||
- `launch_presentation({path, app})`: Phase 5 specialized launcher with slideshow activation.
|
||||
- `control_presentation({app, action})`: Remote navigation (next/prev) for active decks.
|
||||
- `kill_processes({process_name_li})`: Graceful application termination.
|
||||
- `manage_recording({action})`: Presentation session capture control (Aperture).
|
||||
- `list_tools()`: Manifest of all available native bridge functions.
|
||||
|
||||
### Path Placeholders
|
||||
To ensure cross-platform compatibility, all paths should use:
|
||||
- `[home]`: User home directory.
|
||||
- `[tmp]`: System temporary directory.
|
||||
76
documentation/history/AETHER_NATIVE_APP_ELECTRON_NEW_2026.md
Normal file
76
documentation/history/AETHER_NATIVE_APP_ELECTRON_NEW_2026.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Aether Native Electron App - V3 Architecture (2026)
|
||||
|
||||
## 1. Overview
|
||||
The Aether Native App serves as the OS-level bridge for the SvelteKit frontend. It enables functionality that is normally restricted by browser sandboxing, such as local filesystem management, hardware telemetry, and direct control of third-party presentation software (PowerPoint, Keynote, LibreOffice).
|
||||
|
||||
**Core Tasks (Completed Jan 2026):**
|
||||
* **[Infrastructure]**: Restore AE Events Presentation Launcher (Electron) (ID: 221513945)
|
||||
* **[Frontend]**: V3 File Caching: Implement Launcher CRUD Migration (ID: 173518010)
|
||||
* **[Frontend]**: Native App Bridge: Standardize Electron IPC (ID: 173448078)
|
||||
|
||||
---
|
||||
|
||||
## 2. The Three-Layer Architecture
|
||||
|
||||
### 2.1 The Engine (`src/main/*.ts`)
|
||||
* **Process:** Main Process (Node.js/TypeScript)
|
||||
* **Role:** Performs the actual OS-level operations.
|
||||
* **Key Responsibilities:**
|
||||
* **Shell Handlers (`shell_handlers.ts`)**: Executing shell commands, AppleScripts, and process management.
|
||||
* **File Handlers (`file_handlers.ts`)**: Managing the permanent Hashed Cache (`file_cache/`) and atomic Safe Handover.
|
||||
* Resolving global path placeholders like `[home]` and `[tmp]` via `file_utils.ts`.
|
||||
|
||||
### 2.2 The Bridge (`src/preload/index.ts`)
|
||||
* **Process:** Preload Script
|
||||
* **Role:** The security gatekeeper.
|
||||
* **Key Responsibilities:**
|
||||
* Uses Electron's `contextBridge` to securely expose Main Process functions to the UI.
|
||||
* Exposes the `window.aetherNative` object.
|
||||
* Ensures that only whitelisted IPC channels can be triggered by the renderer.
|
||||
|
||||
### 2.3 The Messenger (`src/lib/electron/electron_relay.ts`)
|
||||
* **Process:** Renderer Process (SvelteKit)
|
||||
* **Role:** The TypeScript API used by Svelte components.
|
||||
* **Key Responsibilities:**
|
||||
* Standardizing IPC calls to snake_case.
|
||||
* Implementing "Smart Fallbacks" (e.g., UI-side placeholder resolution if the bridge is inactive).
|
||||
|
||||
---
|
||||
|
||||
## 3. Core Lifecycle
|
||||
|
||||
1. **Seed Phase:** The Electron shell reads `resources/seed_config.json` to identify the device.
|
||||
2. **Hydration Phase:** The shell authenticates with the Aether V3 API to pull device-specific settings.
|
||||
3. **Injection Phase:** The shell injects the **JWT** and **Native Config** into the SvelteKit environment.
|
||||
4. **Observation Phase:** Background sync loops manage file warming and heartbeat telemetry.
|
||||
|
||||
---
|
||||
|
||||
## 4. Native Tool Library (`window.aetherNative`)
|
||||
|
||||
### File & Cache Management
|
||||
- `check_cache({hash})`: Verify if a file exists in the hidden hashed storage.
|
||||
- `download_to_cache({url, hash})`: Secure background download using the native API key.
|
||||
- `launch_from_cache({hash, filename})`: **Safe Handover** — copies from cache to temp with the original name and triggers the specialized launcher.
|
||||
|
||||
### OS Execution (The "Actuators")
|
||||
- `launch_presentation({path, app})`: Phase 5 specialized launcher with auto-focus (`activate`) and slideshow start.
|
||||
- **Linux:** Triggers `libreoffice --impress`.
|
||||
- **macOS:** Triggers AppleScript for Keynote or PowerPoint.
|
||||
- `control_presentation({app, action})`: Remote navigation for active decks.
|
||||
- **Actions:** `next`, `prev`, `start`, `stop`.
|
||||
- `run_cmd({cmd})`: Executes raw shell commands with automatic path resolution.
|
||||
- `kill_processes([names])`: Force-closes apps to clean the podium.
|
||||
|
||||
### Metadata & Discovery
|
||||
- `get_device_info()`: Provides CPU/RAM stats and absolute system paths.
|
||||
- `list_tools()`: Returns a JSON manifest of all available native functions for self-documentation.
|
||||
|
||||
---
|
||||
|
||||
## 5. Path Placeholder System
|
||||
To maintain cross-platform compatibility, the system uses a placeholder syntax for all paths:
|
||||
- `[home]`: Resolves to the user's home directory (e.g., `/home/scott` or `/Users/scott`).
|
||||
- `[tmp]`: Resolves to the system temporary directory.
|
||||
|
||||
**Resolution Logic:** All native handlers utilize a global regex (`/\[home\]/g`) to ensure these are converted to absolute paths before any disk or shell operation occurs.
|
||||
146
documentation/history/NATIVE_APP_AUTOMATION_SCRIPTS.md
Normal file
146
documentation/history/NATIVE_APP_AUTOMATION_SCRIPTS.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Specification: Aether Native Host Automation & Scripting
|
||||
|
||||
**Target OS:** macOS (Primary), Linux/Windows (Secondary)
|
||||
**Languages:** AppleScript (`osascript`), Bash (`sh`), Node.js `child_process`
|
||||
**Implementation:** `src/main/shell_handlers.ts` (Electron App)
|
||||
|
||||
## 1. Presentation Launch & Control (AppleScript)
|
||||
To provide a seamless "Podium Experience," the app uses AppleScript to control third-party presentation software.
|
||||
|
||||
### 1.1 Microsoft PowerPoint
|
||||
* **Launch:** `powerpoint:launch`
|
||||
```applescript
|
||||
tell application "Microsoft PowerPoint"
|
||||
activate
|
||||
open (POSIX file "[FILE_PATH]")
|
||||
delay 1
|
||||
run slide show of active presentation
|
||||
end tell
|
||||
```
|
||||
* **Control:**
|
||||
* **Next:** `tell application "Microsoft PowerPoint" to next slide of slide show view of active presentation`
|
||||
* **Prev:** `tell application "Microsoft PowerPoint" to previous slide of slide show view of active presentation`
|
||||
* **Start:** `tell application "Microsoft PowerPoint" to run slide show of active presentation`
|
||||
* **Stop:** `tell application "Microsoft PowerPoint" to stop slide show of active presentation`
|
||||
* **Quit:** `quit application "Microsoft PowerPoint" saving no`
|
||||
|
||||
### 1.2 Apple Keynote
|
||||
* **Launch:** `keynote:launch`
|
||||
```applescript
|
||||
tell application "Keynote"
|
||||
activate
|
||||
open (POSIX file "[FILE_PATH]")
|
||||
delay 1
|
||||
start (front document)
|
||||
end tell
|
||||
```
|
||||
* **Control:**
|
||||
* **Next:** `tell application "Keynote" to show next`
|
||||
* **Prev:** `tell application "Keynote" to show previous`
|
||||
* **Start:** `tell application "Keynote" to start (front document)`
|
||||
* **Stop:** `tell application "Keynote" to stop`
|
||||
|
||||
### 1.3 Adobe Acrobat (PDF)
|
||||
* **Launch:** `acrobat:fullscreen`
|
||||
```applescript
|
||||
tell application "Adobe Acrobat Reader"
|
||||
activate
|
||||
-- Acrobat doesn't have a direct "Start Slideshow" AppleScript command
|
||||
-- We use system events to trigger Cmd+L (Full Screen)
|
||||
tell application "System Events" to keystroke "l" using {command down}
|
||||
end tell
|
||||
```
|
||||
|
||||
### 1.4 LibreOffice (Linux Testing)
|
||||
* **Launch:** `libreoffice:launch`
|
||||
```bash
|
||||
libreoffice --impress "[FILE_PATH]"
|
||||
```
|
||||
* **Note:** LibreOffice control on Linux is currently limited to launch-only.
|
||||
|
||||
## 2. Process Management (Bash/Node)
|
||||
The app must ensure that only one presentation is "Active" to prevent audio overlap or confusion.
|
||||
|
||||
| Action | macOS Command | Linux/Windows Mock |
|
||||
| --- | --- | --- |
|
||||
| **Kill Office** | `killall -INT "Microsoft PowerPoint"` | `pkill -f powerpnt` |
|
||||
| **Kill Keynote**| `killall -INT "Keynote"` | `echo "Keynote Not Supported"` |
|
||||
| **Kill Acrobat**| `killall -9 "Acrobat Reader"` | `pkill -f acroread` |
|
||||
| **Kill Parallels**| `pkill -i -f '(Parallels).*(PowerPoint)'` | `N/A` |
|
||||
|
||||
## 3. Recording Lifecycle (`aperture_wrapper`)
|
||||
The app manages high-quality screen and audio recording using the `aperture` CLI or a custom wrapper.
|
||||
|
||||
### 3.1 Start Recording
|
||||
* **Intent:** `record:start`
|
||||
* **Action:** Launch `aperture` as a child process.
|
||||
* **Command Pattern:**
|
||||
```bash
|
||||
aperture --fps 30 --highlight-clicks --audio-device "[DEVICE_ID]" --output "[PATH]/[SESSION_ID].mp4"
|
||||
```
|
||||
* **Telemetry:** Push `record_status: "Recording"` and the PID to the V3 API.
|
||||
|
||||
### 3.2 Stop Recording
|
||||
* **Intent:** `record:stop`
|
||||
* **Action:**
|
||||
1. Send `SIGINT` (Interrupt) to the recorded process.
|
||||
2. Wait for file finalization.
|
||||
3. Verify file existence and minimum size.
|
||||
4. Push `record_status: "Idle"` to the V3 API.
|
||||
|
||||
## 4. Host Hardening & "Odd Stuff"
|
||||
Specialized scripts to ensure the Mac laptop behaves as a dedicated podium.
|
||||
|
||||
### 4.1 Podium Lockdown (macOS)
|
||||
* **Prevent Sleep:** `caffeinate -dis &` (Stores PID).
|
||||
* **Volume Enforce:** `osascript -e "set volume output volume 100"`
|
||||
* **Timezone Sync:** Force `America/New_York` (ET) for all device status pushes to ensure dashboard consistency.
|
||||
* **Hide Menu Bar/Dock:** (Optional) Use `System Events` AppleScript to toggle auto-hide.
|
||||
|
||||
### 4.2 Digital Poster Screen Saver
|
||||
To prevent screen burn-in and provide branding when the podium is idle:
|
||||
* **Idle Detection:** Uses `svelte-idle` to track user activity.
|
||||
* **Action:** Automatically rotates through a random list of `event_file` objects marked as "poster".
|
||||
* **Override:** Any mouse movement or click immediately kills the screen saver modal.
|
||||
|
||||
### 4.3 WebSocket Remote Control (The "Tech Bridge")
|
||||
Allows onsite staff to manage the podium without physical access.
|
||||
* **Intents:**
|
||||
* `ae_refresh:now`: Triggers a full page reload.
|
||||
* `ae_native:cmd`: Executes a whitelisted shell command.
|
||||
* `ae_open:event_file`: Remotely opens a specific presentation or image.
|
||||
* `ae_record:start/stop`: Remotely toggles the Aperture wrapper.
|
||||
|
||||
## 5. Accessibility & Permissions (macOS TCC)
|
||||
Since this is a specialized app, we must handle Apple's TCC (Transparency, Consent, and Control) layer:
|
||||
- **AV Access:** Use `systemPreferences.askForMediaAccess('camera')` and `microphone`.
|
||||
- **Accessibility:** For remote control/automation, check `systemPreferences.isTrustedAccessibilityClient(true)`.
|
||||
- **Screen Recording:** Triggered by the first `aperture` call; the app should provide a UI guide to help the user enable it in System Settings.
|
||||
- **Check Command:** `osascript -e 'tell application "System Events" to get UI elements enabled'`
|
||||
|
||||
## 6. Automation Strategy (The "Intent" Pattern)
|
||||
To keep the bridge secure, we do **not** send raw scripts from the UI. Instead, we send an "Intent."
|
||||
|
||||
**Renderer Call:**
|
||||
```javascript
|
||||
window.aetherNative.launch_presentation({ path: '/tmp/my_deck.pptx', app: 'powerpoint' });
|
||||
window.aetherNative.control_presentation({ app: 'powerpoint', action: 'next' });
|
||||
```
|
||||
|
||||
**Main Process Handler (`src/main/shell_handlers.ts`):**
|
||||
1. Verify the file path is within the allowed `[tmp]` directory.
|
||||
2. Select the corresponding AppleScript template based on `app` and `action`.
|
||||
3. Replace `[FILE_PATH]` and execute via `child_process.exec`.
|
||||
|
||||
## 7. Linux Development Mocking
|
||||
Since development happens on Arch Linux, the `execIntent` handler will check `process.platform`:
|
||||
- If `darwin`: Execute `osascript`.
|
||||
- If `linux`: Use `libreoffice` for launch, or log intent for control commands.
|
||||
- **Recording Mock:** Use `ffmpeg` or generate a fake `.mp4` file to test the sync/upload logic.
|
||||
|
||||
## 8. Refresh & Sync Loops
|
||||
Decoupled polling to balance performance and responsiveness:
|
||||
- **Session Loop (30s):** High frequency for active podium changes.
|
||||
- **Location Loop (2m):** Medium frequency for room configuration.
|
||||
- **Device Loop (5m):** Low frequency for background heartbeat and telemetry.
|
||||
- **Sync Loop (15m):** Background file warming for upcoming presentations.
|
||||
52
documentation/history/NATIVE_APP_DEPLOYMENT_PLAN.md
Normal file
52
documentation/history/NATIVE_APP_DEPLOYMENT_PLAN.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Deployment & Update Plan: Aether Native V3
|
||||
|
||||
**Mechanism:** Syncthing + Admin Share
|
||||
**Target:** macOS Fleet
|
||||
**Primary Controller:** `admin_share` directory
|
||||
|
||||
## 1. Distribution via Syncthing
|
||||
We will leverage the existing Syncthing mesh to distribute binaries and configurations.
|
||||
|
||||
### 1.1 Directory Structure (Admin Share)
|
||||
```text
|
||||
admin_share/
|
||||
├── configs/
|
||||
│ └── seed_[DEVICE_ID].json # Specific seed files for auto-provisioning
|
||||
├── binaries/
|
||||
│ └── native_app/
|
||||
│ ├── version.json # Latest version metadata
|
||||
│ └── Aether_Native.app/ # The macOS App Bundle (or .zip)
|
||||
└── scripts/
|
||||
└── update_helper.sh # macOS script to swap binaries
|
||||
```
|
||||
|
||||
## 2. Self-Update Protocol
|
||||
The V3 app will monitor for updates without relying on external internet access (perfect for isolated event networks).
|
||||
|
||||
### 2.1 The Update Flow
|
||||
1. **Check:** On launch (and periodically), the app reads `admin_share/binaries/native_app/version.json`.
|
||||
2. **Compare:** If `version.json > package.json`, the app signals the user: "Update Available".
|
||||
3. **Stage:** The app copies the new `.app` bundle from the sync folder to a local `~/Library/Caches/Aether/updates/` directory.
|
||||
4. **Swap:** The app launches `update_helper.sh` and exits. The script moves the new version into `/Applications/` and restarts the app.
|
||||
|
||||
## 3. Provisioning (The "Seed" Strategy)
|
||||
To set up a new laptop:
|
||||
1. Install Syncthing and link the `admin_share`.
|
||||
2. The Electron app looks for `admin_share/configs/seed_$(hostname).json`.
|
||||
3. If found, it copies it to its local config path and bootstraps itself.
|
||||
4. **Result:** Zero manual configuration for the onsite tech.
|
||||
|
||||
## 4. macOS Specific Lifecycle
|
||||
- **Gatekeeper:** Since these are distributed via Syncthing, we must handle the "App is damaged or from an unidentified developer" prompt.
|
||||
- **Plan:** Include a `post-sync` script that runs `xattr -rd com.apple.quarantine` on the binary folder within the admin share (if permissions allow) or instructs the user on the first run.
|
||||
|
||||
## 5. Development Workflow (Arch Linux -> Mac)
|
||||
1. **Build:** On Arch Linux, run `npm run build:mac`.
|
||||
2. **Package:** Use `electron-packager` to create the macOS `.app` bundle.
|
||||
3. **Distribute:** Move the built `.app` into the local Syncthing `admin_share` folder.
|
||||
4. **Verify:** Watch the fleet of Macs automatically pull the update via Syncthing.
|
||||
|
||||
## 6. Project Document Updates
|
||||
The following files have been updated to reflect this deployment strategy:
|
||||
- `NATIVE_APP_V3_REWRITE_PLAN.md`: Added self-update logic requirements.
|
||||
- `NATIVE_BRIDGE_INTERFACE_SPEC.md`: Added `ae_sys.checkForUpdates()` method.
|
||||
75
documentation/history/NATIVE_APP_FUNCTIONAL_SPEC.md
Normal file
75
documentation/history/NATIVE_APP_FUNCTIONAL_SPEC.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Functional Specification: Aether Native App (Electron)
|
||||
|
||||
**Date:** 2026-01-30
|
||||
**Status:** V5 / Phase 5 Specification
|
||||
**Target OS:** macOS (Primary), Linux/Windows (Secondary)
|
||||
|
||||
## 1. Core Objectives
|
||||
The Native App acts as a "Privileged Shell" for the Aether SvelteKit UI, providing capabilities that standard web browsers block for security reasons. It turns a standard laptop into a managed "Podium Kiosk."
|
||||
|
||||
## 2. macOS Permission Matrix (TCC)
|
||||
To function as a podium controller, the Electron app requires specific entitlements.
|
||||
|
||||
| Permission | Reason | Criticality |
|
||||
| :--- | :--- | :--- |
|
||||
| **Accessibility** | Required to send AppleScript commands (Next/Prev) to Keynote and PowerPoint. | **CRITICAL** |
|
||||
| **Screen Recording** | Required by the `aperture` utility to record the presentation session. | **CRITICAL** |
|
||||
| **Microphone** | Required to capture room audio/presenter voice during recording. | **CRITICAL** |
|
||||
| **Camera** | Optional, only if "Presenter View" (PiP) recording is enabled. | Low |
|
||||
| **Automation** | Allows the app to control "System Events", "Finder", "Keynote", and "Microsoft PowerPoint". | **CRITICAL** |
|
||||
| **Full Disk Access** | Recommended to ensure access to `~/OSIT` and `~/Downloads` without nagging prompts. | High |
|
||||
|
||||
## 3. Handler Registry (V5)
|
||||
The following IPC handlers are exposed via `window.aetherNative`.
|
||||
|
||||
### 3.1 File & Cache System
|
||||
| Handler | Description |
|
||||
| :--- | :--- |
|
||||
| `native:check-cache` | Verifies file existence in the sharded local cache (`~/OSIT/native_app/cache/xx/hash.file`). |
|
||||
| `native:download-to-cache` | Streams a file from the API to the local cache with SHA-256 verification. |
|
||||
| `native:launch-from-cache` | **Atomic Launch:** Copies file from cache -> temp with original filename -> launches app. |
|
||||
|
||||
### 3.2 Automation & Control (Phase 5)
|
||||
| Handler | Description |
|
||||
| :--- | :--- |
|
||||
| `native:launch-presentation` | Opens a file using the specific app (Keynote/PPT) with "Slide Show" mode enabled immediately. |
|
||||
| `native:control-presentation` | Sends navigation commands: `next`, `prev`, `start`, `stop`. |
|
||||
| `native:kill-processes` | Force quits applications by name (e.g., "Microsoft PowerPoint") to resolve freezes. |
|
||||
|
||||
### 3.3 System Management (New Requirements)
|
||||
These handlers are required for full "Kiosk" management.
|
||||
|
||||
| Handler | Description | Implementation Note |
|
||||
| :--- | :--- | :--- |
|
||||
| `native:set-wallpaper` | Resets desktop background to a specific image. | AppleScript: `tell application "System Events" to set picture of every desktop...` |
|
||||
| `native:update-app` | Checks `~/OSIT/admin_share/...` for newer versions and self-updates. | Requires specific logic to swap the `.app` bundle and restart. |
|
||||
| `native:window-control` | Controls the Electron window: `maximize`, `minimize`, `kiosk`, `devtools`. | Direct Electron `BrowserWindow` API calls. |
|
||||
| `native:manage-recording` | Controls `aperture` process: `start`, `stop`, `status`. | Must track the PID of the spawned recording process. |
|
||||
| `native:set-display-layout` | Toggles between **Mirror** and **Extended** modes. | Use bundled `displayplacer` binary (AppleScript is unreliable for this). |
|
||||
| `native:power-control` | Initiates `shutdown` or `restart`. | Command: `shutdown -h now` (may require admin/sudo setup or user-level fallback). |
|
||||
| `native:open-external` | Opens a URL in a specific browser (Chrome/Firefox). | `spawn('open', ['-a', 'Google Chrome', url])`. |
|
||||
|
||||
## 4. Feature Specifications
|
||||
|
||||
### 4.1 Self-Update Strategy
|
||||
1. **Path:** `~/OSIT/Speaker Ready System/Admin Share/Custom Applications/osit_binaries/`
|
||||
2. **Logic:**
|
||||
* Compare `package.json` version in running app vs. remote path.
|
||||
* If remote > local:
|
||||
* Display "Updating..." splash.
|
||||
* Copy new `.app` to `/Applications` (or current location).
|
||||
* Relaunch.
|
||||
|
||||
### 4.2 Web Page Handling
|
||||
The Launcher avoids Safari.
|
||||
* **Strategy A (Simple):** `native:open-external` -> Opens in Google Chrome Kiosk Mode (`--kiosk`).
|
||||
* **Strategy B (Integrated):** Use an Electron `BrowserView` (not `iframe`) to render the website *inside* the Aether window, ensuring we keep the "Back" button overlay visible.
|
||||
|
||||
### 4.3 Display Layouts
|
||||
To reliably switch between Mirroring (for setup) and Extended (for presentation):
|
||||
* **Tool:** Bundle **`displayplacer`** (Homebrew utility) inside `resources/bin`.
|
||||
* **Command:** `displayplacer "id:<main> res:1920x1080" "id:<proj> res:1920x1080 origin:(1920,0)"` (Example).
|
||||
|
||||
## 5. Security Guardrails
|
||||
* **IPC Whitelisting:** All `run-cmd` calls are deprecated in favor of specific named handlers (e.g., `set-wallpaper`) to prevent arbitrary command execution.
|
||||
* **Path Validation:** All file operations must be restricted to `~/OSIT` or `~/tmp` directories.
|
||||
91
documentation/history/NATIVE_APP_V3_API_PAYLOAD.md
Normal file
91
documentation/history/NATIVE_APP_V3_API_PAYLOAD.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Specification: Aether V3 API Device Config Payload
|
||||
|
||||
**Endpoint:** `GET /v3/crud/event_device/{id_random}?view=native_bootstrap`
|
||||
**Goal:** Provide full operational context to an Electron instance with zero local configuration.
|
||||
|
||||
## 1. Response Structure (Draft)
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"identity": {
|
||||
"device_id_random": "GZvFjgIIZQg",
|
||||
"device_code": "macbook_air_scott_idem",
|
||||
"account_id_random": "xFP7AhU8Zlc",
|
||||
"event_id_random": "UFu-gF-rZ-ws",
|
||||
"location_id_random": "PFGP-37-81-80"
|
||||
},
|
||||
"network": {
|
||||
"api_base_url": "https://api.oneskyit.com",
|
||||
"file_server_url": "https://files.oneskyit.com",
|
||||
"heartbeat_interval_ms": 30000
|
||||
},
|
||||
"filesystem": {
|
||||
"cache_path": "[home]/Library/Caches/OSIT/file_cache",
|
||||
"temp_path": "[home]/tmp/OSIT/temp",
|
||||
"use_sharding": true,
|
||||
"verify_on_launch": true
|
||||
},
|
||||
"launcher": {
|
||||
"app_mode": "native",
|
||||
"auto_start_slideshow": true,
|
||||
"prevent_sleep": true,
|
||||
"whitelisted_apps": ["PowerPoint", "Keynote", "Acrobat Reader"]
|
||||
},
|
||||
"ui_prefs": {
|
||||
"theme_name": "cerberus",
|
||||
"theme_mode": "dark",
|
||||
"show_clock": true,
|
||||
"show_admin_tools": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Key Payload Fields
|
||||
|
||||
### 2.1 Identity & Scoping
|
||||
- `account_id_random`: Automatically scopes all subsequent V3 API calls for the SvelteKit UI.
|
||||
- `location_id_random`: Locks the UI to a specific room/podium.
|
||||
|
||||
### 2.2 Filesystem Strategy
|
||||
- `cache_path`: Uses the `[home]` placeholder. The Electron Main process will resolve this to the local user profile.
|
||||
- `use_sharding`: Tells the Sync Engine to use the `/ab/abcdef...` directory structure.
|
||||
|
||||
### 2.3 Automation Whitelist
|
||||
- To prevent security risks, the `launcher` object defines exactly which applications the native shell is allowed to "Kill" or "Open".
|
||||
|
||||
## 3. Telemetry & Heartbeat (Push Strategy)
|
||||
To support the onsite dashboard (`src/routes/events/.../device`), the Electron app must push its status back to the server.
|
||||
|
||||
### 3.1 Heartbeat Payload (`PATCH /v3/crud/event_device/{id}`)
|
||||
```json
|
||||
{
|
||||
"heartbeat": "2026-01-20T14:30:00Z",
|
||||
"status": "Online",
|
||||
"status_msg": "Presentation: 'Introduction to AE.pptx' (Slide 4/20)",
|
||||
"record_status": "Idle",
|
||||
"info_ip_list": "192.168.1.10, 10.0.0.5",
|
||||
"meta_json": {
|
||||
"cpu_usage": 12,
|
||||
"memory_free_gb": 4.2,
|
||||
"sync_progress": 100,
|
||||
"foreground_app": "PowerPoint",
|
||||
"is_fullscreen": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. The "Bootstrap Paradox" Resolution
|
||||
To allow unauthenticated config fetching for new devices:
|
||||
1. **Device API Key:** Each device record in the DB has an `api_secret_key`.
|
||||
2. **Initial Header:** The Electron app sends `x-aether-device-key: <key>` in the bootstrap request.
|
||||
3. **JWT Hand-off:** The response `meta` will contain a short-lived JWT that the app uses to authenticate its first "Real" V3 requests.
|
||||
|
||||
## 5. Database Mapping (V3 Enriched View)
|
||||
The `v_event_device` SQL view must be updated to include:
|
||||
- `account_id_random` (joined from `account`)
|
||||
- `event_id_random` (joined from `event`)
|
||||
- `location_id_random` (joined from `event_location`)
|
||||
- `theme_name` (joined from `site_cfg_json` via `account`)
|
||||
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.
|
||||
74
documentation/history/NATIVE_BRIDGE_INTERFACE_SPEC.md
Normal file
74
documentation/history/NATIVE_BRIDGE_INTERFACE_SPEC.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Specification: Aether Native V3 Bridge Interface
|
||||
|
||||
**Namespace:** `window.native_app`
|
||||
**Security:** Context Isolated, Sandboxed IPC
|
||||
|
||||
## 1. Device & Identity (`ae_device`)
|
||||
Functions for bootstrapping the app from the `seed.json`.
|
||||
|
||||
| Method | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `getSeed()` | `() => Promise<SeedConfig>` | Returns the local `event_device_id` and `api_base_url`. |
|
||||
| `getDeviceInfo()` | `() => Promise<DeviceInfo>` | Returns OS, Arch, and unique hardware UUID. |
|
||||
| `getPermissions()`| `() => Promise<PermStatus>` | Returns status of Mic, Camera, and Accessibility. |
|
||||
| `requestAccess()` | `(type: string) => Promise<boolean>` | Triggers macOS TCC permission prompts. |
|
||||
|
||||
## 2. Sync Engine (`ae_sync`)
|
||||
The Sync Engine manages the "Cold Cache" (`~/Library/Caches/Aether/`). It handles atomic downloads and hash verification.
|
||||
|
||||
| Method | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `getCacheStatus()` | `(file_hash: string) => Promise<CacheInfo>` | Checks if a file exists and is valid. |
|
||||
| `startSync()` | `(task: SyncRequest) => Promise<void>` | Begins background download of a presentation. |
|
||||
| `cancelSync()` | `(file_hash: string) => Promise<void>` | Aborts an active download. |
|
||||
| `clearCache()` | `() => Promise<void>` | Wipes the cold cache (Maintenance). |
|
||||
|
||||
### Events (Main -> Renderer)
|
||||
- `sync:progress`: `{ hash, percent, speed, bytesLoaded }`
|
||||
- `sync:complete`: `{ hash, success, error }`
|
||||
|
||||
## 3. Launcher (`ae_launcher`)
|
||||
The "Big Red Button" logic. Handles the hand-off to the OS.
|
||||
|
||||
| Method | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `launch()` | `(req: LaunchRequest) => Promise<void>` | 1. Moves file to Temp. 2. Opens with default app. 3. Starts slideshow. |
|
||||
| `killApp()` | `(appName: string) => Promise<void>` | Closes PowerPoint/Keynote/Acrobat gracefully. |
|
||||
| `preventSleep()` | `(enable: boolean) => Promise<void>` | Prevents the laptop from sleeping during a session. |
|
||||
|
||||
## 4. System Control (`ae_sys`)
|
||||
Low-level macOS/Windows/Linux wrappers.
|
||||
|
||||
| Method | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `setVolume()` | `(level: number) => Promise<void>` | Sets system master volume (0-100). |
|
||||
| `checkForUpdates()`| `() => Promise<UpdateStatus>` | Checks the Syncthing share for a newer version. |
|
||||
| `applyUpdate()` | `() => Promise<void>` | Triggers the `update_helper.sh` and exits. |
|
||||
| `execIntent()` | `(intent: string, args: any) => Promise<any>` | Executes a whitelisted command (e.g. `open-logs-folder`). |
|
||||
|
||||
---
|
||||
|
||||
## 5. TypeScript Interface (Draft)
|
||||
|
||||
```typescript
|
||||
export interface AE_Native_Bridge {
|
||||
device: {
|
||||
getSeed: () => Promise<{ device_id: string; api_url: string }>;
|
||||
requestPermissions: () => Promise<void>;
|
||||
};
|
||||
sync: {
|
||||
getStatus: (hash: string) => Promise<{ exists: boolean; verified: boolean }>;
|
||||
queueDownload: (payload: { url: string; hash: string; jwt: string }) => void;
|
||||
};
|
||||
launcher: {
|
||||
launch: (file: { hash: string; name: string; type: 'pptx'|'key'|'pdf' }) => Promise<boolean>;
|
||||
killAll: () => Promise<void>;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 6. Podium Reliability Protocol
|
||||
To ensure the podium never fails:
|
||||
1. **Pre-Flight Check:** The SvelteKit UI will call `sync.getStatus` for every file in the session as soon as the page loads.
|
||||
2. **Auto-Warmup:** If a file is missing, the UI automatically calls `sync.queueDownload` in the background.
|
||||
3. **Verification:** The `launcher.launch` command will perform a final `sha256` check on the temp file *before* executing `shell.openPath`.
|
||||
37
documentation/history/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md
Normal file
37
documentation/history/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Project: Launcher Configuration UI/UX Overhaul
|
||||
|
||||
**Status:** IN-PROGRESS
|
||||
**Goal:** Create a standardized, responsive, and categorized configuration interface for the AE Events Launcher.
|
||||
|
||||
## 1. Objectives
|
||||
- **Standardization**: Use consistent naming (`snake_case`), styling, and layout across all config pieces.
|
||||
- **Flexibility**: Support mobile, tablet, and high-res Macbook displays using responsive widths.
|
||||
- **Intelligent Collapsing**: Implement a 3-way state logic: `collapsed`, `auto_collapse`, `pinned`.
|
||||
- **Contextual Fields**: Hide technical/editable fields unless `$ae_loc.edit_mode` is enabled.
|
||||
|
||||
## 2. 3-Way State Logic
|
||||
- **`collapsed`**: Section content is hidden.
|
||||
- **`auto`**: Section is expanded by default, but closes if another "auto" section is opened.
|
||||
- **`pinned`**: Section is expanded and *ignores* the auto-collapse signals from other sections.
|
||||
|
||||
## 3. Component Architecture
|
||||
- **`Launcher_Cfg`**: The main container with Tabbed Navigation (System, Sync, General).
|
||||
- **`Launcher_Cfg_Section`**: Shared wrapper component providing the header, 3-way toggle, and responsive container.
|
||||
- **Sub-components**: Individual sections (Health, Native OS, Timers, etc.) refactored to use the shared wrapper.
|
||||
|
||||
## 4. Feature Matrix & `edit_mode`
|
||||
| Component | Always Visible (Read-Only) | Edit Mode Only (Write/Technical) |
|
||||
| :--- | :--- | :--- |
|
||||
| **Health** | Heartbeat Status, RAM/CPU Gauges | Raw Metadata JSON, Hostname, IPs |
|
||||
| **Native OS** | Folder Open Buttons, Recording Toggle | Manual Terminal CMD, Reset Wallpaper |
|
||||
| **Sync** | Sync Stats (Total/Cached) | Millisecond Timers, Hash Prefix Length |
|
||||
| **Updates** | Current Version, Check Button | Update Path/URL inputs |
|
||||
|
||||
## 5. Progress Tracker
|
||||
- [ ] Migrate `events_loc.launcher` visibility flags to 3-way states.
|
||||
- [ ] Implement `Launcher_Cfg_Section` wrapper component.
|
||||
- [ ] Refactor `Launcher_Cfg_Health`.
|
||||
- [ ] Refactor `Launcher_Cfg_Native_OS`.
|
||||
- [ ] Refactor `Launcher_Cfg_Sync_Timers`.
|
||||
- [ ] Refactor `Launcher_Cfg_Updates`.
|
||||
- [ ] Final UI/UX Polish.
|
||||
62
documentation/history/PROJECT_NATIVE_ELECTRON_INTEGRATION.md
Normal file
62
documentation/history/PROJECT_NATIVE_ELECTRON_INTEGRATION.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Project: Aether Native Electron Integration
|
||||
|
||||
**Status:** Planning / Documentation
|
||||
**Date:** 2026-01-20
|
||||
**Target Platform:** macOS (Production), Arch Linux (Development)
|
||||
|
||||
## 1. Overview
|
||||
This project aims to integrate the modern SvelteKit-based Aether UI into the established Electron native shell (`aether_app_native`). This enables "Native Mode" functionality, such as local file system access, presentation management, and hardware integration, which are restricted in standard web browsers.
|
||||
|
||||
## 2. Component Mapping
|
||||
|
||||
### 2.1 The Shell (`aether_app_native`)
|
||||
- **Main Process:** Handles window creation, lifecycle, and IPC handlers.
|
||||
- **Config:** Uses `ae_native_app_sk_config.json` located in `~/OSIT/native_app/` or `~/.config/OSIT/`.
|
||||
- **Preload Script:** (To be standardized) The bridge that injects functionality into the UI.
|
||||
|
||||
### 2.2 The UI (`aether_app_sveltekit`)
|
||||
- **Framework:** Svelte 5 / SvelteKit.
|
||||
- **Detection:** Uses `+layout.svelte` to check for `window.native_app`.
|
||||
- **Relay:** `src/lib/electron/electron_relay.js` acts as the frontend-side API for the native bridge.
|
||||
|
||||
## 3. Development Strategy (Arch Linux)
|
||||
Since production targets macOS but development happens on Linux:
|
||||
1. **Mocking macOS APIs:** Any calls to `osascript` or macOS-specific shell commands must be wrapped in a platform check.
|
||||
2. **Path Handling:** Use `[home]` placeholders in config files to ensure paths resolve correctly on both `/home/scott/` (Linux) and `/Users/scott/` (Mac).
|
||||
3. **Packaging:** Use `electron-packager` with macOS target flags to verify build integrity on Linux.
|
||||
|
||||
## 4. Implementation Plan
|
||||
|
||||
### Phase 1: Bridge Standardization
|
||||
- Move existing logic from `aether_app_native/app/js/aether_app_native_v4.js` into a formal `preload.js`.
|
||||
- Use `contextBridge.exposeInMainWorld` to provide a secure `native_app` object.
|
||||
- Standardize return types (Promises) for all IPC calls.
|
||||
|
||||
### Phase 2: SvelteKit Build Integration
|
||||
- Transition SvelteKit build to support relative asset paths (required for `file://` protocol).
|
||||
- Update the native app's `index.js` to load the built SvelteKit `index.html` instead of a remote URL.
|
||||
|
||||
### Phase 3: Feature Parity (Events Module)
|
||||
- Port the "Event Launcher" logic to the new bridge.
|
||||
- Implement robust file caching using the `local_file_cache_path` from the native config.
|
||||
- Ensure `kill_processes` works for both `pkill` (Linux) and `killall` (Mac).
|
||||
|
||||
## 5. Security Protocols
|
||||
- **Context Isolation:** Must remain enabled.
|
||||
- **Sandbox:** Enabled where possible.
|
||||
- **IPC Whitelisting:** Only specific, pre-defined commands can be executed via `run_cmd`.
|
||||
|
||||
## 6. Project Documentation Index
|
||||
The following documents provide detailed specifications for the V3 Native App rebuild:
|
||||
|
||||
- **[NATIVE_APP_FUNCTIONAL_SPEC.md](NATIVE_APP_FUNCTIONAL_SPEC.md)**: Detailed audit of legacy features (process management, file caching, automation) to be preserved in the rewrite.
|
||||
- **[NATIVE_APP_V3_REWRITE_PLAN.md](NATIVE_APP_V3_REWRITE_PLAN.md)**: Technical strategy for Electron 33+, including the Zero-Config hydration flow and macOS permission handling.
|
||||
- **[NATIVE_APP_V3_API_PAYLOAD.md](NATIVE_APP_V3_API_PAYLOAD.md)**: JSON schema definitions for the V3 bootstrap payload and the push-telemetry heartbeat logic.
|
||||
- **[NATIVE_BRIDGE_INTERFACE_SPEC.md](NATIVE_BRIDGE_INTERFACE_SPEC.md)**: Definition of the `window.native_app` IPC contract and the "Podium Reliability Protocol."
|
||||
- **[NATIVE_APP_DEPLOYMENT_PLAN.md](NATIVE_APP_DEPLOYMENT_PLAN.md)**: Strategy for binary distribution and self-updates using the existing Syncthing `admin_share` infrastructure.
|
||||
- **[NATIVE_APP_AUTOMATION_SCRIPTS.md](NATIVE_APP_AUTOMATION_SCRIPTS.md)**: Specifications for AppleScript intents, recording lifecycle (Aperture), and Arch Linux mocking logic.
|
||||
|
||||
## 7. References
|
||||
- Existing Native Docs: `aether_app_native/Aether App Native setup documentation.txt`
|
||||
- Electron Integration: `src/lib/electron/README.md`
|
||||
- Svelte 5 Runes: `documentation/ARCHITECTURE.md`
|
||||
Reference in New Issue
Block a user