Sponsor to downline messaging: lineage view, daily broadcast (email+inbox), login modal

- Downline resolver (3 levels); email visible for directs only, username+ID deeper
- Broadcast composer (rich editor) to directs or full downline, 1/day cap, sends email + on-site inbox
- Upline messages inbox in My line; unmissable sign-in modal for unread, ack marks read
- messages.js dual-mode store; sponsor_messages table; sanitizeRich reused

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-06 08:39:06 -05:00
parent 289538dbeb
commit 7701a29169
14 changed files with 344 additions and 27 deletions
+11
View File
@@ -110,6 +110,17 @@ async function bootstrap() {
await alterSafe('ALTER TABLE campaigns ADD COLUMN height INT NULL'); // banner size (IAB) → also NAS height
await alterSafe('ALTER TABLE campaigns ADD COLUMN nas_ad_id INT NULL'); // syndicated NAS sponsorads.ID
await alterSafe('ALTER TABLE campaigns ADD COLUMN nas_served INT NOT NULL DEFAULT 0'); // NAS impressions already reconciled into spend
await q(`CREATE TABLE IF NOT EXISTS sponsor_messages (
id INT AUTO_INCREMENT PRIMARY KEY,
from_member INT NOT NULL,
from_email VARCHAR(190) NOT NULL,
to_email VARCHAR(190) NOT NULL,
subject VARCHAR(160) NOT NULL,
body TEXT NULL,
sent BIGINT NOT NULL,
read_ts BIGINT NULL,
INDEX (to_email, read_ts), INDEX (from_email, sent)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`);
await q(`CREATE TABLE IF NOT EXISTS burns (
id VARCHAR(32) PRIMARY KEY,
member_id INT NOT NULL,