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>
378 lines
21 KiB
Markdown
378 lines
21 KiB
Markdown
# Project: Pres Mgmt Config Cleanup & Config UI
|
|
|
|
**Status:** 🟢 Complete — all Implementation Steps and known regressions resolved
|
|
**Priority:** Low (maintenance/monitoring only — re-open if new sync inconsistencies surface)
|
|
**Created:** 2026-04-02
|
|
**Last Updated:** 2026-06-16 (`lock_config` removed; sync is now fully unconditional)
|
|
**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__` and `hide__` prefixes for the same concepts
|
|
- Some features have BOTH `show__foo` and `hide__foo` keys 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: false` vs `"LCI member ID"` string)
|
|
- Keys in the DB not consumed by `sync_config__event_pres_mgmt()`
|
|
- Bug: `label__session_poc_name_short` is read then immediately overwritten (line 970-972 in ae_events__event.ts)
|
|
- `hide_launcher_link` / `hide_launcher_link_legacy` missing the `__` separator (inconsistent)
|
|
- `show_content__presentation_description` uses 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
|
|
|
|
1. **Canonical config schema** — define a TypeScript interface for `mod_pres_mgmt_json`
|
|
2. **Consistent naming convention** — one rule for all `show__`/`hide__` keys
|
|
3. **New Svelte 5 store** — break out local pres_mgmt config from `events_loc`
|
|
4. **Config UI** — admin page within pres_mgmt to manage the remote config
|
|
5. **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`:
|
|
|
|
```typescript
|
|
interface PressMgmtRemoteCfg {
|
|
// No system/lock_config field — every field below syncs unconditionally,
|
|
// to every browser, on every event load. Removed 2026-06-16; see note below.
|
|
|
|
// 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`
|
|
|
|
```typescript
|
|
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 from `ae_events_loc`)
|
|
- Version gate: add `AE_PRES_MGMT_LOC_VERSION` to `store_versions.ts`
|
|
- `sync_config__event_pres_mgmt()` writes to `pres_mgmt_loc.current` directly
|
|
|
|
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_json` fresh 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]/settings` has its pres_mgmt section removed or replaced with a link
|
|
|
|
### Form sections (grouped)
|
|
|
|
No System section — there is no `lock_config` (removed 2026-06-16).
|
|
|
|
1. **Labels** — `label__*` fields (text inputs, nullable)
|
|
2. **Code Visibility** — `hide__*_code` toggles
|
|
3. **Session Display** — `hide__session_description/location/msg` (just the simple ones —
|
|
POC split out below 2026-06-16 for clarity)
|
|
4. **POC Settings** (Point of Contact) — `hide__session_poc` rendered as a visually distinct
|
|
master switch, with `show__session_li_poc_field` / `hide__session_poc_biography` /
|
|
`hide__session_poc_profile` / `hide__session_poc_profile_pic` indented and
|
|
auto-`disabled` underneath it when the master switch is on. Was previously flat in
|
|
"Session Field Visibility" with `hide__session_poc` and `show__session_li_poc_field`
|
|
sitting adjacent with opposite checked-state polarity ("Hide POC" checked = remove,
|
|
"Show POC Column" checked = add) — confusing, per direct user feedback. Splitting it
|
|
into its own section with explicit master/sub-setting hierarchy fixed it without
|
|
touching the underlying field semantics (still `hide__`/`show__` per the naming
|
|
convention — only the *presentation* changed).
|
|
5. **Presenter Visibility** — `hide__presenter_*` toggles
|
|
6. **Presentation Visibility** — `hide__presentation_*` toggles
|
|
7. **Opt-in Features** — `show__*` toggles
|
|
8. **Requirements** — `require__presenter_agree`, `require__session_agree`
|
|
9. **Navigation Limits** — `limit__navigation` (`limit__options` removed — YAGNI)
|
|
10. **File Purpose Config** — `file_purpose_option_kv` (JSON editor or structured form)
|
|
11. **Report Visibility** — `hide__report_kv` (key-value toggles)
|
|
|
|
---
|
|
|
|
## Migration Path
|
|
|
|
Safe and backward compatible — old DB records fall through to `?? false` defaults.
|
|
|
|
1. No DB migration script needed — old keys are simply ignored by the updated sync function
|
|
2. Active events (BGH) get updated via the new UI after it's built
|
|
3. 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
|
|
|
|
- [x] **Step 1** — Define `PressMgmtRemoteCfg` TypeScript interface (new file or in `ae_events__event.ts`)
|
|
- [x] **Step 2** — New `ae_events_stores__pres_mgmt.svelte.ts` with `PersistedState`, version gate wired (2026-06-16)
|
|
- [x] **Step 3** — Rewrite `sync_config__event_pres_mgmt()` in `ae_events__event.ts` to use canonical keys; syncs unconditionally, no `lock_config` gate (2026-06-16)
|
|
- [x] **Step 4** — Build config UI page at `(pres_mgmt)/pres_mgmt/config/+page.svelte` (manager_access + edit_mode gated)
|
|
- [x] **Step 5** — `ae_comp__event_settings_pres_mgmt_form.svelte` moved to trash (2026-06-16) — it was already fully orphaned (zero imports anywhere); the settings page already links to the canonical Config page with a raw-JSON fallback
|
|
- [x] **Step 6** — Migrate all `$events_loc.pres_mgmt.*` references in pres_mgmt templates to `pres_mgmt_loc.current.*`
|
|
- [x] **Step 7** — Active events' `lock_config` keys are now just inert orphan data in the DB, ignored by the sync function — no migration needed, nothing to update
|
|
- [x] **Step 8** — `npx svelte-check` clean
|
|
|
|
### Regression Fixes Needed (2026-06-12 Audit)
|
|
|
|
- [x] **`hide__launcher_link_legacy` removed entirely** (other agent's "config schema cleanup
|
|
phase 2" commit, 2026-06-16) — Flask launcher is fully retired, no longer hard-coded or
|
|
present anywhere in `PressMgmtRemoteCfg` / `PresMgmtLocState` / the sync function.
|
|
- [x] **`hide__launcher_link*` / `show__launcher_link` local/remote conflict resolved
|
|
(2026-06-16)** — kept separate (they serve different purposes: `hide__launcher_link`
|
|
gates the launcher link *content*, `show__launcher_link` gates the manual toggle
|
|
*button*'s visibility), but `show__launcher_link` was never actually assigned by
|
|
`sync_config__event_pres_mgmt()` — only its inverse `hide__launcher_link` was. So the
|
|
toggle button's `show__launcher_link || trusted_access` gate (in
|
|
`ae_comp__events_menu_opts.svelte`, `event_page_menu.svelte`,
|
|
`location_page_menu.svelte`) always collapsed to trusted-only, ignoring the admin's
|
|
setting. Added the missing `loc.show__launcher_link = ...` assignment right next to
|
|
`hide__launcher_link` in the lock-synced block.
|
|
- [x] **`AE_PRES_MGMT_LOC_VERSION` properly wired into `store_versions.ts` (2026-06-16)**
|
|
— the other agent's commit bumped this constant to 2 claiming it "forces a localStorage
|
|
reset," but `_check_and_wipe()` was never actually called for `ae_pres_mgmt_loc`, and
|
|
even if it had been, the store's serializer never wrote a `__version` field for it to
|
|
compare against — so the bump was a complete no-op. Fixed: `ae_events_stores__pres_mgmt.svelte.ts`'s
|
|
custom serializer now stamps `__version` on every write, and `store_versions.ts` calls
|
|
`_check_and_wipe('ae_pres_mgmt_loc', AE_PRES_MGMT_LOC_VERSION)`. Side effect: every
|
|
browser's existing `ae_pres_mgmt_loc` (no `__version` ever written before) will wipe
|
|
once on next load and resync clean from the remote config — this is expected and fine.
|
|
**Found the same bug already live in `ae_leads_loc`** (actively wiping leads users' local
|
|
prefs on *every* page load, not just once) and fixed it the same way — see
|
|
`ae_events_stores__leads.svelte.ts`. `badges_loc`/`launcher_loc`/`events_auth_loc` have
|
|
version constants declared but not wired into `_check_and_wipe()` at all (dormant, not
|
|
actively harmful) — not fixed, flagged for whoever picks that up next.
|
|
- [x] **POC column local/remote conflict fixed (2026-06-16)** — `show__session_li_poc_field` was
|
|
local-only (never synced) and the session-list-table prop computation ignored the admin's
|
|
`hide__session_poc` master switch entirely. Fixed: added `show__session_li_poc_field` to
|
|
`PressMgmtRemoteCfg` + Config UI (Session Field Visibility) + `sync_config__event_pres_mgmt()`
|
|
lock-synced block; list/table column visibility is now
|
|
`hide__session_poc || !show__session_li_poc_field` in `pres_mgmt/+page.svelte` and
|
|
`locations/ae_comp__event_location_obj_li.svelte`. The local per-browser "Show/Hide POC
|
|
Column" toggle buttons in `ae_comp__events_menu_opts.svelte` and `event_page_menu.svelte`
|
|
were removed — the field is lock-synced from the per-event Config page now, same as the
|
|
other session field visibility toggles.
|
|
- [x] **Presenter QR matched to session QR pattern (2026-06-16)** — `show__session_qr` /
|
|
`show__presenter_qr` are the admin-set **global default for everyone**, signed in or not.
|
|
`show_content__*_qr` is 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 requiring `show_content__presenter_qr` to be
|
|
true even when the admin had enabled it for everyone, which non-trusted users (presenters)
|
|
have no way to set. Fixed `presenter_view.svelte` (generation effect + display block) to
|
|
`show__presenter_qr || (trusted_access && show_content__presenter_qr)`. Also corrected two
|
|
toggle-button visibility bugs found along the way: `ae_comp__events_menu_opts.svelte` was
|
|
showing the QR toggle to all `authenticated_access` users (not just trusted) whenever the
|
|
admin had enabled QR globally, even though the toggle had no effect for them; and
|
|
`presenter_page_menu.svelte`'s QR toggle was gated to `administrator_access`, hiding it from
|
|
plain Trusted onsite staff entirely. Both now use the canonical pattern from
|
|
`session_page_menu.svelte`: `trusted_access && !show__*_qr`.
|
|
- [x] **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 into
|
|
`pres_mgmt_loc.current` at all, since only `pres_mgmt/+page.svelte` and
|
|
`session/[session_id]/+page.svelte` called 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 in
|
|
`session/[session_id]/+page.svelte`) to `presenter/[presenter_id]/+page.svelte`,
|
|
`locations/+page.svelte`, `location/[event_location_id]/+page.svelte`, and
|
|
`reports/+page.svelte`. Any new pres_mgmt page that can be a first-load entry point
|
|
(i.e. not always reached via `/pres_mgmt` or `/session/[id]` first) needs this same block.
|
|
- [x] **Config page save was a race, not deterministic (2026-06-16)** — after PATCHing
|
|
`mod_pres_mgmt_json`, the save handler only called `load_ae_obj_id__event()` (SWR —
|
|
returns the stale Dexie cache immediately, refreshes from the API in the background,
|
|
*not awaited*) and assumed that "picked up the new config." It never actually called
|
|
`sync_config__event_pres_mgmt()` itself. Whether the editor's own browser reflected the
|
|
change depended entirely on winning a race against an un-awaited background fetch —
|
|
explains why specific just-changed fields (QR, POC column, profile-pic visibility, one
|
|
report key) intermittently looked stale even to the admin who just saved them, while
|
|
older unchanged fields stayed correct. Fixed: the save handler now calls
|
|
`sync_config__event_pres_mgmt({ pres_mgmt_cfg_remote: draft })` directly with the
|
|
just-saved draft, so the editing browser updates instantly with no race. (Kept the
|
|
`load_ae_obj_id__event()` call too, with its default `try_cache: true` — that's what
|
|
propagates the fresh record to Dexie for *other* browsers/tabs. Do not pass
|
|
`try_cache: false` there — that skips the Dexie write entirely, see the documented
|
|
"try_cache: false Bug" in `GUIDE__SvelteKit2_Svelte5_DexieJS.md`.)
|
|
- [x] **Removed dead "Lock Config" Sync/Unlink toggle (2026-06-16)** — a Manager-only
|
|
button in the sign-in panel (`e_app_access_type.svelte`) wrote to
|
|
`$ae_loc.lock_config`/`sync_local_config` and `pres_mgmt_loc.current.lock_config`/
|
|
`sync_local_config`. Confirmed via full-repo grep that none of those four fields are
|
|
read anywhere. It also confusingly shared the name "Lock Config" with the real,
|
|
functional checkbox on the Pres Mgmt Config page (`draft.lock_config`, part of
|
|
`PressMgmtRemoteCfg`, which actually gates `sync_config__event_pres_mgmt()`'s
|
|
remote→local sync). Removed the button and the now-fully-orphaned
|
|
`lock_config`/`sync_local_config` fields from `PresMgmtLocState`. Left
|
|
`$ae_loc.lock_config`/`sync_local_config` (the general app store) alone — `lock_config`
|
|
was never even in `ae_loc`'s declared defaults (a phantom field created ad-hoc by the
|
|
dead button), and `ae_loc.sync_local_config` is out of scope for a pres_mgmt-only pass;
|
|
defer to the planned `ae_loc` migration in `PROJECT__Stores_Svelte5_Migration.md`.
|
|
- [x] **`lock_config` removed from `PressMgmtRemoteCfg` entirely (2026-06-16)** — the real
|
|
one this time (the item above was a different, dead local-only mirror of the same name).
|
|
This was the actual root cause of the "POC column / Hide POC sometimes works" reports.
|
|
`lock_config` made roughly half of `sync_config__event_pres_mgmt()`'s fields conditional:
|
|
they only updated in a given browser if `lock_config` happened to be `true` at the exact
|
|
moment that browser last synced. A field's local value therefore depended on the *history*
|
|
of saves, not the current setting — undebuggable from the UI, and easy to corrupt by
|
|
toggling Lock Config off even briefly during testing. Checked the DB: every event, old and
|
|
new, already had `lock_config: true` — the "unlocked, per-browser preference" use case it
|
|
was built for has never actually been used. Removed it from `PressMgmtRemoteCfg`,
|
|
`PresMgmtLocState`, the sync function (no more conditional block — every field syncs
|
|
unconditionally, same as labels/Require Agreements always did), and the Config page UI
|
|
(no more System section). Old DB records with a `lock_config` key are simply ignored now,
|
|
same as any other removed key. Moved the now-fully-orphaned
|
|
`ae_comp__event_settings_pres_mgmt_form.svelte` to trash in the same pass (Step 5).
|
|
- [x] **Location column ignored the admin's "Hide Location" setting (2026-06-16)** — same
|
|
bug pattern as the POC column fix earlier, just missed for Location. The Session Search
|
|
results table's Location column prop only ever read the local-only, never-synced
|
|
`hide__session_li_location_field` — it never looked at the admin-synced
|
|
`hide__session_location` (Config page → Session Field Visibility → Hide Location) at all.
|
|
So the column always showed regardless of that setting or the user's permission level,
|
|
exactly as reported. Fixed in `pres_mgmt/+page.svelte`:
|
|
`hide__session_location || hide__session_li_location_field`. The two other usages of this
|
|
component (`locations/ae_comp__event_location_obj_li.svelte`,
|
|
`location/[event_location_id]/+page.svelte`) already hardcode `hide__session_location={true}`
|
|
— correct, since you're already on that location's own page. Worth auditing the other
|
|
per-event hide__* fields for the same "admin field exists but the list/table prop
|
|
computation never reads it" gap if more reports come in.
|
|
|
|
### Step 6 scope (mechanical find-replace)
|
|
|
|
The `$events_loc.pres_mgmt` pattern appears across:
|
|
- `ae_comp__event_session_obj_li.svelte`
|
|
- `ae_comp__events_menu_opts.svelte`
|
|
- `session/[session_id]/+page.svelte`
|
|
- `session/[session_id]/session_view.svelte`
|
|
- `session/[session_id]/session_page_menu.svelte`
|
|
- `locations/locations_page_menu.svelte`
|
|
- `reports/+page.svelte`
|
|
- `pres_mgmt/+page.svelte`
|
|
- (and likely others — run `grep -r 'events_loc.pres_mgmt' src/` to get full list)
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- All pres_mgmt display config now always syncs from remote, unconditionally, to every
|
|
browser, on every event load (no `lock_config` toggle — removed 2026-06-16). This is
|
|
intentional — it prevents presenter laptops from drifting into different configs, which
|
|
is exactly what `lock_config: true` was meant to guarantee, minus the conditional that
|
|
made it fragile.
|
|
- `file_purpose_option_kv` may 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__navigation` and `limit__options` are in the DB but not currently read by
|
|
`sync_config__event_pres_mgmt()`. Confirm where they're consumed before adding to sync.
|