diff --git a/documentation/aether_sql_tables/aether_dev__account__2026-01-06_18_25_42.sql b/documentation/aether_sql_tables/aether_dev__account__2026-01-06_18_25_42.sql deleted file mode 100644 index 80552f29..00000000 --- a/documentation/aether_sql_tables/aether_dev__account__2026-01-06_18_25_42.sql +++ /dev/null @@ -1,105 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:25 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `account` --- - -CREATE TABLE `account` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `code` varchar(50) DEFAULT NULL, - `name` varchar(200) DEFAULT NULL, - `short_name` varchar(20) DEFAULT NULL, - `description` text DEFAULT NULL, - `hide` tinyint(1) DEFAULT 0, - `enable` tinyint(1) NOT NULL DEFAULT 0, - `enable_from` datetime DEFAULT NULL, - `enable_to` datetime DEFAULT NULL, - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `account` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_account` BEFORE INSERT ON `account` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_account` BEFORE UPDATE ON `account` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `account` --- -ALTER TABLE `account` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD UNIQUE KEY `code` (`code`), - ADD KEY `enable` (`enable`), - ADD KEY `name` (`name`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `account` --- -ALTER TABLE `account` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__data_store__2026-01-06_18_25_28.sql b/documentation/aether_sql_tables/aether_dev__data_store__2026-01-06_18_25_28.sql deleted file mode 100644 index 43f80f99..00000000 --- a/documentation/aether_sql_tables/aether_dev__data_store__2026-01-06_18_25_28.sql +++ /dev/null @@ -1,124 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:25 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `data_store` --- - -CREATE TABLE `data_store` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `account_id` int(11) DEFAULT NULL, - `for_type` varchar(50) DEFAULT NULL, - `for_id` int(11) DEFAULT NULL, - `person_id` int(11) DEFAULT NULL COMMENT 'the creator or owner', - `user_id` int(11) DEFAULT NULL COMMENT 'the creator or owner', - `code` varchar(75) NOT NULL COMMENT 'adding a record that matches an existing code should always have an account_id', - `name` varchar(150) DEFAULT NULL, - `description` text DEFAULT NULL, - `type` varchar(10) NOT NULL DEFAULT 'html' COMMENT 'html, json, md, text', - `json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'case sensitive', - `text` longtext DEFAULT NULL COMMENT 'case insensitive', - `meta_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`meta_json`)), - `meta_text` longtext DEFAULT NULL, - `access_read` varchar(20) DEFAULT NULL COMMENT '''super'', ''administrator'', ''trusted'', ''anonymous''', - `access_write` varchar(20) DEFAULT NULL COMMENT '''super'', ''administrator'', ''trusted'', ''anonymous''', - `access_delete` varchar(20) DEFAULT NULL COMMENT '''super'', ''administrator'', ''trusted'', ''anonymous''', - `enable` tinyint(1) NOT NULL DEFAULT 0, - `hide` tinyint(1) DEFAULT NULL, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `data_store` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_data_store` BEFORE INSERT ON `data_store` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_data_store` BEFORE UPDATE ON `data_store` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `data_store` --- -ALTER TABLE `data_store` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `code` (`code`), - ADD KEY `account_id` (`account_id`), - ADD KEY `for_type` (`for_type`,`for_id`), - ADD KEY `enable` (`enable`), - ADD KEY `priority` (`priority`), - ADD KEY `sort` (`sort`), - ADD KEY `group` (`group`), - ADD KEY `hide` (`hide`), - ADD KEY `account_id_2` (`account_id`,`for_type`,`for_id`,`code`,`enable`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `data_store` --- -ALTER TABLE `data_store` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__event__2026-01-06_18_24_24.sql b/documentation/aether_sql_tables/aether_dev__event__2026-01-06_18_24_24.sql deleted file mode 100644 index aa8641a7..00000000 --- a/documentation/aether_sql_tables/aether_dev__event__2026-01-06_18_24_24.sql +++ /dev/null @@ -1,259 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:24 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `event` --- - -CREATE TABLE `event` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `code` varchar(100) DEFAULT NULL, - `account_id` int(11) DEFAULT NULL, - `poc_event_person_id` int(11) DEFAULT NULL COMMENT 'use this when possible', - `poc_person_id` int(11) DEFAULT NULL COMMENT 'use this only if needed', - `external_person_id` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'person ID generated by external system', - `user_id` int(11) DEFAULT NULL COMMENT 'user that owns the event', - `lu_event_type_id` int(11) DEFAULT NULL, - `conference` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'yes allows for abstracts, sessions, presentations, presenters, badges, etc', - `type` varchar(50) DEFAULT NULL, - `name` varchar(200) NOT NULL, - `summary` text DEFAULT NULL, - `description` text DEFAULT NULL, - `format` text DEFAULT NULL COMMENT 'format of the event', - `lu_time_zone_id` int(11) DEFAULT NULL, - `timezone` varchar(100) DEFAULT NULL, - `start_datetime` datetime DEFAULT NULL, - `end_datetime` datetime DEFAULT NULL, - `recurring` tinyint(1) DEFAULT NULL COMMENT 'recurring event', - `recurring_pattern` varchar(50) DEFAULT NULL, - `recurring_start_time` time DEFAULT NULL COMMENT 'recurring event start time', - `recurring_end_time` time DEFAULT NULL COMMENT 'recurring event end time', - `recurring_text` text DEFAULT NULL COMMENT 'text describing how and when the event recurs', - `weekday_sunday` tinyint(1) DEFAULT NULL, - `weekday_monday` tinyint(1) DEFAULT NULL, - `weekday_tuesday` tinyint(1) DEFAULT NULL, - `weekday_wednesday` tinyint(1) DEFAULT NULL, - `weekday_thursday` tinyint(1) DEFAULT NULL, - `weekday_friday` tinyint(1) DEFAULT NULL, - `weekday_saturday` tinyint(1) DEFAULT NULL, - `address_location_id` int(11) DEFAULT NULL, - `location_address_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `location_address_json_ext` longtext GENERATED ALWAYS AS (json_unquote(json_extract(`location_address_json`,'$'))) STORED, - `location_text` text DEFAULT NULL COMMENT 'text information about the location', - `online_start` datetime DEFAULT NULL, - `online_end` datetime DEFAULT NULL, - `reg_deadline_1` datetime DEFAULT NULL, - `reg_deadline_2` datetime DEFAULT NULL, - `reg_deadline_3` datetime DEFAULT NULL, - `reg_deadline_4` datetime DEFAULT NULL, - `max_registrants` int(11) DEFAULT NULL, - `private` tinyint(1) DEFAULT 0 COMMENT 'invite only event', - `physical` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'physical in person event', - `virtual` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'virtual remote access event', - `image_path` varchar(500) DEFAULT NULL, - `logo_path` varchar(500) DEFAULT NULL, - `logo_bg_color` varchar(25) DEFAULT NULL, - `banner_path` varchar(500) DEFAULT NULL, - `banner_bg_color` varchar(25) DEFAULT NULL, - `logo_filename` varchar(200) DEFAULT NULL, - `banner_image_filename` varchar(200) DEFAULT NULL, - `banner_html` text DEFAULT NULL, - `site_h1` varchar(500) DEFAULT NULL, - `site_h2` varchar(500) DEFAULT NULL, - `external_url` varchar(500) DEFAULT NULL, - `external_url_text` varchar(500) DEFAULT NULL, - `attend_url` varchar(500) DEFAULT NULL, - `attend_url_text` varchar(500) DEFAULT NULL, - `attend_url_code` varchar(50) DEFAULT NULL COMMENT 'id, code, nickname, alias', - `attend_url_passcode` varchar(50) DEFAULT NULL, - `attend_phone` varchar(50) DEFAULT NULL, - `attend_phone_passcode` varchar(50) DEFAULT NULL, - `attend_text` text DEFAULT NULL, - `attend_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`attend_json`)), - `contact_1_id` int(11) DEFAULT NULL, - `contact_2_id` int(11) DEFAULT NULL, - `contact_3_id` int(11) DEFAULT NULL, - `contact_li_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`contact_li_json`)), - `contact_li_json_ext` longtext GENERATED ALWAYS AS (json_unquote(json_extract(`contact_li_json`,'$'))) STORED, - `contact_name` varchar(200) DEFAULT NULL, - `contact_email` varchar(254) DEFAULT NULL, - `contact_phone` varchar(50) DEFAULT NULL, - `contact_other` text DEFAULT NULL, - `contact_text` text DEFAULT NULL, - `event_file_upload_information` text DEFAULT NULL, - `enable` tinyint(1) NOT NULL DEFAULT 1, - `enable_from` datetime DEFAULT NULL, - `enable_to` datetime DEFAULT NULL, - `enable_for_administrator` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_support` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_assistant` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_trusted` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_authenticated` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_anonymous` tinyint(1) NOT NULL DEFAULT 0, - `enable_comments` tinyint(1) NOT NULL DEFAULT 0, - `send_moderator_email` tinyint(1) DEFAULT NULL, - `moderator_email` varchar(254) DEFAULT NULL, - `disable_navigation` tinyint(1) NOT NULL DEFAULT 0, - `enable_event_file_upload_for_event` tinyint(1) DEFAULT NULL, - `enable_event_file_upload_for_location` tinyint(1) DEFAULT NULL, - `enable_event_file_upload_for_session` tinyint(1) DEFAULT NULL, - `enable_event_file_upload_for_presentation` tinyint(1) DEFAULT NULL, - `enable_event_file_upload_for_presenter` tinyint(1) DEFAULT NULL, - `enable_event_file_upload_review_question` tinyint(1) DEFAULT NULL, - `enable_event_file_upload_email_question` tinyint(1) DEFAULT NULL, - `enable_event_file_upload_comments_question` tinyint(1) DEFAULT NULL, - `enable_event_file_approval_option` tinyint(1) DEFAULT NULL, - `enable_event_file_public_use_option` tinyint(1) DEFAULT NULL, - `enable_event_file_member_use_option` tinyint(1) DEFAULT NULL, - `enable_event_file_attendee_use_option` tinyint(1) DEFAULT NULL, - `enable_event_file_publish_option` tinyint(1) DEFAULT NULL, - `enable_event_file_purpose_option` tinyint(1) DEFAULT NULL, - `enable_event_file_os_selection_option` tinyint(1) DEFAULT NULL COMMENT 'allow selection between macOS and Windows', - `enable_event_file_os_change_option` tinyint(1) DEFAULT NULL, - `custom_event_file_upload_description` text DEFAULT NULL, - `custom_event_file_agreement_1_text` text DEFAULT NULL, - `custom_event_file_agreement_1_description` text DEFAULT NULL, - `ask_speaker_ready_room` tinyint(1) DEFAULT NULL, - `ask_presentation_publish_optout` tinyint(1) DEFAULT NULL, - `default_event_file_to_public_use` tinyint(1) DEFAULT NULL, - `ask_for_public_version` tinyint(1) DEFAULT NULL, - `hide_file_upload_presentation_name` tinyint(1) DEFAULT NULL, - `hide_session_codes` tinyint(1) DEFAULT NULL, - `custom_agreement_1_text` text DEFAULT NULL, - `custom_agreement_1_description` text DEFAULT NULL, - `unauthenticated_access` tinyint(1) NOT NULL DEFAULT 0, - `unauthenticated_access_public_endpoint` tinyint(1) NOT NULL DEFAULT 0, - `mod_abstracts_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`mod_abstracts_json`)), - `mod_badges_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'badges config options' CHECK (json_valid(`mod_badges_json`)), - `mod_exhibits_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'exhibits config options' CHECK (json_valid(`mod_exhibits_json`)), - `mod_meetings_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`mod_meetings_json`)), - `mod_pres_mgmt_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`mod_pres_mgmt_json`)), - `cfg_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'config in JSON format' CHECK (json_valid(`cfg_json`)), - `hide` tinyint(1) DEFAULT NULL, - `status` varchar(25) DEFAULT NULL, - `review` tinyint(1) DEFAULT NULL, - `approve` tinyint(1) DEFAULT NULL, - `ready` tinyint(1) DEFAULT NULL, - `ready_on` datetime DEFAULT NULL, - `archive` tinyint(1) DEFAULT NULL, - `archive_on` datetime DEFAULT NULL, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `default_qry_str` text DEFAULT NULL COMMENT 'for FULLTEXT indexed searches', - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `event` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_event` BEFORE INSERT ON `event` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_pattern('3CN-2CN-2CN-2CN'); - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - SET NEW.default_qry_str = event_default_qry_str(NEW.id_random, NEW.type, NEW.name, NEW.description, NEW.timezone, NEW.recurring_pattern, NEW.recurring_text, NEW.location_text, NEW.attend_text, NEW.contact_text); - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_event` BEFORE UPDATE ON `event` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - SET NEW.id_random = gen_rand_pattern('3CN-2CN-2CN-2CN'); - END IF; - - SET NEW.default_qry_str = event_default_qry_str(NEW.id_random, NEW.type, NEW.name, NEW.description, NEW.timezone, NEW.recurring_pattern, NEW.recurring_text, NEW.location_text, NEW.attend_text, NEW.contact_text); - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `event_after_delete` AFTER DELETE ON `event` FOR EACH ROW BEGIN -DELETE FROM event_person WHERE event_person.id = old.poc_event_person_id; -DELETE FROM address WHERE address.for_id = old.id AND address.for_type = 'event'; -DELETE FROM address WHERE address.id = old.address_location_id; -DELETE FROM contact WHERE contact.for_id = old.id AND contact.for_type = 'event'; -DELETE FROM contact WHERE contact.id = old.contact_1_id; -DELETE FROM contact WHERE contact.id = old.contact_2_id; -DELETE FROM contact WHERE contact.id = old.contact_3_id; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `event` --- -ALTER TABLE `event` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `account_id` (`account_id`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `sort` (`sort`), - ADD KEY `conference` (`conference`), - ADD KEY `enable` (`enable`), - ADD KEY `archive` (`archive`), - ADD KEY `address_location_id` (`address_location_id`) USING HASH, - ADD KEY `poc_event_person_id` (`poc_event_person_id`) USING HASH, - ADD KEY `contact_id_1` (`contact_1_id`) USING HASH, - ADD KEY `contact_id_2` (`contact_2_id`) USING HASH, - ADD KEY `priority` (`priority`), - ADD KEY `hide` (`hide`); -ALTER TABLE `event` ADD FULLTEXT KEY `tbl_fulltext_default_qry_str` (`default_qry_str`); -ALTER TABLE `event` ADD FULLTEXT KEY `fulltext_location_address_json` (`location_address_json`); -ALTER TABLE `event` ADD FULLTEXT KEY `fulltext_contact_li_json` (`contact_li_json`); -ALTER TABLE `event` ADD FULLTEXT KEY `fulltext_location_address_json_ext` (`location_address_json_ext`); -ALTER TABLE `event` ADD FULLTEXT KEY `fulltext_contact_li_json_ext` (`contact_li_json_ext`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `event` --- -ALTER TABLE `event` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__event_badge__2026-01-06_18_24_55.sql b/documentation/aether_sql_tables/aether_dev__event_badge__2026-01-06_18_24_55.sql deleted file mode 100644 index 27d72246..00000000 --- a/documentation/aether_sql_tables/aether_dev__event_badge__2026-01-06_18_24_55.sql +++ /dev/null @@ -1,235 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:24 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `event_badge` --- - -CREATE TABLE `event_badge` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) NOT NULL, - `external_id` varchar(100) DEFAULT NULL, - `external_event_id` varchar(75) DEFAULT NULL COMMENT 'externally generated event ID', - `external_registration_id` varchar(75) DEFAULT NULL COMMENT 'registration ID generated by external system (was external_reg_id)', - `external_person_id` varchar(75) DEFAULT NULL COMMENT 'person ID generated by external system (was external_sys_id)', - `event_id_only` int(11) DEFAULT NULL COMMENT 'This should only be used when the event_person record can not be created.', - `event_person_id` int(11) DEFAULT NULL, - `event_badge_template_id` int(11) DEFAULT NULL COMMENT 'if null then use the "default" template for the event', - `pronouns` varchar(50) DEFAULT NULL COMMENT 'preferred pronouns', - `pronouns_override` varchar(50) DEFAULT NULL COMMENT 'override for pronouns', - `informal_name` varchar(50) DEFAULT NULL COMMENT 'nickname', - `title_names` varchar(100) DEFAULT NULL COMMENT 'prefix', - `given_name` varchar(50) DEFAULT NULL COMMENT 'first name', - `middle_name` varchar(50) DEFAULT NULL, - `family_name` varchar(100) DEFAULT NULL COMMENT 'last name', - `designations` varchar(100) DEFAULT NULL COMMENT 'designations and suffix', - `professional_title` varchar(150) DEFAULT NULL COMMENT 'includes degrees and credentials', - `professional_title_override` varchar(200) DEFAULT NULL COMMENT 'override for professional title', - `full_name` varchar(200) DEFAULT NULL, - `full_name_override` varchar(150) DEFAULT NULL COMMENT 'was display_name', - `affiliations` text DEFAULT NULL, - `affiliations_override` varchar(200) DEFAULT NULL COMMENT 'override for affiliations', - `email` varchar(254) DEFAULT NULL, - `email_override` varchar(254) DEFAULT NULL COMMENT 'override for email', - `phone` varchar(25) DEFAULT NULL, - `phone_override` varchar(25) DEFAULT NULL COMMENT 'override for phone', - `address_line_1` varchar(200) DEFAULT NULL, - `address_line_2` varchar(200) DEFAULT NULL, - `address_line_3` varchar(200) DEFAULT NULL, - `city` varchar(100) DEFAULT NULL, - `country_subdivision_code` varchar(8) DEFAULT NULL, - `state_province` varchar(100) DEFAULT NULL, - `state_province_abb` varchar(10) DEFAULT NULL COMMENT 'state/province abbreviation', - `postal_code` varchar(25) DEFAULT NULL, - `country_alpha_2_code` varchar(2) DEFAULT NULL, - `country` varchar(100) DEFAULT NULL, - `full_address` varchar(200) DEFAULT NULL, - `location` varchar(200) DEFAULT NULL, - `location_override` varchar(200) DEFAULT NULL COMMENT 'override for location', - `location_short` varchar(100) DEFAULT NULL COMMENT 'auto gen with trigger', - `location_long` varchar(200) DEFAULT NULL COMMENT 'auto gen with trigger', - `query_str` varchar(150) DEFAULT NULL, - `badge_type_code` varchar(50) DEFAULT NULL, - `badge_type_code_override` varchar(50) DEFAULT NULL, - `badge_type` varchar(100) DEFAULT NULL, - `badge_type_override` varchar(100) DEFAULT NULL, - `member_type_code` varchar(50) DEFAULT NULL, - `member_type` varchar(100) DEFAULT NULL, - `member_status` varchar(50) DEFAULT NULL, - `registration_type_code` varchar(50) DEFAULT NULL, - `registration_type` varchar(100) DEFAULT NULL, - `other_1` varchar(100) DEFAULT NULL, - `other_2` varchar(100) DEFAULT NULL, - `ticket_1_code` varchar(100) DEFAULT NULL, - `ticket_2_code` varchar(100) DEFAULT NULL, - `ticket_3_code` varchar(100) DEFAULT NULL, - `ticket_4_code` varchar(100) DEFAULT NULL, - `ticket_5_code` varchar(100) DEFAULT NULL, - `ticket_6_code` varchar(100) DEFAULT NULL, - `ticket_7_code` varchar(100) DEFAULT NULL, - `ticket_8_code` varchar(100) DEFAULT NULL, - `allow_tracking` tinyint(1) DEFAULT NULL, - `allow_tracking_field_li` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '[''given_name'', ''family_name'', ''email'']' CHECK (json_valid(`allow_tracking_field_li`)), - `agree_to_tc` tinyint(1) DEFAULT NULL COMMENT 'agree to terms and conditions', - `print_first_datetime` datetime DEFAULT NULL, - `print_last_datetime` datetime DEFAULT NULL, - `print_count` int(11) DEFAULT NULL, - `data_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`data_json`)), - `cfg_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`cfg_json`)), - `hide` tinyint(1) DEFAULT 0, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `enable` tinyint(1) DEFAULT 1, - `default_qry_str` text DEFAULT NULL COMMENT 'for FULLTEXT indexed searches', - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `event_badge` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_event_badge` BEFORE INSERT ON `event_badge` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - SET NEW.full_name = name_for_full_name(NEW.informal_name, NEW.title_names, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.designations); - - IF (NEW.location IS NULL OR NEW.location = '') - THEN - SET NEW.location = make_location_str(NEW.city, NEW.state_province, NEW.country); - END IF; - - IF (NEW.full_address IS NULL OR NEW.full_address = '') - THEN - SET NEW.full_address = make_full_address_str(NEW.address_line_1, NEW.address_line_2, NEW.address_line_3, NEW.city, NEW.state_province, NEW.postal_code, NEW.country); - /*SET NEW.notes = CONCAT(COALESCE(`NEW`.`notes`,''), ';;sys::overide empty full_address');*/ - END IF; - - IF (NEW.city IS NOT NULL OR NEW.state_province IS NOT NULL OR NEW.country IS NOT NULL) - THEN - SET NEW.location_long = badge_full_address(NEW.city, NEW.state_province, NEW.country); - /*SET NEW.notes = CONCAT(COALESCE(`NEW`.`notes`,''), ';;sys::overide empty location');*/ - END IF; - - IF (NEW.city IS NOT NULL OR NEW.state_province_abb IS NOT NULL OR NEW.country_alpha_2_code IS NOT NULL) - THEN - SET NEW.location_short = badge_location_short(NEW.city, NEW.state_province_abb, NEW.country_alpha_2_code); - /*SET NEW.notes = CONCAT(COALESCE(`NEW`.`notes`,''), ';;sys::overide empty location');*/ - END IF; - - SET NEW.default_qry_str = event_badge_default_qry_str(NEW.id_random, NEW.full_name, NEW.full_name_override, NEW.affiliations, NEW.affiliations_override, NEW.email, NEW.email_override, NEW.location, NEW.location_override); - SET NEW.query_str = badge_query_str(NEW.id_random, NEW.informal_name, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.email); - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_event_badge` BEFORE UPDATE ON `event_badge` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); - END IF; - - SET NEW.full_name = name_for_full_name(NEW.informal_name, NEW.title_names, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.designations); - - IF (NEW.location IS NULL OR NEW.location = '') - THEN - SET NEW.location = make_location_str(NEW.city, NEW.state_province, NEW.country); - END IF; - - IF (NEW.full_address IS NULL OR NEW.full_address = '') - THEN - SET NEW.full_address = make_full_address_str(NEW.address_line_1, NEW.address_line_2, NEW.address_line_3, NEW.city, NEW.state_province, NEW.postal_code, NEW.country); - /*SET NEW.notes = CONCAT(COALESCE(`NEW`.`notes`,''), ';;sys::overide empty full_address');*/ - END IF; - - IF (NEW.city IS NOT NULL OR NEW.state_province IS NOT NULL OR NEW.country IS NOT NULL) - THEN - SET NEW.location_long = badge_full_address(NEW.city, NEW.state_province, NEW.country); - /*SET NEW.notes = CONCAT(COALESCE(`NEW`.`notes`,''), ';;sys::overide empty location');*/ - END IF; - - IF (NEW.city IS NOT NULL OR NEW.state_province_abb IS NOT NULL OR NEW.country_alpha_2_code IS NOT NULL) - THEN - SET NEW.location_short = badge_location_short(NEW.city, NEW.state_province_abb, NEW.country_alpha_2_code); - /*SET NEW.notes = CONCAT(COALESCE(`NEW`.`notes`,''), ';;sys::overide empty location');*/ - END IF; - - SET NEW.default_qry_str = event_badge_default_qry_str(NEW.id_random, NEW.full_name, NEW.full_name_override, NEW.affiliations, NEW.affiliations_override, NEW.email, NEW.email_override, NEW.location, NEW.location_override); - SET NEW.query_str = badge_query_str(NEW.id_random, NEW.informal_name, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.email); - END; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `event_badge` --- -ALTER TABLE `event_badge` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `external_id` (`external_id`), - ADD KEY `event_person_id` (`event_person_id`), - ADD KEY `given_name` (`given_name`), - ADD KEY `family_name` (`family_name`), - ADD KEY `display_name` (`full_name_override`), - ADD KEY `email` (`email`), - ADD KEY `badge_type_code` (`badge_type_code`), - ADD KEY `member_type_code` (`member_type_code`), - ADD KEY `registration_type_code` (`registration_type_code`), - ADD KEY `enable` (`enable`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `external_event_id` (`external_event_id`), - ADD KEY `event_badge_template_id` (`event_badge_template_id`); -ALTER TABLE `event_badge` ADD FULLTEXT KEY `query_str` (`query_str`); -ALTER TABLE `event_badge` ADD FULLTEXT KEY `tbl_fulltext_default_qry_str` (`default_qry_str`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `event_badge` --- -ALTER TABLE `event_badge` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__event_file__2026-01-06_18_25_10.sql b/documentation/aether_sql_tables/aether_dev__event_file__2026-01-06_18_25_10.sql deleted file mode 100644 index d4204b64..00000000 --- a/documentation/aether_sql_tables/aether_dev__event_file__2026-01-06_18_25_10.sql +++ /dev/null @@ -1,242 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:25 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `event_file` --- - -CREATE TABLE `event_file` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `hosted_file_id` int(11) DEFAULT NULL, - `for_type` varchar(50) DEFAULT NULL, - `for_id` int(11) DEFAULT NULL, - `event_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `event_session_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `event_presentation_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `event_presenter_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `event_location_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `event_track_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `event_exhibit_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `filename` varchar(255) DEFAULT NULL, - `extension` varchar(10) DEFAULT NULL, - `title` varchar(500) DEFAULT NULL, - `description` text DEFAULT NULL, - `internal_use` tinyint(1) DEFAULT NULL COMMENT 'hide from non-support people', - `internal_start_datetime` datetime DEFAULT NULL, - `internal_end_datetime` datetime DEFAULT NULL, - `internal_filename` varchar(255) DEFAULT NULL, - `internal_extension` varchar(10) DEFAULT NULL, - `open_in_os` varchar(50) DEFAULT NULL COMMENT 'change to open_in: [mac,win,local browser/client,remote browser/client,api,websocket,download]', - `internal_hide` tinyint(1) DEFAULT NULL, - `private_use` tinyint(1) DEFAULT NULL, - `private_start_datetime` datetime DEFAULT NULL, - `private_end_datetime` datetime DEFAULT NULL, - `private_filename` varchar(255) DEFAULT NULL, - `private_extension` varchar(10) DEFAULT NULL, - `private_hide` tinyint(1) DEFAULT NULL, - `public_use` tinyint(1) DEFAULT NULL, - `public_start_datetime` datetime DEFAULT NULL, - `public_end_datetime` datetime DEFAULT NULL, - `public_filename` varchar(255) DEFAULT NULL, - `public_extension` varchar(10) DEFAULT NULL, - `public_hide` tinyint(1) DEFAULT NULL, - `lu_file_purpose_id` int(11) DEFAULT NULL, - `file_purpose` varchar(100) DEFAULT NULL, - `publish_optout` tinyint(1) DEFAULT NULL, - `download_start_datetime` datetime DEFAULT NULL, - `download_end_datetime` datetime DEFAULT NULL, - `approved` int(11) DEFAULT NULL, - `approved_on` timestamp NULL DEFAULT NULL, - `public` tinyint(1) DEFAULT NULL, - `hide` tinyint(1) DEFAULT NULL, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `enable` tinyint(1) NOT NULL DEFAULT 1, - `enable_after_datetime` datetime DEFAULT NULL, - `enable_before_datetime` datetime DEFAULT NULL, - `enable_for_administrator` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_support` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_assistant` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_trusted` tinyint(1) NOT NULL DEFAULT 0, - `enable_for_authenticated` tinyint(1) NOT NULL DEFAULT 0, - `status` int(11) DEFAULT NULL, - `review` tinyint(1) DEFAULT NULL, - `approve` tinyint(1) DEFAULT NULL, - `ready` tinyint(1) DEFAULT NULL, - `ready_datetime` datetime DEFAULT NULL, - `archive` tinyint(1) DEFAULT NULL, - `archive_datetime` datetime DEFAULT NULL, - `enable_for_anonymous` tinyint(1) NOT NULL DEFAULT 0, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `event_file` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_event_file` BEFORE INSERT ON `event_file` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_insert_event_file_fix_ids` BEFORE INSERT ON `event_file` FOR EACH ROW BEGIN - BEGIN - IF (NEW.for_type = 'event_location' AND NEW.for_id IS NOT NULL) - THEN - SET NEW.event_location_id = NEW.for_id; - SET NEW.event_id = (SELECT event_id FROM event_location WHERE event_location.id = NEW.for_id); - END IF; - - IF (NEW.for_type = 'event_presenter' AND NEW.for_id IS NOT NULL) - THEN - SET NEW.event_presenter_id = NEW.for_id; - SET NEW.event_presentation_id = (SELECT event_presentation_id FROM event_presenter WHERE event_presenter.id = NEW.for_id); - SET NEW.event_session_id = (SELECT event_session_id FROM event_presentation WHERE event_presentation.id = NEW.event_presentation_id); - SET NEW.event_location_id = (SELECT event_location_id FROM event_session WHERE event_session.id = NEW.event_session_id); - SET NEW.event_id = (SELECT event_id FROM event_session WHERE event_session.id = NEW.event_session_id); - END IF; - - IF (NEW.for_type = 'event_session' AND NEW.for_id IS NOT NULL) - THEN - SET NEW.event_session_id = NEW.for_id; - SET NEW.event_location_id = (SELECT event_location_id FROM event_session WHERE event_session.id = NEW.for_id); - SET NEW.event_id = (SELECT event_id FROM event_session WHERE event_session.id = NEW.for_id); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_event_file` BEFORE UPDATE ON `event_file` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_event_file_fix_ids` BEFORE UPDATE ON `event_file` FOR EACH ROW BEGIN - BEGIN - IF (NEW.for_type = 'event_location' AND NEW.for_id IS NOT NULL) - THEN - SET NEW.event_location_id = NEW.for_id; - SET NEW.event_id = (SELECT event_id FROM event_location WHERE event_location.id = NEW.for_id); - END IF; - - IF (NEW.for_type = 'event_presenter' AND NEW.for_id IS NOT NULL) - THEN - SET NEW.event_presenter_id = NEW.for_id; - SET NEW.event_presentation_id = (SELECT event_presentation_id FROM event_presenter WHERE event_presenter.id = NEW.for_id); - SET NEW.event_session_id = (SELECT event_session_id FROM event_presentation WHERE event_presentation.id = NEW.event_presentation_id); - SET NEW.event_location_id = (SELECT event_location_id FROM event_session WHERE event_session.id = NEW.event_session_id); - SET NEW.event_id = (SELECT event_id FROM event_session WHERE event_session.id = NEW.event_session_id); - END IF; - - IF (NEW.for_type = 'event_session' AND NEW.for_id IS NOT NULL) - THEN - SET NEW.event_session_id = NEW.for_id; - SET NEW.event_location_id = (SELECT event_location_id FROM event_session WHERE event_session.id = NEW.for_id); - SET NEW.event_id = (SELECT event_id FROM event_session WHERE event_session.id = NEW.for_id); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `event_file_after_delete` AFTER DELETE ON `event_file` FOR EACH ROW BEGIN - DELETE FROM hosted_file_link WHERE hosted_file_link.hosted_file_id = OLD.hosted_file_id AND hosted_file_link.link_to_type = OLD.for_type AND hosted_file_link.link_to_id = OLD.for_id; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `event_file_after_insert` AFTER INSERT ON `event_file` FOR EACH ROW BEGIN - INSERT IGNORE INTO hosted_file_link (hosted_file_id, link_to_type, link_to_id) VALUES (NEW.hosted_file_id, NEW.for_type, NEW.for_id); -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `update approved_on` BEFORE UPDATE ON `event_file` FOR EACH ROW IF NEW.approved = 1 THEN SET NEW.approved_on = CURRENT_TIMESTAMP; END IF -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `event_file` --- -ALTER TABLE `event_file` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD UNIQUE KEY `hosted_file_id_for` (`hosted_file_id`,`for_type`,`for_id`), - ADD KEY `event_session_id` (`event_session_id`), - ADD KEY `event_id` (`event_id`), - ADD KEY `hosted_file_id` (`hosted_file_id`), - ADD KEY `event_presentation_id` (`event_presentation_id`), - ADD KEY `event_presenter_id` (`event_presenter_id`), - ADD KEY `event_location_id` (`event_location_id`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `event_track_id` (`event_track_id`), - ADD KEY `event_exhibit_id` (`event_exhibit_id`), - ADD KEY `hide` (`hide`), - ADD KEY `enable` (`enable`), - ADD KEY `sort` (`sort`), - ADD KEY `priority` (`priority`), - ADD KEY `for_type` (`for_type`,`for_id`), - ADD KEY `filename` (`filename`), - ADD KEY `extension` (`extension`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `event_file` --- -ALTER TABLE `event_file` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__event_session__2026-01-06_18_26_04.sql b/documentation/aether_sql_tables/aether_dev__event_session__2026-01-06_18_26_04.sql deleted file mode 100644 index 8bae320a..00000000 --- a/documentation/aether_sql_tables/aether_dev__event_session__2026-01-06_18_26_04.sql +++ /dev/null @@ -1,201 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:26 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `event_session` --- - -CREATE TABLE `event_session` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `external_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `code` varchar(100) DEFAULT NULL, - `number` int(11) DEFAULT NULL, - `for_type` varchar(50) DEFAULT NULL COMMENT 'avoid using', - `for_id` int(11) DEFAULT NULL COMMENT 'avoid using', - `event_id` int(11) DEFAULT NULL, - `event_type_id` int(11) DEFAULT NULL, - `type_id` int(11) DEFAULT NULL COMMENT 'not used', - `type_code` varchar(25) DEFAULT NULL COMMENT 'from client', - `event_location_id` int(11) DEFAULT NULL, - `event_track_id` int(11) DEFAULT NULL, - `poc_event_person_id` int(11) DEFAULT NULL COMMENT 'still needed?', - `poc_person_id` int(11) DEFAULT NULL, - `poc_agree` tinyint(1) DEFAULT NULL COMMENT 'catchall for agreement or consent', - `poc_kv_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'advocate, chair, champion, moderator, organizer', - `passcode` varchar(25) DEFAULT NULL COMMENT 'for basic access', - `name` varchar(300) DEFAULT NULL, - `description` text DEFAULT NULL, - `proposal_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'responses to proposal questions in JSON format' CHECK (json_valid(`proposal_json`)), - `start_datetime` datetime DEFAULT NULL, - `end_datetime` datetime DEFAULT NULL, - `attend_url` text DEFAULT NULL, - `attend_url_text` text DEFAULT NULL, - `attend_url_passcode` varchar(15) DEFAULT NULL, - `attend_phone` varchar(15) DEFAULT NULL, - `attend_phone_passcode` varchar(15) DEFAULT NULL, - `attend_text` text DEFAULT NULL, - `rehearsal_start_datetime` datetime DEFAULT NULL, - `rehearsal_end_datetime` datetime DEFAULT NULL, - `rehearsal_url` text DEFAULT NULL, - `rehearsal_url_passcode` varchar(15) DEFAULT NULL COMMENT 'remove field?', - `rehearsal_phone` varchar(15) DEFAULT NULL COMMENT 'remove field?', - `rehearsal_phone_passcode` varchar(15) DEFAULT NULL COMMENT 'remove field?', - `rehearsal_text` text DEFAULT NULL, - `image_path` varchar(7) DEFAULT NULL COMMENT 'remove field?', - `download_start_datetime` datetime DEFAULT NULL, - `download_end_datetime` datetime DEFAULT NULL, - `internal_use` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'hide from non-support people', - `record_audio` tinyint(1) DEFAULT 0 COMMENT 'record presentations', - `record_video` tinyint(1) DEFAULT 0 COMMENT 'record presentations', - `internal_notes` text DEFAULT NULL COMMENT 'general notes', - `internal_notes_access` text DEFAULT NULL COMMENT 'accessibility and accommodations', - `internal_notes_av` text DEFAULT NULL COMMENT 'audio video', - `internal_notes_fb` text DEFAULT NULL COMMENT 'food and beverage', - `internal_notes_it` text DEFAULT NULL COMMENT 'IT and networking', - `internal_notes_staff` text DEFAULT NULL COMMENT 'staffing and labor', - `ux_mode` varchar(50) DEFAULT NULL COMMENT 'colloquium, lecture, panel, poster, symposium, workshop; replaces type_code', - `enable` tinyint(1) NOT NULL DEFAULT 1, - `enable_after_datetime` datetime DEFAULT NULL, - `enable_before_datetime` datetime DEFAULT NULL, - `enable_event_file_approval_option` tinyint(1) DEFAULT NULL, - `hide` tinyint(1) DEFAULT 0, - `public` tinyint(1) DEFAULT NULL, - `public_hide` tinyint(1) DEFAULT NULL, - `hide_event_launcher` tinyint(1) DEFAULT NULL, - `status` int(11) DEFAULT NULL, - `review` tinyint(1) DEFAULT NULL COMMENT 'ready for or needs review', - `approve` tinyint(1) DEFAULT NULL COMMENT 'approved', - `ready` tinyint(1) DEFAULT NULL, - `ready_on` datetime DEFAULT NULL, - `archive` tinyint(1) DEFAULT NULL, - `archive_on` datetime DEFAULT NULL, - `alert` tinyint(1) DEFAULT NULL, - `alert_msg` text DEFAULT NULL COMMENT 'a short message from user', - `priority` tinyint(1) DEFAULT 0, - `sort` int(11) DEFAULT 0, - `group` varchar(100) DEFAULT NULL, - `default_qry_str` text DEFAULT NULL COMMENT 'for FULLTEXT indexed searches', - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `event_session` --- -DELIMITER $$ -CREATE TRIGGER `after_update_event_session` AFTER UPDATE ON `event_session` FOR EACH ROW BEGIN - IF (NEW.event_location_id) THEN - UPDATE `event_file` - SET `event_file`.event_location_id = NEW.event_location_id - WHERE `event_file`.event_session_id = OLD.id OR (`event_file`.for_type = 'event_session' AND `event_file`.for_id = OLD.id); - END IF; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_insert_event_session` BEFORE INSERT ON `event_session` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - SET NEW.default_qry_str = event_session_default_qry_str(NEW.id_random, NEW.name, NEW.description, NEW.code, NEW.type_code, NEW.start_datetime); - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_event_session` BEFORE UPDATE ON `event_session` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - SET NEW.default_qry_str = event_session_default_qry_str(NEW.id_random, NEW.name, NEW.description, NEW.code, NEW.type_code, NEW.start_datetime); - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `event_session_after_delete` AFTER DELETE ON `event_session` FOR EACH ROW BEGIN - DELETE FROM event_file WHERE event_file.for_type = 'event_session' AND event_file.for_id = OLD.id; - - DELETE FROM event_presentation WHERE event_presentation.event_session_id = OLD.id; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `event_session` --- -ALTER TABLE `event_session` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `event_id` (`event_id`), - ADD KEY `start_datetime` (`start_datetime`), - ADD KEY `event_location_id` (`event_location_id`), - ADD KEY `poc_event_person_id` (`poc_event_person_id`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `sort` (`sort`), - ADD KEY `enable` (`enable`), - ADD KEY `hide` (`hide`), - ADD KEY `priority` (`priority`), - ADD KEY `name` (`name`), - ADD KEY `external_id` (`external_id`), - ADD KEY `code` (`code`), - ADD KEY `event_track_id` (`event_track_id`), - ADD KEY `hide_event_launcher` (`hide_event_launcher`), - ADD KEY `type_code` (`type_code`), - ADD KEY `poc_person_id` (`poc_person_id`), - ADD KEY `poc_agree` (`poc_agree`); -ALTER TABLE `event_session` ADD FULLTEXT KEY `tbl_fulltext_default_qry_str` (`default_qry_str`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `event_session` --- -ALTER TABLE `event_session` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__hosted_file__2026-01-03_00_03_33.sql b/documentation/aether_sql_tables/aether_dev__hosted_file__2026-01-03_00_03_33.sql deleted file mode 100644 index 60497152..00000000 --- a/documentation/aether_sql_tables/aether_dev__hosted_file__2026-01-03_00_03_33.sql +++ /dev/null @@ -1,121 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 03, 2026 at 12:03 AM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `hosted_file` --- - -CREATE TABLE `hosted_file` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `hash_sha256` varchar(64) DEFAULT NULL, - `account_id` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `title` varchar(500) DEFAULT NULL, - `description` text DEFAULT NULL, - `version` int(11) DEFAULT NULL, - `directory_path` varchar(1000) DEFAULT NULL, - `subdirectory_path` varchar(1000) DEFAULT NULL COMMENT 'new as of 2021-08-26', - `filename` varchar(255) DEFAULT NULL, - `extension` varchar(10) DEFAULT NULL, - `content_type` varchar(100) DEFAULT NULL, - `mimetype` varchar(100) DEFAULT NULL, - `size` int(11) UNSIGNED DEFAULT NULL COMMENT 'bytes', - `cloud_storage` text DEFAULT NULL, - `owner_user_id` int(11) DEFAULT NULL, - `group_user_id` int(11) DEFAULT NULL, - `package_name` varchar(500) DEFAULT NULL, - `hide` tinyint(1) DEFAULT 0, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `enable` tinyint(1) DEFAULT 1, - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `hosted_file` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_hosted_file` BEFORE INSERT ON `hosted_file` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_hosted_file` BEFORE UPDATE ON `hosted_file` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `hosted_file` --- -ALTER TABLE `hosted_file` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD UNIQUE KEY `hash_sha256` (`hash_sha256`), - ADD KEY `account_id` (`account_id`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `filename` (`filename`), - ADD KEY `extension` (`extension`), - ADD KEY `hide` (`hide`), - ADD KEY `enable` (`enable`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `hosted_file` --- -ALTER TABLE `hosted_file` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__hosted_file_link__2026-01-03_00_03_53.sql b/documentation/aether_sql_tables/aether_dev__hosted_file_link__2026-01-03_00_03_53.sql deleted file mode 100644 index 0844c2a1..00000000 --- a/documentation/aether_sql_tables/aether_dev__hosted_file_link__2026-01-03_00_03_53.sql +++ /dev/null @@ -1,52 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 03, 2026 at 12:03 AM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `hosted_file_link` --- - -CREATE TABLE `hosted_file_link` ( - `account_id` int(11) DEFAULT NULL COMMENT 'is this needed?', - `hosted_file_id` int(11) NOT NULL, - `link_to_type` varchar(50) NOT NULL COMMENT 'change to for_object_type', - `link_to_id` int(11) NOT NULL COMMENT 'change to for_object_id', - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='All hosted files that are actively linked or in use'; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `hosted_file_link` --- -ALTER TABLE `hosted_file_link` - ADD PRIMARY KEY (`hosted_file_id`,`link_to_type`,`link_to_id`) USING BTREE; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__journal__2026-01-02_22_18_03.sql b/documentation/aether_sql_tables/aether_dev__journal__2026-01-02_22_18_03.sql deleted file mode 100644 index 5bf5098b..00000000 --- a/documentation/aether_sql_tables/aether_dev__journal__2026-01-02_22_18_03.sql +++ /dev/null @@ -1,138 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 02, 2026 at 10:18 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `journal` --- - -CREATE TABLE `journal` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `account_id` int(11) DEFAULT NULL, - `person_id` int(11) DEFAULT NULL, - `user_id` int(11) DEFAULT NULL, - `type_code` varchar(25) DEFAULT NULL, - `default_private` tinyint(1) DEFAULT NULL COMMENT 'default to private', - `default_public` tinyint(1) DEFAULT NULL COMMENT 'default to public', - `default_personal` tinyint(1) DEFAULT NULL COMMENT 'default to personal', - `default_professional` tinyint(1) DEFAULT NULL COMMENT 'default to professional', - `private_passcode` varchar(20) DEFAULT NULL COMMENT 'passcode to show private entries', - `public_passcode` varchar(20) DEFAULT NULL COMMENT 'passcode to show only public entries', - `name` varchar(250) NOT NULL, - `short_name` varchar(25) DEFAULT NULL, - `summary` text DEFAULT NULL, - `outline` text DEFAULT NULL, - `description` text DEFAULT NULL, - `description_html` text DEFAULT NULL, - `description_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`description_json`)), - `alert` tinyint(1) DEFAULT NULL, - `alert_msg` text DEFAULT NULL, - `allow_auth` tinyint(1) NOT NULL DEFAULT 0, - `auth_key` varchar(25) DEFAULT NULL, - `passcode` varchar(25) DEFAULT NULL, - `passcode_timeout` int(11) NOT NULL DEFAULT 300 COMMENT 'in seconds', - `cfg_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`cfg_json`)), - `data_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`data_json`)), - `enable` tinyint(1) NOT NULL DEFAULT 1, - `hide` tinyint(1) DEFAULT NULL, - `status` int(11) DEFAULT NULL, - `archive_on` datetime DEFAULT NULL, - `archive` tinyint(1) DEFAULT NULL, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `journal` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_journal` BEFORE INSERT ON `journal` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); - /* SET NEW.id_random = gen_rand_pattern('3CN-2CN-2CN-2CN'); */ - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - /* SET NEW.default_qry_str = journal_default_qry_str(NEW.id_random, NEW.name, NEW.summary, NEW.description); */ - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_journal` BEFORE UPDATE ON `journal` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); - /* SET NEW.id_random = gen_rand_pattern('3CN-2CN-2CN-2CN'); */ - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - /* SET NEW.default_qry_str = journal_default_qry_str(NEW.id_random, NEW.name, NEW.summary, NEW.description); */ - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `journal_after_delete` AFTER DELETE ON `journal` FOR EACH ROW BEGIN - DELETE FROM journal_entry WHERE journal_entry.journal_id = OLD.id; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `journal` --- -ALTER TABLE `journal` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `account_id` (`account_id`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `journal` --- -ALTER TABLE `journal` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__journal_entry__2026-01-02_22_19_31.sql b/documentation/aether_sql_tables/aether_dev__journal_entry__2026-01-02_22_19_31.sql deleted file mode 100644 index b8363e39..00000000 --- a/documentation/aether_sql_tables/aether_dev__journal_entry__2026-01-02_22_19_31.sql +++ /dev/null @@ -1,166 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 02, 2026 at 10:19 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `journal_entry` --- - -CREATE TABLE `journal_entry` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `journal_id` int(11) NOT NULL, - `code` varchar(20) DEFAULT NULL, - `lu_type_id` int(11) DEFAULT NULL, - `type` varchar(50) DEFAULT NULL, - `topic_id` int(11) DEFAULT NULL, - `topic` varchar(50) DEFAULT NULL, - `activity_id` int(11) DEFAULT NULL, - `activity` varchar(50) DEFAULT NULL, - `private` tinyint(1) DEFAULT NULL COMMENT 'implies encryption if possible', - `public` tinyint(1) DEFAULT NULL, - `personal` tinyint(1) DEFAULT NULL, - `professional` tinyint(1) DEFAULT NULL, - `name` varchar(250) DEFAULT NULL, - `short_name` varchar(25) DEFAULT NULL, - `summary` text DEFAULT NULL, - `content` text DEFAULT NULL, - `content_html` text DEFAULT NULL, - `content_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`content_json`)), - `content_encrypted` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `history` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'content history', - `history_encrypted` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'content history encrypted', - `passcode_hash` varchar(64) DEFAULT NULL COMMENT 'to match with index', - `template` tinyint(1) DEFAULT NULL COMMENT 'use as template entry', - `type_code` varchar(25) DEFAULT NULL, - `topic_code` varchar(25) DEFAULT NULL, - `category_code` varchar(25) DEFAULT NULL, - `tags` varchar(255) DEFAULT NULL COMMENT 'comma delimited list', - `start_datetime` datetime DEFAULT NULL, - `end_datetime` datetime DEFAULT NULL, - `seconds` int(11) DEFAULT NULL, - `hours` decimal(3,2) DEFAULT NULL, - `timezone` varchar(50) DEFAULT NULL, - `location` text DEFAULT NULL COMMENT 'probably an address', - `latitude` float DEFAULT NULL, - `longitude` float DEFAULT NULL, - `billable` tinyint(1) DEFAULT 0, - `billable_to_id` int(11) DEFAULT NULL, - `billiable_to` varchar(100) DEFAULT NULL, - `alert` tinyint(1) DEFAULT NULL, - `alert_msg` text DEFAULT NULL, - `data_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`data_json`)), - `enable` tinyint(1) NOT NULL DEFAULT 1, - `hide` tinyint(1) DEFAULT NULL, - `status` int(11) DEFAULT NULL, - `archive_on` datetime DEFAULT NULL, - `archive` tinyint(1) DEFAULT NULL, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `default_qry_str` text DEFAULT NULL COMMENT 'for FULLTEXT indexed searches', - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `journal_entry` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_journal_entry` BEFORE INSERT ON `journal_entry` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_pattern('3CN-2CN-2CN-2CN'); - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - SET NEW.default_qry_str = journal_entry_default_qry_str(NEW.id_random, NEW.name, NEW.summary, NEW.content, NEW.history, NEW.category_code, NEW.tags, NEW.alert_msg, NEW.data_json); - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_journal_entry` BEFORE UPDATE ON `journal_entry` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_pattern('3CN-2CN-2CN-2CN'); - /* SET NEW.id_random = gen_rand_str(11, 'URL'); */ - END IF; - - SET NEW.default_qry_str = journal_entry_default_qry_str(NEW.id_random, NEW.name, NEW.summary, NEW.content, NEW.history, NEW.category_code, NEW.tags, NEW.alert_msg, NEW.data_json); - END; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `journal_entry` --- -ALTER TABLE `journal_entry` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `journal_id` (`journal_id`), - ADD KEY `tags` (`tags`), - ADD KEY `enable` (`enable`), - ADD KEY `hide` (`hide`), - ADD KEY `status` (`status`), - ADD KEY `priority` (`priority`), - ADD KEY `archive` (`archive`), - ADD KEY `sort` (`sort`), - ADD KEY `group` (`group`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `start_datetime` (`start_datetime`), - ADD KEY `private` (`private`), - ADD KEY `public` (`public`), - ADD KEY `personal` (`personal`), - ADD KEY `professional` (`professional`), - ADD KEY `name` (`name`); -ALTER TABLE `journal_entry` ADD FULLTEXT KEY `tbl_fulltext_default_qry_str` (`default_qry_str`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `journal_entry` --- -ALTER TABLE `journal_entry` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__person__2026-01-06_18_23_59.sql b/documentation/aether_sql_tables/aether_dev__person__2026-01-06_18_23_59.sql deleted file mode 100644 index 51326123..00000000 --- a/documentation/aether_sql_tables/aether_dev__person__2026-01-06_18_23_59.sql +++ /dev/null @@ -1,213 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:23 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `person` --- - -CREATE TABLE `person` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `source_code` varchar(25) DEFAULT NULL, - `external_id` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `external_sys_id` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'generated by external system', - `account_id` int(11) DEFAULT NULL, - `user_id` int(11) DEFAULT NULL, - `organization_id` int(11) DEFAULT NULL, - `informal_name` varchar(50) DEFAULT NULL COMMENT 'nickname', - `title_names` varchar(100) DEFAULT NULL COMMENT 'prefix', - `given_name` varchar(50) NOT NULL DEFAULT '' COMMENT 'first name', - `middle_name` varchar(50) DEFAULT NULL, - `family_name` varchar(50) DEFAULT NULL COMMENT 'last name', - `designations` varchar(175) DEFAULT NULL COMMENT 'designations and suffix', - `professional_title` varchar(100) DEFAULT NULL COMMENT ' includes degrees and credentials ', - `full_name` varchar(150) DEFAULT NULL COMMENT 'set by triggers', - `full_name_override` varchar(150) DEFAULT NULL COMMENT 'was display_name', - `last_first_name` varchar(50) DEFAULT NULL COMMENT 'set by triggers', - `informal_full_name` varchar(150) DEFAULT NULL COMMENT 'set by triggers', - `affiliations` varchar(200) DEFAULT NULL, - `primary_email` varchar(254) DEFAULT NULL, - `tagline` text DEFAULT NULL, - `description` text DEFAULT NULL, - `biography` text DEFAULT NULL, - `birth_date` date DEFAULT NULL, - `death_date` date DEFAULT NULL, - `lu_gender_id` int(11) DEFAULT NULL, - `lu_sexuality_id` int(11) DEFAULT NULL, - `lu_race_id` int(11) DEFAULT NULL, - `lu_ethnicity_id` int(11) DEFAULT NULL, - `language_native` varchar(2) DEFAULT NULL, - `language_primary` varchar(2) DEFAULT NULL, - `language_secondary` varchar(2) DEFAULT NULL, - `lu_education_degree_id` int(11) DEFAULT NULL, - `lu_education_level_id` int(11) DEFAULT NULL, - `photo_path` varchar(2500) DEFAULT NULL, - `photo_bg_color` varchar(25) DEFAULT NULL, - `thumbnail_path` varchar(2500) DEFAULT NULL, - `thumbnail_bg_color` varchar(25) DEFAULT NULL, - `email_allowed` tinyint(1) DEFAULT NULL COMMENT 'global opt in or out for person', - `paper_mail_allowed` tinyint(1) DEFAULT NULL COMMENT 'global opt in or out for person', - `stripe_customer_id` varchar(50) DEFAULT NULL, - `allow_auth_key` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'defaults to true', - `auth_key` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `passcode` varchar(25) DEFAULT NULL COMMENT 'for basic access', - `status` varchar(25) DEFAULT NULL COMMENT 'pending, hold, approved, rejected, banned, retired, deceased', - `status_id` int(11) DEFAULT NULL COMMENT 'not sure if using yet 2022-03-15', - `hide` tinyint(1) DEFAULT NULL, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL, - `group` varchar(100) DEFAULT NULL, - `notes` text DEFAULT NULL, - `cfg_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'config options' CHECK (json_valid(`cfg_json`)), - `data_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`data_json`)), - `other_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `meta_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`meta_json`)), - `enable` tinyint(1) DEFAULT 1, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Information that generally does not change often or ever.'; - --- --- Triggers `person` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_person` BEFORE INSERT ON `person` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_insert_person_names` BEFORE INSERT ON `person` FOR EACH ROW BEGIN - SET NEW.full_name = name_for_full_name(NEW.informal_name, NEW.title_names, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.designations); - - SET NEW.last_first_name = name_for_last_first_name(NEW.given_name, NEW.middle_name, NEW.family_name); - - SET NEW.informal_full_name = name_for_informal_full_name(NEW.informal_name, NEW.title_names, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.designations); - - /* - IF (NEW.full_name_override IS NULL OR NEW.full_name_override = '') - THEN - SET NEW.full_name_override = name_for_display_name(NEW.informal_name, NEW.given_name, NEW.middle_name, NEW.family_name); - END IF; - */ - - /* - IF (NEW.informal_full_name_override IS NULL OR NEW.informal_full_name_override = '') - THEN - SET NEW.informal_full_name_override = name_for_informal_display_name(NEW.informal_name, NEW.given_name, NEW.middle_name, NEW.family_name); - END IF; - */ -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_person` BEFORE UPDATE ON `person` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_person_names` BEFORE UPDATE ON `person` FOR EACH ROW BEGIN - SET NEW.full_name = name_for_full_name(NEW.informal_name, NEW.title_names, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.designations); - - SET NEW.last_first_name = name_for_last_first_name(NEW.given_name, NEW.middle_name, NEW.family_name); - - SET NEW.informal_full_name = name_for_informal_full_name(NEW.informal_name, NEW.title_names, NEW.given_name, NEW.middle_name, NEW.family_name, NEW.designations); - - /* - IF (NEW.full_name_override IS NULL OR NEW.full_name_override = '') - THEN - SET NEW.full_name_override = name_for_display_name(NEW.informal_name, NEW.given_name, NEW.middle_name, NEW.family_name); - END IF; - */ - - /* - IF (NEW.informal_full_name_override IS NULL OR NEW.informal_full_name_override = '') - THEN - SET NEW.informal_full_name_override = name_for_informal_display_name(NEW.informal_name, NEW.given_name, NEW.middle_name, NEW.family_name); - END IF; - */ -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `person_after_delete` AFTER DELETE ON `person` FOR EACH ROW BEGIN -DELETE FROM user WHERE user.id = old.user_id; -DELETE FROM contact WHERE contact.for_id = old.id AND contact.for_type = 'person'; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `person` --- -ALTER TABLE `person` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `account_id` (`account_id`), - ADD KEY `user_id` (`user_id`), - ADD KEY `organization_id` (`organization_id`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `external_id` (`external_sys_id`), - ADD KEY `family_name` (`family_name`), - ADD KEY `given_name` (`given_name`), - ADD KEY `enable` (`enable`), - ADD KEY `priority` (`priority`), - ADD KEY `sort` (`sort`), - ADD KEY `group` (`group`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `person` --- -ALTER TABLE `person` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__site__2026-01-06_18_22_58.sql b/documentation/aether_sql_tables/aether_dev__site__2026-01-06_18_22_58.sql deleted file mode 100644 index 7d38d766..00000000 --- a/documentation/aether_sql_tables/aether_dev__site__2026-01-06_18_22_58.sql +++ /dev/null @@ -1,128 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:22 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `site` --- - -CREATE TABLE `site` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `code` varchar(100) DEFAULT NULL, - `account_id` int(11) DEFAULT NULL, - `name` varchar(200) NOT NULL, - `description` text DEFAULT NULL, - `restrict_access` tinyint(1) NOT NULL DEFAULT 1, - `access_key` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `access_code_kv_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'for super, manager, administrator, trusted, public, authenticated' CHECK (json_valid(`access_code_kv_json`)), - `enable` tinyint(1) NOT NULL DEFAULT 0, - `enable_from` datetime DEFAULT NULL, - `enable_to` datetime DEFAULT NULL, - `logo_path` varchar(200) DEFAULT NULL, - `logo_bg_color` varchar(25) DEFAULT NULL, - `background_image_path` varchar(200) DEFAULT NULL, - `background_bg_color` varchar(25) DEFAULT NULL, - `site_menu_html_path` varchar(200) DEFAULT NULL COMMENT 'path to html file for site menu', - `site_menu` text DEFAULT NULL COMMENT 'not currently used; but want to use', - `title` varchar(200) DEFAULT NULL, - `header_html` text DEFAULT NULL, - `header_css` text DEFAULT NULL, - `header_image_path` varchar(200) DEFAULT NULL, - `header_image_bg_color` varchar(25) DEFAULT NULL, - `body_html` text DEFAULT NULL, - `tagline` text DEFAULT NULL COMMENT 'catchphrase or slogan', - `site_header_h1` text DEFAULT NULL COMMENT 'field not currently used', - `site_header_h2` text DEFAULT NULL COMMENT 'field not currently used', - `style_href` varchar(200) DEFAULT NULL, - `script_src` varchar(200) DEFAULT NULL, - `google_tracking_id` varchar(14) DEFAULT NULL, - `cfg_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '{}' COMMENT 'config in JSON format' CHECK (json_valid(`cfg_json`)), - `hide` tinyint(1) DEFAULT NULL, - `notes` text DEFAULT NULL, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `site` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_site` BEFORE INSERT ON `site` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_site` BEFORE UPDATE ON `site` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `site` --- -ALTER TABLE `site` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `account_id` (`account_id`), - ADD KEY `enable` (`enable`), - ADD KEY `access_key` (`access_key`), - ADD KEY `name` (`name`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `site` --- -ALTER TABLE `site` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__site_domain__2026-01-06_18_22_25.sql b/documentation/aether_sql_tables/aether_dev__site_domain__2026-01-06_18_22_25.sql deleted file mode 100644 index 3bfbcd1e..00000000 --- a/documentation/aether_sql_tables/aether_dev__site_domain__2026-01-06_18_22_25.sql +++ /dev/null @@ -1,104 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:22 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `site_domain` --- - -CREATE TABLE `site_domain` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `site_id` int(11) NOT NULL, - `fqdn` varchar(200) NOT NULL, - `access_key` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `required_referrer` varchar(200) DEFAULT NULL, - `valid_for` int(11) DEFAULT NULL COMMENT 'number of hours to allow before checking again', - `enable` tinyint(1) DEFAULT 1, - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Triggers `site_domain` --- -DELIMITER $$ -CREATE TRIGGER `before_insert_site_domain` BEFORE INSERT ON `site_domain` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_site_domain` BEFORE UPDATE ON `site_domain` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `site_domain` --- -ALTER TABLE `site_domain` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `fqdn` (`fqdn`), - ADD KEY `access_key` (`access_key`), - ADD KEY `required_referrer` (`required_referrer`), - ADD KEY `site_id` (`site_id`), - ADD KEY `enable` (`enable`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `site_domain` --- -ALTER TABLE `site_domain` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/aether_sql_tables/aether_dev__user__2026-01-06_18_23_35.sql b/documentation/aether_sql_tables/aether_dev__user__2026-01-06_18_23_35.sql deleted file mode 100644 index 49604c8a..00000000 --- a/documentation/aether_sql_tables/aether_dev__user__2026-01-06_18_23_35.sql +++ /dev/null @@ -1,163 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.2.3 --- https://www.phpmyadmin.net/ --- --- Host: localhost --- Generation Time: Jan 06, 2026 at 06:23 PM --- Server version: 12.1.2-MariaDB-log --- PHP Version: 8.4.15 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Database: `aether_dev` --- - --- -------------------------------------------------------- - --- --- Table structure for table `user` --- - -CREATE TABLE `user` ( - `id` int(11) NOT NULL, - `id_random` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'NULL', - `account_id` int(11) DEFAULT NULL, - `contact_id` int(11) DEFAULT NULL COMMENT 'no longer going to be used', - `organization_id` int(11) DEFAULT NULL COMMENT 'no longer going to be used', - `person_id` int(11) DEFAULT NULL COMMENT 'no longer going to be used', - `username` varchar(100) NOT NULL, - `name` varchar(100) DEFAULT NULL, - `email` varchar(254) NOT NULL, - `email_verified` tinyint(1) NOT NULL DEFAULT 0, - `password` varchar(100) DEFAULT NULL, - `allow_auth_key` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'allow use of auth key to sign in', - `auth_key` varchar(22) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'auth key for single use log in', - `enable` tinyint(1) NOT NULL DEFAULT 0, - `enable_from` datetime DEFAULT current_timestamp(), - `enable_to` datetime DEFAULT NULL, - `super` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Super user for the entire system. Can do everything.', - `manager` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Manager for the entire system. Can do almost everything.', - `administrator` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Administrator for a client account. Can do almost anything within that account.', - `public` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'public or shared account', - `verified` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Is this a verified user account?', - `level` int(11) DEFAULT NULL COMMENT 'access level (1 to 5)', - `status_id` int(11) DEFAULT NULL COMMENT 'offline, away, dnd, online', - `password_set_on` timestamp NOT NULL DEFAULT current_timestamp(), - `password_reset_token` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, - `password_reset_expire_on` datetime DEFAULT NULL, - `logged_in_on` timestamp NULL DEFAULT NULL, - `last_activity_on` timestamp NULL DEFAULT NULL, - `hide` tinyint(1) DEFAULT NULL, - `priority` tinyint(1) DEFAULT NULL, - `sort` int(11) DEFAULT NULL COMMENT 'used as access level', - `group` varchar(100) DEFAULT NULL COMMENT 'used as access group', - `notes` text DEFAULT NULL, - `other_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`other_json`)), - `created_on` timestamp NOT NULL DEFAULT current_timestamp(), - `updated_on` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='The user account.'; - --- --- Triggers `user` --- -DELIMITER $$ -CREATE TRIGGER `after_insert_user_person_id` AFTER INSERT ON `user` FOR EACH ROW BEGIN - IF (NEW.person_id IS NOT NULL) - THEN - UPDATE person SET person.user_id = NEW.id WHERE person.id = NEW.person_id AND person.user_id IS NULL; - END IF; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `after_update_user_person_id` AFTER UPDATE ON `user` FOR EACH ROW BEGIN - IF (NEW.person_id IS NOT NULL AND OLD.person_id IS NULL) - THEN - UPDATE person SET person.user_id = NEW.id WHERE person.id = NEW.person_id AND person.user_id IS NULL; - END IF; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_insert_user` BEFORE INSERT ON `user` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_user` BEFORE UPDATE ON `user` FOR EACH ROW BEGIN - BEGIN - IF (NEW.id_random IS NULL OR NEW.id_random = '' OR LENGTH(NEW.id_random) < 6) - THEN - /* SET NEW.id_random = gen_rand_pattern('3C-2N-2N-2N'); */ - /* SET NEW.id_random = gen_rand_pattern('4C-2N-2N-2N'); */ - SET NEW.id_random = gen_rand_str(11, 'URL'); - END IF; - END; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `before_update_user_email` BEFORE UPDATE ON `user` FOR EACH ROW BEGIN - IF (NEW.username IS NULL OR NEW.username = '') - THEN - SET NEW.username = NEW.email; - SET NEW.notes = CONCAT(COALESCE(`NEW`.`notes`,''), ';;sys::overide empty username'); - END IF; -END -$$ -DELIMITER ; -DELIMITER $$ -CREATE TRIGGER `update_password_set_on` BEFORE UPDATE ON `user` FOR EACH ROW IF NEW.password <> OLD.password THEN SET NEW.password_set_on = CURRENT_TIMESTAMP; END IF -$$ -DELIMITER ; - --- --- Indexes for dumped tables --- - --- --- Indexes for table `user` --- -ALTER TABLE `user` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id_random` (`id_random`), - ADD KEY `username` (`username`) USING BTREE, - ADD KEY `account_id` (`account_id`), - ADD KEY `email` (`email`), - ADD KEY `email_2` (`email`), - ADD KEY `created_on` (`created_on`), - ADD KEY `updated_on` (`updated_on`), - ADD KEY `enable` (`enable`), - ADD KEY `name` (`name`); - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `user` --- -ALTER TABLE `user` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/documentation/history/AETHER_NATIVE_APP_ELECTRON_NEW_2026.md b/documentation/history/AETHER_NATIVE_APP_ELECTRON_NEW_2026.md deleted file mode 100644 index f1eb29ae..00000000 --- a/documentation/history/AETHER_NATIVE_APP_ELECTRON_NEW_2026.md +++ /dev/null @@ -1,76 +0,0 @@ -# Aether Native Electron App - V3 Architecture (2026) - -## 1. Overview -The Aether Native App serves as the OS-level bridge for the SvelteKit frontend. It enables functionality that is normally restricted by browser sandboxing, such as local filesystem management, hardware telemetry, and direct control of third-party presentation software (PowerPoint, Keynote, LibreOffice). - -**Core Tasks (Completed Jan 2026):** -* **[Infrastructure]**: Restore AE Events Presentation Launcher (Electron) (ID: 221513945) -* **[Frontend]**: V3 File Caching: Implement Launcher CRUD Migration (ID: 173518010) -* **[Frontend]**: Native App Bridge: Standardize Electron IPC (ID: 173448078) - ---- - -## 2. The Three-Layer Architecture - -### 2.1 The Engine (`src/main/*.ts`) -* **Process:** Main Process (Node.js/TypeScript) -* **Role:** Performs the actual OS-level operations. -* **Key Responsibilities:** - * **Shell Handlers (`shell_handlers.ts`)**: Executing shell commands, AppleScripts, and process management. - * **File Handlers (`file_handlers.ts`)**: Managing the permanent Hashed Cache (`file_cache/`) and atomic Safe Handover. - * Resolving global path placeholders like `[home]` and `[tmp]` via `file_utils.ts`. - -### 2.2 The Bridge (`src/preload/index.ts`) -* **Process:** Preload Script -* **Role:** The security gatekeeper. -* **Key Responsibilities:** - * Uses Electron's `contextBridge` to securely expose Main Process functions to the UI. - * Exposes the `window.aetherNative` object. - * Ensures that only whitelisted IPC channels can be triggered by the renderer. - -### 2.3 The Messenger (`src/lib/electron/electron_relay.ts`) -* **Process:** Renderer Process (SvelteKit) -* **Role:** The TypeScript API used by Svelte components. -* **Key Responsibilities:** - * Standardizing IPC calls to snake_case. - * Implementing "Smart Fallbacks" (e.g., UI-side placeholder resolution if the bridge is inactive). - ---- - -## 3. Core Lifecycle - -1. **Seed Phase:** The Electron shell reads `resources/seed_config.json` to identify the device. -2. **Hydration Phase:** The shell authenticates with the Aether V3 API to pull device-specific settings. -3. **Injection Phase:** The shell injects the **JWT** and **Native Config** into the SvelteKit environment. -4. **Observation Phase:** Background sync loops manage file warming and heartbeat telemetry. - ---- - -## 4. Native Tool Library (`window.aetherNative`) - -### File & Cache Management -- `check_cache({hash})`: Verify if a file exists in the hidden hashed storage. -- `download_to_cache({url, hash})`: Secure background download using the native API key. -- `launch_from_cache({hash, filename})`: **Safe Handover** — copies from cache to temp with the original name and triggers the specialized launcher. - -### OS Execution (The "Actuators") -- `launch_presentation({path, app})`: Phase 5 specialized launcher with auto-focus (`activate`) and slideshow start. - - **Linux:** Triggers `libreoffice --impress`. - - **macOS:** Triggers AppleScript for Keynote or PowerPoint. -- `control_presentation({app, action})`: Remote navigation for active decks. - - **Actions:** `next`, `prev`, `start`, `stop`. -- `run_cmd({cmd})`: Executes raw shell commands with automatic path resolution. -- `kill_processes([names])`: Force-closes apps to clean the podium. - -### Metadata & Discovery -- `get_device_info()`: Provides CPU/RAM stats and absolute system paths. -- `list_tools()`: Returns a JSON manifest of all available native functions for self-documentation. - ---- - -## 5. Path Placeholder System -To maintain cross-platform compatibility, the system uses a placeholder syntax for all paths: -- `[home]`: Resolves to the user's home directory (e.g., `/home/scott` or `/Users/scott`). -- `[tmp]`: Resolves to the system temporary directory. - -**Resolution Logic:** All native handlers utilize a global regex (`/\[home\]/g`) to ensure these are converted to absolute paths before any disk or shell operation occurs. diff --git a/documentation/history/Aether_API_CRUD_V3_beta_recommendations.md b/documentation/history/Aether_API_CRUD_V3_beta_recommendations.md deleted file mode 100644 index 80a53f0d..00000000 --- a/documentation/history/Aether_API_CRUD_V3_beta_recommendations.md +++ /dev/null @@ -1,31 +0,0 @@ -# Aether API CRUD V3 Beta Recommendations - -Following the initial migration of the Journals module to the V3 CRUD endpoints, the following architectural recommendations are proposed for the FastAPI backend to improve developer experience and frontend efficiency. - ---- - -## 1. "View" Selection (`use_alt_tbl` Replacement) -In V2, the `use_alt_tbl` flag was frequently used to fetch "rich" objects (e.g., including joined data like `person_name`). -- **Recommendation:** Implement a `response_view` (or `view`) query parameter for both GET list and POST search endpoints. -- **Example:** `GET /v3/crud/journal/?view=enriched` -- **Goal:** Allow the client to request a heavier model with joined fields only when necessary, keeping the default response lightweight. - -## 2. Hybrid Filtering for Search -Currently, the `/search` endpoint requires a full JSON body even for simple standard filters like `enabled` or `hidden`. -- **Recommendation:** Update the `POST .../search` endpoint to accept standard query parameters that automatically append `AND` conditions to the logic defined in the body. -- **Example:** `POST /v3/crud/journal/search?enabled=true` -- **Goal:** Simplifies frontend code for common toggles while still allowing complex logic in the POST body. - -## 3. Standardized Full-Text Search Field -The current migration uses a field named `default_qry_str` with a `match` operator for text search. -- **Recommendation:** Implement a reserved top-level property in the Search Pydantic model (e.g., `_search_` or `query_string`) specifically for global text search. -- **Goal:** Decouples the frontend from knowing specific database column names used for full-text indexing. The backend can then decide which columns (name, description, tags, etc.) to include in the search. - -## 4. Explicit "Parent" Filtering in Search -Filtering by parent (e.g., Account or Site) is a primary use case but currently requires manual injection into the `and` array. -- **Recommendation:** Expose `for_obj_type` and `for_obj_id` as top-level arguments in the Search API. -- **Goal:** Standardizes how parent context is passed, allowing the backend to more easily perform ownership and permission validation before executing the search. - ---- -**Date:** 2026-01-02 -**Status:** Beta Feedback diff --git a/documentation/history/GEMINI_Flowbite_upgrade_2025-12.md b/documentation/history/GEMINI_Flowbite_upgrade_2025-12.md deleted file mode 100644 index 809a243c..00000000 --- a/documentation/history/GEMINI_Flowbite_upgrade_2025-12.md +++ /dev/null @@ -1,51 +0,0 @@ -# Flowbite-Svelte Upgrade Notes (December 2025) - -## Overview -This document tracks the process of upgrading the Flowbite-Svelte UI library within the Aether SvelteKit project. The primary goal is to determine if a compatible version exists for Svelte 5 and Tailwind CSS v4, and to plan for its integration or replacement if necessary. - -## Current Status (Pre-Upgrade) -- **Flowbite-Svelte Version:** v1.28.1 (as per `package.json` at commit `90ee6bb1`) -- **Target Version:** v1.30.0 (or newest compatible) -- **Initial Issue (Pre-Rollback):** Previous attempts to update `flowbite-svelte` (and other packages) indicated peer dependency conflicts. Earlier versions of `flowbite-svelte` (compatible with Tailwind v3) required Svelte v4, which conflicted with the project's Svelte v5. -- **Current Re-evaluation:** After rolling back to commit `90ee6bb1` and updating SkeletonLabs (which failed the build due to other reasons), `npm install` succeeded with `flowbite-svelte@1.28.1` present in `package.json`. This implies it *can install* alongside Svelte 5 and Tailwind 4. However, its runtime compatibility and rendering correctness with Svelte 5 (runes mode) and Tailwind CSS v4 remain untested. -- **Svelte Version:** Svelte 5 (runes mode) -- **Tailwind CSS Version:** v4.1.10 - -## Phase 1: Research and Planning (No Code Changes Yet) - -### Goal -Determine if Flowbite-Svelte has a version that is explicitly compatible with Svelte 5 (runes mode) and Tailwind CSS v4, and to identify any breaking changes or migration paths. - -### Steps -1. **Thoroughly Review Flowbite-Svelte Changelog:** - * **Link:** `https://github.com/themesberg/flowbite-svelte/blob/main/CHANGELOG.md` - * **Action:** Read the changelog for versions from `1.28.1` up to the latest stable release (e.g., `1.30.0` or newer). - * **Goal:** Look for specific mentions of Svelte 5 support, "runes mode" compatibility, or compatibility with Tailwind CSS v4. Note any breaking changes or migration instructions related to Svelte version or component API changes. - -### Expected Outcome of Phase 1 -A clear understanding of Flowbite-Svelte's compatibility with our current stack. This will inform the decision on whether to attempt an upgrade or if abandoning it (and creating custom replacements) is necessary. The expectation is that if a version is compatible, any breaking changes to component APIs (like renaming `Modal` to `Dialog`) will be identified. - -## Phase 2: Execution (After Approval) - -### Steps (To be detailed after Phase 1) -1. **If a compatible version exists:** - * Update `package.json` to the compatible version. - * Run `npm install`. - * Run `npm run build` and `npm run dev` and thoroughly check for errors and visual regressions. - * Apply any necessary code changes based on identified breaking changes (e.g., component name changes like `Modal` to `Dialog`). -2. **If no compatible version exists or issues persist:** - * **Decision:** Abandon Flowbite-Svelte. - * **Action:** Systematically replace its components with custom-built Svelte/Tailwind components, starting with critical ones like `Modal` (using our `element_modal_v1.svelte` if not using Skeleton's `Dialog`). - -## Final Decision (2025-12-08) - -**Outcome:** Hold off on upgrading Flowbite-Svelte. - -**Reasoning:** -The changelog indicates that experimental Svelte 5 support was added in version `0.45.0`. However, there is no mention of compatibility with Tailwind CSS v4. Since SkeletonLabs (the other major UI library) is being removed due to build failures, our immediate priority is to stabilize the project and replace Skeleton's components. Introducing another potential variable by upgrading Flowbite-Svelte at the same time is not advisable. - -**Path Forward:** -1. The currently installed version of `flowbite-svelte` (`1.28.1`) will be kept for now. -2. After SkeletonLabs is removed and the project builds successfully, we will test the functionality of existing Flowbite-Svelte components. -3. If they work, we will continue to use them. -4. If they cause build or runtime errors after SkeletonLabs is removed, we will then evaluate either upgrading to `v0.45.0` (with careful testing against Tailwind v4) or abandoning Flowbite-Svelte and replacing its components with custom ones. diff --git a/documentation/history/GEMINI_SkeletonLabs_upgrade_2025-12.md b/documentation/history/GEMINI_SkeletonLabs_upgrade_2025-12.md deleted file mode 100644 index 6617dd69..00000000 --- a/documentation/history/GEMINI_SkeletonLabs_upgrade_2025-12.md +++ /dev/null @@ -1,62 +0,0 @@ -# SkeletonLabs Upgrade Notes (December 2025) - -## Overview -This document tracks the process of upgrading the SkeletonLabs UI library (from v3 to v4.7.4) within the Aether SvelteKit project. The primary goal is to resolve build issues caused by incompatibility with Svelte 5 and Tailwind CSS v4, and to integrate the updated library correctly. - -## Current Status (Pre-Upgrade) -- **SkeletonLabs Version:** v3.2.2 (as per `package.json` at commit `90ee6bb1`) -- **Target Version:** v4.7.4 -- **Issue:** Previous attempts to upgrade SkeletonLabs to v4.7.4 resulted in a persistent, blocking build error: `[@tailwindcss/vite:generate:build] Cannot use `@variant` with unknown variant: md` originating from `node_modules/@skeletonlabs/skeleton/src/index.css`. This indicates a fundamental incompatibility in how Tailwind CSS v4 processes SkeletonLabs' pre-compiled CSS. -- **Svelte Version:** Svelte 5 (runes mode) -- **Tailwind CSS Version:** v4.1.10 - -## Phase 1: Research and Planning (No Code Changes Yet) - -### Goal -Understand the required migration steps from Skeleton v3 to v4 as per official documentation, specifically to address the `@variant` build error and ensure compatibility with Svelte 5 and Tailwind CSS v4. - -### Steps -1. **Thoroughly Review Skeleton v3 to v4 Migration Guide:** - * **Link:** `https://www.skeleton.dev/docs/svelte/get-started/migrate-from-v3` - * **Action:** Read the guide carefully to identify all breaking changes related to: - * Tailwind CSS plugin setup in `tailwind.config.ts`. - * Required changes to `app.css` or any other global CSS files. - * Changes in component class names, especially theme-related classes (`preset-*`, `variant-*`, etc.), which could be related to the `@variant` error. - * The new `Dialog` component and how it replaces any previous modal-like components. - * **Deliverable:** Summarize the required code changes based on this guide. - -2. **Review Skeleton v4.0 Launch Discussion:** - * **Link:** `https://github.com/skeletonlabs/skeleton/discussions/3920` - * **Action:** Look for community insights, common issues, and suggested solutions related to upgrading. - -3. **Review Skeleton Dialog Documentation:** - * **Link:** `https://www.skeleton.dev/docs/svelte/framework-components/dialog` - * **Action:** Understand the API and usage of Skeleton's native dialog component, as this will be the preferred replacement for any missing `` components. - -### Expected Outcome of Phase 1 -A detailed, step-by-step plan for migrating SkeletonLabs from v3 to v4, specifically targeting the resolution of the `@variant` build error and outlining the new usage of its UI components. This plan will be presented for approval before any code changes are made. - -## Phase 2: Execution (After Approval) - -### Steps (To be detailed after Phase 1) -1. **Update `package.json`:** Set `@skeletonlabs/skeleton` and `@skeletonlabs/skeleton-svelte` to `4.7.4`. -2. **Adjust `tailwind.config.ts`:** Apply changes as per migration guide (e.g., plugin configuration). -3. **Adjust `src/app.css`:** Apply changes as per migration guide (e.g., CSS imports, custom theme definitions). -4. **Run `npm install`**. -5. **Run `npm run build` and `npm run dev`** to verify the build and functionality. -6. **Replace `Modal` components:** Update existing components that used an older `` (e.g., from `flowbite-svelte` or previous custom efforts) with Skeleton's new `Dialog` component. -7. **Address Svelte 5 reactivity warnings:** Fix any warnings related to data handling or non-reactive updates. - -## Final Decision (2025-12-08) - -**Outcome:** Abandoning SkeletonLabs. - -**Reasoning:** -Despite following the official migration guide and attempting various configurations, the upgrade from SkeletonLabs v3 to v4.7.4 consistently fails with a blocking build error: `[@tailwindcss/vite:generate:build] Cannot use @variant with unknown variant: md`. This error points to a fundamental incompatibility between SkeletonLabs' pre-compiled CSS and the Tailwind CSS v4 build process in this Vite project. - -Given the significant time spent debugging this issue without a clear resolution path through configuration, the most pragmatic decision is to remove SkeletonLabs entirely and proceed with custom UI component implementation. - -**Path Forward:** -1. All SkeletonLabs dependencies (`@skeletonlabs/skeleton`, `@skeletonlabs/skeleton-svelte`) will be removed from `package.json`. -2. All SkeletonLabs configurations (e.g., in `tailwind.config.ts`, `app.css`) will be removed. -3. UI components previously provided by SkeletonLabs will be replaced with custom Svelte components styled with pure Tailwind CSS. diff --git a/documentation/history/GEMINI_debug_notes.md b/documentation/history/GEMINI_debug_notes.md deleted file mode 100644 index 0e96d210..00000000 --- a/documentation/history/GEMINI_debug_notes.md +++ /dev/null @@ -1,71 +0,0 @@ -# Skeleton/Tailwind Build Debugging Log - -This file tracks the troubleshooting steps taken to resolve the build and dev server errors after updating packages. - -## Initial State (Pre-Rollback to 90ee6bb1) - -- **Packages Updated:** Attempted to update `@skeletonlabs/skeleton` to `4.7.4`, `tailwindcss` to `4.1.10`, and `flowbite-svelte` (version not explicitly stated in previous logs but was part of the update attempts). -- **`dev` Error:** `Cannot apply unknown utility class 'preset-tonal-secondary'` -- **`build` Error:** `Cannot use @variant with unknown variant: md` -- **Dependency Conflicts:** Persistent `ERESOLVE` errors, primarily due to: - - `flowbite-svelte` versions compatible with Tailwind v3 requiring `svelte@^4.0.0` (while project is Svelte v5). - - `@skeletonlabs/skeleton` versions requiring `tailwindcss@^4.0.0` (while attempting to use Tailwind v3 for `flowbite-svelte` compatibility). -- **Conclusion:** A fundamental incompatibility between Svelte v5, Tailwind v4, and the existing versions of UI component libraries (Skeleton, Flowbite-Svelte) when trying to achieve a stable `npm install`. - -## Troubleshooting Steps (Pre-Rollback) - -(Summarized from previous extensive debugging logs) -- Multiple attempts to downgrade/upgrade Tailwind, Skeleton, and Flowbite-Svelte led to a "dependency nightmare." -- Identified that Flowbite-Svelte was the primary blocker for maintaining Svelte v5 compatibility while also using an older Tailwind. -- Attempted a strategy to remove *all* pre-built UI component libraries (Skeleton, Flowbite-Svelte) to achieve a clean Svelte v5 + Tailwind v4 base. This led to: - - `ReferenceError: Modal is not defined` due to the removal of the underlying `Modal` component. - - `` syntax error due to incorrect commenting out of the `` component's block. - - Server-side `500 Internal Error` (diagnosis interrupted by rollback decision). - -## Current State (Post-Rollback to 90ee6bb1) - -- **Commit:** `90ee6bb1 - All packages have now been updated. This includes the skeletonlabs packages. Everything seems to be working. (Except for some unrelated known bugs. Why did the badge search stop working (AGAIN)?)` -- **Status:** Application is confirmed to be "mostly working" at this commit. This provides a stable baseline. -- **Key Observation from Commit Message:** "All packages have now been updated. This includes the skeletonlabs packages. Everything seems to be working." This implies that at this point, the `skeletonlabs` packages *were* working with some configuration of Svelte and Tailwind. - -## Revised Path Forward: Re-evaluate UI Library Compatibility - -**Context:** The previous issues stemmed from an inability to reconcile `skeletonlabs/skeleton` (requiring Tailwind v4), `flowbite-svelte` (preferring Svelte v4 for Tailwind v3 compatibility), and the project's Svelte v5 base. Before attempting to re-implement all UI components from scratch, we will re-evaluate if the latest versions of these libraries have resolved their internal conflicts or if a stable configuration now exists. - -**Phase 1: Re-evaluate SkeletonLabs Compatibility (Primary Focus)** - -**Rationale:** Skeleton UI appears to be the most deeply integrated UI library in the project. If it can be made to work, it will significantly reduce the need for custom component development. - -1. **Update `GEMINI.md` and related notes:** (Completed in this step) Document this new strategy and the decision to re-evaluate packages. -2. **Create a new Git branch:** Name it `feature/re_evaluate_ui_libs`. (Pending) -3. **Identify latest compatible `@skeletonlabs/skeleton` and `skeleton-svelte` versions:** - * Consult their official documentation, release notes, and GitHub issues for compatibility with **Svelte v5** and **Tailwind CSS v4**. - * Determine if there's a specific version range that is known to work. -4. **Attempt to update SkeletonLabs packages (one at a time, or as a pair if tightly coupled):** - * Modify `package.json` to specify the identified compatible versions of `@skeletonlabs/skeleton` and `@skeletonlabs/skeleton-svelte`. - * Run `npm install`. - * Run `npm run build` and `npm run dev`. - * **Crucially:** Thoroughly check for *all* types of errors: - * Terminal errors (build, compilation, server-side). - * Browser console errors (client-side JS, hydration). - * Visual regressions or missing styles. - * **Document findings:** Note down exact errors or success status. -5. **If successful:** If SkeletonLabs works without major issues, proceed to Phase 2. -6. **If unsuccessful:** If significant conflicts or errors persist, revert changes on the branch and document the specific incompatibilities. This would then lead to immediately pursuing custom UI component implementation. - -**Phase 2: Address Other UI Library Needs (Conditional, based on Phase 1 outcome)** - -1. **If SkeletonLabs is working:** - * Re-evaluate the need for `flowbite-svelte`. Is its functionality still required, or is it covered by Skeleton UI or can be easily done with pure Tailwind? - * If still needed, attempt to update `flowbite-svelte` to the latest version, following the same cautious approach as with SkeletonLabs (package.json update, `npm install`, full testing). -2. **If SkeletonLabs (and/or Flowbite) cannot be made to work with Svelte v5 / Tailwind v4:** - * **Prioritize Custom Component Implementation:** Immediately proceed with implementing custom replacements, starting with critical components. The `element_modal_v1.svelte` (which was partially developed before the rollback) is a prime candidate for immediate completion and integration. - * **Identify other critical missing UI components:** Systematically list other essential components (e.g., dropdowns, tabs, accordions, cards, forms elements) that were previously provided by these libraries and prioritize their custom implementation using pure Tailwind CSS and native Svelte. Consider headless UI libraries (e.g., Headless UI, Radix UI) for complex components where accessibility and functionality are key without dictating styling. - -## User Request Confirmation - -- **Incompatibility of essential packages:** Confirmed. `flowbite-svelte` and `skeletonlabs/skeleton` were incompatible with Svelte v5 / Tailwind v4 in our previous attempts. We *will* safely double-check this as part of Phase 1 and 2. -- **CSS and missing style issues:** Confirmed. This was the direct consequence of removing the UI libraries. -- **`` component replacement:** Confirmed. This was our immediate focus for custom replacement. - -**The immediate next steps are to update my internal `GEMINI.md` for this project with this new plan and create the `feature/re_evaluate_ui_libs` branch.** \ No newline at end of file diff --git a/documentation/history/NATIVE_APP_AUTOMATION_SCRIPTS.md b/documentation/history/NATIVE_APP_AUTOMATION_SCRIPTS.md deleted file mode 100644 index 75fd071b..00000000 --- a/documentation/history/NATIVE_APP_AUTOMATION_SCRIPTS.md +++ /dev/null @@ -1,146 +0,0 @@ -# Specification: Aether Native Host Automation & Scripting - -**Target OS:** macOS (Primary), Linux/Windows (Secondary) -**Languages:** AppleScript (`osascript`), Bash (`sh`), Node.js `child_process` -**Implementation:** `src/main/shell_handlers.ts` (Electron App) - -## 1. Presentation Launch & Control (AppleScript) -To provide a seamless "Podium Experience," the app uses AppleScript to control third-party presentation software. - -### 1.1 Microsoft PowerPoint -* **Launch:** `powerpoint:launch` - ```applescript - tell application "Microsoft PowerPoint" - activate - open (POSIX file "[FILE_PATH]") - delay 1 - run slide show of active presentation - end tell - ``` -* **Control:** - * **Next:** `tell application "Microsoft PowerPoint" to next slide of slide show view of active presentation` - * **Prev:** `tell application "Microsoft PowerPoint" to previous slide of slide show view of active presentation` - * **Start:** `tell application "Microsoft PowerPoint" to run slide show of active presentation` - * **Stop:** `tell application "Microsoft PowerPoint" to stop slide show of active presentation` -* **Quit:** `quit application "Microsoft PowerPoint" saving no` - -### 1.2 Apple Keynote -* **Launch:** `keynote:launch` - ```applescript - tell application "Keynote" - activate - open (POSIX file "[FILE_PATH]") - delay 1 - start (front document) - end tell - ``` -* **Control:** - * **Next:** `tell application "Keynote" to show next` - * **Prev:** `tell application "Keynote" to show previous` - * **Start:** `tell application "Keynote" to start (front document)` - * **Stop:** `tell application "Keynote" to stop` - -### 1.3 Adobe Acrobat (PDF) -* **Launch:** `acrobat:fullscreen` - ```applescript - tell application "Adobe Acrobat Reader" - activate - -- Acrobat doesn't have a direct "Start Slideshow" AppleScript command - -- We use system events to trigger Cmd+L (Full Screen) - tell application "System Events" to keystroke "l" using {command down} - end tell - ``` - -### 1.4 LibreOffice (Linux Testing) -* **Launch:** `libreoffice:launch` - ```bash - libreoffice --impress "[FILE_PATH]" - ``` -* **Note:** LibreOffice control on Linux is currently limited to launch-only. - -## 2. Process Management (Bash/Node) -The app must ensure that only one presentation is "Active" to prevent audio overlap or confusion. - -| Action | macOS Command | Linux/Windows Mock | -| --- | --- | --- | -| **Kill Office** | `killall -INT "Microsoft PowerPoint"` | `pkill -f powerpnt` | -| **Kill Keynote**| `killall -INT "Keynote"` | `echo "Keynote Not Supported"` | -| **Kill Acrobat**| `killall -9 "Acrobat Reader"` | `pkill -f acroread` | -| **Kill Parallels**| `pkill -i -f '(Parallels).*(PowerPoint)'` | `N/A` | - -## 3. Recording Lifecycle (`aperture_wrapper`) -The app manages high-quality screen and audio recording using the `aperture` CLI or a custom wrapper. - -### 3.1 Start Recording -* **Intent:** `record:start` -* **Action:** Launch `aperture` as a child process. -* **Command Pattern:** - ```bash - aperture --fps 30 --highlight-clicks --audio-device "[DEVICE_ID]" --output "[PATH]/[SESSION_ID].mp4" - ``` -* **Telemetry:** Push `record_status: "Recording"` and the PID to the V3 API. - -### 3.2 Stop Recording -* **Intent:** `record:stop` -* **Action:** - 1. Send `SIGINT` (Interrupt) to the recorded process. - 2. Wait for file finalization. - 3. Verify file existence and minimum size. - 4. Push `record_status: "Idle"` to the V3 API. - -## 4. Host Hardening & "Odd Stuff" -Specialized scripts to ensure the Mac laptop behaves as a dedicated podium. - -### 4.1 Podium Lockdown (macOS) -* **Prevent Sleep:** `caffeinate -dis &` (Stores PID). -* **Volume Enforce:** `osascript -e "set volume output volume 100"` -* **Timezone Sync:** Force `America/New_York` (ET) for all device status pushes to ensure dashboard consistency. -* **Hide Menu Bar/Dock:** (Optional) Use `System Events` AppleScript to toggle auto-hide. - -### 4.2 Digital Poster Screen Saver -To prevent screen burn-in and provide branding when the podium is idle: -* **Idle Detection:** Uses `svelte-idle` to track user activity. -* **Action:** Automatically rotates through a random list of `event_file` objects marked as "poster". -* **Override:** Any mouse movement or click immediately kills the screen saver modal. - -### 4.3 WebSocket Remote Control (The "Tech Bridge") -Allows onsite staff to manage the podium without physical access. -* **Intents:** - * `ae_refresh:now`: Triggers a full page reload. - * `ae_native:cmd`: Executes a whitelisted shell command. - * `ae_open:event_file`: Remotely opens a specific presentation or image. - * `ae_record:start/stop`: Remotely toggles the Aperture wrapper. - -## 5. Accessibility & Permissions (macOS TCC) -Since this is a specialized app, we must handle Apple's TCC (Transparency, Consent, and Control) layer: -- **AV Access:** Use `systemPreferences.askForMediaAccess('camera')` and `microphone`. -- **Accessibility:** For remote control/automation, check `systemPreferences.isTrustedAccessibilityClient(true)`. -- **Screen Recording:** Triggered by the first `aperture` call; the app should provide a UI guide to help the user enable it in System Settings. -- **Check Command:** `osascript -e 'tell application "System Events" to get UI elements enabled'` - -## 6. Automation Strategy (The "Intent" Pattern) -To keep the bridge secure, we do **not** send raw scripts from the UI. Instead, we send an "Intent." - -**Renderer Call:** -```javascript -window.aetherNative.launch_presentation({ path: '/tmp/my_deck.pptx', app: 'powerpoint' }); -window.aetherNative.control_presentation({ app: 'powerpoint', action: 'next' }); -``` - -**Main Process Handler (`src/main/shell_handlers.ts`):** -1. Verify the file path is within the allowed `[tmp]` directory. -2. Select the corresponding AppleScript template based on `app` and `action`. -3. Replace `[FILE_PATH]` and execute via `child_process.exec`. - -## 7. Linux Development Mocking -Since development happens on Arch Linux, the `execIntent` handler will check `process.platform`: -- If `darwin`: Execute `osascript`. -- If `linux`: Use `libreoffice` for launch, or log intent for control commands. -- **Recording Mock:** Use `ffmpeg` or generate a fake `.mp4` file to test the sync/upload logic. - -## 8. Refresh & Sync Loops -Decoupled polling to balance performance and responsiveness: -- **Session Loop (30s):** High frequency for active podium changes. -- **Location Loop (2m):** Medium frequency for room configuration. -- **Device Loop (5m):** Low frequency for background heartbeat and telemetry. -- **Sync Loop (15m):** Background file warming for upcoming presentations. \ No newline at end of file diff --git a/documentation/history/NATIVE_APP_DEPLOYMENT_PLAN.md b/documentation/history/NATIVE_APP_DEPLOYMENT_PLAN.md deleted file mode 100644 index 4cea536a..00000000 --- a/documentation/history/NATIVE_APP_DEPLOYMENT_PLAN.md +++ /dev/null @@ -1,52 +0,0 @@ -# Deployment & Update Plan: Aether Native V3 - -**Mechanism:** Syncthing + Admin Share -**Target:** macOS Fleet -**Primary Controller:** `admin_share` directory - -## 1. Distribution via Syncthing -We will leverage the existing Syncthing mesh to distribute binaries and configurations. - -### 1.1 Directory Structure (Admin Share) -```text -admin_share/ -├── configs/ -│ └── seed_[DEVICE_ID].json # Specific seed files for auto-provisioning -├── binaries/ -│ └── native_app/ -│ ├── version.json # Latest version metadata -│ └── Aether_Native.app/ # The macOS App Bundle (or .zip) -└── scripts/ - └── update_helper.sh # macOS script to swap binaries -``` - -## 2. Self-Update Protocol -The V3 app will monitor for updates without relying on external internet access (perfect for isolated event networks). - -### 2.1 The Update Flow -1. **Check:** On launch (and periodically), the app reads `admin_share/binaries/native_app/version.json`. -2. **Compare:** If `version.json > package.json`, the app signals the user: "Update Available". -3. **Stage:** The app copies the new `.app` bundle from the sync folder to a local `~/Library/Caches/Aether/updates/` directory. -4. **Swap:** The app launches `update_helper.sh` and exits. The script moves the new version into `/Applications/` and restarts the app. - -## 3. Provisioning (The "Seed" Strategy) -To set up a new laptop: -1. Install Syncthing and link the `admin_share`. -2. The Electron app looks for `admin_share/configs/seed_$(hostname).json`. -3. If found, it copies it to its local config path and bootstraps itself. -4. **Result:** Zero manual configuration for the onsite tech. - -## 4. macOS Specific Lifecycle -- **Gatekeeper:** Since these are distributed via Syncthing, we must handle the "App is damaged or from an unidentified developer" prompt. -- **Plan:** Include a `post-sync` script that runs `xattr -rd com.apple.quarantine` on the binary folder within the admin share (if permissions allow) or instructs the user on the first run. - -## 5. Development Workflow (Arch Linux -> Mac) -1. **Build:** On Arch Linux, run `npm run build:mac`. -2. **Package:** Use `electron-packager` to create the macOS `.app` bundle. -3. **Distribute:** Move the built `.app` into the local Syncthing `admin_share` folder. -4. **Verify:** Watch the fleet of Macs automatically pull the update via Syncthing. - -## 6. Project Document Updates -The following files have been updated to reflect this deployment strategy: -- `NATIVE_APP_V3_REWRITE_PLAN.md`: Added self-update logic requirements. -- `NATIVE_BRIDGE_INTERFACE_SPEC.md`: Added `ae_sys.checkForUpdates()` method. diff --git a/documentation/history/NATIVE_APP_FUNCTIONAL_SPEC.md b/documentation/history/NATIVE_APP_FUNCTIONAL_SPEC.md deleted file mode 100644 index ae3a793b..00000000 --- a/documentation/history/NATIVE_APP_FUNCTIONAL_SPEC.md +++ /dev/null @@ -1,75 +0,0 @@ -# Functional Specification: Aether Native App (Electron) - -**Date:** 2026-01-30 -**Status:** V5 / Phase 5 Specification -**Target OS:** macOS (Primary), Linux/Windows (Secondary) - -## 1. Core Objectives -The Native App acts as a "Privileged Shell" for the Aether SvelteKit UI, providing capabilities that standard web browsers block for security reasons. It turns a standard laptop into a managed "Podium Kiosk." - -## 2. macOS Permission Matrix (TCC) -To function as a podium controller, the Electron app requires specific entitlements. - -| Permission | Reason | Criticality | -| :--- | :--- | :--- | -| **Accessibility** | Required to send AppleScript commands (Next/Prev) to Keynote and PowerPoint. | **CRITICAL** | -| **Screen Recording** | Required by the `aperture` utility to record the presentation session. | **CRITICAL** | -| **Microphone** | Required to capture room audio/presenter voice during recording. | **CRITICAL** | -| **Camera** | Optional, only if "Presenter View" (PiP) recording is enabled. | Low | -| **Automation** | Allows the app to control "System Events", "Finder", "Keynote", and "Microsoft PowerPoint". | **CRITICAL** | -| **Full Disk Access** | Recommended to ensure access to `~/OSIT` and `~/Downloads` without nagging prompts. | High | - -## 3. Handler Registry (V5) -The following IPC handlers are exposed via `window.aetherNative`. - -### 3.1 File & Cache System -| Handler | Description | -| :--- | :--- | -| `native:check-cache` | Verifies file existence in the sharded local cache (`~/OSIT/native_app/cache/xx/hash.file`). | -| `native:download-to-cache` | Streams a file from the API to the local cache with SHA-256 verification. | -| `native:launch-from-cache` | **Atomic Launch:** Copies file from cache -> temp with original filename -> launches app. | - -### 3.2 Automation & Control (Phase 5) -| Handler | Description | -| :--- | :--- | -| `native:launch-presentation` | Opens a file using the specific app (Keynote/PPT) with "Slide Show" mode enabled immediately. | -| `native:control-presentation` | Sends navigation commands: `next`, `prev`, `start`, `stop`. | -| `native:kill-processes` | Force quits applications by name (e.g., "Microsoft PowerPoint") to resolve freezes. | - -### 3.3 System Management (New Requirements) -These handlers are required for full "Kiosk" management. - -| Handler | Description | Implementation Note | -| :--- | :--- | :--- | -| `native:set-wallpaper` | Resets desktop background to a specific image. | AppleScript: `tell application "System Events" to set picture of every desktop...` | -| `native:update-app` | Checks `~/OSIT/admin_share/...` for newer versions and self-updates. | Requires specific logic to swap the `.app` bundle and restart. | -| `native:window-control` | Controls the Electron window: `maximize`, `minimize`, `kiosk`, `devtools`. | Direct Electron `BrowserWindow` API calls. | -| `native:manage-recording` | Controls `aperture` process: `start`, `stop`, `status`. | Must track the PID of the spawned recording process. | -| `native:set-display-layout` | Toggles between **Mirror** and **Extended** modes. | Use bundled `displayplacer` binary (AppleScript is unreliable for this). | -| `native:power-control` | Initiates `shutdown` or `restart`. | Command: `shutdown -h now` (may require admin/sudo setup or user-level fallback). | -| `native:open-external` | Opens a URL in a specific browser (Chrome/Firefox). | `spawn('open', ['-a', 'Google Chrome', url])`. | - -## 4. Feature Specifications - -### 4.1 Self-Update Strategy -1. **Path:** `~/OSIT/Speaker Ready System/Admin Share/Custom Applications/osit_binaries/` -2. **Logic:** - * Compare `package.json` version in running app vs. remote path. - * If remote > local: - * Display "Updating..." splash. - * Copy new `.app` to `/Applications` (or current location). - * Relaunch. - -### 4.2 Web Page Handling -The Launcher avoids Safari. -* **Strategy A (Simple):** `native:open-external` -> Opens in Google Chrome Kiosk Mode (`--kiosk`). -* **Strategy B (Integrated):** Use an Electron `BrowserView` (not `iframe`) to render the website *inside* the Aether window, ensuring we keep the "Back" button overlay visible. - -### 4.3 Display Layouts -To reliably switch between Mirroring (for setup) and Extended (for presentation): -* **Tool:** Bundle **`displayplacer`** (Homebrew utility) inside `resources/bin`. -* **Command:** `displayplacer "id:
res:1920x1080" "id: res:1920x1080 origin:(1920,0)"` (Example). - -## 5. Security Guardrails -* **IPC Whitelisting:** All `run-cmd` calls are deprecated in favor of specific named handlers (e.g., `set-wallpaper`) to prevent arbitrary command execution. -* **Path Validation:** All file operations must be restricted to `~/OSIT` or `~/tmp` directories. diff --git a/documentation/history/NATIVE_APP_V3_API_PAYLOAD.md b/documentation/history/NATIVE_APP_V3_API_PAYLOAD.md deleted file mode 100644 index 69ca8cc0..00000000 --- a/documentation/history/NATIVE_APP_V3_API_PAYLOAD.md +++ /dev/null @@ -1,91 +0,0 @@ -# Specification: Aether V3 API Device Config Payload - -**Endpoint:** `GET /v3/crud/event_device/{id_random}?view=native_bootstrap` -**Goal:** Provide full operational context to an Electron instance with zero local configuration. - -## 1. Response Structure (Draft) - -```json -{ - "status": "success", - "data": { - "identity": { - "device_id_random": "GZvFjgIIZQg", - "device_code": "macbook_air_scott_idem", - "account_id_random": "xFP7AhU8Zlc", - "event_id_random": "UFu-gF-rZ-ws", - "location_id_random": "PFGP-37-81-80" - }, - "network": { - "api_base_url": "https://api.oneskyit.com", - "file_server_url": "https://files.oneskyit.com", - "heartbeat_interval_ms": 30000 - }, - "filesystem": { - "cache_path": "[home]/Library/Caches/OSIT/file_cache", - "temp_path": "[home]/tmp/OSIT/temp", - "use_sharding": true, - "verify_on_launch": true - }, - "launcher": { - "app_mode": "native", - "auto_start_slideshow": true, - "prevent_sleep": true, - "whitelisted_apps": ["PowerPoint", "Keynote", "Acrobat Reader"] - }, - "ui_prefs": { - "theme_name": "cerberus", - "theme_mode": "dark", - "show_clock": true, - "show_admin_tools": false - } - } -} -``` - -## 2. Key Payload Fields - -### 2.1 Identity & Scoping -- `account_id_random`: Automatically scopes all subsequent V3 API calls for the SvelteKit UI. -- `location_id_random`: Locks the UI to a specific room/podium. - -### 2.2 Filesystem Strategy -- `cache_path`: Uses the `[home]` placeholder. The Electron Main process will resolve this to the local user profile. -- `use_sharding`: Tells the Sync Engine to use the `/ab/abcdef...` directory structure. - -### 2.3 Automation Whitelist -- To prevent security risks, the `launcher` object defines exactly which applications the native shell is allowed to "Kill" or "Open". - -## 3. Telemetry & Heartbeat (Push Strategy) -To support the onsite dashboard (`src/routes/events/.../device`), the Electron app must push its status back to the server. - -### 3.1 Heartbeat Payload (`PATCH /v3/crud/event_device/{id}`) -```json -{ - "heartbeat": "2026-01-20T14:30:00Z", - "status": "Online", - "status_msg": "Presentation: 'Introduction to AE.pptx' (Slide 4/20)", - "record_status": "Idle", - "info_ip_list": "192.168.1.10, 10.0.0.5", - "meta_json": { - "cpu_usage": 12, - "memory_free_gb": 4.2, - "sync_progress": 100, - "foreground_app": "PowerPoint", - "is_fullscreen": true - } -} -``` - -## 4. The "Bootstrap Paradox" Resolution -To allow unauthenticated config fetching for new devices: -1. **Device API Key:** Each device record in the DB has an `api_secret_key`. -2. **Initial Header:** The Electron app sends `x-aether-device-key: ` in the bootstrap request. -3. **JWT Hand-off:** The response `meta` will contain a short-lived JWT that the app uses to authenticate its first "Real" V3 requests. - -## 5. Database Mapping (V3 Enriched View) -The `v_event_device` SQL view must be updated to include: -- `account_id_random` (joined from `account`) -- `event_id_random` (joined from `event`) -- `location_id_random` (joined from `event_location`) -- `theme_name` (joined from `site_cfg_json` via `account`) diff --git a/documentation/history/NATIVE_APP_V3_REWRITE_PLAN.md b/documentation/history/NATIVE_APP_V3_REWRITE_PLAN.md deleted file mode 100644 index a6f836ba..00000000 --- a/documentation/history/NATIVE_APP_V3_REWRITE_PLAN.md +++ /dev/null @@ -1,166 +0,0 @@ -# Project Plan: Aether Native V3 Rewrite - -**Target:** Electron 33+ -**Primary Platform:** macOS (Production) -**Development Platform:** Arch Linux -**API Version:** Aether V3 (REST + JWT) - -## 0. Project Purpose -The sole purpose of this Native App is to serve as the **AE Events Launcher**. It provides the SvelteKit frontend with the ability to: -- Persistently cache files in the local filesystem. -- Execute OS-level shell commands and scripts (e.g., launching presentation software). -- Provide a "Zero-Config" experience for onsite event laptops. - -### 0.1 Application Modes -The system must support three distinct operational modes: - -| Mode | Refresh Logic | File Handling | -| --- | --- | --- | -| **Default** | Slower auto-refresh timers. | Standard browser downloads. No local caching. | -| **Onsite** | Faster auto-refresh timers. | Downloads files with modified extensions (e.g., .pptxwin). | -| **Native** | Fastest auto-refresh timers. | Full background pre-caching. Launching from local temp directory with original names. | - ---- - -## 1. Minimalist Configuration Strategy -To simplify laptop deployment, we will move away from large local JSON files. - -### 1.1 The "Seed" Config -Each laptop will contain a `seed.json`. For development, this is located at `~/seed.json`. In production, it will move to standard OS config paths (e.g., `~/.config/aether/seed.json` or `~/Library/Application Support/Aether/`). - -```json -{ - "event_device_id": "dbgMWS3KEHE", - "primary_api_base_url": "https://dev-api.oneskyit.com", - "backup_api_base_url": null, - "onsite_api_base_url": null, - "aether_api_key": "INSdG85ANwsEIru3nUttMw" -} -``` -*Note: only `event_device_id` is strictly required for the bootstrapper to start.* - -### 1.2 The Bootstrap Flow -1. **Launch:** Electron reads the `seed.json`. -2. **Identity:** App calls `GET /v3/crud/event_device/{id}`. -3. **Hydrate:** App uses `app_base_url` from the device record to search for the corresponding `site_domain`. -4. **Target URL:** Electron constructs the launcher URL: - `http://[app_base_url]/events/[event_id]/launcher/[event_location_id]` -5. **Inject:** Config and JWT are injected into the SvelteKit frontend via the Preload script. - -### 1.3 Technical Flow: Startup & Background Caching -The system utilizes a multi-layered hydration and synchronization strategy to ensure files are available instantly. - -#### Step 1: Zero-Config Initialization (Main Process) -- **Seed Discovery:** Main process reads `seed.json`. -- **Identity Exchange:** Main process authenticates with the API using the `aether_api_key`. -- **Global Injections:** Once hydrated, the Main process provides the SvelteKit frontend with: - - `native_device`: Full record from `event_device` table (contains timers). - - `aether_api_key`: For authorized background downloads. - - `local_file_cache_path`: Root for the permanent hashed cache. - - `host_file_temp_path`: Root for the operational launch directory. - -#### Step 2: Session-Driven Caching (Renderer Process) -- **View Trigger:** When a user navigates to a session or location, the SvelteKit frontend populates the `event_file_obj_li` store. -- **Sync Cycle:** The `LauncherBackgroundSync` component detects the new file list and: - 1. Extracts all `event_file_id` values. - 2. Fetches full metadata (hashes) from the local Dexie IndexedDB. - 3. Asynchronously checks the Native Cache for each hash. -- **Background Download:** Missing files are downloaded directly to the hashed cache using the authorized Native API Key. -- **Timer Loop:** A background loop runs every `check_event_loop_period` (configurable via API) to ensure the cache stays in sync with server-side changes. - -#### Step 3: Hashed Cache Pattern (Filesystem) -To prevent filename collisions and handle versioning, the permanent cache follows the server's structure: -- **Root:** `[local_file_cache_path]` -- **Subdirectory:** First 2 characters of SHA256 (e.g., `ab/`) -- **Filename:** Full SHA256 with `.file` extension (e.g., `abc123...file`) - -#### Step 4: Safe Handover (Launch Sequence) -When a user clicks "Open", the system follows a non-destructive handover: -1. **Verify:** Confirm hash exists in `local_file_cache_path`. -2. **Prepare:** Copy the hashed file to `host_file_temp_path`. -3. **Restore:** Rename the copy back to its original filename (e.g., `Presentation.pptx`). -4. **Execute:** Trigger OS-level `shell.openPath()` on the temp file. -*This ensures the permanent cache remains clean while the third-party app (PowerPoint, etc.) can operate on a file with a familiar name.* - -### 1.3 Technical Flow: Startup & Background Caching -The system utilizes a multi-layered hydration and synchronization strategy to ensure files are available instantly. - -#### Step 1: Zero-Config Initialization (Main Process) -- **Seed Discovery:** Main process reads `seed.json`. -- **Identity Exchange:** Main process authenticates with the API using the `aether_api_key`. -- **Global Injections:** Once hydrated, the Main process provides the SvelteKit frontend with: - - `native_device`: Full record from `event_device` table (contains timers). - - `aether_api_key`: For authorized background downloads. - - `local_file_cache_path`: Root for the permanent hashed cache. - - `host_file_temp_path`: Root for the operational launch directory. - -#### Step 2: Session-Driven Caching (Renderer Process) -- **View Trigger:** When a user navigates to a session or location, the SvelteKit frontend populates the `event_file_obj_li` store. -- **Sync Cycle:** The `LauncherBackgroundSync` component detects the new file list and: - 1. Extracts all `event_file_id` values. - 2. Fetches full metadata (hashes) from the local Dexie IndexedDB. - 3. Asynchronously checks the Native Cache for each hash. -- **Background Download:** Missing files are downloaded directly to the hashed cache using the authorized Native API Key. -- **Timer Loop:** A background loop runs every `check_event_loop_period` (configurable via API) to ensure the cache stays in sync with server-side changes. - -#### Step 3: Hashed Cache Pattern (Filesystem) -To prevent filename collisions and handle versioning, the permanent cache follows the server's structure: -- **Root:** `[local_file_cache_path]` -- **Subdirectory:** First 2 characters of SHA256 (e.g., `ab/`) -- **Filename:** Full SHA256 with `.file` extension (e.g., `abc123...file`) - -#### Step 4: Safe Handover (Launch Sequence) -When a user clicks "Open", the system follows a non-destructive handover: -1. **Verify:** Confirm hash exists in `local_file_cache_path`. -2. **Prepare:** Copy the hashed file to `host_file_temp_path`. -3. **Restore:** Rename the copy back to its original filename (e.g., `Presentation.pptx`). -4. **Execute:** Trigger OS-level `shell.openPath()` on the temp file. -*This ensures the permanent cache remains clean while the third-party app (PowerPoint, etc.) can operate on a file with a familiar name.* - -## 2. macOS Hardening (Permissions) -... -macOS requires explicit user consent for several features. The new app will handle these during the "Splash Screen" phase. - -- **AV Access:** Use `systemPreferences.askForMediaAccess('camera')` and `microphone`. -- **Accessibility:** For remote control/automation, check `systemPreferences.isTrustedAccessibilityClient(true)`. -- **Screen Recording:** Required for the presentation tracker. We will use a "Check and Prompt" loop. - -## 3. Cross-Platform Handling -| Feature | macOS (Production) | Linux/Windows (Dev/Comp) | -| --- | --- | --- | -| **Process Kill** | `killall -INT "PowerPoint"` | `pkill -f "powerpnt.exe"` | -| **Automation** | AppleScript (`osascript`) | Mocked via logs or Shell commands. | -| **Paths** | `~/Library/Caches/Aether` | `~/.cache/aether` | -| **Window** | Frameless, Transparent support. | Standard decorated window. | - -## 4. Proposed Directory Structure -```text -aether_app_native_v3/ -├── src/ -│ ├── main/ -│ │ ├── index.ts # Window lifecycle -│ │ ├── ipc_handlers.ts # Whitelisted OS commands -│ │ ├── macos_perms.ts # Mic/Cam/Accessibility logic -│ │ └── api_client.ts # V3 Auth & Config sync -│ ├── preload/ -│ │ └── index.ts # Secure ContextBridge -│ └── shared/ -│ └── types.ts # TS Interfaces for the bridge -├── resources/ # Icons and splash screens -└── electron-builder.yml # Multi-platform build config -``` - -## 5. Security Upgrades -1. **JWT Storage:** Store the session token in Electron's `safeStorage` (OS-level encryption) rather than simple `localStorage`. -2. **Navigation Lock:** Prevent the SvelteKit UI from navigating away from the Aether domain. -3. **Command Whitelisting:** Instead of a generic `run_cmd`, implement specific handlers like `native:launch-presentation` which only accepts a file hash. - -## 6. Deployment & Self-Update -To support onsite deployment via Syncthing: -1. **Version Watcher:** Main process monitors `admin_share/binaries/native_app/version.json`. -2. **Atomic Swap:** Use a dedicated `update_helper.sh` to swap the `.app` bundle while the app is closed. -3. **Zero-Touch Provisioning:** Auto-copy `seed_[hostname].json` from the sync share if local config is missing. - -## 7. Development Tools (Arch Linux) -- Use `fakeroot` and `binutils` to package for macOS on Linux. -- Use `Xvfb` for headless testing of Electron windows in CI/CD. diff --git a/documentation/history/NATIVE_BRIDGE_INTERFACE_SPEC.md b/documentation/history/NATIVE_BRIDGE_INTERFACE_SPEC.md deleted file mode 100644 index 19ab5a51..00000000 --- a/documentation/history/NATIVE_BRIDGE_INTERFACE_SPEC.md +++ /dev/null @@ -1,74 +0,0 @@ -# Specification: Aether Native V3 Bridge Interface - -**Namespace:** `window.native_app` -**Security:** Context Isolated, Sandboxed IPC - -## 1. Device & Identity (`ae_device`) -Functions for bootstrapping the app from the `seed.json`. - -| Method | Type | Description | -| --- | --- | --- | -| `getSeed()` | `() => Promise` | Returns the local `event_device_id` and `api_base_url`. | -| `getDeviceInfo()` | `() => Promise` | Returns OS, Arch, and unique hardware UUID. | -| `getPermissions()`| `() => Promise` | Returns status of Mic, Camera, and Accessibility. | -| `requestAccess()` | `(type: string) => Promise` | Triggers macOS TCC permission prompts. | - -## 2. Sync Engine (`ae_sync`) -The Sync Engine manages the "Cold Cache" (`~/Library/Caches/Aether/`). It handles atomic downloads and hash verification. - -| Method | Type | Description | -| --- | --- | --- | -| `getCacheStatus()` | `(file_hash: string) => Promise` | Checks if a file exists and is valid. | -| `startSync()` | `(task: SyncRequest) => Promise` | Begins background download of a presentation. | -| `cancelSync()` | `(file_hash: string) => Promise` | Aborts an active download. | -| `clearCache()` | `() => Promise` | Wipes the cold cache (Maintenance). | - -### Events (Main -> Renderer) -- `sync:progress`: `{ hash, percent, speed, bytesLoaded }` -- `sync:complete`: `{ hash, success, error }` - -## 3. Launcher (`ae_launcher`) -The "Big Red Button" logic. Handles the hand-off to the OS. - -| Method | Type | Description | -| --- | --- | --- | -| `launch()` | `(req: LaunchRequest) => Promise` | 1. Moves file to Temp. 2. Opens with default app. 3. Starts slideshow. | -| `killApp()` | `(appName: string) => Promise` | Closes PowerPoint/Keynote/Acrobat gracefully. | -| `preventSleep()` | `(enable: boolean) => Promise` | Prevents the laptop from sleeping during a session. | - -## 4. System Control (`ae_sys`) -Low-level macOS/Windows/Linux wrappers. - -| Method | Type | Description | -| --- | --- | --- | -| `setVolume()` | `(level: number) => Promise` | Sets system master volume (0-100). | -| `checkForUpdates()`| `() => Promise` | Checks the Syncthing share for a newer version. | -| `applyUpdate()` | `() => Promise` | Triggers the `update_helper.sh` and exits. | -| `execIntent()` | `(intent: string, args: any) => Promise` | Executes a whitelisted command (e.g. `open-logs-folder`). | - ---- - -## 5. TypeScript Interface (Draft) - -```typescript -export interface AE_Native_Bridge { - device: { - getSeed: () => Promise<{ device_id: string; api_url: string }>; - requestPermissions: () => Promise; - }; - sync: { - getStatus: (hash: string) => Promise<{ exists: boolean; verified: boolean }>; - queueDownload: (payload: { url: string; hash: string; jwt: string }) => void; - }; - launcher: { - launch: (file: { hash: string; name: string; type: 'pptx'|'key'|'pdf' }) => Promise; - killAll: () => Promise; - }; -} -``` - -## 6. Podium Reliability Protocol -To ensure the podium never fails: -1. **Pre-Flight Check:** The SvelteKit UI will call `sync.getStatus` for every file in the session as soon as the page loads. -2. **Auto-Warmup:** If a file is missing, the UI automatically calls `sync.queueDownload` in the background. -3. **Verification:** The `launcher.launch` command will perform a final `sha256` check on the temp file *before* executing `shell.openPath`. diff --git a/documentation/history/OLD__README__Guidelines_UI_UX.md b/documentation/history/OLD__README__Guidelines_UI_UX.md deleted file mode 100644 index 650e3a3e..00000000 --- a/documentation/history/OLD__README__Guidelines_UI_UX.md +++ /dev/null @@ -1,137 +0,0 @@ -# AE UI Components, Layout, and Style Standards (HTML/CSS) - -## Aether Components - -### System Components - -- [header] -- [main/module]s -- [footer] -- [app] refresh, clear IDB, clear local storage (settings), iframe toggle (also updates URL param), copy URL, generate and show QR -- [menu][mode] edit, more (all or details) -- [menu][access_type] passcode input, clear -- [menu][user] sign in/out, reset password, email link, change username and email -- [menu][theme] mode (light/dark), name (theme list) -- [debug] toggle (also updates URL param), show core and module storages, manually set init timestamp -- [scroll_to] top, page up, page down, bottom - -### Core Components - -- [copy_btn] clipboard, bind:value, btn_text, btn_html -- [txt_editor] textarea -- [md_editor] CodeMirror, ShadEditor TipTap (need to remove) -- [html_editor] -- [media_player] - - hosted_file archive_content media_player, - - bind:host_id, - - bind:media_type - - status - stopped, paused, playing -- [hosted_file_li] manage_hosted_file_li, make available for selection -- [hosted_file_link_to] list links per object, bind:add link, bind:remove link -- [upload_to_host] - input_hosted_file; needs to handle multiple files - - link_type, - - link_id, - - inner fragment - label html - - bind:trigger - - bind:show_spinner - - bind:show_percent - - status - - result - started, uploading, finished -- [upload_file_tbl] input_hosted_file_tbl, check for dup file hash, remove from list -- [download_from_host] - - bind:host_file_id - - bind:filename - - bind:file_ext - - btn inner fragment - - bind:trigger - - bind:show_spinner - - bind:show_percent - - status - - result - started, downloading, finished -- [data_store] -- [ae_crud] need to simplify! obj, prop, current_value, bind:value, bind:trigger, inner fragment -- [ae_obj_prop_val] - essentially a wrapper for the function - - bind:obj_type - - bind:obj_id - - bind:obj_prop - - bind:obj_value - - bind:obj_new_value - - bind:trigger - - bind:show_spinner - - bind:show_percent - - status - - result -- [sql_qry] -- [obj_tbl] obj sql results tbl or similar -- [qr_scanner] -- [websocket] - -### Main / Module Components - -- [menu][options] various settings, show/hide content and options, limit, sorting options, etc -- [menu][actions] various actions, sign in/out, email - -### Object Menu - -- properties: id, name, group, priority, sort, alert, hide, enable, note -- future properties: ext_id (not ready yet), ext_sys_id (not ready yet), code (not ready yet) -- actions: create, view, edit, update, hide, disable, delete, alert (message), archive (not ready yet) -- future actions: copy, import -- sort options: - - [default] group > priority > sort (ASC/DESC) > alert > name - - [sort_updated] group > priority > sort (ASC/DESC) > alert > updated_on > created_on - - [priority_updated] group > priority > updated_on (ASC/DESC) > created_on - - [priority_name] group > priority > name (ASC/DESC) > sort > alert > updated_on > created_on - - [name] priority > name (ASC/DESC) > sort > alert > updated_on > created_on - - [created_on] priority > created_on (ASC/DESC) - - [updated_on] priority > updated_on (ASC/DESC) > created_on - -### Pop-ups: - -- modal_header - - title - - close -- modal_main -- modal_meta -- modal_footer - - close - -#### Pop-up Modal (blocking) - -- modal position - -#### Pop-up Modal Inline - -- inline, inline-block, block - -#### Pop-up Dialog - -- dialog position - -## Containers - -### Navigation - -- link -- download - -### Forms - -- save -- clear value -- set null value - -### Other Containers - -- help - blue -- info - blue -- alert - yellow -- warning - orange -- error - red -- message - green - ---- - -## Need to organize: - -- lu: id, account_id, for_obj_id, code, name, description, group, sort, priority, enable, perm_level diff --git a/documentation/history/OLD__README__Guidelines_v1.md b/documentation/history/OLD__README__Guidelines_v1.md deleted file mode 100644 index 82f4192b..00000000 --- a/documentation/history/OLD__README__Guidelines_v1.md +++ /dev/null @@ -1,80 +0,0 @@ -# One Sky IT's Aether App - UI and UX Guidelines and Rules - -## General - -### Events - -#### layout header - -#### layout footer - -### Journals - -#### buttons - -##### alert - -##### info - -##### priority, flag - -##### warning, hide - -```css -variant-soft-warning hover:variant-filled-warning -``` - -##### error, delete, disable - -```css -variant-soft-error hover:variant-filled-error -``` - -#### new root layout header - -#### submenu - -```css -flex flex-row items-center justify-center gap-1 -``` - -#### new layout footer - -## Svelte 5 and SvelteKit v2 (framework and routing) - -## Tailwind 3.x CSS (styles) - -Waiting to upgrade to 4.x when ShadCN is ready. ShadCN is still being worked on as of late March 2025. - -- https://ui.shadcn.com/docs/tailwind-v4 - -## CodeMirror 6.x (text and code editor) - -- https://codemirror.net - -## ShadCN (Tailwind Components) - -- https://ui.shadcn.com/docs -- https://github.com/shadcn-ui/ui - -## Skeleton (Design System, Tailwind Components, Functional Components) - -Waiting to upgrade to Skeleton v3. Mostly because of the Tailwind 4.x upgrade needed for ShadCN. - -- https://www.skeleton.dev/docs/get-started/migrate-from-v2 - -## Flowbite (Tailwind Components) - -## Lucide Icons (SVG Icons) - -- https://lucide.dev/icons/ - -## Markdown - -Using marked for Markdown parsing. - -- https://marked.js.org/ - -## Edra (TipTap based Rich Text Editor) - -- https://edra.tsuzat.com/ diff --git a/documentation/history/OLD__README__Guidelines_v2.md b/documentation/history/OLD__README__Guidelines_v2.md deleted file mode 100644 index e167724e..00000000 --- a/documentation/history/OLD__README__Guidelines_v2.md +++ /dev/null @@ -1,173 +0,0 @@ -# AE Svelte and SvelteKit Technical Standards - -## Official Modules - -### Core - -- Accounts - Minimal -- Files -- People - Minimal -- Sites - Minimal -- Users - Minimal - -### Extended - -Archives - Minimal, Events - Badges, Events - Presentation Management, Posts - Minimal, Journals - -### Custom - -IDAA - Archives, IDAA - BB, IDAA - Recovery Meetings - ---- - -## localStorage: - -- api -- app - global -- core - core modules -- [module] - extended modules -- [custom] - custom modules - ---- - -## Indexed DB - -- ae_core_db -- [module] -- [custom] - custom modules: none currently - ---- - -## Data Sorting - -- group > priority > sort > updated/created on -- type > start date/time > code or name - ---- - -## Objects - -### Function - Obj Prop Update - -- obj_type -- obj_id -- obj_prop -- obj_value - -### Core - -### Extended - -### Custom - ---- - -## Object Properties or Fields - -### Core - -Expected standard field names: id, id_random, [obj-type]\_id_random, code, name, enable, hide, priority, sort, group, notes, created_on, updated_on -Special use field names: for_type, for_id, archive_on, passcode, external_id - -### Configs and Fields with JSON - -- cfg_json -- data_json -- linked_li_json - -### Special Generated Fields - -tmp_sort_1, tmp_sort_2, - -### Future standard fields!!! - -obj_id?: null|string; -obj_ext_uid?: null|string; // Probably not needed for journals -obj_ext_id?: null|string; // Probably not needed for journals -obj_import_id?: null|string; // Probably not needed for journals -obj_code?: null|string; -obj_account_id?: null|string; -obj_passcode?: null|string; -obj_type?: null|string; // Should always be 'journal' in this case -obj_type_ver_id?: null|string; // The ID from the table for the object type -obj_name?: null|string; -obj_summary?: null|string; // LLM (AI) generated summary...??? -obj_outline?: null|string; // LLM (AI) generated outline...??? -obj_description?: null|string; // Probably not needed for journals -obj_enable?: null|boolean; -obj_enable_on?: null|Date; -obj_archive_on?: null|Date; -obj_hide?: null|boolean; -obj_priority?: null|number; -obj_sort?: null|number; -obj_group?: null|string; -obj_cfg_json?: null|string; -obj_notes?: null|string; -obj_created_on?: Date; -obj_updated_on?: null|Date; - -## Dixie IDB liveQuery with Select Objects (slct) and Lists of Objects (slct_x_li) - -Use this method below to create a read/write snapshot of the current liveQuery results. This allows you to use it as part of a form and binding values. It might make since to call this something like "lqw**x_obj" and "lqw**x_obj_li". lqw = liveQuery writable - -lq**xyz_obj - Use for general read only -lqw**xyz_obj - Use for forms and binding values. What happens if the actual LQ obj is updated after the bind? -$slct or $lqw ? - -Sort of related.... more permission/security though: Create a new table that will be attached to every v\_ view in the DB. This new table would be a field permission list. It could work similar to the data_store table and related view. This seems like a good idea????? 2025-08-11 - -```ts -let lq__post_obj = $derived( - liveQuery(async () => { - if (log_lvl) { - console.log(`lq__post_obj: post_id = ${$idaa_slct?.post_id}`); - } - let results = await db_posts.post.get($idaa_slct.post_id ?? ''); // null or undefined does not reset things like '' does - - // Check if results are different than the current $idaa_slct.post_obj - if ($idaa_slct.post_obj && results) { - if (JSON.stringify($idaa_slct.post_obj) !== JSON.stringify(results)) { - $idaa_slct.post_obj = { ...results }; - if (log_lvl) { - console.log(`$idaa_slct.post_obj = `, $idaa_slct.post_obj); - } - } else { - if (log_lvl) { - console.log(`Post object has not changed for post_id: ${$idaa_slct.post_id}`); - } - } - } - - return results; - }) -); - -let lq__post_comment_obj_li = $derived( - liveQuery(async () => { - let results = await db_posts.comment - .where('post_id') - .equals($idaa_slct.post_id ?? '') // null or undefined does not reset things like '' does - .reverse() - .sortBy('updated_on'); - // .sortBy('title'); - - if ( - $idaa_slct.post_comment_obj_li && - JSON.stringify($idaa_slct.post_comment_obj_li) !== JSON.stringify(results) - ) { - $idaa_slct.post_comment_obj_li = [...results]; - if (log_lvl) { - console.log(`$idaa_slct.post_comment_obj_li = `, $idaa_slct.post_comment_obj_li); - } - } else { - if (log_lvl) { - console.log( - `Post comment object list has not changed for post_id: ${$idaa_slct.post_id}` - ); - } - } - - return results; - }) -); -``` diff --git a/documentation/history/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md b/documentation/history/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md deleted file mode 100644 index 5dae7beb..00000000 --- a/documentation/history/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md +++ /dev/null @@ -1,37 +0,0 @@ -# Project: Launcher Configuration UI/UX Overhaul - -**Status:** IN-PROGRESS -**Goal:** Create a standardized, responsive, and categorized configuration interface for the AE Events Launcher. - -## 1. Objectives -- **Standardization**: Use consistent naming (`snake_case`), styling, and layout across all config pieces. -- **Flexibility**: Support mobile, tablet, and high-res Macbook displays using responsive widths. -- **Intelligent Collapsing**: Implement a 3-way state logic: `collapsed`, `auto_collapse`, `pinned`. -- **Contextual Fields**: Hide technical/editable fields unless `$ae_loc.edit_mode` is enabled. - -## 2. 3-Way State Logic -- **`collapsed`**: Section content is hidden. -- **`auto`**: Section is expanded by default, but closes if another "auto" section is opened. -- **`pinned`**: Section is expanded and *ignores* the auto-collapse signals from other sections. - -## 3. Component Architecture -- **`Launcher_Cfg`**: The main container with Tabbed Navigation (System, Sync, General). -- **`Launcher_Cfg_Section`**: Shared wrapper component providing the header, 3-way toggle, and responsive container. -- **Sub-components**: Individual sections (Health, Native OS, Timers, etc.) refactored to use the shared wrapper. - -## 4. Feature Matrix & `edit_mode` -| Component | Always Visible (Read-Only) | Edit Mode Only (Write/Technical) | -| :--- | :--- | :--- | -| **Health** | Heartbeat Status, RAM/CPU Gauges | Raw Metadata JSON, Hostname, IPs | -| **Native OS** | Folder Open Buttons, Recording Toggle | Manual Terminal CMD, Reset Wallpaper | -| **Sync** | Sync Stats (Total/Cached) | Millisecond Timers, Hash Prefix Length | -| **Updates** | Current Version, Check Button | Update Path/URL inputs | - -## 5. Progress Tracker -- [ ] Migrate `events_loc.launcher` visibility flags to 3-way states. -- [ ] Implement `Launcher_Cfg_Section` wrapper component. -- [ ] Refactor `Launcher_Cfg_Health`. -- [ ] Refactor `Launcher_Cfg_Native_OS`. -- [ ] Refactor `Launcher_Cfg_Sync_Timers`. -- [ ] Refactor `Launcher_Cfg_Updates`. -- [ ] Final UI/UX Polish. diff --git a/documentation/history/PROJECT_NATIVE_ELECTRON_INTEGRATION.md b/documentation/history/PROJECT_NATIVE_ELECTRON_INTEGRATION.md deleted file mode 100644 index 5c3d91c2..00000000 --- a/documentation/history/PROJECT_NATIVE_ELECTRON_INTEGRATION.md +++ /dev/null @@ -1,62 +0,0 @@ -# Project: Aether Native Electron Integration - -**Status:** Planning / Documentation -**Date:** 2026-01-20 -**Target Platform:** macOS (Production), Arch Linux (Development) - -## 1. Overview -This project aims to integrate the modern SvelteKit-based Aether UI into the established Electron native shell (`aether_app_native`). This enables "Native Mode" functionality, such as local file system access, presentation management, and hardware integration, which are restricted in standard web browsers. - -## 2. Component Mapping - -### 2.1 The Shell (`aether_app_native`) -- **Main Process:** Handles window creation, lifecycle, and IPC handlers. -- **Config:** Uses `ae_native_app_sk_config.json` located in `~/OSIT/native_app/` or `~/.config/OSIT/`. -- **Preload Script:** (To be standardized) The bridge that injects functionality into the UI. - -### 2.2 The UI (`aether_app_sveltekit`) -- **Framework:** Svelte 5 / SvelteKit. -- **Detection:** Uses `+layout.svelte` to check for `window.native_app`. -- **Relay:** `src/lib/electron/electron_relay.js` acts as the frontend-side API for the native bridge. - -## 3. Development Strategy (Arch Linux) -Since production targets macOS but development happens on Linux: -1. **Mocking macOS APIs:** Any calls to `osascript` or macOS-specific shell commands must be wrapped in a platform check. -2. **Path Handling:** Use `[home]` placeholders in config files to ensure paths resolve correctly on both `/home/scott/` (Linux) and `/Users/scott/` (Mac). -3. **Packaging:** Use `electron-packager` with macOS target flags to verify build integrity on Linux. - -## 4. Implementation Plan - -### Phase 1: Bridge Standardization -- Move existing logic from `aether_app_native/app/js/aether_app_native_v4.js` into a formal `preload.js`. -- Use `contextBridge.exposeInMainWorld` to provide a secure `native_app` object. -- Standardize return types (Promises) for all IPC calls. - -### Phase 2: SvelteKit Build Integration -- Transition SvelteKit build to support relative asset paths (required for `file://` protocol). -- Update the native app's `index.js` to load the built SvelteKit `index.html` instead of a remote URL. - -### Phase 3: Feature Parity (Events Module) -- Port the "Event Launcher" logic to the new bridge. -- Implement robust file caching using the `local_file_cache_path` from the native config. -- Ensure `kill_processes` works for both `pkill` (Linux) and `killall` (Mac). - -## 5. Security Protocols -- **Context Isolation:** Must remain enabled. -- **Sandbox:** Enabled where possible. -- **IPC Whitelisting:** Only specific, pre-defined commands can be executed via `run_cmd`. - -## 6. Project Documentation Index -The following documents provide detailed specifications for the V3 Native App rebuild: - -- **[NATIVE_APP_FUNCTIONAL_SPEC.md](NATIVE_APP_FUNCTIONAL_SPEC.md)**: Detailed audit of legacy features (process management, file caching, automation) to be preserved in the rewrite. -- **[NATIVE_APP_V3_REWRITE_PLAN.md](NATIVE_APP_V3_REWRITE_PLAN.md)**: Technical strategy for Electron 33+, including the Zero-Config hydration flow and macOS permission handling. -- **[NATIVE_APP_V3_API_PAYLOAD.md](NATIVE_APP_V3_API_PAYLOAD.md)**: JSON schema definitions for the V3 bootstrap payload and the push-telemetry heartbeat logic. -- **[NATIVE_BRIDGE_INTERFACE_SPEC.md](NATIVE_BRIDGE_INTERFACE_SPEC.md)**: Definition of the `window.native_app` IPC contract and the "Podium Reliability Protocol." -- **[NATIVE_APP_DEPLOYMENT_PLAN.md](NATIVE_APP_DEPLOYMENT_PLAN.md)**: Strategy for binary distribution and self-updates using the existing Syncthing `admin_share` infrastructure. -- **[NATIVE_APP_AUTOMATION_SCRIPTS.md](NATIVE_APP_AUTOMATION_SCRIPTS.md)**: Specifications for AppleScript intents, recording lifecycle (Aperture), and Arch Linux mocking logic. - -## 7. References -- Existing Native Docs: `aether_app_native/Aether App Native setup documentation.txt` -- Electron Integration: `src/lib/electron/README.md` -- Svelte 5 Runes: `documentation/ARCHITECTURE.md` diff --git a/documentation/history/REVIEW__AE_Svelte5_performance.md b/documentation/history/REVIEW__AE_Svelte5_performance.md deleted file mode 100644 index e069f4eb..00000000 --- a/documentation/history/REVIEW__AE_Svelte5_performance.md +++ /dev/null @@ -1,187 +0,0 @@ -# Aether Svelte 5 App — Performance Review - -Date: 2026-01-26 - -This document collects findings from a quick code review of the Aether Svelte 5 app (focused on `src/routes/+layout.svelte`, `src/routes/+page.svelte`, and the events launcher layout). It lists concrete performance issues observed, their likely impact, remediation recommendations (quick wins first), code examples for safe refactors, measurement steps, and a prioritized action plan. - -**Scope** -- Files inspected: `src/routes/+layout.svelte`, `src/routes/+page.svelte`, event launcher `+layout.svelte` and related store initialization logic. -- Platform: SvelteKit with Vite (assumed from repo files). Builds use Tailwind CSS and manual global CSS. - ---- - -## Summary of Key Findings - -- Large synchronous imports at module evaluation time (notably `highlight.js` and its stylesheet) increase initial bundle size and run before first paint. -- Many components and icon imports are static at top-level even when rendered conditionally (`Analytics`, `MyClipboard`, `E_app_debug_menu`, `E_app_sys_menu`, multiple Lucide icons). This inflates the client bundle. -- Significant initialization and cache logic runs synchronously during module evaluation: store writes, cache expiration checks, IndexedDB operations, localStorage population, calls to `invalidateAll()` and conditional `window.location.reload()` paths — these can block initial render and cause reload loops or extra round trips. -- Dexie `liveQuery` usages in nested layouts are eager and may execute multiple DB queries on route entry, causing CPU and I/O work up-front. -- Multiple synchronous CSS imports (global CSS + highlight CSS) can delay first paint and increase transfer size. -- Many localStorage/sessionStorage writes and store updates are done immediately and synchronously; iterating many keys on startup can stall the main thread. -- Analytics, WebSocket connections, and external network resource usage may be triggered too early. - -Impact: Slow Time to First Paint (TTFP), increased Time to Interactive (TTI), larger JS bundles, higher CPU main-thread blocking, worse Lighthouse/perceived performance. - ---- - -## Concrete, Prioritized Recommendations - -Priority ordering: Quick wins (low code risk) → Short-term (moderate refactor) → Long-term (architectural). - -### Quick Wins (apply first) -- Lazy-load `highlight.js` and its CSS in `onMount` only when highlighting is needed. This removes a heavy library and stylesheet from the initial bundle. -- Dynamically import non-critical components (`Analytics`, debug menus, clipboard UI, large icon modules) when they will actually render. -- Move non-UI, non-blocking initialization to `onMount` and/or `requestIdleCallback` so SSR rendering and first paint aren't blocked by client-only logic. -- Guard `invalidateAll()` / `window.location.reload()` so they run only after a user-visible prompt or on explicit action; avoid automatic reload on subtle mismatches. - -### Short-Term Changes (next 1–2 days) -- Defer expensive Dexie `liveQuery` and database queries until their containing route/section mounts, or add limits/pagination to reduce initial query size. -- Batch localStorage writes (use a single write or `requestIdleCallback`/`setTimeout(…,0)`), or store a single object rather than many keys. -- Replace heavy icon imports with an icon-on-demand strategy (SVG sprite, `unplugin-icons`, or inlining only icons used on first paint). -- Lazy-load large CSS (e.g., highlight theme) with dynamic import or by adding/removing link elements. - -### Long-Term / Architectural -- Split routes to ensure route-level code-splitting is effective — verify that `+layout` doesn't import many route-specific modules. Keep `+layout.svelte` as thin as possible. -- Use a bundle analyzer to identify largest modules and tune dependencies. -- Serve production build with proper HTTP caching, compression (Brotli), and HTTP/2 or HTTP/3. -- Consider server-side rendering vs. partial hydration boundaries (islands) for heavy interactive regions. - ---- - -## Concrete Code Examples - -These are safe, copy-pasteable snippets for common quick fixes. - -1) Lazy-load `highlight.js` in `src/routes/+layout.svelte` (move work to `onMount`): - -```svelte - -``` - -2) Dynamic component import for `Analytics`: - -```svelte - - -{#if showAnalytics && Analytics} - -{/if} -``` - -3) Batch localStorage writes using `requestIdleCallback` fallback: - -```ts -function batchSetLocalStorage(obj: Record) { - const work = () => { - for (const [k, v] of Object.entries(obj)) { - try { localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} - } - }; - if ('requestIdleCallback' in window) { - (window as any).requestIdleCallback(work); - } else { - setTimeout(work, 0); - } -} -``` - -4) Avoid automatic reloads — example guard: - -```ts -// Only force reload after user consent or if critical mismatch -if (flag_reload) { - const reloadKey = 'aether_reload_shown_v' + ($ae_loc?.ver ?? 'unknown'); - if (!localStorage.getItem(reloadKey)) { - if (confirm('A new version is available. Reload now?')) { - localStorage.setItem(reloadKey, '1'); - location.reload(); - } - } -} -``` - ---- - -## Measurement & Tooling - -Run these locally to find concrete hotspots and bundle contributors. - -- Bundle analysis (Vite): - -```bash -# Build and open analyzer (if plugin configured) -npm run build -npx vite build --sourcemap -# Use source-map-explorer or webpack-bundle-analyzer (adapt if using Rollup) -npx source-map-explorer dist/assets/*.js -``` - -- Vite visualizer (install `rollup-plugin-visualizer` or `vite-plugin-visualizer`): - -```bash -# add plugin and run build with report -# then open .html output from the plugin -``` - -- Lighthouse / DevTools: - - Run Lighthouse (Performance, TTI, Largest Contentful Paint, Main thread) in Chrome. - - In Performance panel record page load to find long main-thread tasks (JS parsing/execution) and identify blocking code paths. - -- Runtime marks: add `performance.mark('init-start')` / `performance.mark('init-end')` to measure areas (e.g., store population, Dexie queries) then `performance.measure()`. - ---- - -## Prioritized Action Plan (Checklist) - -- [ ] Move `highlight.js` imports and theme stylesheet to `onMount` (quick win). -- [ ] Convert `Analytics` and other developer tools to dynamic imports (quick win). -- [ ] Move non-critical store population, IndexedDB maintenance, and cache-expiration logic to `onMount` or `requestIdleCallback`. -- [ ] Add guard & confirmation around `invalidateAll()` and `location.reload()` to avoid reload loops. -- [ ] Defer Dexie `liveQuery` initialization to the route or component that needs it (avoid running all live queries globally). -- [ ] Batch localStorage writes and avoid iterating thousands of keys synchronously. -- [ ] Run bundle analysis and produce a top-10 biggest modules list. -- [ ] Replace heavy icon imports with icon-on-demand solution. -- [ ] Re-run Lighthouse and validate improvements. - ---- - -## Appendix: Quick Checklist for PRs - -- Ensure client-only code is inside `onMount` or guarded by `if (browser)`. -- Where dynamic import used, use `` pattern. -- Add performance marks around expensive blocks and log durations in dev mode. -- Avoid unconditional network or socket connections in top-level layout; open them after user interaction or when component mounts. - ---- - -If you want, I can implement the first quick wins now: lazy-load `highlight.js` and convert `Analytics` import in `src/routes/+layout.svelte`, then run a local bundle analysis. Tell me which of the quick wins you'd like me to patch first and I'll start. diff --git a/documentation/history/V3_API_HARDENING_SESSION_REPORT_2026-01-19.md b/documentation/history/V3_API_HARDENING_SESSION_REPORT_2026-01-19.md deleted file mode 100644 index c2dc7827..00000000 --- a/documentation/history/V3_API_HARDENING_SESSION_REPORT_2026-01-19.md +++ /dev/null @@ -1,57 +0,0 @@ -# Session Report: V3 API Hardening & Stabilization (2026-01-19) - -## 👤 User / Context -- **Developer:** Scott Idem -- **Date:** Monday, January 19, 2026 -- **Objective:** Stabilize V3 API helpers, resolve 403 race conditions, and fix IDAA module crashes. - ---- - -## 🏗️ 1. Completed & Committed Work - -### **A. Core API Helpers (GET/POST/PATCH)** -- **Structured Error Handling:** Updated helpers to extract and return rich metadata (`meta.details`) from V3 API 400/500 responses. This allows for specific debugging (e.g., "Unknown column") instead of generic HTTP codes. -- **Immediate JWT Injection:** Refactored `+layout.ts` to read the JWT directly from `localStorage` during bootstrap. This ensures the first requests of a page load are correctly authenticated, solving race conditions. -- **Hardened Bypass Logic:** Refined the "Bootstrap Paradox" logic to strictly check for valid values (e.g., `bypass`). Placeholder environment variables are now proactively stripped so they don't interfere with account context. -- **Fail-Fast Protocol:** Added `400` and `422` to the Fail-Fast list to prevent unnecessary retries on invalid requests or schema violations. -- **JWT Fallback:** Implemented a direct `localStorage` check for the `ae_loc` key as a final resort in the helpers if the Svelte stores haven't synchronized yet. - -### **B. Module Fixes** -- **Archives Stability:** Resolved a critical async race condition in `load_ae_obj_li__archive` that caused a `TypeError` when loading nested content before the primary promise resolved. -- **Generic Processor Hardening:** Updated `_process_generic_props` to robustly handle non-array API responses, preventing "obj_li is not iterable" crashes. -- **Event Search Logic:** Refactored `qry_ae_obj_li__event` to use raw `account_id_random` in the search body to attempt bypassing backend ID-mapping conflicts. - -### **C. Testing & Diagnostics** -- **Enhanced Dashboard:** Updated `/testing` with a "Live V3 Header Inspection" tool. -- **Hardening Audits:** Added automated tests for **Permissive Mode** (x-ae-ignore-extra-fields) and **Structured Error** extraction. - ---- - -## 🚧 2. The Current Blocker: Zero-Result Search - -The `event/search` endpoint for IDAA Recovery Meetings is consistently returning `200 OK` with `data: []` or intermittent `403 Forbidden`. - -### **Failed Attempts / Observations:** -- **Raw ID Bypass:** Sending `account_id_random` directly in the body did not restore the listings. -- **Hybrid Filtering:** Moving `physical`, `virtual`, and `conference` filters to the client side resolved 400 errors but resulted in empty lists. -- **Header Diagnostics:** Confirmed that `x-account-id` and `x-aether-api-key` are present, but `Authorization` is occasionally marked as `MISSING` in the very first bootstrap trace. - ---- - -## 🧠 3. Best Guesses for Root Cause - -1. **The "Integer Trap":** FastAPI logs show the backend is mapping the account context to an integer (`{'account_id': 13}`). If the backend search logic compares this integer to a string column in a view, the query returns zero rows. -2. **Mapping Conflict:** Injecting `account_id_random` in the search body while the backend automatically injects its own isolation may be creating conflicting `WHERE` clauses. -3. **Whitelisting/Permissions:** The "Authentication required" 403 on search suggests the backend might be rejecting the combination of search fields for the `event` object specifically, or the user's JWT permissions for that object aren't being resolved correctly. - ---- - -## 🚀 4. Plan for Tomorrow - -1. **CURL Trace:** Execute raw CURL requests with the payloads captured today to see the raw backend traceback (bypassing CORS masking). -2. **Backend Audit:** Check the `v_event` view and `mdl_search` Pydantic model in the API for strict type constraints on the `account_id` field. -3. **Filter Re-alignment:** Once backend search whitelisting is confirmed, test reverting to the standard `for_obj_type: 'account'` pattern. -4. **JWT Verification:** Confirm if the JWT provided in `ae_loc` is correctly scoped for the `event` object search. - ---- -**Status:** API helpers are solid; store sync is stable. Issue is narrowed to SQL/Filter logic for V3 Event Search. diff --git a/documentation/history/V3_FRONTEND_API_GUIDE.md b/documentation/history/V3_FRONTEND_API_GUIDE.md deleted file mode 100644 index dc04a2ae..00000000 --- a/documentation/history/V3_FRONTEND_API_GUIDE.md +++ /dev/null @@ -1,236 +0,0 @@ -# Aether API V3 Frontend Integration Guide (Svelte/TypeScript) - -This guide explains how to update or create frontend functions to interact with the new **Aether API V3 CRUD** endpoints. V3 introduces a nested URL structure, a powerful POST-based search, and improved performance. - ---- - -## 1. Key Differences (V2 vs V3) - -| Feature | CRUD V2 (Legacy) | CRUD V3 (Modern) | -| --- | --- | --- | -| **Base Prefix** | `/v2/crud` | `/v3/crud` | -| **List Suffix** | Uses `/list` | **No suffix** (e.g., `/v3/crud/journal/`) | -| **Nested Path** | Not supported in URL | **Supported** (e.g., `/v3/crud/journal/{id}/journal_entry/`) | -| **View Selection**| `tbl_alt`, `mdl_alt` | **`view` parameter** (e.g., `?view=enriched`) | -| **Complex Search**| Limited to GET `jp` | **POST `/search`** (Unlimited size + Hybrid params) | -| **Full-Text Search**| Manual column names | **Reserved `q` property** in SearchQuery | - ---- - -## 2. Authentication and Security (Mandatory in V3) - -As of January 2026, the V3 architecture enforces strict **Multi-Tenant Isolation**. Most requests now require valid authentication to prevent data leakage between accounts. - -### A. Authentication Requirement -Almost all V3 CRUD endpoints require a standard Bearer token in the `Authorization` header. - -* **Mandatory:** You must provide a valid JWT for nearly all requests. -* **Account Isolation:** The backend automatically filters all results based on the `account_id` found in your JWT. You cannot access data belonging to another account even if you know the random ID. -* **Status Codes:** - * `401 Unauthorized`: Your JWT is invalid or expired. - * `403 Forbidden`: No authentication provided, or you attempted to access an object belonging to a different account. - -**Example Request Header:** -```http -Authorization: Bearer -``` - -### B. The "Bootstrap Paradox" Exception (`site_domain`) -There is one critical exception to strict authentication: **`site_domain` search**. - -Because the frontend needs to lookup the site configuration (to know which account it's on) *before* a user can log in, the following endpoint allows unauthenticated (guest) access: - -**Endpoint:** `POST /v3/crud/site_domain/search` - -This is the only V3 search allowed without a JWT. All other object types (journal, account, post, etc.) will return `403 Forbidden` if accessed without a token. - ---- - -## 3. Implementing V3 CRUD Functions - -### A. List & Single Object (GET) -Support for view selection allows fetching richer data models when needed. - -```ts -// Example: Get enriched journal details -// GET /v3/crud/journal/{id}?view=enriched -export async function get_ae_obj_v3({ api_cfg, obj_type, obj_id, view = 'default' }) { - const endpoint = `/v3/crud/${obj_type}/${obj_id}`; - return await get_object({ api_cfg, endpoint, params: { view } }); -} -``` - -### B. Advanced & Hybrid Search (POST) -The `/search` endpoint combines the power of complex logical bodies with the simplicity of query parameters. - -```ts -export async function search_ae_obj_v3({ - api_cfg, - obj_type, - search_query, // { q: "search term", and: [...] } - enabled = 'enabled', - view = 'default', - for_obj_type, - for_obj_id -}) { - const endpoint = `/v3/crud/${obj_type}/search`; - - // Standard filters can be passed as query params - const params: any = { enabled, view }; - if (for_obj_type) params.for_obj_type = for_obj_type; - if (for_obj_id) params.for_obj_id = for_obj_id; - - return await post_object({ - api_cfg, - endpoint, - params, - data: search_query - }); -} -``` - -### C. Standardized Global Search (`q`) -Use the `q` property in your search body for a keyword search. -- **Wildcard Support**: Setting `q: "%"` will bypass all text filtering and return all records (respecting only logical filters like `enable`). -- **Fallback**: If the table lacks a `default_qry_str` column, the API automatically performs a `LIKE` search across all searchable fields. - -```json -{ - "q": "Annual Meeting", - "and": [{ "field": "enable", "op": "eq", "value": true }] -} -``` - ---- - -## 4. Create, Update, & Delete (POST, PATCH, DELETE) - -V3 supports both top-level operations and nested parent/child operations. - -### A. Create (POST) -When creating objects, V3 strictly validates the incoming JSON against the `mdl_in` Pydantic model. - -```ts -// POST /v3/crud/{obj_type}/ -export async function create_ae_obj_v3({ api_cfg, obj_type, data }) { - const endpoint = `/v3/crud/${obj_type}/`; - return await post_object({ api_cfg, endpoint, data }); -} - -// POST /v3/crud/{parent_obj_type}/{parent_obj_id}/{child_obj_type}/ -// Note: Parent ID is automatically injected into the child record. -export async function create_nested_obj_v3({ api_cfg, parent_type, parent_id, child_type, data }) { - const endpoint = `/v3/crud/${parent_type}/${parent_id}/${child_type}/`; - return await post_object({ api_cfg, endpoint, data }); -} -``` - -### B. Update (PATCH) -V3 uses `PATCH` for partial updates. Only the fields provided in the body will be modified in the database. - -```ts -// PATCH /v3/crud/{obj_type}/{obj_id} -export async function update_ae_obj_v3({ api_cfg, obj_type, obj_id, data }) { - const endpoint = `/v3/crud/${obj_type}/${obj_id}`; - return await patch_object({ api_cfg, endpoint, data }); -} -``` - -### C. Delete (DELETE) -The `DELETE` method is used for removal. The backend may implement soft-delete (hide/disable) depending on the configuration. - -```ts -// DELETE /v3/crud/{obj_type}/{obj_id} -export async function delete_ae_obj_v3({ api_cfg, obj_type, obj_id }) { - const endpoint = `/v3/crud/${obj_type}/${obj_id}`; - return await delete_object({ api_cfg, endpoint }); -} -``` - ---- - -## 5. Specialized & Context Endpoints - -### A. Context Resolution (FQDN) -Used during initial load to find the `account_id` associated with the domain. - -**Legacy Method:** `GET /crud/site/domain/{fqdn}?use_alt_table=true&use_alt_base=true` -**Modern V3 Method (Preferred):** `POST /v3/crud/site_domain/search` with `{ "q": "your-domain.com" }` - -### B. Schema Discovery -**Path**: `GET /v3/crud/{obj_type}/schema` - -Used for developer tools or dynamic UI builders to understand the structure of an AE object. - -```ts -// GET /v3/crud/account/schema -export async function get_obj_schema_v3({ api_cfg, obj_type }) { - const endpoint = `/v3/crud/${obj_type}/schema`; - return await get_object({ api_cfg, endpoint }); -} -``` - ---- - -## 6. Secure File Downloads (URL Parameter) -For `hosted_file` and `event_file`, browsers often need to download files without complex header modifications. In these cases, you can pass the JWT directly in the URL. - -```ts -// Example: Creating a secure download link for a browser -// GET /v3/crud/hosted_file/{id}/?jwt={token} -const downloadUrl = `${BASE_URL}/v3/crud/hosted_file/${fileId}/?jwt=${jwtToken}`; -``` - ---- - -## 7. Best Practices for V3 - -1. **Use `view` for Rich Data**: Instead of manually joining data in separate calls, use `?view=enriched` or `?view=detail`. -2. **Singular Nouns**: Always use singular names for `obj_type` (e.g., `journal`). -3. **Strict Typing**: Ensure your `data` objects match the backend models to avoid `400 Bad Request` validation errors. - ---- - -## 8. Standard Patterns & Common Pitfalls (2026 Update) - -To ensure stability across the Aether mesh, all frontend components must adhere to these established patterns. - -### A. The "Whitelist" Standard for Saves -**Problem:** Sending the entire object returned by a `GET` request back to a `PATCH` endpoint will cause a `400 Bad Request`. This happens because the object contains technical metadata (like `journal_id`, `created_on`, `for_type`) that the API cannot "SET". - -**Standard:** When preparing a save payload, explicitly whitelist ONLY the user-editable fields. -```typescript -// ✅ CORRECT: Whitelist only editable fields -const data_kv = { - name: tmp_obj.name, - content: tmp_obj.content, - tags: tmp_obj.tags, - category_code: tmp_obj.category_code -}; - -// ❌ WRONG: Passing the whole object or just blacklisting a few -const data_kv = { ...tmp_obj }; -delete data_kv.id; // Still contains other computed columns! -``` - -### B. The Triple-ID Save Pattern -**Standard:** When sending an ID in a POST/PATCH payload (e.g. creating a child object), use the random string version with the `_id_random` suffix. -* **Property:** `[obj_type]_id_random` -* **Value:** A string (e.g., `qpgvOh5nOYI`) - -**Warning:** Sending a string value under an integer key (e.g. `journal_id: "qpgvOh5nOYI"`) will trigger a Pydantic validation error on the backend. - -### C. Handle 'NULL' vs '0' for Booleans -**Pitfall:** Fields like `hide` or `priority` can be `NULL` in the database. -**Standard:** Ensure your synchronization logic in components handles `null`, `undefined`, and `0` identically for boolean checks to prevent "ghost" changes being detected by Svelte 5. - ---- - -## 9. Planned API Improvements (2026 Roadmap) - -The following refinements have been requested from the Backend Agent to further improve frontend productivity: - -1. **Permissive Update Mode**: A new header (`x-ae-ignore-extra-fields: true`) is planned to allow the API to ignore non-writable columns in `PATCH` requests instead of returning a `400 Bad Request`. -2. **Automated ID Resolution**: Backend will soon support automatic resolution of `_id_random` strings to integer IDs during `POST/PATCH`, reducing the need for manual lookups in the frontend. -3. **Schema Evolution Tools**: New orchestration tools are being developed to automate field creation and renaming, including the automatic regeneration of the enriched SQL views. -4. **Structured Validation Errors**: Move from string-based error details to a machine-readable format for better inline form validation.