2nd release that day
This release closes the top PRD gaps for the SOURCE (influencer/publisher) role, ships a full in-app notification system with real-time delivery, rebuilds the Settings page, and hardens auth + error handling.
Role-Gating & Security
- Fixed 4 role-leaks: SOURCE can no longer call
POST /briefs,GET /influencers/search,GET /advertiser/overview,GET /analytics/performance(all return 403) - Suspended-workspace middleware —
get_current_usernow blocks API calls from users whose workspace hasis_active=false(SA bypasses). Fixes a real authorization hole. - Error boundaries —
(dashboard)/error.tsxand rooterror.tsxcatch unhandled React errors with friendly UI (previously blank screens on crashes) - Fixed
/briefs/{id}/recipients500 caused by SQLAlchemy misuse ofUser.full_nameproperty
SOURCE Earnings Dashboard
- New
GET /source/earnings-summaryaggregates real data from scheduling deals, marketplace deals, forward listings, availability slots, brief recipients - Replaces hardcoded demo data in
influencer/dashboardandpublisher/dashboard - Shared
SourceEarningsDashboardcomponent with theme parameter (influencer pink/purple vs publisher teal/cyan) - Sections: hero stats, KPIs, deals breakdown by source, inventory overview, recent earnings table, empty-state CTAs
Property Verification Pipeline
- Migration
c3d4e5f7a8b9— addsverification_method,verification_code,verification_attempted_at,last_synced_at,sync_status,sync_errortoinfluencer_properties - 4 new endpoints:
verify/init,verify/check,sync,verify/status - Working methods : DNS-TXT (challenge via
adnet-verify=<code>TXT record) and URL-Probe (HTTP GET of profile URL) - OAuth scaffolded and returns 501 "OAuth verification not yet configured" — ready to wire when Instagram/YouTube app keys are available
- New dep:
dnspython==2.8.0 - Verify modal UI on
/propertieswith 3-step flow (method pick → code + instructions → verify)
Media Kit PDF + Public URL
GET /marketplace/influencers/{id}/media-kit/pdf— owner/SA downloads A4 PDF via WeasyPrint + Jinja2 templateGET /public/media-kit/{slug-or-id}— unauthenticated public route (new layout infrontend/src/app/public/)- PDF template: gradient hero, stats, per-property rate cards, red restriction chips, reviews, "Powered by" footer
- "Download PDF" + "Copy Public Link" buttons on media-kit management page
Weekly Opportunity Digest
- New service
backend/services/scheduling/digest_service.py GET /scheduling/digest/opportunities(user on-demand) +POST /scheduling/admin/digest/run(SA batch, cron-ready)- Personalized digest includes upcoming seasonal moments (14-day window), active forward listings, open availability slots
- In-app notification + HTML+text email template with gradient branding
- Celery not required — SA endpoint designed for external cron or systemd timer
Notifications System (Phases 1 + 2 + 3)
Phase 1 — Foundation:
- Fixed latent
NotificationPreference.categorybug that silently dropped notifications - New
NotificationService.emit_event(event_key, user_id, context, group_key=...)— templated event emitter with preference gating and multi-channel dispatch - 10 seeded
NotificationTemplaterows viaseed_notification_templates.py(re-runnable): deal lifecycle, bids, briefs, property events, digests, payment failures
Phase 2 — UI:
- New
NotificationBellcomponent in header — unread badge, 360px dropdown, polls/unread-countevery 10s, EventSource subscription to SSE, category dots, hover archive, mark-all-read /notificationspage rewritten: All/Unread tabs with live counts, category dropdown, 7/30/90-day filter, pagination, per-row archive + navigate + mark-read- New endpoints:
POST /{id}/mark-read,POST /mark-all-read,DELETE /{id}(archive),GET /notifications?category=&include_archived=
Phase 3 — Real-time + grouping:
- SSE endpoint
/notifications/streampushes new notifications in real time - Auth via Authorization header (primary) or
?token=<jwt>query fallback (EventSource limitation) - Grouping mechanism:
emit_event(group_key='bids.{listing_id}', group_window_minutes=60)collapses repeats into a single notification with(N updates)suffix
Wired into business actions:
book_forward_listing,submit_eoi,respond_to_eoi,update_deal_status(scheduling)create_bid,accept_bid,reject_bid,submit_delivery,mark_complete,dispute,pay(marketplace)- Existing
_notify()callers inbriefs.pyleft unchanged (already working)
Vendor Dashboard Rewrite
- Removed misplaced Listings/Bids/Deals sections (vendors are service providers, not marketplace sellers)
- New
GET /vendors/me/dashboard-summaryendpoint - KPI cards: Active Deliverables (with overdue pill), Pending Invoices, Paid This Month, On-Time Delivery %
- 2-column main: Work Queue (top 5 urgency-sorted) + Earnings (6-month revenue chart + recent invoices)
- Empty-state CTA when no Vendor profile exists
Settings Page — All 6 Tabs Now Functional
- Profile — fixed phone field silent-drop bug (schema was missing the field)
- Workspace — expanded from 1 field to Identity (name, slug, logo URL) + Branding (colors with live preview) + Commerce (default currency) + Brand Category
- Notifications — master channel toggles + 9×3 category × channel matrix + quiet hours (timezone-aware)
- Security — built from scratch: change password, 2FA enable/disable (QR code + backup codes), active sessions with per-session sign-out
- Billing — summary card (methods count, pending invoices amount) + deep link to
/billing - Team — clean redirect card to
/team - New backend:
POST /auth/mfa/enable(authenticated TOTP verification, distinct from login-flow/mfa/verify)
API/Product Gap Closures
- Brief "Send Brief" button added to both influencer detail pages (
/marketplace/influencers/[id]and/influencers/[id]) — extracted reusableSendBriefModalcomponent - Property dropdown for collaboration types (multi-select from master list)
- Pill sub-tabs on Discover/My Bookings/My Listings for advertiser side (mirrors publisher side)
- Restriction display on
/influencers/[id]detail page (advertiser view)
Data Model Changes (this release)
influencer_properties— 6 verification/sync columns (migration c3d4e5f7a8b9)dealstable — workflow columns already added in prior releaseusers.phone— existed but was silently dropped by request schema; now actually saves- New templates:
notification_templatesseeded with 10 rows
Documentation
CHANGELOG.md— daily entries through 2026-04-21CLAUDE.md— ongoing router registry + gotchas updates- This file — consolidated release notes
Known Gaps (unchanged)
- Payment webhooks still skeleton only
- External integrations (Meta/Google/TikTok Ads, OpenAI, DocuSign, Twilio, Firebase, S3) not wired
- No automated test suite
- Email provider not configured (digest/notifications log in dev mode)
- Celery not set up (digest runs on-demand; weekly cron not scheduled)
---

