-- Protocol Droid — MySQL Schema -- Works with MySQL 5.7+ / MariaDB 10.3+ CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) UNIQUE NOT NULL, display_name VARCHAR(128), bio TEXT, password_hash VARCHAR(255), -- bcrypt; NULL if SSO-only sso_provider VARCHAR(64), -- 'oidc', 'github', 'google', etc. sso_id VARCHAR(255), -- external identity id role ENUM('admin','member','viewer') DEFAULT 'member', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS protocols ( id INT AUTO_INCREMENT PRIMARY KEY, slug VARCHAR(128) UNIQUE NOT NULL, title VARCHAR(255) NOT NULL, description TEXT, source VARCHAR(255), -- free text or @username source_url VARCHAR(500), tags VARCHAR(500), -- JSON array string forked_from VARCHAR(128), -- slug of parent protocol image VARCHAR(500), steps TEXT, -- JSON array of {headline, description} outcome TEXT, practice TEXT, author_id INT REFERENCES users(id), visibility ENUM('public','private','unlisted') DEFAULT 'public', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_visibility (visibility), INDEX idx_author (author_id), INDEX idx_forked (forked_from) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS collections ( id INT AUTO_INCREMENT PRIMARY KEY, slug VARCHAR(128) UNIQUE NOT NULL, title VARCHAR(255) NOT NULL, description TEXT, source VARCHAR(255), image VARCHAR(500), author_id INT REFERENCES users(id), visibility ENUM('public','private','unlisted') DEFAULT 'public', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_visibility (visibility), INDEX idx_author (author_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS collection_items ( collection_id INT NOT NULL REFERENCES collections(id) ON DELETE CASCADE, item_type ENUM('protocol','collection') NOT NULL, item_slug VARCHAR(128) NOT NULL, position INT DEFAULT 0, PRIMARY KEY (collection_id, item_type, item_slug) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS votes ( user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, protocol_slug VARCHAR(128) NOT NULL, value INT DEFAULT 1, -- +1 upvote, -1 downvote comment TEXT, -- optional evaluation text created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, protocol_slug) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS config ( `key` VARCHAR(64) PRIMARY KEY, `value` TEXT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- Default config entries INSERT INTO config (`key`, `value`) VALUES ('site_name', 'Protocol Droid'), ('site_tagline', 'A commons of social protocols'), ('registration_enabled', 'true'), ('require_approval', 'false') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);