Commit Graph

2095 Commits

Author SHA1 Message Date
Scott Idem
08fdb2bddf chore(docs): prune fully-completed subsections from TODO__Agents.md 2026-04-02 18:26:44 -04:00
Scott Idem
84875d1daa Moving older files around. 2026-04-02 18:21:39 -04:00
Scott Idem
09757d249c chore(docs): archive completed TODO items to TODO__Agents__ARCHIVE_2026-03.md and tidy main TODO 2026-04-02 18:20:03 -04:00
Scott Idem
fae4bba037 Commenting out alert/notice for now. 2026-04-02 18:19:13 -04:00
Scott Idem
7b2694e9b7 fix(lead): remove invalid 'fill' prop from Star icon 2026-04-02 18:15:52 -04:00
Scott Idem
e27ff2c67f Limit who can create a new badge. This may need to change later. 2026-04-02 18:11:54 -04:00
Scott Idem
c198ca2454 chore(badges): remove legacy badge_id_only_search; sync remote badges config into badges_loc; docs update 2026-04-02 18:03:23 -04:00
Scott Idem
0ab8b936ce badges(runtime): honor mod_badges_json flags (badge_id_only search, QR toggle, add/upload/mass-print gating) 2026-04-02 17:23:35 -04:00
Scott Idem
4a5b4bf7cd badges(config): fix duplicate keys and initialize draft when mod_badges_json missing; update settings button style 2026-04-02 17:06:23 -04:00
Scott Idem
1935564645 Quick version bump again. 2026-04-02 16:30:34 -04:00
Scott Idem
fface58751 fix: add default_qry_str to db_events Event interface, remove incorrect global augment
The field exists on the DB object but was missing from the TypeScript interface,
causing a false error in recovery_meetings search. Added it to db_events.ts where
it belongs. Removed the incorrect global DOM Event augment from the temp augments
file (was patching the wrong interface).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 16:04:49 -04:00
Scott Idem
4a1b0dac86 pres_mgmt config: remove legacy launcher option, add back button + dirty state to config UI
- Remove show__launcher_link_legacy from PressMgmtRemoteCfg, PresMgmtLocState, and
  pres_mgmt_loc_defaults — the Flask/legacy launcher is retired
- Sync function now hardcodes hide__launcher_link_legacy=true (always hidden)
- Config page: back button to pres_mgmt, save buttons disabled until changes made
- Fix {#each} key expressions in config page
- Migrate e_app_access_type and element_manage_event_file_li to pres_mgmt_loc store
- Add temporary svelte type augments file (src/types/)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 15:53:55 -04:00
Scott Idem
fd9e5f6dc0 pres_mgmt: migrate to typed PersistedState store, canonical config schema
Replaces untyped $events_loc.pres_mgmt (svelte-persisted-store) with a
dedicated pres_mgmt_loc (runed PersistedState) backed by a fully typed
PresMgmtLocState interface and PressMgmtRemoteCfg for the server-side JSON.

Key changes:
- ae_events_stores__pres_mgmt_defaults.ts: canonical interfaces + defaults
  covering all hide__/show__ fields, labels, report prefs, query filters,
  and lock_config sync fields; qry_enabled uses 'not_enabled' (matches API)
- ae_events_stores__pres_mgmt.svelte.ts: new PersistedState store
- ae_events__event.ts: sync_config__event_pres_mgmt() rewired to write
  directly to pres_mgmt_loc.current; launcher link inversion preserved
- All 26+ pres_mgmt templates migrated from $events_loc.pres_mgmt.* to
  pres_mgmt_loc.current.*
- New config UI at (pres_mgmt)/pres_mgmt/config/ — manager + edit mode only
- Event settings page: removed embedded pres_mgmt form, links to config page
- event_page_menu: Config button visible only when manager_access + edit_mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 15:27:12 -04:00
Scott Idem
21f0fe69af Quick version bump 2026-04-02 15:03:01 -04:00
Scott Idem
01c895f7ba feat(pres_mgmt): make session start/end datetime editable in edit mode
start_datetime and end_datetime were visible as chips but had no edit control.
Added two datetime-local field editors shown in edit_mode below the display chip:

- Converts stored "YYYY-MM-DD HH:mm:ss" → "YYYY-MM-DDTHH:MM" for the input
  (safe because dayjs has no timezone plugin — times are stored as local time)
- Falls back to event start date + 08:00/09:00 when session datetime is null,
  so staff only need to adjust the time rather than retype the full date
- Editors are side-by-side in a flex-wrap row with min-width so they wrap on mobile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 13:56:06 -04:00
Scott Idem
3a4c4a1e64 feat(pres_mgmt): make session code editable in edit mode
The code badge was display-only — replaced with a field editor so staff
can correct session codes without going to a separate admin view.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 13:46:39 -04:00
Scott Idem
75664ad2e1 feat(pres_mgmt): restore location and description editing in session view
Event location (FK lookup) and description were both visible in the session
view but had no edit controls — lost during V3 migration. Restored both:

- event_location_id: select dropdown populated from this event's location list
  (liveQuery on db_events.location filtered by event_id from the session object)
- description: textarea editor shown directly in edit_mode (no collapse needed
  when actively editing)

Also added event_location_id to editable_fields__event_session, which was
missing and would have caused backend rejections on PATCH.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 13:44:00 -04:00
Scott Idem
2a5adda6cb idaa/video_conferences: restrict invite button to trusted_access staff only
The Jitsi invite dialog can expose backend room URLs and paths.
Previously invite was gated on is_moderator (any Novi group moderator).

Now restricted to $ae_loc.trusted_access (IDAA staff in Aether) so
regular member moderators cannot send invites. All other toolbar
buttons are unchanged.
2026-04-02 13:27:05 -04:00
Scott Idem
be3634d750 No longer allow regular attendees to send an invite. The moderators may be next. 2026-04-02 13:11:23 -04:00
Scott Idem
fd5d5e371b idaa/video_conferences: issue JWT to all verified Novi users
Previously only moderators received a JWT; non-moderators joined
anonymously. Now all verified Novi users get a JWT with the
is_moderator flag set appropriately, allowing the Jitsi server to
enforce authentication and respect context.user.moderator for
all participants.

Also adds JWT payload decode logging (client-side, signature not
verified) so the moderator flag and user identity can be confirmed
in the browser console during testing.
2026-04-02 12:51:05 -04:00
Scott Idem
75d85bf904 Working through bugs... Related to data stores and not using the for type and for id... They were locked. 2026-04-01 19:39:26 -04:00
Scott Idem
5e0f35d3df Working on security defaults and layout of menus. 2026-04-01 19:18:38 -04:00
Scott Idem
0767e2ff82 More cosmetic and permissions review 2026-04-01 18:41:23 -04:00
Scott Idem
38c5345060 Making things look nicer. 2026-04-01 18:09:17 -04:00
Scott Idem
601bcf94b0 Added an extra backup just in case Edit Mode toggle. 2026-04-01 17:43:36 -04:00
Scott Idem
197d136c59 Fixing stuff that was lost with the upgrade to AE v3. 2026-04-01 17:11:21 -04:00
Scott Idem
7d8981bcb5 Version bump just because. I think things are working well from a technical standpoint. 2026-04-01 16:52:10 -04:00
Scott Idem
828a2a0b10 Making things work and look a little nicer. Missing business logic and functions. 2026-04-01 16:50:37 -04:00
Scott Idem
665eb48280 fix(events): show session codes by default
hide__session_code was defaulting to true, suppressing the code badge
in the session list on fresh sessions. Flip to false so codes are
visible out of the box — users can still hide via the menu toggle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 16:43:27 -04:00
Scott Idem
d12a4bf71f feat(events): restore inc_file_counts opt-in, session list layout + button polish
- Add `inc_file_counts` flag to `load_ae_obj_id__event_session` — maps to
  backend alt view (v_event_session_w_file_count) when true; default stays
  lightweight. Callers never pass raw view names.
- Preserve-on-write fallback in `_refresh_session_id_background` keeps
  cached file_count/file_count_all if API response omits them.
- Session detail +page.ts uses `inc_file_counts: true` so SvelteKit prefetch
  no longer clobbers counts via bulkPut on hover.
- Remove explicit `view: 'alt'` from launcher +page.ts (now invalid param).
- Session list link: flex-1 + min-w-0 for full-row width; name flex-1 pushes
  badge group right; code + file_count stacked in flex-col items-end.
- Hover styling: button-like appearance with slow fade-out (duration-500) /
  fast snap-in (hover:duration-150).
- Session +page.svelte: use url_session_id (string) for link_to_id props and
  auth__kv.session[] index — fixes TS type error from number|undefined.
- IDAA layout: dormant tech notice banner (guarded by 1==3, remove when ready).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 16:38:13 -04:00
Scott Idem
214fca3713 fix(auth): disable access_key check — always grant access
Access keys cleared from all site_domain records. Bypassing the entire
key verification block to unblock IDAA. TODO: restore when keys are re-added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 09:59:24 -04:00
Scott Idem
802d0ec368 fix(idaa): preserve Novi session on internal iframe navigation
When navigating within the iframe (e.g. meeting list → meeting detail),
the UUID is only present on the initial iframe src URL — internal SvelteKit
<a href> links don't carry it forward. The layout effect was unconditionally
clearing novi_verified on every navigation that lacked a UUID, causing
"Access Denied" on every internal link click.

Fix: if a valid TTL-cached Novi session exists when no UUID is in the URL,
treat it as internal navigation and preserve the session rather than wiping it.
Non-Novi paths (no session, no UUID) still clear and deny as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 09:55:36 -04:00
Scott Idem
113aae23a7 fix(auth): preserve key string in key_checked to prevent access denied on navigation
key_checked was set to boolean true in Case 3, which +layout.svelte then
persisted back to localStorage. On the next keyless navigation, the check
true === 'actual-key-string' always failed, causing Access Denied after
just one internal page navigation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 09:44:34 -04:00
Scott Idem
62e1115b05 style(layout): add RefreshCw icon to offline/retry buttons, adjust error banner color
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 09:33:26 -04:00
Scott Idem
63ec7f4cc2 feat(auth): persist verified access key to allow keyless internal navigation
Sites requiring a ?key= param (e.g. IDAA Novi iframe pages) no longer need
the key appended to every internal link after the first successful verification.
Stored key is always validated against the current site config from the API —
stale or rotated keys are denied immediately. Key present in URL always takes
the strict live-validation path with no cache shortcut.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 09:33:21 -04:00
Scott Idem
8fabaf28f7 fix(idaa): preserve default sound mute settings when URL params absent
Unconditional assignment was overwriting $state defaults (incoming msg,
reactions, raise hand all muted) with false whenever the iframe template
didn't pass the sound URL params — which it never does.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 19:04:11 -04:00
Scott Idem
f1bce485ab fix(idaa): revert JWT to moderators-only pending Jitsi server config
Temporary rollback — non-moderators rejoin anonymously until Prosody is
configured with allow_empty_token=false to enforce JWT moderator claims.
TODO comment left in place to track the follow-up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 18:52:00 -04:00
Scott Idem
58dbb68601 Minor documentation update 2026-03-31 17:53:31 -04:00
Scott Idem
9b0c05b80c fix(idaa): require JWT for all Novi users, remove embed meeting button
- Issue JWT to all verified Novi users, not just moderators; unauthenticated
  URL access no longer sufficient to join an IDAA video conference
- Remove 'embedmeeting' from Jitsi toolbar via explicit toolbarButtons whitelist;
  the embed dialog exposed the Jitsi host/room URL violating IDAA privacy rules

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 17:53:09 -04:00
Scott Idem
ae4b94f1b2 fix(idaa): expand recovery_meetings search to use default_qry_str from API
Backend updated (2026-03-31) to return default_qry_str in event API responses.
Frontend now stores it via properties_to_save and searches it in both the local
Dexie fast-path filter and the secondary post-API client filter. Previously, the
server searched default_qry_str (e.g. day-of-week, recurring_text) while the
client only checked name/description/location_text -- causing local results to
drop valid matches on revalidation (e.g. searching 'Thursday').

Also adds TODO note to audit other event search pages for the same mismatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 16:16:43 -04:00
Scott Idem
e6daf6b503 fix(bootstrap): validate access_key server-side, prevent stale cache bypass
When a URL access_key is present, skip the Dexie cache fast-path in
lookup_site_domain entirely — the key must be validated against the API.
Previously, a stale cached entry with a previously-valid key would be
returned immediately, allowing access even after the key changed or
was revoked in the URL.

Also: add site_domain_access_key to properties_to_save__site_domain
so domain-level keys are persisted to Dexie for cache validation;
remove shadow access_key re-declaration in +layout.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 15:07:41 -04:00
Scott Idem
84dc3dd158 feat(site): forward optional access_key from URL into site_domain search 2026-03-31 13:35:09 -04:00
Scott Idem
aa5ba8c9c6 docs: clarify access_key guidance; mark prod deploy completed in TODO__Agents.md 2026-03-31 12:57:43 -04:00
Scott Idem
c53a993bab Improved the open meeting externally buttons and style. 2026-03-30 20:06:23 -04:00
Scott Idem
d8ce04304b fix(idaa): re-verify UUID on SvelteKit navigation, not just full reloads
Root cause: url_uuid was read once from window.location.search (const),
assuming UUID changes always cause a full iframe reload (Novi impersonation).
Manual URL edits within the same SvelteKit session keep the layout mounted,
leaving url_uuid stale — the TTL cache then hit for the OLD valid UUID,
granting access under the wrong identity without re-verifying.

Fix:
- url_uuid is now $derived from $page.url.searchParams, updated on every
  SvelteKit navigation
- url_uuid is read outside untrack() in Effect 2 so UUID changes trigger
  a fresh verification run
- verify_failed (boolean) replaced with verify_failed_for_uuid (string|null)
  so the retry-loop latch is keyed to the specific failed UUID — a different
  UUID in the URL is always a clean slate that gets verified fresh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:43:12 -04:00
Scott Idem
525ce1db79 feat(idaa): add manual-copy fallback textarea to breakout modal
Clipboard API is blocked by default in many browsers when running inside
an iframe (requires explicit permission grant). IDAA members shouldn't need
to navigate browser settings to get a meeting link.

Added a readonly textarea below the two action buttons — click it to
select all, then Ctrl+C/Cmd+C. Works in every browser without any
permissions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:16:16 -04:00
Scott Idem
6559e3393c fix(idaa): close Jitsi fake-UUID access hole + add breakout modal
Security fixes (3 layers):
1. layout: verify_novi_uuid now rejects Novi 200 responses with no member
   data — prevents non-existent UUIDs from passing as verified members
2. layout: access gate now requires $idaa_loc.novi_verified in addition to
   novi_uuid (stale UUID alone was insufficient)
3. video_conferences: onMount guard aborts Jitsi init if the layout-verified
   UUID doesn't match the URL UUID (defense-in-depth)

Also fixes an infinite verification loop: when verification fails, writes to
$idaa_loc trigger storage events that cause $ae_loc to re-notify subscribers,
re-running Effect 2 indefinitely. Added verify_failed latch to stop retries —
the UUID is fixed for the page lifetime, retrying always produces the same result.

Feature: "Open Externally" button + modal (iframe mode only) lets IDAA members
escape the Novi iframe when scrolling/layout is broken. Options: copy link to
clipboard or open in new tab. Accessible to all users without edit-mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:15:21 -04:00
Scott Idem
702a7a73de docs: update architecture notes and TODO with Svelte 5 store migration plan
- AE__Architecture.md: minor wording fix
- TODO__Agents.md: add Svelte 4→5 store migration task (root cause of IDAA
  Novi re-auth bug; prerequisite for Phase 2c store refactor)
- PROJECT__Stores_Svelte5_Migration.md: new migration planning doc

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:49:29 -04:00
Scott Idem
847d89054d feat(idaa): show reset button if Novi verification stalls after 8s
If the "Verifying identity..." spinner is still visible after 8 seconds,
show an escape-hatch button that clears ae_loc + ae_idaa_loc from
localStorage and reloads — forcing a fresh site config fetch which
re-populates novi_idaa_api_key so verification can actually run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:45:17 -04:00
Scott Idem
0d49ff3b8d fix(stores): bump AE_LOC_VERSION to 2; add ae_idaa_loc version wipe
AE_LOC_VERSION 1→2: force-clears stale ae_loc localStorage on next page
load for all users. Fixes users stuck on "Verifying identity..." in the
IDAA iframe — their cached site_cfg_json predated novi_idaa_api_key being
added to the site record, leaving api_key null so verification never ran.

AE_IDAA_LOC_VERSION 1: ae_idaa_loc (Novi auth state) was never included in
store_versions.ts — no wipe mechanism existed for it. Added now so future
schema changes can be handled cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:41:13 -04:00