From b7d9e9669d8dbb8de380a8057f876435a5a3f897 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 10 Mar 2026 16:19:23 -0400 Subject: [PATCH] chore: clean up env templates, docs, and TODO - .env.staging.default / .env.prod.default: remove dead Red/Green/Blue container vars, OSIT_WEB_PORT vars, DOCKER_AE_EXTRA_HOST entries, AE_APP_CFG_ID, AE_APP_NODE_PORT_RED/GREEN/BLUE, PUBLIC_AE_API_SERVER_INTERNAL; replace real staging key with XXXX placeholder (default files are committed to git); fix .prod PUBLIC_AE_API_PORT 5005 -> 443 (external rev proxy, not gunicorn) - TODO__Agents.md: clean up completed items, condense history, update DevOps section - PROJECT__AE_combined_front_back_Docker.md: mark unified Docker architecture complete --- .env.prod.default | 38 +++------- .env.staging.default | 44 +++-------- .../PROJECT__AE_combined_front_back_Docker.md | 3 + documentation/TODO__Agents.md | 74 +++++++------------ 4 files changed, 53 insertions(+), 106 deletions(-) diff --git a/.env.prod.default b/.env.prod.default index 0fed6943..200857a2 100644 --- a/.env.prod.default +++ b/.env.prod.default @@ -1,28 +1,14 @@ -# One Sky IT's Aether Framework and System -TESTING=This is a test env variable -PUBLIC_TESTING=This is a public test env variable +# One Sky IT's Aether Framework and System β€” PRODUCTION template +# Copy to .env.prod and fill in real values. +# AE_CFG_ID: 1=Default, 5=Home Dev, 7=Live Testing/Prod -CONTAINER_AE_APP_NODE=ae_app_node_prod -CONTAINER_AE_APP_NODE_RED=ae_app_node_prod_red -CONTAINER_AE_APP_NODE_GREEN=ae_app_node_prod_green -CONTAINER_AE_APP_NODE_BLUE=ae_app_node_prod_blue -OSIT_WEB_HTTP_PORT=8082 -OSIT_WEB_HTTPS_PORT=4435 - -# DOCKER_AE_SERVER_EXTRA_HOST=srv-nyx.oneskyit.com:104.237.143.4 -# DOCKER_AE_API_SERVER_EXTRA_HOST=api.oneskyit.com:104.237.143.4 -# DOCKER_AE_API_BAK_SERVER_EXTRA_HOST=bak-api.oneskyit.com:104.237.143.4 - -# Aether general shared config options -# For general shared config options like API access and use, database access and use, Redis, and SMTP -# home development, live testing, live production, onsite development, onsite testing, onsite production??? +# Shared config record (controls SMTP, API routing, external keys from DB) AE_CFG_ID=7 -## Aether API access and use +# Aether API access PUBLIC_AE_API_PROTOCOL=https PUBLIC_AE_API_SERVER=api.oneskyit.com PUBLIC_AE_API_BAK_SERVER=bak-api.oneskyit.com -PUBLIC_AE_API_SERVER_INTERNAL=aether_api_gunicorn PUBLIC_AE_API_PORT=443 PUBLIC_AE_API_PATH= PUBLIC_AE_API_SECRET_KEY=XXXX @@ -30,14 +16,10 @@ PUBLIC_AE_API_CRUD_SUPER_KEY=XXXX PUBLIC_AE_NO_ACCOUNT_ID=No_Account_ID_Here PUBLIC_AE_NO_ACCOUNT_ID_TOKEN=Nothing_to_see_here -# Aether app specific config (SvelteKit) -AE_APP_CFG_ID=99 -AE_APP_ENV=development +# SvelteKit app config AE_APP_NODE_PORT=3001 -AE_APP_NODE_PORT_RED=3002 -AE_APP_NODE_PORT_GREEN=3003 -AE_APP_NODE_PORT_BLUE=3004 -PUBLIC_AE_ACCOUNT_ID=XXXX # OSIT = _XY7DXtc9MY; CHOW = 3Iid1aIRY5j -PUBLIC_AE_EVENT_ID=XXXX # OSIT = pjrcghqwert; CHOW = Mw6-Nv-Zf-5A -PUBLIC_AE_SPONSORSHIP_CFG_ID=XXXX # OSIT = t8jdjONCs0k; CHOW = ygjEuQQCzvk +# Default demo/client context (set to the target account for this deployment) +PUBLIC_AE_ACCOUNT_ID=XXXX +PUBLIC_AE_EVENT_ID=XXXX +PUBLIC_AE_SPONSORSHIP_CFG_ID=XXXX diff --git a/.env.staging.default b/.env.staging.default index 357aa99d..65763887 100644 --- a/.env.staging.default +++ b/.env.staging.default @@ -1,45 +1,25 @@ -# One Sky IT's Aether Framework and System -TESTING=This is a test env variable -PUBLIC_TESTING=This is a public test env variable +# One Sky IT's Aether Framework and System β€” STAGING / HOME DEV template +# Copy to .env.staging and fill in real values. +# AE_CFG_ID: 1=Default, 5=Home Dev, 7=Live Testing/Prod -CONTAINER_AE_APP_NODE=ae_app_node_prod -CONTAINER_AE_APP_NODE_RED=ae_app_node_prod_red -CONTAINER_AE_APP_NODE_GREEN=ae_app_node_prod_green -CONTAINER_AE_APP_NODE_BLUE=ae_app_node_prod_blue -OSIT_WEB_HTTP_PORT=8082 -OSIT_WEB_HTTPS_PORT=4435 - -# DOCKER_AE_SERVER_EXTRA_HOST=srv-nyx.oneskyit.com:104.237.143.4 -# DOCKER_AE_API_SERVER_EXTRA_HOST=dev-api.oneskyit.com:192.168.32.20 # Odd because this env is the development server -# DOCKER_AE_API_SERVER_EXTRA_HOST=dev-api.oneskyit.com:192.168.32.99 # Odd because this env is the development server -# DOCKER_AE_API_BAK_SERVER_EXTRA_HOST=test-api.oneskyit.com:104.237.143.4 # Odd because this env is the development server -# DOCKER_AE_API_TEST_SERVER_EXTRA_HOST=test-api.oneskyit.com:104.237.143.4 - -# Aether general shared config options -# For general shared config options like API access and use, database access and use, Redis, and SMTP -# home development, live testing, live production, onsite development, onsite testing, onsite production??? +# Shared config record (controls SMTP, API routing, external keys from DB) AE_CFG_ID=5 -## Aether API access and use +# Aether API access PUBLIC_AE_API_PROTOCOL=https PUBLIC_AE_API_SERVER=dev-api.oneskyit.com PUBLIC_AE_API_BAK_SERVER=test-api.oneskyit.com -PUBLIC_AE_API_SERVER_INTERNAL=aether_api_gunicorn PUBLIC_AE_API_PORT=443 PUBLIC_AE_API_PATH= -PUBLIC_AE_API_SECRET_KEY=dFP6J9DVj9hUgIMn-fNIqg -PUBLIC_AE_API_CRUD_SUPER_KEY=zp5PtX4zUsI +PUBLIC_AE_API_SECRET_KEY=XXXX +PUBLIC_AE_API_CRUD_SUPER_KEY=XXXX PUBLIC_AE_NO_ACCOUNT_ID=No_Account_ID_Here PUBLIC_AE_NO_ACCOUNT_ID_TOKEN=Nothing_to_see_here -# Aether app specific config (SvelteKit) -AE_APP_CFG_ID=99 -AE_APP_ENV=development +# SvelteKit app config AE_APP_NODE_PORT=3001 -AE_APP_NODE_PORT_RED=3002 -AE_APP_NODE_PORT_GREEN=3003 -AE_APP_NODE_PORT_BLUE=3004 -PUBLIC_AE_ACCOUNT_ID=XXXX # OSIT = _XY7DXtc9MY; CHOW = 3Iid1aIRY5j -PUBLIC_AE_EVENT_ID=XXXX # OSIT = pjrcghqwert; CHOW = Mw6-Nv-Zf-5A -PUBLIC_AE_SPONSORSHIP_CFG_ID=XXXX # OSIT = t8jdjONCs0k; CHOW = ygjEuQQCzvk +# Default demo/client context (set to the target account for this deployment) +PUBLIC_AE_ACCOUNT_ID=XXXX # OSIT = _XY7DXtc9MY +PUBLIC_AE_EVENT_ID=XXXX # OSIT = pjrcghqwert +PUBLIC_AE_SPONSORSHIP_CFG_ID=XXXX diff --git a/documentation/PROJECT__AE_combined_front_back_Docker.md b/documentation/PROJECT__AE_combined_front_back_Docker.md index 9a75c35b..f32de9fb 100644 --- a/documentation/PROJECT__AE_combined_front_back_Docker.md +++ b/documentation/PROJECT__AE_combined_front_back_Docker.md @@ -1,4 +1,7 @@ # Project: Unified Aether Platform Orchestration (V3) +> **Status: βœ… COMPLETE (2026-03-10)** +> `ae_app` is live in `aether_container_env/docker-compose.yml`. Both frontend and backend deploy together via `npm run deploy:staging` / `npm run deploy:prod`. Internal `ae_api` networking active. Healthcheck wired. Old `ae_env_node_app` is superseded (archive when ready). + > **Goal:** Consolidate the SvelteKit Frontend and FastAPI Backend into a single Docker Compose environment within `aether_container_env`. ## 1. Overview & Benefits diff --git a/documentation/TODO__Agents.md b/documentation/TODO__Agents.md index 23230458..8df14355 100644 --- a/documentation/TODO__Agents.md +++ b/documentation/TODO__Agents.md @@ -1,28 +1,22 @@ # Frontend Agent Task List > Use this file to track steps for complex features or bug fixes. -> **Status:** πŸ”΄ Sev-1 Security Incident Recovery / Stabilized. +> **Status:** οΏ½ Stable β€” ongoing development. -## πŸ“‹ Active Task: Post-Incident Security Recovery -- [ ] **Step 1:** Conduct full audit of `PUBLIC_AE_API_SECRET_KEY` usage. Determine if it can be moved to server-side only. -- [x] **Step 2:** Replace simulation tests (`tests/verify_jwt_logic.js`) with real Playwright integration tests hitting the local dev API. -- [x] **Step 3:** ~~Implement formal error boundaries for 403/401 API responses~~ β€” **Reclassified as UX, not a security item.** See `[UX] Session Expired & Access Denied` in General below. +## πŸ“‹ Open: Security +- [ ] **PUBLIC_AE_API_SECRET_KEY Audit:** Conduct full audit of usage. Determine if it can be moved to server-side only. ## 🚧 Upcoming High Priority -### [Launcher] Active bugs & features (identified 2026-03-06) - -- ~~**Location select β†’ session auto-load bug:**~~ βœ… Fixed (2026-03-10) β€” The `$derived.by()` liveQuery pattern in `+layout.svelte` correctly recreates the session observable when `$events_slct.event_location_id` changes (including the null-to-value case). The double-load (`onchange` + `+page.ts`) still exists but is benign: `onchange` awaits the detailed load first, then `+page.ts` runs a background shell load. Sessions reliably appear. **Minor remaining:** `slct_event_location_id` prop in `menu_location_list.svelte` is not `$bindable()` but `bind:value={slct_event_location_id}` is used β€” Svelte 5 compiler warning. Functionally fine since `onchange` writes directly to `$events_slct.event_location_id`. +### [Launcher] Active features (identified 2026-03-06) - **Font size cycler (Launcher sidebar):** Staff onsite may not have access to the system menu, so the launcher sidebar needs its own font size cycler. Add `font_size_step: number` to `$events_loc.launcher` store. Add a cycle button in `launcher_menu.svelte` alongside the "All Files"/"All Sessions" show/hide buttons. Three steps: compact (`text-xs`) β†’ default (`text-sm`) β†’ large (`text-base`). Apply the class to the launcher sidebar root container `
`. -- ~~**Session Search button visible on search page:**~~ Not an actual bug β€” `event_page_menu.svelte` already passes `events__session_search={false}` to `ae_comp__events_menu_nav.svelte`, correctly hiding the link on the pres_mgmt page. The TODO item was inaccurate. +- **Minor Svelte warning:** `slct_event_location_id` prop in `menu_location_list.svelte` is not `$bindable()` but `bind:value={slct_event_location_id}` is used. Functionally fine since `onchange` writes directly to `$events_slct.event_location_id`. -### [UI] Dark mode fix (identified 2026-03-06) - -- ~~**Dark mode select option hover (Manage Files):**~~ βœ… Fixed (2026-03-10) β€” Added `html.dark { color-scheme: dark }` / `html.light { color-scheme: light }` to `app.css`. This globally syncs all native browser controls (select dropdowns, scrollbars, inputs) to the app's class-based dark mode, rather than a per-element fix. +### [Svelte] State reference warnings +- **42 `state_referenced_locally` warnings remain** in `recovery_meetings/ae_idaa_comp__event_obj_id_edit.svelte` and `..._v2.svelte`. Same pattern as the 10 fixed on 2026-03-09 β€” move reactive reads into `onMount`. ### [Badges] Remaining badge work before first live event -- ~~**QR code on badge front:**~~ βœ… Done β€” `ae_comp__badge_obj_view.svelte` already generates the QR via `core_func.js_generate_qr_code()` and renders it on the badge face inside a `{#await qr_data_url}` block. `hide_qr` provides a double-click print-suppress toggle. Consent text controlled by `allow_tracking`. The template `show_qr` gate was never needed β€” the QR section is always present. - **Badge print controls UX polish:** Scott has improvements in mind β€” TBD next session. File: `ae_comp__badge_print_controls.svelte`. @@ -32,15 +26,13 @@ the badge. Check if `documentation/MODULE__AE_Events_Leads.md` exists for full s Key questions before starting: which routes, does the Electron app scan, what does the lead record look like in the DB? -### [DevOps] Deployment Optimization (identified 2026-03-09) -- [ ] **Consolidate Service Architecture:** Simplify `ae_env_node_app/docker-compose.yml` by removing the manual Red/Green/Blue/etc. container definitions. Transition to a single service definition that can be scaled using Docker's native `--scale` flag if needed. -- [ ] **Unified Port Mapping:** Standardize on a single exposed port (e.g., 3000 or 3001) for the reverse proxy to point to, rather than managing 4+ separate ports for staging subdomains. -- [x] **Auto-Healing & Healthchecks:** Implement a `/health` endpoint in the SvelteKit app (`src/routes/health/+server.ts`) and re-enable Docker/Nginx health-based routing to ensure zero-downtime deploys and auto-recovery. βœ… (Done 2026-03-10) -- [ ] **Build Optimization:** Explore using a private container registry to separate the build phase from the deployment phase (Build once, deploy anywhere). +### [DevOps] Remaining deployment items +- [ ] **Wire AE_APP_REPLICAS:** `docker-compose.yml` has `scale: 1` hardcoded β€” change to `${AE_APP_REPLICAS:-1}` to use the env var consistently. +- [ ] **Archive ae_env_node_app:** The old Red/Green/Blue node env has been superseded by the unified `aether_container_env`. Archive or move that directory once confirmed nothing depends on it. +- [ ] **Build Optimization:** Explore using a private container registry to separate build from deploy (build once, deploy anywhere). ### [General] -- ~~**CRUD v2 Refactor:** Finalize retirement of `Element_ae_crud_v2.svelte` in favor of V3 Editor.~~ βœ… Done (2026-03-05) β€” all non-IDAA usages migrated; IDAA had zero usages. - **Temp Cleanup:** Auto-removal of native `.tmp` files older than 24h. - **`window.print()` for badge print button:** Wire the existing `handle_print_badge()` to trigger `window.print()`. Browser print works well across Chrome/Chromium/Firefox β€” no Electron needed. - **Input Field Audit:** Several input fields are missing `name`/`id` attributes or `data-testid`. Known examples: badge override fields in `ae_comp__badge_obj_view.svelte`; template name input in `ae_comp__badge_template_form.svelte`. Matters for: accessibility, autofill, label associations, and test targeting. (For tests, use `getByLabel()` rather than `input[value*=...]` which only checks the HTML attribute, not the Svelte-bound DOM property.) @@ -65,30 +57,20 @@ Two related UX gaps to handle together: - Create a reusable `element_access_denied.svelte` component (small: icon + message + optional action button) - Swap the ad-hoc patterns to use it consistently -## βœ… Completed Recently -- [x] **[Svelte]** **`state_referenced_locally` warning fixes (2026-03-09):** Resolved 10 Svelte 5 warnings where `$state`/`$props()` variables were read in top-level synchronous script code instead of inside a reactive closure. Fixed by moving `if (browser) { ... }` blocks and timezone-loading blocks into `onMount`. Files: `archives/[archive_id]/+page.svelte`, `archives/[archive_id]/ae_idaa_comp__archive_obj_id_edit.svelte`, `archives/[archive_id]/ae_idaa_comp__archive_content_obj_id_edit.svelte`, `bb/[post_id]/+page.svelte`. Note: 42 similar warnings remain in `recovery_meetings/ae_idaa_comp__event_obj_id_edit.svelte` and `..._v2.svelte` β€” same pattern, fix next session. -- [x] **[TypeScript]** **Sign In/Out TS errors fixed (2026-03-09):** `user_id` and `person_id` in `e_app_sign_in_out.svelte` were implicitly typed `null` from `$state(null)`, causing assignment errors. Explicitly typed as `string | null`. -- [x] **[UI]** **Firefly Theme:** Created `AE_Firefly` dark/light theme. Primary=teal (~184Β°), Secondary=amber (~90Β°), Tertiary=indigo (~277Β°), Surface=moonlit slate. Files: `src/ae-firefly.css`, `src/app.css`, `src/lib/elements/e_app_theme.svelte`, `src/lib/ae_core/ae_stores.ts`. Set as app default in stores. (2026-03-06, branch `ae_app_3x_llm`) -- [x] **[UI]** **Pres Mgmt Visual Redesign:** Full redesign of Events Presentation Management pages using Firefly theme tokens. Hero card layout, info chips (time=teal, room=indigo), skeleton loading states, dark-mode-safe colors throughout. 5 files: `session_view.svelte`, `ae_comp__event_session_obj_li.svelte`, `ae_comp__event_presentation_obj_li.svelte`, `pres_mgmt/+page.svelte`, `[session_id]/+page.svelte`. (2026-03-06, branch `ae_app_3x_llm`) -- [x] **[Docs]** **UI Design System Docs:** Created two cheatsheet/reference docs: `documentation/GUIDE__AE_UI_Style_Guidelines.md` (design philosophy, color token rules, forbidden classes, Skeleton v3β†’v4 migration table, transitions, dark mode rules, a11y checklist) and `documentation/AE__UI_Component_Patterns.md` (hero cards, content cards, table rows, list item cards, info chips, empty state panels, warning/error banners, file upload zones, section wrappers, modals, muted text, QR code pattern). (2026-03-06) -- [x] **[Badges]** **Badge Print Controls Panel:** New `ae_comp__badge_print_controls.svelte` β€” per-field accordion with inline edit forms, font size controls, access-level gating. Fixed-right-edge layout replaces collapsed `flex-1` panel. (2026-03-02, branch `ae_app_3x_llm`) -- [x] **[Badges]** **badge_type_override coupling:** Selecting badge type from dropdown now saves both `badge_type_code_override` AND `badge_type_override` in `ae_comp__badge_obj_view.svelte`, `ae_comp__badge_review_form.svelte`, and `ae_comp__badge_print_controls.svelte`. -- [x] **[Badges]** **Layout CSS system:** `data-layout` attribute, `@page` injection, `style_href` for per-template CSS files. Two templates: `badge_layout_epson_4x5_fanfold.css`, `badge_layout_zebra_zc10l_pvc.css`. -- [x] **[Badges]** **Duplex field wiring:** Badge back hidden for single-sided templates. -- [x] **[Badges]** **Badge Review Form:** Complete with QR code, field edits, access-level gating, accessibility toggle, help modal. (`ae_comp__badge_review_form.svelte`) -- [x] **[API]** **V3 Lookup System Integration:** Implemented standardized `/v3/lookup/` endpoints for Countries, Subdivisions, and Time Zones. Added support for `only_priority` filtering in IDAA editors. -- [x] **[UI]** **Events Launcher Location Fix:** Resolved room select list issues by ensuring all enabled/hidden locations are proactively loaded and synced. -- [x] **[API]** **Event File V3 Mapping:** Implemented `inc_hosted_file` support and mapped prefixed backend fields (`hosted_file_hash_sha256`, etc.) to flat properties. -- [x] **[UI]** **Badge Rendering Fix:** Refactored `badge_template` lookup to use V3 Triple ID pattern. -- [x] **[API]** **event_session Search Fix:** Resolved 400 error (`Unauthorized search field β€˜account_id’`) via backend update. -- [x] **[Security]** Purged redundant `x-aether-api-token` from frontend and notified backend. -- [x] **[Security]** Fixed misplaced `Access-Control-Allow-Origin` request headers. -- [x] **[Security]** Implemented "Account ID Scavenging" to fix hydration race conditions. -- [x] **[API]** Unified all CRUD helpers to standard V3 `/v3/crud/...` paths. -- [x] **[Framework]** Implemented `AE_Obj_Field_Editor_V3` with Svelte 5 Runes. -- [x] **[IDAA]** Verify Bulletin Board and Recovery Meetings functionality. -- [x] **[Badges]** **Multi-word fulltext search fix:** Split query on whitespace, apply AND logic per word. `"scott idem"` now matches records containing both words. (dc0f3066) -- [x] **[Badges]** **Print button implemented:** `handle_print_badge()` increments `print_count`, records `print_first_datetime`/`print_last_datetime`. Button has loading/done/error states. (d1ded2d4) -- [x] **[Badges]** **`data-testid` attributes added** to badge view interactive elements (`badge-edit-btn`, `badge-save-btn`, `badge-cancel-btn`, `badge-print-btn`, `badge-professional-title-input`) for reliable test targeting. -- [x] **[Tests]** **Attendee badge workflow test passing:** `event_badge_attendee_workflow.test.ts` β€” navigate β†’ edit professional title β†’ save (verify PATCH body) β†’ print (verify count/timestamps) β†’ return to search. (d1ded2d4) -- [x] **[Tests]** **All badge data integrity tests fixed:** All 6 tests in `event_badge_data_integrity.test.ts` now pass. Root causes: (1) search mock used nested URL instead of flat `/v3/crud/event_badge/search`, (2) template list mock used nested URL instead of flat with `for_obj_id`, (3) missing `_random` ID fields in mock badge objects, (4) CSS `input[value*=...]` selector doesn’t work for Svelte-bound inputs β€” fixed to `getByLabel()`. (f5e98b8c) +## βœ… Completed (2026-03) +- [x] **[DevOps]** Frontend + Backend unified into single `aether_container_env` Docker Compose. `ae_app` service live with healthcheck, single exposed port (`AE_APP_NODE_PORT`), internal `ae_api` networking. Deploy scripts in `package.json` both target `../aether_container_env/docker-compose.yml`. (2026-03-10) +- [x] **[DevOps]** `/health` endpoint live at `src/routes/health/+server.ts`. Docker `HEALTHCHECK` uses it. (2026-03-10) +- [x] **[UI]** Dark mode `color-scheme` fix β€” `html.dark/light { color-scheme }` in `app.css`; all native browser controls now sync to app dark mode. (2026-03-10) +- [x] **[Launcher]** Location select β†’ session auto-load bug fixed via `$derived.by()` liveQuery pattern. (2026-03-10) +- [x] **[Svelte]** `state_referenced_locally` warning fixes β€” 10 warnings resolved in IDAA archives/BB. (2026-03-09) +- [x] **[TypeScript]** Sign In/Out TS errors fixed β€” `user_id` / `person_id` typed as `string | null`. (2026-03-09) +- [x] **[Tests]** All badge data integrity and attendee workflow Playwright tests passing. Root causes documented in `tests/README.md`. (2026-03) +- [x] **[Badges]** Badge print controls panel, QR code, duplex wiring, review form, print button, multi-word fulltext search, `data-testid` attributes. (2026-03) +- [x] **[UI]** Firefly Theme + Pres Mgmt Visual Redesign (5 files). (2026-03-06) +- [x] **[Docs]** UI Style Guidelines + Component Patterns docs created. (2026-03-06) +- [x] **[API]** V3 Lookup system integration; Event File V3 mapping; `event_session` search 400-error fix. (2026-02/03) +- [x] **[API]** All CRUD helpers on V3 `/v3/crud/...` paths. (2026-02) +- [x] **[Security]** Purged `x-aether-api-token`; fixed misplaced CORS headers; Account ID Scavenging. (2026-02) +- [x] **[Security]** Playwright integration tests replace `verify_jwt_logic.js` simulation tests. (2026-03) +- [x] **[Framework]** `AE_Obj_Field_Editor_V3` with Svelte 5 Runes. CRUD v2 fully retired. (2026-03-05) +- [x] **[IDAA]** Bulletin Board and Recovery Meetings functionality verified. (2026-02)