event_file delete was broken since the module was first created (Oct 2024).
delete_ae_obj_id__event_file passed delete_hosted_file=true + rm_orphan=true to
the generic V3 CRUD endpoint, but delete_obj_template never handled those params —
it only did a raw sql_delete on the event_file row. The hosted_file_link record,
hosted_file DB record, and physical file on disk were never cleaned up.
Fix: call api.delete_hosted_file (the action endpoint) BEFORE deleting the
event_file record so the backend can still resolve link_to_id via Redis.
Pass link_to_type='event_file', link_to_id=event_file_id, rm_orphan=true,
method=delete. hosted_file_id is now an optional param on
delete_ae_obj_id__event_file; component passes event_file_obj.hosted_file_id.
Also fix hosted_file delete in /core/files/ admin page (same root cause):
load links first, then call delete_hosted_file for each link with correct
link_to_type/link_to_id_random and method=delete before removing the record.
Also: add clickable navigation links in the files admin link sub-row.
Direct types (event, journal, archive, post) resolve immediately; nested types
(event_session, event_location, event_presenter, journal_entry, etc.) fetch
their parent ID via the V3 CRUD endpoint and construct the correct route.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Search hosted files across all accounts (including disabled)
- Sortable columns, pagination, per-row delete, download, and SHA-256 copy
- Lazy-load file link records per row via /v3/action/hosted_file/{id}/links
- Fix delete to load links first, remove each via correct link_to_type/link_to_id_random,
then hard-delete with method=delete and rm_orphan=true
- Remove Linked To and Group columns (moved Group/ForType to filter bar only)
- SHA-256 column now visible at lg breakpoint (was xl)
- Added /core/files nav link to /core layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TODO__Agents.md: check off completed passcode JWT migration items;
document the three remaining cleanup steps (deferred ~a few days)
- PROJECT__AE_Site_Passcode_Security.md: update status to active/cleanup-deferred,
check off completed implementation checklist items
- GUIDE__SvelteKit2_Svelte5_DexieJS.md: add new section documenting the
async-function-from-$effect guard-reset infinite loop pattern, with the
real example from the passcode auth bug (2026-06-18)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Passcodes are no longer compared locally against cached localStorage data.
Entry now POSTs to /v3/action/auth/authenticate_passcode; on success the
returned JWT (with per-role TTL) is stored in $ae_loc.jwt. Page-load
expiry check in +layout.ts resets access_type to anonymous when the JWT
has expired, targeting only auth_type='passcode' JWTs.
- Debounce (600 ms) auto-fires the check after typing stops; Enter key
fires immediately as a secondary trigger — preserving the original UX
- Inline spinner and error message added to the passcode input
- Silent fallback to local comparison on network error or unresolved
site_id (ghost), so IDAA staff and Electron/Launcher contexts are safe
- USE_API_PASSCODE_AUTH = true (active); local fallback retained while
production is observed; site_access_code_kv cleanup deferred
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Removed invalid two-way bindings to read-only Dexie observables in the test page
- Fixed 'state_referenced_locally' warning in Field Editor by refactoring draft_value initialization
- Cleaned up empty else block in session list to resolve Vite build warning
- Verified successful production build and clean 'npm run check' output
- Completed rewrite of `element_ae_obj_field_editor.svelte` to Svelte 5 + Tailwind v4
- Set `display_modal = true`, `modal_blocking = false`, and `modal_placement = 'center'` as new defaults
- Implemented trigger-relative modal positioning with automatic viewport boundary clamping to prevent off-screen rendering
- Migrated all 12 call sites across core and events modules (Session, Presenter, Location, Exhibit, etc.)
- Removed legacy datetime-to-local manual conversion logic from views as the component now handles it natively
- Retired Skeleton-based legacy component
- Updated testing page and documentation to reflect the new standardized primitive
- Refactored core layout and dashboard to follow AE Firefly guidelines
- Added proper theme-aware backgrounds and transitioned to Skeleton v4 tokens
- Grouped navigation and cards by functional color (Teal: Infra, Indigo: Identity, Amber: Config)
- Reordered items to: Accounts, Sites, Users, People, Data Stores, Lookups, Addresses, Contacts
- Fixed color inconsistency for Activity Logs in dashboard vs navigation
- Enabled non-blocking modal mode for inline field editors in Data Stores table
- New `display_modal` prop opens the edit panel as a native <dialog> anchored
near the pencil trigger instead of shifting inline content
- `modal_placement` (center|above|below|left|right, default center) positions
the dialog relative to the trigger via getBoundingClientRect + CSS transform
- `modal_blocking` (default true) toggles showModal() vs show(); non-modal
mode adds a document pointerdown listener to close on outside click
- `cancel_edit()` now warns "Discard unsaved changes?" when draft differs from
saved value (matches data store form behaviour); skips warning after a
successful save
- Dialog background uses theme CSS vars directly (--color-surface-50/900) via
:global CSS — Skeleton tonal presets are intentionally semi-transparent and
rendered behind table content without explicit position:fixed + z-index
- Extracted edit panel to {#snippet edit_panel()} — shared by inline and
dialog paths with no duplication
- data-stores table: all three inline field editors switched to display_modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Edit button now has SquarePen icon + text per button UX standard
- Style guidelines: extract button icon+text rule into its own section 8
(was buried in Accessibility); renumber Accessibility to section 9;
add code examples and context table for the rule
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Row is no longer a giant click target. Code, Name, and Type cells now use
AE_Field_Editor for inline editing (pencil in edit_mode). Edit button opens
the full modal for everything else. Preview column hidden (kept in markup).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- order_by_li was sent as an array; backend expects plain object — fixes sort
- pass enabled/hidden directly to search_ae_obj (was defaulting to 'enabled'/'not_hidden')
- account column now shows code/short_name from Dexie cache via SvelteMap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
element_data_store_form.svelte is now the single source of truth for
editing data stores — owns the modal, all form fields, change detection,
save/delete API calls, and IDB cache update.
- element_data_store.svelte: remove ~120 lines of duplicated form/handler
code; now delegates to AE_DataStore_Form via bind:open + callbacks
- data_stores/+page.svelte: open_edit/open_new are now 2 lines each;
remove all draft state, submit_status, handle_save/delete; fix label
a11y (wrapping labels on all filter + bulk-rename inputs)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add original_obj prop + has_changes bindable output to element_data_store_form
- Derive has_changes by comparing each draft field to original_obj; null = always dirty (new record)
- Wire bind:has_changes + original_obj={is_new ? null : editing_obj} in management page
- Fix Save button: preset-filled-primary → preset-filled-primary-500 (matches element_data_store)
- Disable Save when !has_changes; block modal outsideclose when changes are pending
- Restore textarea rows 10 → 15 to match element_data_store.svelte
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New element_data_store_form.svelte handles all form fields for creating/
editing a Data Store. Replaces the inline form in the management page modal.
Features vs old inline form:
- Help text on every label (type descriptions, constraint notes, etc.)
- Advanced section (collapsible, hidden by default): Enable, Hide, Priority,
Sort, Group, Notes — each with hint text
- For ID: editable on new, read-only on edit (with explanation why)
- show_account_field / show_for_fields props for embedded widget use later
- html_edit_mode + show_advanced are internal state, reset via {#key} on parent
Management page: drops html_edit_mode state + Code/Eye/editor imports; uses
{#key editing_obj?.id ?? 'new'} to recreate the form on each record change.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- api.ts: remove get_data_store_obj_w_code (hit /data_store/code/, non-V3)
and its export. V3 get_data_store (/v3/data_store/code/) stays.
- ae_core_functions.ts: remove load_ae_obj_code__data_store (wrapper around
the removed function) and its export from core_func.
element_data_store.svelte replaced this with Dexie LiveQuery + V3 API.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Click any column header to sort; click again to toggle ASC/DESC.
Sort re-runs the current search immediately if results are showing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Bulk Rename panel: code filter (% wildcard), find/replace text,
preview table before apply, sequential PATCH with IDB cache update
- Fix Code filter label/placeholder to show % wildcard syntax
- Add note that API results are scoped to the active account (backend behavior)
- Replace bg-black/5 with bg-surface-500/10 for light/dark compatibility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full CRUD for all data_store records: search by code, account_id,
for_type, for_id; create/edit/delete via modal with type-aware content
editor (CodeMirror / TipTap / textarea). Wired into core nav and
dashboard. for_id shown read-only on edit (DB integer FK constraint).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
for_id is an integer FK in the DB but the frontend passes the random
string ID — sending it on update causes a 400. These fields are
parent-context set at creation time and should never change on edit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two fixes in presenter_view:
1. Name-sync warning (given/family mismatch) was showing even when no
Person was linked. Guard now checks person_id first.
2. Person link replaced the two-step Re-link button flow with on_open
pattern (matches Session POC). Pencil+Re-link button removed; pencil
icon opens the editor and loads the person list in one action.
Admin-only re-link restriction preserved: non-admin staff with a
linked person see a read-only link instead of the editor.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v_event_presenter and v_event_presentation both use INNER JOIN with event
on event_id. Without event_id in the payload the view returns 0 rows after
INSERT, the API falls back to a minimal response, and Dexie save fails
with "Object is missing a valid ID". Pull event_id (and event_session_id
for presenters) from events_slct at creation time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace pill grid (too tall) with a single-row label + select
- Use <optgroup> to keep System / AE grouping without any extra height
- Prune unused Skeleton system themes: concord, crimson, hamlindigo,
rocket, terminus, vintage removed (6 of 10 — never used in practice)
Remaining: nouveau, cerberus, modern, wintry
- Added comment noting Firefly event-specific variants can be pruned
when their events are no longer active
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Theme picker (e_app_sys_bar.svelte):
- Replace flat <select> dropdown with grouped pill buttons
- Two groups: 'System' (Skeleton defaults) and 'AE' (custom themes)
- Active theme highlighted via bg-primary-500 (shows in the current theme's
own primary color — instant visual confirmation)
- Pill labels shortened where helpful (e.g. 'AE_Firefly_SteelBlue' → 'Steel ✦')
- Rename theme_options → skeleton_themes + ae_themes; extract apply_theme()
shared handler (removes duplicated setAttribute + ae_loc.update pattern)
Orphaned component removal (→ ~/tmp/agents_trash):
- e_app_theme.svelte — only imported by the dead legacy menu; the sys_bar
Appearance section fully covers it
- e_app_sys_menu_legacy.svelte — no consumers anywhere in the codebase;
sys_bar (mounted in +layout.svelte) fully replaces it
- e_app_cfg.svelte — only mounted from the dead legacy menu; its live
functionality (iframe toggle, reload, URL builder) is all in sys_bar's
Dev/Tools section
npx svelte-check: 0 errors (file count drops from 5403 → 5400)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- app.css: import ae-c-lci-new.css alongside existing ae-c-lci.css
- e_app_theme.svelte, e_app_sys_bar.svelte, e_app_url_builder.svelte:
add 'LCI (New ✦)' option pointing to AE_c_LCI_new selector
Both themes coexist — switch between 'LCI' and 'LCI (New ✦)' in the
theme picker to compare old vs brand-guide-accurate colors and fonts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New parallel theme (data-theme='AE_c_LCI_new') based on the LCI Brand
Guidelines (March 2023, leanconstruction.org). The current ae-c-lci.css
is untouched. Both can coexist.
To activate for review: add @import './ae-c-lci-new.css' to app.css and
add 'AE_c_LCI_new' as a theme option in e_app_theme.svelte /
e_app_sys_bar.svelte / e_app_url_builder.svelte.
Changes vs current theme:
- Primary blue: anchored to #3a5997 (oklch 39% 0.14 264°) — was too
light (47%) and undersaturated (C=0.11). Pantone Surf the Web.
- Secondary: rebuilt from 3-stop LCI scale (#d4e7f7 → #3598dc → #173378),
hue shifted from 264° to 245° (brighter sky-blue direction).
- Tertiary purple: corrected to #8f44ad oklch(43% 0.20 309°) — was too
light (52.73%) and low chroma (0.17). Pantone Dewberry.
- Success teal: minor tweak to #1bbc9d oklch(68% 0.14 175°). Pantone Mint Leaf.
- Error red: corrected to #df3527 oklch(53% 0.27 28°) — was too light
(59.32%) and undersaturated (C=0.21). Pantone Cherry Tomato.
- Typography: heading-font-family → Proxima Nova/Montserrat (brand spec);
base-font-family → Palatino/serif (brand spec). See file for Montserrat
Google Fonts note and app-UI override guidance.
- Heading color: primary-500 (LCI blue) per brand guide PDF.
- Surface: hue shifted from 196° (teal, wrong direction) to 248° (blue).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Updated Element_ae_obj_field_editor_new.svelte with on_open callback support.
- Improved Select field UX in the editor with an inline loading spinner when options are empty.
- Streamlined session_view.svelte by using on_open to trigger person record loading automatically.
- Removed redundant manual 'Select Person' button in favor of automated lazy-loading.
element_data_store.svelte:
- Source/Visual HTML mode toggles: add Code/Eye icons and title attributes
- Cancel button: add X icon and title="Discard changes and close"
- Delete button: add title="Permanently delete this data store — cannot be undone"
- Save button: add title, and Check icon for updated/created success state
(Check was imported but unused; now put to work matching field editor pattern)
- Remove Eraser import (unused)
- Remove ds_submit_results $state (declared but never read in template —
submit status already tracked via $ae_sess.ds.submit_status; drop the
assignment in handle_submit_form too)
element_ae_obj_field_editor_new.svelte:
- Fix duplicate is_editing declaration: user promoted it to a $bindable prop;
remove the now-conflicting local $state declaration
npx svelte-check: 0 errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Integrated AE_Comp_Editor_CodeMirror as a supported field_type.
- Enhanced button UX with descriptive Lucide icons and title text (Eraser for Clear, etc.).
- Switched Location View description field to use the CodeMirror editor.
- Updated test playground to include a CodeMirror example.
Rolls out the full rewrite of the generic inline field editor, standardizing on
Tailwind v4 + Flowbite styling and resolving several long-standing contract issues.
Component Improvements:
- Fully implemented datetime/date conversion (component now owns format normalization).
- Added type-safety via Svelte 5 generics (<script generics="T">).
- Added automatic select value coercion (prevents stuck optimistic state).
- Added support for 'email', 'url', and 'tel' field types.
- Rebuilt styling on Tailwind v4 utility classes, removing legacy Skeleton UI.
- Improved accessibility: added ARIA labels, Escape-to-cancel, and autofocus.
- Improved error handling with visible inline error messages.
Rollout/Migration:
- Migrated all 8 primary call sites (person_view, device_li, locations_li,
location_view, presentation_li, leads_manage, presenter_view, session_view).
- Swapped manual datetime pre-conversion at call sites for internal handling.
- Updated the test playground to show legacy vs. new side-by-side.
This migration runs the new component in parallel with the old one (still present)
ensuring a safe transition.
Creates the _new version of the field editor element alongside the working
original (which remains untouched). The _new file starts from the original's
hardened optimistic-update state machine and adds:
- Svelte 5 generics (T) on current_value/draft_value instead of any
- email / url / tel added to the field_type union with edit-mode branches
- object_reload prop removed (was declared, never implemented — on_success
is and remains the caller's cache-refresh hook)
- to_input_value() / from_input_value() stubs at the two right call sites
for datetime conversion (both directions, TODO #4 to implement)
- coerce_select_value() stub for select type-mismatch fix (TODO #5)
- Inline TODO mini how-to checked-list mirroring the project doc
- Styling still uses Skeleton classes — tagged for Tailwind/Flowbite swap
(TODO #6) and a11y gaps marked at their exact markup locations (TODO #7)
Companion files:
- documentation/PROJECT__AE_Obj_Field_Editor_New.md — full plan, migration
order for all 8 call sites, naming convention note
- documentation/TODO__Agents.md — new entry pointing to the project doc
- documentation/README__Docs_Index.md — project doc added to Active Projects
npx svelte-check: 0 errors, 1 expected benign warning (state_referenced_locally
on the field_type initializer, documented in-file).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pure reformatting, no content change. Each bullet/paragraph is now one
logical line instead of manually wrapped at ~80-100 chars, which looked
ragged with short trailing fragments in narrow/variable-width editor
panels. Editors soft-wrap long lines naturally; manual hard wraps don't
adapt to panel width.
Also gave the orphaned "Wallpaper reliability" item (previously sitting
between two --- dividers with no section header and a stray double
blank line) its own section header for consistency with the rest of
the doc.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LCI October — Pres Mgmt Restoration: all items now checked, header
flipped from 🔴 in-progress to ✅ complete.
- Axonius DC — June 9: the show happened, badge layout work is done.
Downgraded the remaining "Badges follow-ups" from 🔴 (event-deadline
urgency) to 🚧 (normal backlog) — no event deadline attached until the
next badge-printing event.
- Checked "Use template badge types in search filter" per request:
confirmed still NOT done — ae_comp__badge_search.svelte still has a
hardcoded "Axonius 2026 badge type codes" list with its own pre-existing
TODO comment. Left open, noted the verification.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
presenter_is_authed only checked sign-in state, never .agree, so a
presenter could upload without ever agreeing whenever the admin's
"Require Presenter Agreement" setting was on.
Added presenter_agree_ok (trusted_access || !require__presenter_agree ||
auth__event_presenter_obj.agree) and presenter_can_upload
(presenter_is_authed && presenter_agree_ok) in
presenter/[presenter_id]/+page.svelte, swapped into every place the
upload UI / file-list permissions are gated in both the default and
manage_files alt views. The alt view's public_access identity bypass is
preserved but now also requires presenter_agree_ok.
Added an inline warning message in place of the upload section when
signed in but pending agreement, instead of it silently disappearing.
Marked done in TODO__Agents.md; all three open LCI Pres Mgmt restoration
items are now resolved (2 were already fixed and just needed verifying).
svelte-check: 0 errors, 0 warnings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Checked all three open items in the LCI October restoration list
against current code:
- Presenter email sign-in link routing — FIXED (2026-06-12, e05602b87).
email_sign_in__event_presenter() routes through the session page with
presenter_id/presentation_id params; verified sign_in_out.svelte reads
them and grants presenter-level auth, not just session read access.
- session_page_menu.svelte sign-in prop — VERIFIED CORRECT, no bug found.
event_session_id prop is the real session object field, not a URL
param. The component's separate url_session_id is intentionally a
different thing (POC/Champion link shape only).
- Presenter agreement not enforced before upload — STILL OPEN, confirmed.
presenter_is_authed (the gate used everywhere upload UI shows) has no
dependency on .agree at all; require__presenter_agree only controls
whether the Agreed/Not Agreed button is shown, never blocks anything.
No enforcement found anywhere in the chain, including inside the
upload component itself. Added a concrete fix direction.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BOOTSTRAP__AI_Agent_Quickstart.md: new category 9 under Common Mistakes
pointing to today's incident (local/remote config sync pitfalls)
- REFERENCE__Common_Agent_Mistakes.md: three new entries —
16) local "shadow field" silently bypasses an admin-synced master field
17) SWR await after a write does not mean dependent caches are fresh
18) conditional/stateful sync gates are effectively undebuggable
- PROJECT__Stores_Svelte5_Migration.md: updated the canonical Migration
Pattern example to stamp __version in the serializer (the old example
silently didn't, which is exactly what caused the leads_loc/pres_mgmt_loc
bugs fixed today); flagged badges_loc/launcher_loc/events_auth_loc as
not yet fixed (dormant, not harmful) and idaa_loc as the next migration
that should get this from day one
- TODO__Agents.md: cross-referenced today's Pres Mgmt config sync overhaul
in the LCI October restoration section for context, without touching
the open items in that list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two things prompted by direct feedback after testing:
1. Every input on the Config page now has a title tooltip explaining what
it actually controls, where, and any interaction with other settings
(e.g. clarifying Hide Location affects both the session detail page AND
the Location column in Session Search results — not obvious from the
label alone).
2. Split "Session Field Visibility" into "Session Display" (just
description/location/message) and a new dedicated "POC Settings"
section. Previously hide__session_poc ("Hide POC", checked = remove)
sat directly next to show__session_li_poc_field ("Show POC Column",
checked = add) in the same flat list — same checked state meaning
opposite things for adjacent fields, confusing even though each field's
own hide__/show__ naming is internally consistent with the project
convention. Hide POC is now rendered as a visually distinct master
switch (bold, its own row) with the three dependent settings indented
under a left border below it and auto-disabled (with reduced opacity)
whenever Hide POC is checked, so the "no effect once hidden" dependency
is visible in the UI, not just documented in a footnote.
No field semantics changed — same PressMgmtRemoteCfg, same sync function,
same save path. Pure presentation/documentation pass.
Logged the rationale in PROJECT__AE_Events_PressMgmt_Config_Cleanup.md.
svelte-check: 0 errors, 0 warnings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Same bug pattern as the earlier POC column fix. The Session Search
results table's Location column prop only ever read the local-only,
never-synced hide__session_li_location_field — never the admin-synced
hide__session_location (Config page > Session Field Visibility > Hide
Location). Column always showed regardless of that setting or
permission level.
Fixed in pres_mgmt/+page.svelte:
hide__session_location || hide__session_li_location_field
The other two usages of this component already hardcode
hide__session_location={true} correctly (you're already on that
location's own page, showing its name again would be redundant).
Logged in PROJECT__AE_Events_PressMgmt_Config_Cleanup.md with a note to
audit other hide__* fields for the same gap if more reports come in.
svelte-check: 0 errors, 0 warnings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>