316 lines
20 KiB
Markdown
316 lines
20 KiB
Markdown
# 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:**
|
|
- [x] `run_osascript` hardened — temp `.scpt` file approach; handles multi-line + special chars
|
|
- [x] `native:copy-from-cache-to-temp` primitive added — copy to tmp, caller decides launch
|
|
- [x] `native:launch-from-cache` executes a provided `native_template` string — AppleScript or `shell:` prefix; no Electron-side fallback
|
|
- [x] `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`
|
|
|
|
**Svelte-side migration — remaining before May 26:**
|
|
- [ ] **[Launcher] Built-in Svelte default profiles** — move the built-in presentation/media
|
|
policy objects into a Svelte constants file (e.g. `ae_launcher__default_launch_profiles.ts`).
|
|
Use canonical profile names plus extension aliases so the media family does not repeat the
|
|
same VLC config for every file type. Cover the core macOS set (`pptx`, `ppt`, `key`, `odp`,
|
|
`pdf`), the media set (`mp4`, `mkv`, `mp3`, and related media types), the Windows /
|
|
Parallels variants (`pptxwin`, `pptwin`, `odpwin`, `pdfwin`), and the URL/web-based
|
|
presentation path. Priority: `get_launch_profile()` already checks device config and event
|
|
config; add a 3rd fallback to these Svelte defaults before returning `null`. Keep the
|
|
fallback in Svelte, not in Electron.
|
|
- [ ] **[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** — when the launch script fails, offer fallback
|
|
to `open_local_file_v2` (OS default handler) rather than silently failing. Show error detail
|
|
in the launcher file row so staff can diagnose onsite.
|
|
- [ ] **[Launcher] Slide control scripts in Svelte config** — `control_presentation` AppleScript
|
|
one-liners are hardcoded in Electron. Move to device config (`data_json.control_scripts`) or
|
|
Svelte constants so slide nav behavior (e.g. keystroke vs. AppleScript command) can be adjusted
|
|
without a rebuild. Wire through `run_osascript` directly.
|
|
- [ ] **[Launcher] `kill_processes` target list in config** — process names to kill on cleanup
|
|
are currently caller-hardcoded. Allow device config to specify the process name list per
|
|
file type / app, so adding a new presentation app doesn't require a Svelte code change.
|
|
- [ ] **[Launcher] Launcher config UI — launch_profiles editor** — add a Technical Mode panel
|
|
in the Launcher config (tabbed settings) to view and edit `launch_profiles` entries on the
|
|
active device record. PATCH via `event_device` V3 CRUD. Lets OSIT staff tune launch behavior onsite
|
|
without needing phpMyAdmin or a code deploy.
|
|
- [ ] **[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] 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.
|
|
- [x] Backend: added `event_location_id` (and `event_location_id_random`) to the `event_presenter` view or API response (2026-04-09)
|
|
- [x] 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 auth** — `passcode_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.
|
|
|
|
- [x] **[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.ts` → `search__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 / 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
|
|
- [x] **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
|
|
Browser console shows repeated errors:
|
|
```text
|
|
TypeError: Failed to execute 'put' on 'Cache': Request scheme 'chrome-extension' is unsupported
|
|
```
|
|
The service worker's fetch/install handler is trying to cache requests with `chrome-extension://`
|
|
URLs (injected by browser extensions), which the Cache API rejects. Fix: filter out non-`http`/`https`
|
|
requests before attempting to cache. In the service worker fetch handler, add a guard:
|
|
```js
|
|
if (!event.request.url.startsWith('http')) return; // skip chrome-extension:// etc.
|
|
```
|
|
Locate in `static/service-worker.js` or the Vite PWA plugin config. Low severity — doesn't break
|
|
functionality, but pollutes the console and may cause unhandled promise rejections.
|
|
|
|
### [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):
|
|
```css
|
|
::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 config** — `dev-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)
|
|
- [x] **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-03.md)
|
|
[documentation/archive/TODO__Agents__ARCHIVE_2026-04.md](documentation/archive/TODO__Agents__ARCHIVE_2026-04.md)
|