15 KiB
Frontend Agent Task List
Use this file to track steps for complex features or bug fixes. Status: Stable — ongoing development.
🚧 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:runedlibrary 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+ filesidaa_loc(persisted) — Novi auth, IDAA query prefs These two cause the most reactive noise. Migrating them also unlocks Phase 2c (separateae_authstore) since the callsite sweep is now required anyway.
-
Phase C — Remaining persisted stores:
ae_api(persisted) — API config / JWTae_events_storespersisted 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_locintoae_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.
- Backend: added
event_location_id(andevent_location_id_random) to theevent_presenterview or API response (2026-04-09) - Frontend: updated
ae_EventPresentertype andproperties_to_save; now pass asevents__launcher_idinpresenter_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-svelteModalcomponent API changed;childrenis no longer a direct prop (now Svelte snippet-based). Affected files span journals, pres_mgmt, events/settings, and IDAA archives. Runnpx svelte-check 2>&1 | grep ModalPropsto get the current list. Fix pattern: replacechildrenprop binding with Svelte snippet syntax per flowbite-svelte docs. -
[IDAA] Make
contact_li_json_extsearchable — Recovery Meeting contact search (2026-04-08) Members cannot search for meetings by contact name or email.contact_li_jsondata is not included indefault_qry_strand MariaDB cannot substring-search a JSON longtext directly. Theeventtable already hascontact_li_json_ext(STORED GENERATED, indexed) to work around this.Backend (blocked on this first): Add
contact_li_json_extto the searchable fields whitelist for theeventobject type — likely a one-line change inae_obj_types_def.pyor 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(): addcontact_li_json_extas an OR condition alongsidedefault_qry_strwhenqry_stris present.src/routes/idaa/(idaa)/recovery_meetings/+page.sveltefast-path IDB filter: parsecontact_li_jsonand include contact names/emails in the local text match check.
-
[IDAA / Events] Audit
default_qry_strcoverage in other event search pages. The backend was updated 2026-03-31 to exposedefault_qry_strin API responses. Frontend fix applied to Recovery Meetings (+page.svelte+properties_to_save). Check all other event search pages that usedb_events.event.filter()or a secondary post-API text filter — they may have the same mismatch (local searchesname/descriptiononly while server usesdefault_qry_str). Start with: any route under/events/or/idaa/that has a full-text search input. -
[package.json] Remove orphaned ShadCN/bits-ui packages.
shadcn-svelteandbits-uiremain inpackage.jsonbut have no usages —src/lib/components/ui/was removed 2026-03-27 (trashed to~/tmp/gemini_trash/shadcn_components_ui_2026-03-27). Removed frompackage.jsonandpackage-lock.jsonon 2026-04-02.
[IDAA] Jitsi config editor + live site fix
-
Fix live site (id=17)
jitsi_token_endpointpointing to dev-api: DB hashttps://dev-api.oneskyit.com/api/jitsi_tokenfor both site 10 and site 17 (IDAA live). Need to update site 17 in production tohttps://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_jsonwithout needing phpMyAdmin:jitsi_token_endpoint— the JWT signing endpoint (needs to point to prod)- Jitsi domain default (currently hardcoded as
jitsi.dgrzone.comfallback 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_jsonon save so it takes effect without re-login.
[PWA] Service worker ignoring chrome-extension:// requests
Browser console shows repeated errors:
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:
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.
[Badges] Remaining badge work before first live event
- Badge print controls UX polish: Scott has improvements in mind — TBD next session.
File:
ae_comp__badge_print_controls.svelte.
[Leads] Exhibitor Lead Scanning — IN PROGRESS (demo-ready prep)
Module is substantially built as a PWA (no Electron). Core flow works end-to-end.
Spec: documentation/PROJECT__AE_Events_Exhibitor_Leads_v3.md and _detail.md.
Full audit: src/routes/events/[event_id]/(leads)/ and src/lib/ae_events/ae_events__exhibit*.ts.
What's working:
- Exhibit search/landing (
/leads/) — SWR, local + API search, sort - Exhibit detail page — 4-tab layout, sticky header with Add/List toggle, auto-refresh timer
- Tab 1 (Start): sign-in via shared passcode OR licensed user (email + passcode)
- Tab 2 (Add): QR scan (confirm mode — replaced rapid/qualify) + manual badge search; duplicate/re-enable detection on both
- Tab 3 (List): SWR lead list, licensee filter (All / My Leads), sort options, export button
- Tab 4 (Manage): admin tools, booth profile edit, passcode, license mgmt, custom questions config, app settings (refresh interval, clear IDB/localStorage, reload)
- Lead detail page: view/edit custom question responses, exhibitor notes (TipTap), priority/enable flags
- Export wired to V3 action endpoint
/v3/action/event_exhibit/{id}/tracking_export(CSV/XLSX)
Remaining before demo:
- Export endpoint — V3 action endpoint confirmed live on backend (2026-03-16). Returns 403 if
leads_api_accessis not enabled on the exhibit — expected behavior. Export button now gated in UI: only renders when$lq__exhibit_obj?.leads_api_access === true. Enable via:PATCH /v3/crud/event_exhibit/{id}with{ "leads_api_access": true }. allow_trackinggate — implemented (2026-03-16). QR scanner shows a warning card and blocks the add. Manual search shows a ShieldOff "Opt-Out" badge per row and guardsadd_as_lead. Opt-in model:allow_trackingmust be explicitlytrueon the badge. Also addedallow_trackingandagree_to_tctoae_EventBadgeinae_types.ts. Demo note: ensure test badges haveallow_tracking = trueor no one can be added.- Payment component —
ae_comp__exhibit_payment.sveltefully implemented (2026-03-27). Reads Stripe config from$ae_loc.site_cfg_json(stripe_publishable_key,stripe_btn_1/3/6/10_license). License tier selector (1/3/6/10 users) with{#key}remount pattern for Stripe web component. 3 states: paid confirmation (priority=true), admin setup hint / "contact organizer" (no Stripe config), payment form.client_reference_id=exhibit_id. TypeScript declaration inapp.d.ts. Stripe keys verified visible in$ae_loc.site_cfg_jsonon dev/demo site. Keys need validity check in Stripe dashboard. - End-to-end smoke test (canceled by client) — sign in with shared passcode, scan/search a badge, add a lead, view detail, add notes/responses, export CSV; canceled 2026-04-09.
- Install prompt — PWA install nudge implemented (2026-03-16).
pwa_install.svelte.tssingleton capturesbeforeinstallprompt(Chrome/Android/desktop) and detects iOS Safari for manual "Share → Add to Home Screen" instructions. Reusableelement_pwa_install_prompt.svelteplaced on the Leads Start tab between the feature grid and sign-in.pwa_install.init()wired into root+layout.svelte; dismiss persists 7 days via localStorage. svelte-check: 0 errors.
[DevOps] Remaining deployment items
- Wire AE_APP_REPLICAS:
docker-compose.ymlline 147 already hasscale: ${AE_APP_REPLICAS:-1}. (verified 2026-03-11) - Archive ae_env_node_app: Archived as tar.gz under
~/OSIT_dev/backups/; old history/docs moved to~/OSIT_dev/for_reference_only/. (2026-03-11) - Build Optimization: Current state finalized. Local Gitea instance stood up at
git.dgrzone.com(Docker, home server) — future: migrate repos from Bitbucket, verify Backblaze/restic backups cover Gitea data. (2026-03-11) - Remote deploy script:
aether_container_env/deploy.sh— SSH-triggered from workstation vianpm run deploy:remote:test/prod. Handles git pull (ff-only) + docker build + restart. Tested and working on test env. (2026-03-25) .env.defaultcleanup: Removed 16 dead variables, added missingAE_NETWORK_NAME/CONTAINER_DOZZLE/AE_DOZZLE_PORT, parameterized all container names (CONTAINER_MARIADB,CONTAINER_PMA,CONTAINER_AE_OPS) with:-defaultfallbacks in compose. ("Dozzle" = log viewer container.) (2026-03-26)- Prod deploy: Run
npm run deploy:remote:prod(off-peak). Prerequisites: both repos pushed to Bitbucket ✓; verify.env.prodexists in/srv/apps/prod_aether_app_sveltekit/on Linode before running. (2026-03-30) - Bitbucket → SSH migration: Switched all three repos (
aether_app_sveltekit,aether_container_env,aether_api_fastapi) to SSH remotes (git@bitbucket.org) on workstation. App passwords deprecated — SSH unaffected. (2026-03-27) - Branch strategy cleanup: All environments (test, prod, bak) currently pull from same branches.
deploy.shdefaults areae_app_3x_llm/development— acceptable for now but should establish proper branch separation (e.g.main/masterfor prod). - Tier 2 deploy (Gitea webhook): Push-triggered deploys via Gitea webhook → listener on Linode →
deploy.sh. Deferred until Gitea usage is more established.
[General]
- Temp Cleanup:
cleanup_tmp_fileswired inlauncher_background_sync.svelte; called at launcher startup. Confirmed working. (2026-03-11) window.print()for badge print button: Wired inae_comp__badge_print_controls.svelte— increments count, fireswindow.print(), redirects to badge search. (done)- Input Field Audit: Several input fields are missing
name/idattributes ordata-testid. Known examples: badge override fields inae_comp__badge_obj_view.svelte; template name input inae_comp__badge_template_form.svelte. Matters for: accessibility, autofill, label associations, and test targeting. (For tests, usegetByLabel()rather thaninput[value*=...]which only checks the HTML attribute, not the Svelte-bound DOM property.)
✅ Completed (2026-03)
✅ Completed (archived)
See the full completed history in documentation/TODO__Agents__ARCHIVE_2026-03.md.