Files
OSIT-AE-App-Svelte/documentation/TODO__Agents.md
Scott Idem bbab9e7c8c feat(idaa): update default recovery meeting limit to 100 and add 75 to stepper
- Update default qry__limit to 100 in idaa_loc
- Add 75 to limit_steps in recovery meetings query component
- Bump AE_IDAA_LOC_VERSION to 2 to apply changes to existing users
- Update IDAA documentation and TODO__Agents.md with SQL optimization task
- Mark implemented UI/UX ideas as done in documentation
2026-05-18 21:25:09 -04:00

24 KiB
Raw Blame History

Frontend Agent Task List

Use this file to track steps for complex features or bug fixes. Status: Stable — ongoing development.

🔴 CMSC Charlotte — May 27 (Presentation Management)

Drive down: May 25 | Setup: May 26 morning | Show: May 27+

[Electron/Launcher] Clean up presentation file launch profiles — BGH show revealed issues with the profiles used to open/launch presentation files. Architecture decision: move launch logic to the Svelte side so it can be changed without an Electron rebuild. Electron becomes a thin OS primitive layer; all business logic lives in Svelte and device config.

Why this matters: the profile map is policy, while the native template is the exact runtime command. Keeping those separate avoids a second hidden source of truth and keeps Electron from guessing defaults.

Electron groundwork (2026-05-11) — DONE:

  • run_osascript hardened — temp .scpt file approach; handles multi-line + special chars
  • native:copy-from-cache-to-temp primitive added — copy to tmp, caller decides launch
  • native:launch-from-cache executes a provided native_template string — AppleScript or shell: prefix; no Electron-side fallback
  • get_launch_profile() in launcher_file_cont.svelte reads from device config then event config; resolves to a native_template string and passes it to launch_from_cache
  • Built-in Launcher defaults refactored into canonical profile names plus extension aliases (ae_launcher__default_launch_profiles.ts)
  • Device-level Launch Timing section added under Launcher Configuration → Device, with per-profile launch_profiles[profile].post_delay_ms overrides
  • URL file launch support (2026-05-13)event_file.extension = 'URL' (or filename starting with http:///https://) is treated as a non-downloaded URL. Background sync skips URL files so they are never treated as cacheable hosted files. Shared AE_Comp_Hosted_Files_Download_Button now hard-bypasses the download path for URL records. In native mode, handle_open_file() routes to native.open_external({ url, app: 'chrome' }) with 'default' fallback. Health section crash fixed (guarded native_device against undefined in preview/edit mode).

Svelte-side migration — remaining before May 26:

  • [Launcher] Built-in Svelte default profiles (2026-05-11) — canonical profile constants live in ae_launcher__default_launch_profiles.ts with extension aliases and a resolve_launch_profile() 3-step fallback (device config → event config → built-in defaults). Covers macOS (pptx, ppt, key, odp, pdf), media (mp4, mkv, mp3, etc.), Windows/Parallels variants, and URL path.

  • [Launcher] Composable open flow — refactor handle_open_file() to use copy_from_cache_to_temp + run_osascript / run_cmd directly instead of the all-in-one launch_from_cache. Finer error handling at each step (verify copy succeeded before attempting script; surface failure clearly in UI).

  • [Launcher] Error handling + fallback (2026-05-14) — post-script failure is non-fatal: surfaces 'fallback' status with error detail (file already open). If open_cmd itself fails, falls back to open_local_file_v2 (OS default); surfaces combined error detail if that also fails. UI renders 'open' / 'fallback' / 'error' states distinctly.

  • [Launcher] Slide control scripts in Svelte configcontrol_presentation AppleScript one-liners are hardcoded in Electron (shell_handlers.ts lines 149159). The Svelte side (launcher_cfg_native_os.svelte) already calls native.control_presentation({ app, action }) with next/prev/start/stop buttons wired and working. The Electron IPC call is stable enough for current shows.

    Remaining (post June 10): Move scripts to device config (data_json.control_scripts) or Svelte constants so behavior can be changed without an Electron rebuild. Replace native.control_presentation() call with native.run_osascript(script) using the config-resolved script string. The run_osascript primitive is already in place; this is purely a wiring/config task. Low priority — hardcoded scripts work fine for PowerPoint and Keynote for now.

  • [Launcher] kill_processes target list in config — The kill_processes IPC primitive exists in Electron and is exposed via electron_relay.ts, but is never called from anywhere in Svelte — no routes, no config components, no file launch flow. No UI exists for it yet.

    What needs doing (post June 10):

    • Decide where the "kill on cleanup" action lives: end of handle_open_file() (auto), or a manual "Kill Apps" button in Native OS config, or both.
    • Process names should come from device config (data_json.kill_process_li) with a built-in fallback list (e.g. ['Microsoft PowerPoint', 'Keynote', 'LibreOffice Impress']).
    • The Native OS config section (launcher_cfg_native_os.svelte) is the natural home for a manual kill button; auto-cleanup on file open would go in launcher_file_cont.svelte.

    Device tab length note: The Device tab now has 6 collapsible sections (Sync Timers, Health, Native OS, Wallpaper, Launch Timing, Updates). Consider moving Launch Timing + a future Kill Apps control into a dedicated "Presentation" section or a fourth tab to keep Device focused on machine/OS concerns rather than per-app launch behavior.

  • [Launcher] Launcher config UI — launch_profiles editor (2026-05-14) — Launch Timing section in launcher_cfg_launch_timing.svelte exposes per-profile post_delay_ms overrides with Save/Reset per row. PATCHes event_device.other_json.launcher.launch_profiles via V3 CRUD. Wired into launcher_cfg.svelte. Shown under Technical Mode ($ae_loc.edit_mode).

  • [Launcher] End-to-end test on macOS — test pptx and key opens on a real podium Mac before May 26 setup day. Verify: file copies to tmp correctly, script fires, app opens in slideshow mode, error fallback works.


🔴 Axonius DC — June 9 (Badge Printing)

Setup/Registration: June 8 | Show: June 9

  • [Badges] Epson C3500 fanfold badge layout — Axonius is using Epson C3500 printers with fanfold (continuous) badge stock. Create/configure a fanfold badge layout compatible with the C3500 format. Must be ready before the June 8 setup/registration day.

🚧 Upcoming High Priority

[Stores] Svelte 4 → Svelte 5 State Migration (prerequisite for Phase 2c)

The app uses svelte-persisted-store (Svelte 4 store contract) for all core persisted state (ae_loc, idaa_loc, ae_api, ae_sess, etc.). In Svelte 5 $effect, reading any field of a Svelte 4 store subscribes to the entire store — coarse-grained reactivity. This is the root cause of the IDAA Novi re-auth bug (2026-03-30): unrelated $ae_loc writes (e.g. iframe height, SWR cfg reload) triggered the Novi verification effect repeatedly.

Migration target: replace svelte-persisted-store with Svelte 5 $state-based persistence (e.g. runed PersistedState, or a lightweight custom wrapper). This gives fine-grained reactivity — only effects that actually read a changed field re-run.

Phased approach (do NOT do all at once):

  • Phase A — Project plan + wrapper decision: Write PROJECT__Stores_Svelte5_Migration.md. Decide: runed library vs. custom $state + localStorage wrapper. Audit all store consumers. Identify stores in priority order. Estimate blast radius per store.

  • Phase B — Core auth stores (highest impact, start here):

    • ae_loc (persisted) — auth flags, site cfg, UI state; ~471 consumer sites across 150+ files
    • idaa_loc (persisted) — Novi auth, IDAA query prefs These two cause the most reactive noise. Migrating them also unlocks Phase 2c (separate ae_auth store) since the callsite sweep is now required anyway.
  • Phase C — Remaining persisted stores:

    • ae_api (persisted) — API config / JWT
    • ae_events_stores persisted entries (badges, launcher, leads, pres_mgmt loc stores)
  • Phase D — Non-persisted writable stores:

    • ae_sess, idaa_sess, slct, slct_trigger, ae_auth_error, ae_trig, ae_snip, etc.
    • Lower urgency (no localStorage churn), but fine-grained reactivity still beneficial.
  • Phase E — Phase 2c (unblocked after B): Split ae_loc into ae_auth + ae_app (see entry below — ~471 callsites, but sweep is cheap once already touching every consumer).

Project plan doc needed: Yes — scope is app-wide. Do NOT start Phase B without Phase A.


[Stores] IDB Content Version System

Scaffolded in store_versions.ts (IDB_CONTENT_VERSIONS constant + check_and_clear_idb_table() helper) and core__idb_dexie.ts (check_and_clear_idb_tables() batch helper). Mirrors AE_LOC_VERSION but targets Dexie table contents rather than localStorage keys.

Currently active: journals.journal_entry (db_journals.ts), events.event (IDAA layout). All other tables are defined but not yet wired.

Real-world impact: Stale IDB records from a properties_to_save change were the root cause of the IDAA Recovery Meetings "no meetings found" bug — a ~1-year unresolved issue (20252026). Fixed 2026-05-16 by wiring events.event into the IDAA layout and bumping its version to 2. See BOOTSTRAP__AI_Agent_Quickstart.md mistake #13 for the full postmortem.

How it works:

  • check_and_clear_idb_table(db_table, 'module', 'table') reads a localStorage key with the expected version from IDB_CONTENT_VERSIONS
  • On mismatch (or missing key), the Dexie table is cleared and the key is updated
  • SWR repopulates from API on next access — no explicit reload needed
  • Cost on version match: one localStorage.getItem() — effectively free
  • Bump a table's version in IDB_CONTENT_VERSIONS when properties_to_save changes shape

IDAA consideration: IDAA tables are already cleared by indexedDB.deleteDatabase() on sign-out/auth failure in (idaa)/+layout.svelte. The content version check is a complementary deploy-time reset, not a replacement.

Tasks:

  • Write check_and_clear_idb_tables() helper in core__idb_dexie.ts (2026-05-14)
  • Wire helper into db_journals.ts (pilot — journal_entry: 2 cleared stale content_md_html) (2026-05-14)
  • Wire events.event into IDAA layout (idaa)/+layout.svelte + bump version to 2 (2026-05-16)
  • Roll out to db_events.ts (module-wide: session, presenter, badge, device, location, file)
  • Roll out to db_core.ts (site_domain, person, user)
  • Roll out to IDAA modules (db_posts.ts, db_archives.ts) — verify auth-wipe interaction first
  • Consolidate the two check_and_clear_idb_table* helpers (single-table in store_versions.ts, batch in core__idb_dexie.ts)

[Stores] Refactor — Phase 2c (deferred)

Phases 1, 2a, 2b are complete (see Completed below). One phase remaining:

  • Phase 2c — Actual separate stores (ae_auth, ae_app): Requires touching ~471 $ae_loc.* auth-field read sites across 150+ files. Deferred until a Svelte runes migration of the store layer itself (touching every component anyway makes the callsite sweep cheap).

[Backend] Join event_location_id onto event_presenter API view

The event_presenter object currently has event_session_id but not event_location_id. When navigating from the Presenter View to the Launcher, the frontend has to do a secondary session lookup to discover the location (magic redirect in launcher base +page.svelte). Joining event_session.event_location_id into the presenter view/response would let the frontend pass the location directly in the Launcher URL without the extra lookup.

  • Backend: added event_location_id (and event_location_id_random) to the event_presenter view or API response (2026-04-09)
  • Frontend: updated ae_EventPresenter type and properties_to_save; now pass as events__launcher_id in presenter_page_menu.svelte (2026-04-09)

[TypeScript] svelte-check hidden errors — discovered 2026-03-27

HOW WE FOUND THIS: The @lucide/svelte 0.577.0 update (2026-03-10) dropped class from IconProps. Fixing it required a declare module '@lucide/svelte' augmentation. That augmentation was mistakenly placed in app.d.ts, which is a script-context declaration file (no export {}). In that context, declare module is an ambient replacement, not a merge — it wiped all icon exports from svelte-check's view, surfacing 1368 previously hidden errors. Once moved to src/lucide-augment.d.ts (a proper module file with export {}), the masking lifted and the real pre-existing errors became visible.

Lesson: A broken ambient declaration can silently hide unrelated errors. If svelte-check suddenly jumps to 0 errors, verify it's not because a bad .d.ts replaced a package's types.

Current state (2026-03-31): 32 errors, 0 warnings — all ModalProps.children.

  • [flowbite-svelte] ModalProps.children — 31 errors across 26 files. The flowbite-svelte Modal component API changed; children is no longer a direct prop (now Svelte snippet-based). Affected files span journals, pres_mgmt, events/settings, and IDAA archives. Run npx svelte-check 2>&1 | grep ModalProps to get the current list. Fix pattern: replace children prop binding with Svelte snippet syntax per flowbite-svelte docs.

[Journals] Journal Entry Config follow-ups

  • [Journals] Visibility / audience toggle contrast — the flag buttons need a clearer selected state in both light and dark mode.

  • [Journals] Footer button style — the actual Done button should read like a real button, not a seamless footer spacer.

  • [Journals] Entry passcode secondary authpasscode_hash stores a hash; compare the entered passcode hash to the stored hash, gate entry loading, and honor the TTL-based access window. This is secondary entry auth, not a plain-text passcode field.

  • [Journals] Summary AI shortcut — add an AI summarize button next to Entry Details Summary so staff can generate a summary directly from the modal.

  • [Journals] Archive On sizing — constrain the Archive On control to a reasonable width instead of letting it expand to full width.

  • [Journals] Archive On behavior — define what Archive On actually means and wire the behavior; it is currently just a UI field with no live effect.

  • [IDAA] Do not cache IDAA data in IDB when access is denied (2026-04-19, audited 2026-04-28) Full audit confirmed all protection layers are in place. No code changes required.

    • All +page.ts / +layout.ts under src/routes/idaa/ are clean — no SWR loads run before auth resolves.
    • All $effect SWR calls in IDAA +page.svelte files are gated on $idaa_loc.novi_verified || $ae_loc.trusted_access.
    • (idaa)/+layout.svelte purges db_posts, db_archives, db_events on auth failure, no-UUID/no-session, and inconsistent state.
    • sign_out() calls indexedDB.deleteDatabase() on all IDAA databases.
    • API 401/403 responses fail-fast in api_get_object.ts (throw before any IDB write).
    • idaa_trig is in-memory writable() only — cannot carry stale trigger state across sessions.
    • $effect auth guards in IDAA page components are reactivity guards (prevent spurious SWR calls on coarse $ae_loc writes), NOT auth-bypass guards. SvelteKit layout hierarchy already prevents child components from mounting when (idaa)/+layout.svelte blocks rendering.
    • Doc: SvelteKit layout hierarchy security model captured in GUIDE__SvelteKit2_Svelte5_DexieJS.md and BOOTSTRAP__AI_Agent_Quickstart.md (Mistake #7).
  • [IDAA] Make contact_li_json_ext searchable — Recovery Meeting contact search (2026-04-08) Members cannot search for meetings by contact name or email. contact_li_json data is not included in default_qry_str and MariaDB cannot substring-search a JSON longtext directly. The event table already has contact_li_json_ext (STORED GENERATED, indexed) to work around this.

    Backend (blocked on this first): Add contact_li_json_ext to the searchable fields whitelist for the event object type — likely a one-line change in ae_obj_types_def.py or the event object definition. Message sent to backend agent 2026-04-08.

    Frontend (after backend ships):

    • src/lib/ae_events/ae_events__event.tssearch__event(): add contact_li_json_ext as an OR condition alongside default_qry_str when qry_str is present.
    • src/routes/idaa/(idaa)/recovery_meetings/+page.svelte fast-path IDB filter: parse contact_li_json and include contact names/emails in the local text match check.
  • [IDAA] Optimize Recovery Meetings SQL VIEW and indexes. The current search query can be taxing on the server. With ~150 active meetings, the view logic and supporting indexes need a performance review to ensure fast responses as the database grows. (Requested 2026-05-18)

  • [IDAA / Events] Audit default_qry_str coverage in other event search pages. The backend was updated 2026-03-31 to expose default_qry_str in API responses. Frontend fix applied to Recovery Meetings (+page.svelte + properties_to_save). Check all other event search pages that use db_events.event.filter() or a secondary post-API text filter — they may have the same mismatch (local searches name/description only while server uses default_qry_str). Start with: any route under /events/ or /idaa/ that has a full-text search input.

[IDAA] Jitsi config editor + live site fix

  • Fix live site (id=17) jitsi_token_endpoint pointing to dev-api: DB has https://dev-api.oneskyit.com/api/jitsi_token for both site 10 and site 17 (IDAA live). Need to update site 17 in production to https://api.oneskyit.com/api/jitsi_token. SQL: UPDATE site SET cfg_json = JSON_SET(cfg_json, '$.jitsi_token_endpoint', 'https://api.oneskyit.com/api/jitsi_token') WHERE id = 17;

  • Add IDAA Jitsi config editor UI to the jitsi_reports page (administrator_access only), alongside the existing Jitsi URL Builder section. Should allow editing key fields in site_cfg_json without needing phpMyAdmin:

    • jitsi_token_endpoint — the JWT signing endpoint (needs to point to prod)
    • Jitsi domain default (currently hardcoded as jitsi.dgrzone.com fallback in the page)
    • novi_jitsi_mod_li — list of Novi UUIDs who get moderator privileges Read from $ae_loc.site_cfg_json, PATCH the site record via V3 CRUD (PATCH /v3/crud/site/{id}/), reload $ae_loc.site_cfg_json on save so it takes effect without re-login.

[IDAA] Jitsi Reports still incomplete

  • Finish Jitsi Reports filters — added Novi UUID exclusion plus meeting-name whitelist filtering, with room-level unique counts based on Novi UUID when present. (2026-05-06)

[PWA] Service worker ignoring chrome-extension:// requests Fixed (2026-05-14)

Guard added to src/service-worker.js fetch handler: if (!event.request.url.startsWith('http')) return; Also skips cross-origin requests entirely (origin check). No console errors from extension URLs.

[CSS] Global placeholder text color — too dark in light mode

Placeholder text inherits full input text color in light mode (Tailwind CSS default), making placeholders indistinguishable from filled-in values. Most visible in badge print controls where placeholders show the actual badge value (e.g. "John Smith").

Workaround: scoped ::placeholder rule added to ae_comp__badge_print_controls.svelte (gray-400 light / gray-500 dark) — commit 7733ef8.

Long-term fix: Add a global rule to the main CSS (e.g. src/app.css or a theme file):

::placeholder {
    color: #9ca3af; /* gray-400 */
    opacity: 1;     /* overrides Firefox's 0.54 default */
}
.dark ::placeholder {
    color: #6b7280; /* gray-500 */
}

Once the global rule is in place, remove the scoped workaround from the badge controls.

[Backend/DevOps] Re-add Access-Control-Allow-Private-Network: true CORS header

Chrome's Private Network Access (PNA) policy blocks public-origin iframes from fetching private-network addresses. Symptom: when dev-api.oneskyit.com resolves to a LAN IP (testing from home), Chrome blocks the site domain lookup → ghost account → site_cfg_json never loads → novi_idaa_api_key is null → IDAA Novi verifier spins forever → timeout banner. Firefox unaffected. Production unaffected (public IPs only).

  • Re-add PNA header to API CORS configdev-api Nginx or FastAPI CORS middleware must respond with Access-Control-Allow-Private-Network: true when Chrome sends Access-Control-Request-Private-Network: true in the preflight. This was fixed ~1 month ago and regressed. Check Nginx site config and FastAPI CORSMiddleware settings. Low urgency (dev-only, Firefox workaround available), but blocks home-network iframe testing.

[DevOps] Remaining deployment items

  • Simplify Dockerfile env file selection — Currently the Dockerfile uses a BUILD_MODE arg to select between .env.dev, .env.test, .env.prod during the Docker build. This is unnecessary complexity: each server (test Linode, prod Linode, workstation) only ever runs one environment, so there will only ever be one env file present in that server's app directory.

    The fix: Each server's app dir (/srv/apps/test_aether_app_sveltekit/, etc.) should have a plain .env file (gitignored, placed manually during server setup). The Dockerfile should just COPY . . and cp .env .env.runtime unconditionally — no if prod / elif test / else dev branching for env file selection.

    What this changes:

    • aether_app_sveltekit/Dockerfile — remove the BUILD_MODE-driven cp block; always use .env
    • Each Linode app dir gets a plain .env instead of .env.test / .env.prod
    • Workstation keeps .env.local (for npm run dev) and .env.dev (for build:docker:dev) — those stay as-is since they legitimately coexist locally
    • BUILD_MODE arg can stay if needed for other build differences; just stop using it to pick the env file
    • Update .gitignore in sveltekit to un-ignore .env.test / remove stale entries if desired

    Do not touch before the April 21 show. Low risk but unnecessary churn right before an event.

  • Branch strategy cleanup: All environments (test, prod, bak) currently pull from the same branches. deploy.sh defaults are ae_app_3x_llm / development — acceptable for now but should establish proper branch separation (e.g. main/master for prod).

  • Tier 2 deploy (Gitea webhook): Push-triggered deploys via Gitea webhook → listener on Linode → deploy.sh. Deferred until Gitea usage is more established.

[Files] Download button — wrong ID used in handle_click() (2026-04-22)

  • Fixed (2026-05-11): All 5 spots in ae_comp__hosted_files_download_button.svelte updated to use hosted_file_obj?.hosted_file_id ?? hosted_file_id instead of the old hosted_file_obj?.id || ... chain that stopped at event_file_id. Needs live re-test to confirm downloads still work correctly from Manage Files.

[Files] db_events.file.clear() on upload clears all cached files (2026-04-22)

In ae_comp__event_files_upload.svelte line 114, db_events.file.clear() wipes the entire file Dexie table, not just files for the current session/presenter. Normally harmless (the reload right after repopulates), but if multiple sessions' file lists are open simultaneously they'd briefly flash empty. Low priority — only noticeable in multi-panel workflows.

[General]

  • Input Field Audit: Several input fields are missing name/id attributes or data-testid. Known examples: badge override fields in ae_comp__badge_obj_view.svelte; template name input in ae_comp__badge_template_form.svelte. Matters for: accessibility, autofill, label associations, and test targeting. (For tests, use getByLabel() rather than input[value*=...] which only checks the HTML attribute, not the Svelte-bound DOM property.)

Completed (2026-04)

Completed (archived)

See the full completed history in: documentation/archive/TODO__Agents__ARCHIVE_2026-03.md documentation/archive/TODO__Agents__ARCHIVE_2026-04.md