Enhance: Integrate Aether Native Bridge and update V3 deployment plan

- Updated +layout.ts to detect window.aetherNative and prioritize hydrated config.
- Mapped native operational paths (cache, recordings) to global location store.
- Refined NATIVE_APP_V3_REWRITE_PLAN.md with Two-Step Bootstrap strategy.
- Updated TODO.md with project progress and next-gen launcher priorities.
This commit is contained in:
Scott Idem
2026-01-23 14:08:37 -05:00
parent 4d932fcd2c
commit 20b41ebaef
4 changed files with 116 additions and 77 deletions

77
TODO.md
View File

@@ -4,63 +4,48 @@ This is a list of tasks to be completed before the next event/show/conference.
--- ---
## Tomorrow's Priorities (Jan 22, 2026) ## High Priority (Active Task)
1. **Journal Entry Search Cleanup:** 1. **Aether Native V3 (Launcher):**
- [ ] Update `ae_comp__journal_entry_obj_qry.svelte` to use dynamic `$journals_loc` values for `enabled` and `hidden` parameters instead of hardcoded strings. - [ ] Scaffold new Electron 33+ shell.
- [ ] Verify that the search results correctly respect these filters. - [ ] Implement V3 "Zero-Config" bridge between shell and SvelteKit frontend.
2. **Hardening V3 Search (Continued):** - [ ] Reference `documentation/NATIVE_APP_V3_REWRITE_PLAN.md` for architectural constraints.
- [x] **Event Presenter Search:** Restore specialized business logic. (Completed 2026-01-21)
- [x] **Event Badge Search:** Restore specialized business logic. (Completed 2026-01-21)
- [ ] **Exhibit Search:** Restore missing search function and logic.
- [x] **IDAA Result Limit:** Resolved over-fetching issue; results are now strictly limited at the API, Cache, and UI layers. (Completed 2026-01-22)
3. **Journal Module (Config Sprint):**
--- ---
## Current Priorities (Jan 21, 2026) ## Current Priorities (Jan 23, 2026)
1. **Hardening V3 Search (URGENT):** 1. **Journal Module (Cleanup):**
- [x] **Event Session Search:** Finalized and verified. Added `default_qry_str` to V3 body. (Completed 2026-01-21) - [x] **Entry Search Refactor:** Update `ae_comp__journal_entry_obj_qry.svelte` to use dynamic `$journals_loc` values. (Completed 2026-01-23)
- [x] **IDAA Recovery Meetings Search:** Restored functionality using V3 `search__event` with `default_qry_str`. (Completed 2026-01-21) - [x] **Verify Filters:** Search results correctly respect Enabled/Hidden toggle states. (Completed 2026-01-23)
- [x] **Journal Entry Search:** Fixed `match` operator error (switched to `like`) and resolved iteration crashes by unwrapping API envelopes. (Completed 2026-01-21) - [x] **Config Sprint:** Added Query Limit configuration to settings modal. (Completed 2026-01-23)
- [x] **Legacy Compatibility:** Restored `qry_ae_obj_li__event`, `qry__event_file`, `qry__event_session`, and `qry__event_badge` aliases to resolve build errors and support Reports. (Completed 2026-01-21) 2. **Hardening V3 Search (Continued):**
- [ ] **Global Rule:** Preserve `ft_qry`, `lk_qry`, and `and_qry` blocks as "sacred" business logic. Never put non-searchable fields in the POST body. - [x] **Event Session Search:** Finalized and verified. (Completed 2026-01-21)
2. **Service Worker Reliability (Mitigated):** - [x] **IDAA Recovery Meetings Search:** Restored functionality. (Completed 2026-01-21)
- [x] **Disable Auto-Registration:** Temporarily disabled `serviceWorker.register` in `svelte.config.js` to stop `TypeError` loop. - [ ] **Exhibit Search:** Restore missing search function and logic.
- [x] **Fix Tool:** Moved `fix-sw` utility to `/testing/fix-sw` for future debugging. - [ ] **Global Rule:** Preserve `ft_qry`, `lk_qry`, and `and_qry` blocks as "sacred" business logic.
- [ ] **Root Cause Investigation:** Re-enable SW registration later and debug why the script evaluation fails (likely caching or build artifact issues). 3. **Service Worker Reliability (Mitigated):**
3. **Aether Native V3:** Technical planning complete. Ready to scaffold the new Electron 33+ shell and implement the V3 "Zero-Config" bridge. - [x] **Disable Auto-Registration:** Temporarily disabled to stop `TypeError` loop.
4. **Jitsi Module Updates:** Prepare for upcoming demo. Audit `video_conferences/+page.svelte` for UI/UX improvements and stability. - [ ] **Root Cause Investigation:** Re-enable SW registration and debug script evaluation failure.
4. **Jitsi Module Updates:** Prepare for upcoming demo. Audit `video_conferences/+page.svelte`.
--- ---
## 🛠️ DX & Tooling (MCP) ## 🛠️ DX & Tooling (MCP)
- [x] **V3 API Parameter Hardening:** Updated `search_ae_obj_v3` to correctly serialize object-type parameters (JSON strings) in URLs. (Completed 2026-01-21) - [x] **V3 API Parameter Hardening:** Updated `search_ae_obj_v3` for URL serialization. (Completed 2026-01-21)
- [ ] **Enhance `ae_obj_info`**: Include field types, constraints (NOT NULL), and default values. - [ ] **Enhance `ae_obj_info`**: Include field types, constraints, and default values.
- [ ] **Payload Validation**: Create a dry-run tool to check payloads against Pydantic models. - [ ] **Payload Validation**: Create dry-run tool for Pydantic model checking.
- [x] **Error Transparency**: Update backend to return specific SQLAlchemy/Pydantic errors in `meta.details`. (Completed 2026-01-19) - [x] **Error Transparency:** Return specific errors in `meta.details`. (Completed 2026-01-19)
- [ ] **Automated Source of Truth**: Generate \`V3_OBJECT_MODELS.md\` automatically in \`agents_sync/Aether/\`.
- [x] **Fix V3 Search for IDAA Recovery Meetings** (Completed 2026-01-20)
- [x] **Restore System Lookups** (Completed 2026-01-20)
--- ---
## Frontier Journals Module (Vision 2026-01-08) ## Frontier Journals Module (Vision 2026-01-08)
*Goal: Transform Journals into the platform flagship with premium UI/UX and robust security.* - [x] **Phase 1: Codebase Audit & Schema** (Completed 2026-01-23)
- [x] Refactor `ae_comp__journal_entry_obj_id_view.svelte`.
- [x] Fix type safety in `[journal_id]/+layout.svelte`.
- [x] Stabilize Query logic and UI search behavior in `+page.svelte`.
- [ ] **Phase 1: Codebase Audit & Schema** ## Recent Accomplishments (Jan 23, 2026)
- [x] Audit `src/lib/ae_journals` and `src/routes/journals` for Tailwind compliance and code quality. - [x] **Journal Stability:** Resolved display issues where entries failed to show on initial load.
- [x] Refactor `ae_comp__journal_entry_obj_id_view.svelte` (Header, Editor, Settings extracted). - [x] **Filter Hardening:** Updated LiveQuery to handle NULL/undefined for Enabled/Hidden flags.
- [x] Fix type safety in `[journal_id]/+layout.svelte` (Recent entries history view). - [x] **Config Expansion:** Added dynamic Query Limits (10-1000) to Journal module settings.
- [/] Verify `db_journals.ts` schema for metadata and encryption support.
- [x] Identify and replace non-standard CSS with Tailwind utility classes.
- [x] Update `db_journals.ts` types using the new `agents_sync` exported interfaces.
## Recent Accomplishments (Jan 21, 2026)
- [x] **API Barrel Safety Protocol:** Established rule to purge barrel files *before* source deletions.
- [x] **PWA Manifest Fix:** Corrected manifest link path in `app.html` to resolve 404s.
- [x] **Search Hardening:** Fixed `search_ae_obj_v3` to support nested object parameters in URLs.
- [x] **Redundancy Cleanup:** Removed all legacy `db_save_ae_obj_li__*` functions and barrel references.
- [x] **Business Logic Restoration:** Began restoring "sacred" search mapping logic for Event Sessions.

View File

@@ -5,26 +5,39 @@
**Development Platform:** Arch Linux **Development Platform:** Arch Linux
**API Version:** Aether V3 (REST + JWT) **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.
## 1. Minimalist Configuration Strategy ## 1. Minimalist Configuration Strategy
To simplify laptop deployment, we will move away from large local JSON files. To simplify laptop deployment, we will move away from large local JSON files.
### 1.1 The "Seed" Config ### 1.1 The "Seed" Config
Each laptop will contain a `seed.json` located in standard OS config paths (e.g., `~/.config/aether/seed.json` or `~/Library/Application Support/Aether/`). 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 ```json
{ {
"event_device_id": "AE-LPT-01", "event_device_id": "dbgMWS3KEHE",
"api_base_url": "https://api.oneskyit.com" "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.2 The Bootstrap Flow
1. **Launch:** Electron reads the `seed.json`. 1. **Launch:** Electron reads the `seed.json`.
2. **Identity:** App calls `GET /v3/crud/event_device/{id}?view=full_config`. 2. **Identity:** App calls `GET /v3/crud/event_device/{id}`.
3. **Hydrate:** API returns the full operational config (Account context, Event settings, File cache paths). 3. **Hydrate:** App uses `app_base_url` from the device record to search for the corresponding `site_domain`.
4. **Auth:** App uses its device-specific API key to exchange for a session JWT. 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. 5. **Inject:** Config and JWT are injected into the SvelteKit frontend via the Preload script.
## 2. macOS Hardening (Permissions) ## 2. macOS Hardening (Permissions)
...
macOS requires explicit user consent for several features. The new app will handle these during the "Splash Screen" phase. 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`. - **AV Access:** Use `systemPreferences.askForMediaAccess('camera')` and `microphone`.

View File

@@ -121,30 +121,66 @@ export async function load({ fetch, params, parent, route, url }) {
let result: any = null; let result: any = null;
let api_error = false; let api_error = false;
try { let is_native = false;
if (log_lvl) console.log(`ROOT LOAD: Starting site lookup V3 for ${fqdn}...`);
// Use dedicated Agent Key for Bootstrap and include the unauthenticated bypass header ONLY for this request
const bootstrap_api_cfg = {
...ae_api_init,
api_secret_key: 'IDF68Em5X4HTZlswRNgepQ',
headers: {
...ae_api_init.headers,
'x-aether-api-key': 'IDF68Em5X4HTZlswRNgepQ',
'x-no-account-id': 'bypass' // Force explicit bypass for bootstrap
}
};
result = await lookup_site_domain_v3({ // Detect Aether Native Bridge (Electron)
api_cfg: bootstrap_api_cfg, if (typeof window !== 'undefined' && (window as any).aetherNative) {
fqdn, is_native = true;
view: 'base', if (log_lvl) console.log('ROOT LOAD: Detected Aether Native Bridge. Requesting device config...');
log_lvl try {
}); const native_device_config = await (window as any).aetherNative.getDeviceConfig();
if (log_lvl) console.log(`ROOT LOAD: Site lookup result for ${fqdn}:`, result); if (native_device_config) {
} catch (err) { if (log_lvl) console.log('ROOT LOAD: Native device config received:', native_device_config);
console.error(`ROOT LOAD: Site lookup critical failure for ${fqdn}.`, err); // Map native device config to the expected result structure
api_error = true; result = {
...native_device_config,
// Ensure naming consistency
account_id: native_device_config.account_id || native_device_config.account_id_random,
site_id: native_device_config.site_id || native_device_config.site_id_random,
site_domain_id: native_device_config.site_domain_id || native_device_config.site_domain_id_random,
};
// Inject native device metadata into the location state
if (native_device_config.native_device) {
ae_loc_init['native_device'] = native_device_config.native_device;
// Map specific operational paths
ae_loc_init['local_file_cache_path'] = native_device_config.native_device.local_file_cache_path;
ae_loc_init['host_file_temp_path'] = native_device_config.native_device.host_file_temp_path;
ae_loc_init['recording_path'] = native_device_config.native_device.recording_path;
}
}
} catch (err) {
console.error('ROOT LOAD: Failed to fetch native device config.', err);
}
}
// Perform standard FQDN lookup if not native or if native fetch failed
if (!result) {
try {
if (log_lvl) console.log(`ROOT LOAD: Starting site lookup V3 for ${fqdn}...`);
// Use dedicated Agent Key for Bootstrap and include the unauthenticated bypass header ONLY for this request
const bootstrap_api_cfg = {
...ae_api_init,
api_secret_key: 'IDF68Em5X4HTZlswRNgepQ',
headers: {
...ae_api_init.headers,
'x-aether-api-key': 'IDF68Em5X4HTZlswRNgepQ',
'x-no-account-id': 'bypass' // Force explicit bypass for bootstrap
}
};
result = await lookup_site_domain_v3({
api_cfg: bootstrap_api_cfg,
fqdn,
view: 'base',
log_lvl
});
if (log_lvl) console.log(`ROOT LOAD: Site lookup result for ${fqdn}:`, result);
} catch (err) {
console.error(`ROOT LOAD: Site lookup critical failure for ${fqdn}.`, err);
api_error = true;
}
} }
// Defensive check: if result is false (common from API helper) or null, use emergency ghost // Defensive check: if result is false (common from API helper) or null, use emergency ghost
@@ -166,8 +202,7 @@ export async function load({ fetch, params, parent, route, url }) {
} }
const json_data = result; const json_data = result;
// CRITICAL: SvelteKit hydration can fail if these are undefined // ... rest of the mapping logic ...
// V3 ID Vision: Use account_id (random string) instead of account_id_random
account_id = json_data.account_id || json_data.account_id_random || 'ghost'; account_id = json_data.account_id || json_data.account_id_random || 'ghost';
data_struct.account_id = account_id; data_struct.account_id = account_id;
ae_acct.account_id = account_id; ae_acct.account_id = account_id;
@@ -178,6 +213,7 @@ export async function load({ fetch, params, parent, route, url }) {
ae_acct.api.account_id = account_id; ae_acct.api.account_id = account_id;
ae_acct.api.headers['x-account-id'] = account_id; ae_acct.api.headers['x-account-id'] = account_id;
ae_loc_init['is_native'] = is_native;
ae_loc_init['account_id'] = account_id; ae_loc_init['account_id'] = account_id;
ae_loc_init['account_code'] = json_data.account_code || 'ghost'; ae_loc_init['account_code'] = json_data.account_code || 'ghost';
ae_loc_init['account_name'] = json_data.account_name || 'Ghost Account'; ae_loc_init['account_name'] = json_data.account_name || 'Ghost Account';

View File

@@ -1,3 +1,8 @@
# Aether (AE) Event Launcher Module (v3) # Aether (AE) Event Launcher Module (v3)
This directory contains the files for the new Event Launcher module (v3). Detailed documentation to follow. This directory contains the files for the new Event Launcher module (v3). Detailed documentation to follow.
This should be able to run in 3 modes:
* Default - What most users will see for demo purposes
* Onsite - This is what is set onsite, usually just in the Speaker Ready Room
* Native App - This is for the native app version of Aether and used on the MacBook laptops in each of the session rooms