Both found during 2026-04-22 late-night review of Manage Files upload/download flow.
Downloads confirmed working despite wrong ID (backend silently accepts event_file_id
at hosted_file endpoint). Needs proper fix before backend tightens validation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SvelteKit load functions fire during link prefetch before Novi auth completes;
`if (browser)` guards do not prevent this. Moving all IDAA data fetching into
$effect hooks gated on `novi_verified || trusted_access` closes the IDB
pre-population race across archives, bb/[post_id], and recovery_meetings/[event_id].
Also documents the Auth-Before-Cache rule and per-route status in
AE__Permissions_and_Security.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TODO: mark BGH file-warning and hide-draft items complete; add detailed
Dockerfile env-file simplification task (deferred post-April 21 show);
strip stale completed DevOps entries from the active list
- package.json: remove build:docker:test/prod (never used locally; deploys
go through remote deploy.sh on Linode)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add +page.ts to trigger load_ae_obj_li__event_location on page load (locations
were never fetched without a manual trigger)
- Fix ae_comp__event_session_obj_li_wrapper: query used event_location_id_random
(deprecated index) instead of event_location_id, causing empty session lists
under each location
- Wire hide__session_poc to pres_mgmt_loc.current.show__session_li_poc_field so
the Options toggle actually takes effect in the per-location session list
- Also set hide__session_location=true since location is implicit in that context
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract session search form into ae_comp__pres_mgmt_session_search.svelte
(parallels ae_comp__badge_search.svelte); removes ~145 lines from +page.svelte
- Add time window filter: Clock icon toggle button reveals compact before/after
selects; trusted users get 3d/7d options; active state highlighted in amber
- Add passes_hide_filter to IDB fast path to mirror API qry_hidden logic and
eliminate the hidden-session blink on revalidation
- Add passes_time_window applied to both IDB fast path and API results
- Add time window state fields to PresMgmtLocState + pres_mgmt_loc_defaults
- Add contextual warning in "No sessions found" when time filter is active
- badges: hide "Start Here" button for trusted_access users; tweak button shade
- badges: scope placeholder CSS fix to input only (not textarea)
- Add MODULE__AE_Events_PressMgmt_Launcher.md doc
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
toggle_field only changed active_field — it never called cancel_field for the
previously open field. Unsaved typed values stayed in edit_full_name_override etc.,
so reopening a field would show the stale typed value and re-apply it to the badge
preview, even though the user had already moved on.
New logic: capture was_open, always call cancel_field for the current field (resets
edit vars + sets active_field = null), then open the new field if it wasn't the one
being closed. Closing a field by re-clicking its pencil now also discards unsaved state,
consistent with the explicit [X] button behavior.
Also: add global placeholder CSS fix to TODO__Agents.md (scoped workaround already
in ae_comp__badge_print_controls; long-term fix belongs in app.css or theme file).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TODO__Agents.md: added task for contact search — backend to whitelist
contact_li_json_ext in event search, frontend to add OR condition in
search__event() and update local IDB fast-path filter. Blocked on backend.
- CLIENT__IDAA_and_customized_mods.md: documented the search architecture
gap under Recovery Meetings — what default_qry_str contains, why
contact_li_json is unsearchable as raw JSON, what contact_li_json_ext is
and what needs to happen to enable contact name/email search.
Backend agent notified via ae_send_message 2026-04-08.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added Section 4 'Staff Editing Rules': documents per-object behavior when
trusted/admin staff edit member content. BB Post external_person_id is readonly
for non-admin staff; Post Comment preserves existing record identity; Recovery
Meeting external_person_id is intentionally editable for ownership reassignment.
Clarifies that staff identity only fills when the record has no existing linkage.
- Added Section 5 'Recovery Meetings — Contact 1 Convention': states the business
rule that Contact 1 is nearly always the same person as external_person_id (the
meeting owner). Documents the distinction between ownership link vs. display contact.
- Added race condition defense note to Section 3 Implementation Patterns: creation
buttons and edit submit handlers must scavenge from localStorage when the Svelte
store is briefly null on mount.
- Updated test coverage table: Recovery Meetings now has substantial Playwright
coverage (idaa_recovery_meeting_edit.test.ts). Noted pending BB Post/Comment tests.
- Updated Last Verified date to 2026-04-07.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CRITICAL IDENTITY FIX:
Ensures all member-generated content (Meetings, Posts, Comments) is explicitly linked to the creator's Novi UUID via 'external_person_id' at the moment of creation.
Changes:
- Added 'external_person_id' to creation payloads in Recovery Meetings and BB Posts.
- Implemented 'identity scavenging' from localStorage in submit handlers to prevent race conditions where Svelte stores are briefly null.
- Refactored Post Comment edit component to robustly initialize and save creator identity.
- Added 'The Novi UUID Rule' to IDAA documentation to mandate this pattern for future development.
- Added Playwright test to verify creation linkage and fixed a version-mismatch bug in the test auth helper.
Note: Archives and Archive Content are excluded as they do not require member ownership.
- New /events/[event_id]/leads/config page: administrator UI for
mod_exhibits_json. Controls leads_require_payment toggle and Stripe
keys (publishable key + buy button IDs per license tier).
- leads_require_payment (mod_exhibits_json) now gates all billing UI:
header CreditCard button in exhibit +page.svelte and Licenses & Billing
accordion in ae_tab__manage.svelte. Default false (client covers costs).
- Stripe keys migrated from site_cfg_json to mod_exhibits_json (per-event).
ae_comp__exhibit_payment accepts them as optional props; falls back to
site_cfg_json for events not yet migrated.
- Fixed "My Leads" bug for shared-passcode users: search_params now maps
licensee_email 'my' → 'shared_passcode' literal (not kv.key passcode
string) so filters correctly match stored external_person_id values.
- Event settings: Exhibits section replaced with config link + raw JSON
fallback, matching pres_mgmt/badges pattern.
- Docs updated: README.md, MODULE__AE_Events_Exhibitor_Leads.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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>
- 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>
Records the root cause of the 2026-03-27 hidden-error discovery (broken ambient
declaration masking 31 pre-existing svelte-check errors), the lesson learned, and
two follow-up tasks: fix ModalProps.children across 26 files, remove shadcn-svelte
and bits-ui from package.json.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full implementation of ae_comp__exhibit_payment.svelte (was a 9-line stub).
Reads Stripe config from $ae_loc.site_cfg_json per-event. License tier
selector (1/3/6/10 users) uses {#key} remount pattern to work around
stripe-buy-button web component ignoring attribute changes after mount.
Three states: paid confirmation (priority=true), not-configured hint, payment
form. client_reference_id=exhibit_id ties payments to booth records.
TypeScript declaration for stripe-buy-button added to app.d.ts via
svelte/elements augmentation. exhibit_id prop wired in +page.svelte and
ae_tab__manage.svelte.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
20 calls/sec, 600/min, 100k/day. Notes the 10s flat backoff + single retry
and the 5-min TTL cache that prevents normal-use rate limiting.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Critical bugs fixed:
- $derived(() => {}) stored the function itself; uuid/api_key were always
undefined so verification never fired. Fixed to $derived.by(() => {}).
- novi_verifying pre-initialized to true (flash prevention) was also used as
the concurrency guard — guard saw it as in-flight and exited immediately,
leaving the spinner stuck forever. Split into separate verify_in_flight flag.
- $idaa_loc reads in dedupe snapshot (outside untrack) subscribed the effect
to idaa_loc writes, causing needless re-runs post-verification.
- Rate limit was not UUID-aware: 429 on one UUID blocked impersonation
(new UUID). TTL and rate-limit guards now both bypass when UUID changes.
Also includes: store defaults for novi_verified_ts + novi_rate_limited_until,
docs update, iframe template g_uuid param (prior agent changes).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added section 7 covering /v3/action/user/ endpoints: authenticate, verify_password,
change_password, new_auth_key, email_auth_key_url — including the legacy→V3
migration table and auth key one-time-use behavior.
Also clarified the response shape note to explicitly list all response types
(GET single, GET list, POST create, PATCH, search) that use the V3 envelope.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tests/README.md — new "IDAA Auth Tests" section with three lessons:
1. ae_idaa_loc seed must include full bb/archives structure or
verify_novi_uuid() throws silently and resets novi_uuid to null
2. StorageEvent pattern for testing reactive persisted-store updates
without pre-seeding Dexie or navigating twice
3. getByText { exact: false } for UUID in multi-field spans
GUIDE__SvelteKit2_Svelte5_DexieJS.md — new "untrack() reactive tracking
trap" section: reading a store value inside untrack() makes it a one-shot
dependency; fix is to hoist the read outside untrack() and add a guard
to avoid redundant work on unrelated store updates.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>