Root cause of the presenter QR not propagating to other browsers/incognito: sync_config__event_pres_mgmt() was only called from pres_mgmt/+page.svelte and session/[session_id]/+page.svelte. A browser landing directly on the presenter page (e.g. via a presenter's sign-in link) never synced remote config into pres_mgmt_loc.current at all — every always-synced and lock-synced field (QR enables, POC visibility, code visibility, labels, etc.) silently stayed at hardcoded local defaults regardless of what was set on the Config page, since that page was never visited in that browser. Added the same sync $effect (mirroring the existing pattern/comment already in session/[session_id]/+page.svelte) to: - presenter/[presenter_id]/+page.svelte - locations/+page.svelte - location/[event_location_id]/+page.svelte - reports/+page.svelte Logged in PROJECT__AE_Events_PressMgmt_Config_Cleanup.md with a note that any future pres_mgmt entry page needs the same block. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
14 KiB
Project: Pres Mgmt Config Cleanup & Config UI
Status: 🟡 ~70% Complete — Core Working, Cleanup Pass Needed
Priority: Medium (core features functional; remaining work is deprecation + consistency)
Created: 2026-04-02
Last Updated: 2026-06-12 (regression audit)
Related: TODO__Agents.md, PROJECT__Stores_Svelte5_Migration.md
Background
The event.mod_pres_mgmt_json config grew organically across several conferences
(LCI, BGH, etc.) and has accumulated serious inconsistencies:
- Mixed
show__andhide__prefixes for the same concepts - Some features have BOTH
show__fooandhide__fookeys active simultaneously - Duplicate keys with different names (
file_purpose_option_kv=file_purpose_option_li) - Dead config (
HOLD__*prefix) - Type inconsistency (
label__person_external_id: falsevs"LCI member ID"string) - Keys in the DB not consumed by
sync_config__event_pres_mgmt() - Bug:
label__session_poc_name_shortis read then immediately overwritten (line 970-972 in ae_events__event.ts) hide_launcher_link/hide_launcher_link_legacymissing the__separator (inconsistent)show_content__presentation_descriptionuses a third naming convention- Admin must edit DB records directly to change config — error-prone
The local config (events_loc.pres_mgmt) is also tangled into the main events_loc
persisted store which is part of the paused Svelte 5 migration.
Goals
- Canonical config schema — define a TypeScript interface for
mod_pres_mgmt_json - Consistent naming convention — one rule for all
show__/hide__keys - New Svelte 5 store — break out local pres_mgmt config from
events_loc - Config UI — admin page within pres_mgmt to manage the remote config
- No more direct DB edits for routine pres_mgmt configuration
Convention Decision
Rule: the prefix reflects the default state.
| Prefix | Default | Use for |
|---|---|---|
hide__ |
false = visible |
Features ON by default that can be turned off |
show__ |
false = hidden |
Features OFF by default that can be turned on |
Never have both show__foo and hide__foo for the same concept.
- Visibility controls (codes, descriptions, POC, biography) → default visible →
hide__ - Opt-in features (access links, launcher, QR links) → default hidden →
show__
Canonical Remote Config Schema
PressMgmtRemoteCfg — the authoritative TypeScript interface for event.mod_pres_mgmt_json:
interface PressMgmtRemoteCfg {
// System
lock_config: boolean; // true = force remote→local sync (prevent user overrides)
// Labels (event-specific terminology overrides)
label__person_external_id: string | null; // default: 'External ID'
label__presenter_external_id: string | null; // default: 'External ID'
label__session_poc_type: string | null; // e.g. 'champion', 'poc'
label__session_poc_name: string | null; // e.g. 'Champion', 'Point of Contact'
// Codes (visible by default — hide to suppress)
hide__location_code: boolean;
hide__presentation_code: boolean;
hide__presenter_code: boolean;
hide__session_code: boolean;
// Session fields (visible by default)
hide__session_description: boolean;
hide__session_location: boolean;
hide__session_msg: boolean;
hide__session_poc: boolean;
hide__session_poc_biography: boolean;
hide__session_poc_profile_pic: boolean;
// Presenter fields
hide__presenter_biography: boolean;
// Presentation fields
hide__presentation_datetime: boolean;
hide__presentation_description: boolean; // replaces show_content__presentation_description
// Opt-in features (hidden by default — show to enable)
show__copy_access_link: boolean;
show__email_access_link: boolean;
show__launcher_link: boolean;
show__launcher_link_legacy: boolean;
show__session_li_poc_field: boolean; // POC column in session list/table; hide__session_poc still wins
// Requirements
require__presenter_agree: boolean;
require__session_agree: boolean;
// Navigation/UI constraints
limit__navigation: boolean;
limit__options: boolean;
// File upload config
file_purpose_option_kv: Record<string, {
name: string;
disabled?: boolean;
hidden?: boolean;
}> | null;
// Report visibility (key = report slug, value = true to hide)
hide__report_kv: Record<string, boolean>;
}
Keys Removed vs. Current DB Records
| Removed Key | Reason |
|---|---|
file_purpose_option_li |
Duplicate of file_purpose_option_kv |
HOLD__file_os_selection_option |
Dead/held feature |
hide__copy_access_link |
Conflicts with show__copy_access_link — use show__ |
hide__email_access_link |
Conflicts with show__email_access_link — use show__ |
hide__launcher_link |
Conflicts with show__launcher_link — use show__ |
hide__launcher_link_legacy |
Conflicts with show__launcher_link_legacy — use show__ |
hide__report_li |
Superseded by hide__report_kv |
show__navigation |
Ambiguous — covered by limit__navigation |
label__session_poc_name_short |
Was a bug — never applied (overwritten immediately) |
show_content__presentation_description |
Renamed to hide__presentation_description |
New Svelte 5 Local Store
Do NOT touch events_loc or the paused Svelte 5 migration.
Instead, create a standalone store for pres_mgmt local config.
File: src/lib/stores/ae_events_stores__pres_mgmt.svelte.ts
import { PersistedState } from 'runed';
import { pres_mgmt_loc_defaults } from './ae_events_stores__pres_mgmt_defaults';
export const pres_mgmt_loc = new PersistedState('ae_pres_mgmt_loc', pres_mgmt_loc_defaults);
// Usage: pres_mgmt_loc.current.hide__session_code
- New localStorage key:
ae_pres_mgmt_loc(separate fromae_events_loc) - Version gate: add
AE_PRES_MGMT_LOC_VERSIONtostore_versions.ts sync_config__event_pres_mgmt()writes topres_mgmt_loc.currentdirectly
Consumer syntax change:
BEFORE: $events_loc.pres_mgmt.hide__session_code
AFTER: pres_mgmt_loc.current.hide__session_code
Config UI Page
Route: /events/[event_id]/(pres_mgmt)/pres_mgmt/config/
Access: $ae_loc.manager_access only
Button visibility: Edit mode only ($ae_loc.edit_mode)
Page behavior
- Loads
event.mod_pres_mgmt_jsonfresh from API on page open - Displays grouped form sections (see below)
- Save = load → merge → PATCH
/v3/crud/event/{event_id}with{ mod_pres_mgmt_json: updated } - The existing settings form at
/events/[id]/settingshas its pres_mgmt section removed or replaced with a link
Form sections (grouped)
- System —
lock_config - Labels —
label__*fields (text inputs, nullable) - Session Visibility —
hide__session_*toggles - Presenter Visibility —
hide__presenter_*toggles - Presentation Visibility —
hide__presentation_*toggles - Code Visibility —
hide__*_codetoggles - Opt-in Features —
show__*toggles - Requirements —
require__presenter_agree,require__session_agree - Navigation Limits —
limit__navigation,limit__options - File Purpose Config —
file_purpose_option_kv(JSON editor or structured form) - Report Visibility —
hide__report_kv(key-value toggles)
Migration Path
Safe and backward compatible — old DB records fall through to ?? false defaults.
- No DB migration script needed — old keys are simply ignored by the updated sync function
- Active events (BGH) get updated via the new UI after it's built
- The
sync_config__event_pres_mgmt()rewrite is the critical step — it must handle the canonical keys and clean defaults before the UI ships
Implementation Steps
- Step 1 — Define
PressMgmtRemoteCfgTypeScript interface (new file or inae_events__event.ts) - Step 2 — New
ae_events_stores__pres_mgmt.svelte.tswithPersistedState⚠️ Missing: version gate instore_versions.ts - Step 3 — Rewrite
sync_config__event_pres_mgmt()inae_events__event.tsto use canonical keys ⚠️ Issue:show__launcher_link_legacyhard-coded instead of synced from remote - Step 4 — Build config UI page at
(pres_mgmt)/pres_mgmt/config/+page.svelte(manager_access + edit_mode gated) - Step 5 — Strip
ae_comp__event_settings_pres_mgmt_form.sveltefrom settings page (or replace with a link to new page) BLOCKING - Step 6 — Migrate all
$events_loc.pres_mgmt.*references in pres_mgmt templates topres_mgmt_loc.current.* - Step 7 — Update BGH (and any other active events) via new UI (blocked on Step 5)
- Step 8 —
npx svelte-checkclean; commit
Regression Fixes Needed (2026-06-12 Audit)
- Add
show__launcher_link_legacytoPressMgmtRemoteCfgor remove entirely if deprecated- Currently hard-coded to
truein sync function (line 1054ae_events__event.ts) - Can't be controlled via config UI
- Currently hard-coded to
- Resolve
hide__launcher_link*local/remote conflict- Menu toggles (ae_comp__events_menu_opts.svelte lines 462-494) use
hide__launcher_linkfor LOCAL UI state - Remote schema uses
show__launcher_link(inverted) - Decision: Keep separate? Document clearly? Unify?
- Menu toggles (ae_comp__events_menu_opts.svelte lines 462-494) use
- Add
AE_PRES_MGMT_LOC_VERSIONtostore_versions.ts(Step 2 requirement) - Clean
hide__launcher_link*from defaults if truly deprecated (lines 154-155, 333-334 inpres_mgmt_defaults.ts) - POC column local/remote conflict fixed (2026-06-16) —
show__session_li_poc_fieldwas local-only (never synced) and the session-list-table prop computation ignored the admin'shide__session_pocmaster switch entirely. Fixed: addedshow__session_li_poc_fieldtoPressMgmtRemoteCfg+ Config UI (Session Field Visibility) +sync_config__event_pres_mgmt()lock-synced block; list/table column visibility is nowhide__session_poc || !show__session_li_poc_fieldinpres_mgmt/+page.svelteandlocations/ae_comp__event_location_obj_li.svelte. The local per-browser "Show/Hide POC Column" toggle buttons inae_comp__events_menu_opts.svelteandevent_page_menu.sveltewere removed — the field is lock-synced from the per-event Config page now, same as the other session field visibility toggles. - Presenter QR matched to session QR pattern (2026-06-16) —
show__session_qr/show__presenter_qrare the admin-set global default for everyone, signed in or not.show_content__*_qris a trusted-staff-only local override, used when the admin has NOT enabled QR globally. The session QR side already worked this way (fixed earlier today); presenter QR was still on the old buggy logic requiringshow_content__presenter_qrto be true even when the admin had enabled it for everyone, which non-trusted users (presenters) have no way to set. Fixedpresenter_view.svelte(generation effect + display block) toshow__presenter_qr || (trusted_access && show_content__presenter_qr). Also corrected two toggle-button visibility bugs found along the way:ae_comp__events_menu_opts.sveltewas showing the QR toggle to allauthenticated_accessusers (not just trusted) whenever the admin had enabled QR globally, even though the toggle had no effect for them; andpresenter_page_menu.svelte's QR toggle was gated toadministrator_access, hiding it from plain Trusted onsite staff entirely. Both now use the canonical pattern fromsession_page_menu.svelte:trusted_access && !show__*_qr. - Missing
sync_config__event_pres_mgmt()calls on deep-link entry pages (2026-06-16) — root cause of the presenter QR bug above: a browser landing directly on the presenter page (e.g. via a presenter sign-in link) never synced remote config intopres_mgmt_loc.currentat all, since onlypres_mgmt/+page.svelteandsession/[session_id]/+page.sveltecalled the sync function. Every "always synced" and "lock-synced" field (QR enables, POC visibility, code visibility, labels, etc.) silently stayed at hardcoded local defaults on that browser regardless of admin Config page settings. Added the same sync$effect(mirroring the existing comment/pattern insession/[session_id]/+page.svelte) topresenter/[presenter_id]/+page.svelte,locations/+page.svelte,location/[event_location_id]/+page.svelte, andreports/+page.svelte. Any new pres_mgmt page that can be a first-load entry point (i.e. not always reached via/pres_mgmtor/session/[id]first) needs this same block.
Step 6 scope (mechanical find-replace)
The $events_loc.pres_mgmt pattern appears across:
ae_comp__event_session_obj_li.svelteae_comp__events_menu_opts.sveltesession/[session_id]/+page.sveltesession/[session_id]/session_view.sveltesession/[session_id]/session_page_menu.sveltelocations/locations_page_menu.sveltereports/+page.sveltepres_mgmt/+page.svelte- (and likely others — run
grep -r 'events_loc.pres_mgmt' src/to get full list)
Notes
- The
lock_config: truedefault means most events will always sync from remote. This is intentional — it prevents presenter laptops from drifting into different configs. file_purpose_option_kvmay need a structured editor (not raw JSON) to be usable. Consider a simple key-value form row per purpose type for Phase 2.- QR link keys (
hide__presenter_qr_link,hide__session_qr_link) appeared in LCI config but are not in the canonical schema above. Evaluate whether they're actively used before adding them back. limit__navigationandlimit__optionsare in the DB but not currently read bysync_config__event_pres_mgmt(). Confirm where they're consumed before adding to sync.