diff --git a/GEMINI.md b/GEMINI.md index 8e444b76..251aa9fa 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -223,30 +223,23 @@ The activity logging functionality is now working as expected. While the origina - **Search Logic Construction:** When building complex V3 `search_query` objects, avoid including empty `and` or `or` arrays, as some backend parsers may strictly validate their presence or content. Only attach these properties if they contain at least one filter. - **Backend Operator Support:** Always verify supported operators (`like`, `eq`, `gt`, etc.) in the backend FastAPI implementation. Using unsupported operators like `ilike` or `contains` will cause immediate backend `ValueError` crashes. -### Session Learnings (2026-01-06 - Night) +### Session Learnings (2026-01-07) -**Context:** Fixed critical IDAA loading issues, optimized API retry logic, and continued V3 migration for IDAA modules. +**Context:** Finalized IDAA Bulletin Board V3 migration and completed the global application of the `editable_fields.ts` pattern. **Key Accomplishments:** -- **IDAA Recovery Meetings Fix:** Resolved a 400 Bad Request error by removing the restricted `conference` field from the V3 search query and implementing local filtering as a temporary frontend workaround. -- **API Retry Optimization:** Updated `post_object` in `api_post_object.ts` to immediately stop retrying on 4xx client-side errors, improving responsiveness and reducing unnecessary network overhead. -- **IDAA V3 Migration:** - - Migrated **Archives** and **Archive Content** modules to V3 CRUD. - - Migrated **Events** (used by Recovery Meetings) to V3 CRUD. - - Created `editable_fields` definitions for Archives and Archive Content. -- **Core Placeholders:** Built logic and UI placeholders for **Addresses** and **Contacts** at `/core/addresses` and `/core/contacts`. -- **Navigation Update:** Integrated the new Address and Contact management routes into the core layout navigation. -- **Inter-Agent Communication:** Established identity as `frontend_svelte` and confirmed the file-based "Inbox" messaging system via `agents_sync/inbox` for coordination with `backend_fastapi` and other agents. +- **IDAA Bulletin Board V3:** Completed migration to V3 CRUD. Resolved a critical bug where results disappeared after filtering by ensuring `account_id` is injected into processed objects before being saved to IndexedDB. +- **Race Condition Resolution:** Identified and fixed a race condition during database refresh by `await`ing Dexie `.clear()` operations. +- **Global Editable Field Whitelists:** Successfully created `.editable_fields.ts` whitelist files for all remaining Aether objects (Journals, Events, Sponsorships). This standardizes secure updates from the frontend by explicitly defining permitted fields for PATCH operations. +- **Documentation:** Updated `TODO.md` and `GEMINI.md` to reflect the current project state and recent milestones. **Key Learnings:** -- **API Health Monitoring:** Learned to use `curl -s https://dev-api.oneskyit.com/v3/crud/health` for direct backend health checks, bypassing frontend complexity during diagnosis. -- **Client Error Handling:** It is critical to differentiate between network failures (worth retrying) and client errors (400, 403) which indicate fundamental request issues. -- **Nested CRUD Pattern:** Successfully applied the `create_nested_obj_v3` and `delete_nested_ae_obj_v3` patterns to the Event Badge and Archive Content modules. -- **Agent Coordination:** The `agents_sync/inbox` provides a low-friction way to align frontend and backend efforts, especially during breaking API transitions. +- **IndexedDB Filter Consistency:** When using client-side filtering (e.g., `liveQuery`) on fields like `account_id`, it is vital that the frontend data processors inject these IDs if the API response omits them (common in nested V3 routes). +- **Asynchronous DB Operations:** Always `await` database cleanup operations (`.clear()`) before triggering new data loads to prevent stale data or empty lists due to race conditions. +- **Strict Data Shaping:** Centralizing field whitelists in `.editable_fields.ts` files provides a clean, maintainable way to control what data is sent back to the API during updates, preventing accidental overwrites of protected fields. **Next Steps:** -- **Bulletin Board (Posts):** Migrate `ae_posts` to V3 CRUD. -- **Person Activity UI:** Finalize the "Linked Activity & Content" section in the Person detail view to show real related data. -- **Address/Contact Details:** Build out the detail pages for these new modules. -- **Agent Inbox:** Periodically check `/home/scott/agents_sync/inbox/frontend_svelte/` for messages from the backend agent. +- **Authentication & Security:** Standardize JWT usage in headers for all V3 calls. +- **Person Management:** Build out the "Linked Activity & Content" section and dedicated edit forms. +- **Address/Contact Details:** Implement detail pages for these newly added modules. diff --git a/TODO.md b/TODO.md index 6fe9183c..e5b77d2a 100644 --- a/TODO.md +++ b/TODO.md @@ -6,6 +6,8 @@ This is a list of tasks to be completed before the next event/show/conference. ## Recent Accomplishments +- [x] **Editable Fields Whitelists (2026-01-07):** Applied the `editable_fields.ts` pattern to all remaining AE objects across Journals, Events, and Sponsorships modules. This ensures secure and explicit field updates from the frontend. +- [x] **IDAA Bulletin Board V3 (2026-01-07):** Fully migrated to V3 CRUD. Resolved UI filtering issues by ensuring 'account_id' injection and awaiting database operations. - [x] **Core Module Migration (2026-01-06):** Fully migrated Accounts, Sites, Site Domains, People, Users, and Activity Logs to Aether API CRUD V3. Implemented standardized "API -> Processor -> DB Save" pattern and editable field whitelists. - [x] **Core Management UI (2026-01-06):** Scaffolded the management dashboard and list/detail routes for Accounts, Sites, Users, and Lookups. - [x] **Event Badges V3 (2026-01-06):** Completed migration of Create, Update, and Delete operations to V3 nested CRUD. @@ -107,7 +109,7 @@ This is a list of tasks to be completed before the next event/show/conference. - [x] **Naming Conventions:** Enforce `snake_case` and consistent file naming (`ae___.ts`). - [x] **Rich Text Editor:** Migration to CodeMirror complete. -- [ ] **Editable Fields:** Apply the `ae___.editable_fields.ts` pattern to all remaining objects. +- [x] **Editable Fields:** Apply the `ae___.editable_fields.ts` pattern to all remaining objects. --- diff --git a/src/lib/ae_events/ae_events__event_badge_template.editable_fields.ts b/src/lib/ae_events/ae_events__event_badge_template.editable_fields.ts new file mode 100644 index 00000000..91d4002d --- /dev/null +++ b/src/lib/ae_events/ae_events__event_badge_template.editable_fields.ts @@ -0,0 +1,33 @@ +export const editable_fields__event_badge_template = [ + 'name', + 'description', + 'logo_filename', + 'logo_path', + 'header_path', + 'secondary_header_path', + 'footer_path', + 'header_row_1', + 'header_row_2', + 'badge_type_list', + 'ticket_list', + 'ticket_1_text', + 'ticket_2_text', + 'ticket_3_text', + 'ticket_4_text', + 'ticket_5_text', + 'ticket_6_text', + 'ticket_7_text', + 'ticket_8_text', + 'wireless_ssid', + 'wireless_password', + 'show_qr_front', + 'show_qr_back', + 'layout', + 'style_filename', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_events/ae_events__event_device.editable_fields.ts b/src/lib/ae_events/ae_events__event_device.editable_fields.ts new file mode 100644 index 00000000..6252f6cd --- /dev/null +++ b/src/lib/ae_events/ae_events__event_device.editable_fields.ts @@ -0,0 +1,32 @@ +export const editable_fields__event_device = [ + 'code', + 'name', + 'description', + 'passcode', + 'local_file_cache_path', + 'host_file_temp_path', + 'recording_path', + 'record_audio', + 'record_video', + 'trigger_open_file_id', + 'trigger_open_session_id', + 'trigger_recording_start', + 'trigger_recording_stop', + 'trigger_reset', + 'trigger_show_admin', + 'trigger_show_hidden', + 'alert', + 'alert_msg', + 'status', + 'status_msg', + 'record_status', + 'record_status_msg', + 'meta_json', + 'other_json', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_events/ae_events__event_file.editable_fields.ts b/src/lib/ae_events/ae_events__event_file.editable_fields.ts new file mode 100644 index 00000000..19bafb7e --- /dev/null +++ b/src/lib/ae_events/ae_events__event_file.editable_fields.ts @@ -0,0 +1,12 @@ +export const editable_fields__event_file = [ + 'filename', + 'extension', + 'open_in_os', + 'file_purpose', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_events/ae_events__event_location.editable_fields.ts b/src/lib/ae_events/ae_events__event_location.editable_fields.ts new file mode 100644 index 00000000..92db2842 --- /dev/null +++ b/src/lib/ae_events/ae_events__event_location.editable_fields.ts @@ -0,0 +1,18 @@ +export const editable_fields__event_location = [ + 'external_id', + 'code', + 'type_code', + 'name', + 'description', + 'passcode', + 'hide_event_launcher', + 'alert', + 'alert_msg', + 'data_json', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_events/ae_events__event_presentation.editable_fields.ts b/src/lib/ae_events/ae_events__event_presentation.editable_fields.ts new file mode 100644 index 00000000..4b184422 --- /dev/null +++ b/src/lib/ae_events/ae_events__event_presentation.editable_fields.ts @@ -0,0 +1,18 @@ +export const editable_fields__event_presentation = [ + 'external_id', + 'code', + 'type_code', + 'abstract_code', + 'name', + 'description', + 'start_datetime', + 'end_datetime', + 'passcode', + 'hide_event_launcher', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_events/ae_events__event_presenter.editable_fields.ts b/src/lib/ae_events/ae_events__event_presenter.editable_fields.ts new file mode 100644 index 00000000..2c528a68 --- /dev/null +++ b/src/lib/ae_events/ae_events__event_presenter.editable_fields.ts @@ -0,0 +1,27 @@ +export const editable_fields__event_presenter = [ + 'external_id', + 'code', + 'pronouns', + 'informal_name', + 'title_names', + 'given_name', + 'middle_name', + 'family_name', + 'designations', + 'professional_title', + 'full_name', + 'affiliations', + 'email', + 'biography', + 'agree', + 'comments', + 'passcode', + 'hide_event_launcher', + 'data_json', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_events/ae_events__event_session.editable_fields.ts b/src/lib/ae_events/ae_events__event_session.editable_fields.ts new file mode 100644 index 00000000..48302f82 --- /dev/null +++ b/src/lib/ae_events/ae_events__event_session.editable_fields.ts @@ -0,0 +1,23 @@ +export const editable_fields__event_session = [ + 'external_id', + 'code', + 'type_code', + 'poc_agree', + 'poc_kv_json', + 'name', + 'description', + 'start_datetime', + 'end_datetime', + 'passcode', + 'hide_event_launcher', + 'alert', + 'alert_msg', + 'data_json', + 'ux_mode', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_events/ae_events__exhibit.editable_fields.ts b/src/lib/ae_events/ae_events__exhibit.editable_fields.ts new file mode 100644 index 00000000..c18a7172 --- /dev/null +++ b/src/lib/ae_events/ae_events__exhibit.editable_fields.ts @@ -0,0 +1,32 @@ +export const editable_fields__event_exhibit = [ + 'code', + 'name', + 'description', + 'staff_passcode', + 'data_json', + 'leads_api_access', + 'leads_custom_questions_json', + 'leads_device_sm_qty', + 'leads_device_lg_qty', + 'license_max', + 'license_li_json', + 'cfg_json', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; + +export const editable_fields__event_exhibit_tracking = [ + 'exhibitor_notes', + 'responses_json', + 'data_json', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_journals/ae_journals__journal.editable_fields.ts b/src/lib/ae_journals/ae_journals__journal.editable_fields.ts new file mode 100644 index 00000000..2c8998a8 --- /dev/null +++ b/src/lib/ae_journals/ae_journals__journal.editable_fields.ts @@ -0,0 +1,32 @@ +export const editable_fields__journal = [ + 'code', + 'type_code', + 'name', + 'short_name', + 'summary', + 'outline', + 'description', + 'description_html', + 'description_json', + 'timezone', + 'alert', + 'alert_msg', + 'sort_by', + 'sort_by_desc', + 'cfg_json', + 'data_json', + 'passcode_read', + 'passcode_read_expire', + 'passcode_write', + 'passcode_write_expire', + 'passcode', + 'passcode_timeout', + 'private_passcode', + 'auth_key', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_journals/ae_journals__journal_entry.editable_fields.ts b/src/lib/ae_journals/ae_journals__journal_entry.editable_fields.ts new file mode 100644 index 00000000..01fb8817 --- /dev/null +++ b/src/lib/ae_journals/ae_journals__journal_entry.editable_fields.ts @@ -0,0 +1,32 @@ +export const editable_fields__journal_entry = [ + 'code', + 'journal_entry_type', + 'activity_code', + 'category_code', + 'type_code', + 'topic_code', + 'tags', + 'public', + 'private', + 'personal', + 'professional', + 'name', + 'short_name', + 'summary', + 'outline', + 'content', + 'content_html', + 'content_json', + 'history', + 'alert', + 'alert_msg', + 'data_json', + 'enable', + 'hide', + 'archive', + 'archive_on', + 'priority', + 'sort', + 'group', + 'notes' +]; diff --git a/src/lib/ae_sponsorships/ae_sponsorships__sponsorship.editable_fields.ts b/src/lib/ae_sponsorships/ae_sponsorships__sponsorship.editable_fields.ts new file mode 100644 index 00000000..a22fe6bc --- /dev/null +++ b/src/lib/ae_sponsorships/ae_sponsorships__sponsorship.editable_fields.ts @@ -0,0 +1,43 @@ +export const editable_fields__sponsorship_cfg = [ + 'for_type', + 'for_id', + 'level_li_json', + 'option_li_json', + 'schedule_li_json', + 'cfg_json', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +]; + +export const editable_fields__sponsorship = [ + 'poc_person_id', + 'poc_json', + 'name', + 'name_override', + 'description', + 'email', + 'website_url', + 'logo_li_json', + 'media_li_json', + 'social_li_json', + 'address_li_json', + 'contact_li_json', + 'guest_li_json', + 'level_num', + 'level_str', + 'amount', + 'questions_li_json', + 'agree', + 'comments', + 'staff_notes', + 'enable', + 'hide', + 'priority', + 'sort', + 'group', + 'notes' +];