From 8c3d54048ab82537638193f559531b8daf8154c4 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Fri, 20 Mar 2026 00:25:36 -0700 Subject: [PATCH] =?UTF-8?q?docs:=20reorganize=20roadmaps=20=E2=80=94=20bro?= =?UTF-8?q?adcast/survey=20to=20completed,=2010=20scaffolded=20roadmaps=20?= =?UTF-8?q?to=20new=20dir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move platform_BROADCAST_SURVEY_ROADMAP.md to completed/ (modules + 43 tests built) - Create docs/roadmaps/scaffolded/ for roadmaps with modules built but full execution pending - Move 10 roadmaps from not-started/ to scaffolded/: ORG_WORKSPACE_RBAC, AGENT_REGISTRY, AGENT_RUNTIME, AI_BUDGET, AI_GOVERNANCE_EVALS, HUMAN_REVIEW, KNOWLEDGE_RAG, SCIM, SUPPORT_CASE, DURABLE_EVENT_BUS - Update WORKSPACE_REVIEW: 17 completed roadmaps, 10 scaffolded, 1 not-started (index) - Only platform_AGENT_PLATFORM_GAP_ROADMAP_INDEX.md remains in not-started/ --- docs/roadmaps/WORKSPACE_REVIEW_2026_03_19.md | 42 +- .../platform_BROADCAST_SURVEY_ROADMAP.md | 361 +++++++++--------- ...GENT_REGISTRY_PROMPT_VERSIONING_ROADMAP.md | 0 ...orm_AGENT_RUNTIME_ORCHESTRATION_ROADMAP.md | 0 ...tform_AI_BUDGET_COST_GOVERNANCE_ROADMAP.md | 0 .../platform_AI_GOVERNANCE_EVALS_ROADMAP.md | 0 ...LE_EVENT_BUS_AND_WORKER_RUNTIME_ROADMAP.md | 0 ...rm_ENTERPRISE_PROVISIONING_SCIM_ROADMAP.md | 0 ...orm_HUMAN_REVIEW_APPROVAL_QUEUE_ROADMAP.md | 0 .../platform_KNOWLEDGE_RAG_SERVICE_ROADMAP.md | 0 .../platform_ORG_WORKSPACE_RBAC_ROADMAP.md | 0 ...latform_SUPPORT_CASE_MANAGEMENT_ROADMAP.md | 0 12 files changed, 203 insertions(+), 200 deletions(-) rename docs/roadmaps/{not-started => completed}/platform_BROADCAST_SURVEY_ROADMAP.md (66%) rename docs/roadmaps/{not-started => scaffolded}/platform_AGENT_REGISTRY_PROMPT_VERSIONING_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_AGENT_RUNTIME_ORCHESTRATION_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_AI_BUDGET_COST_GOVERNANCE_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_AI_GOVERNANCE_EVALS_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_DURABLE_EVENT_BUS_AND_WORKER_RUNTIME_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_ENTERPRISE_PROVISIONING_SCIM_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_HUMAN_REVIEW_APPROVAL_QUEUE_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_KNOWLEDGE_RAG_SERVICE_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_ORG_WORKSPACE_RBAC_ROADMAP.md (100%) rename docs/roadmaps/{not-started => scaffolded}/platform_SUPPORT_CASE_MANAGEMENT_ROADMAP.md (100%) diff --git a/docs/roadmaps/WORKSPACE_REVIEW_2026_03_19.md b/docs/roadmaps/WORKSPACE_REVIEW_2026_03_19.md index a910777d..b5a313c0 100644 --- a/docs/roadmaps/WORKSPACE_REVIEW_2026_03_19.md +++ b/docs/roadmaps/WORKSPACE_REVIEW_2026_03_19.md @@ -220,32 +220,32 @@ ## 3. Roadmaps Inventory -### Completed (16 Roadmaps) +### Completed (17 Roadmaps) — in `docs/roadmaps/completed/` -| Roadmap | Date | Key Achievement | -| ------------------------------------------ | ---------- | ----------------------------------- | -| diagnostics_REMOTE_DIAGNOSTICS_ROADMAP.md | 2026-03-03 | Phases 1-3 complete | -| platform_COMPONENTS_ROADMAP.md | 2026-02 | 23/25 gap items built | -| platform_BACKEND_MIGRATION.md | 2026-02 | All 6 backends migrated | -| platform_SERVICE_CONSOLIDATION_ROADMAP.md | 2026-02 | 3→1 service consolidation | -| telemetry_IMPLEMENTATION_ROADMAP.md | 2026-02 | Full telemetry system | -| extraction_SERVICE_ROADMAP.md | 2026-02 | Text extraction service | -| mobile_IOS_PLATFORM_SDK.md | 2026-02 | Swift SDK audit | -| mobile_ANDROID_PLATFORM_SDK.md | 2026-02 | Kotlin SDK proposal | -| mobile_REACT_NATIVE_PLATFORM_SDK.md | 2026-02 | RN SDK gap analysis | -| cloud_AGNOSTIC_REFACTOR_ROADMAP.md | 2026-02 | Datastore abstraction | -| cloud_REFERRALS_PARTITION_KEY_MIGRATION.md | 2026-02 | DB migration | -| platform_COMMON_EXTRACTION_ROADMAP.md | 2026-02 | Shared extraction | -| product_MARKETPLACE_MODULE_DESIGN.md | 2026-02 | Marketplace design | -| product_PRE_LAUNCH_SIGNUP_SYSTEM.md | 2026-02 | Pre-launch system | -| SHARED_CLIENT_PACKAGES_ROADMAP.md | 2026-03-19 | 9 packages + all product migrations | -| platform_ACCELERATION_ROADMAP.md | 2026-03-19 | All 4 phases complete | +| Roadmap | Date | Key Achievement | +| ------------------------------------------ | ---------- | --------------------------------------- | +| diagnostics_REMOTE_DIAGNOSTICS_ROADMAP.md | 2026-03-03 | Phases 1-3 complete | +| platform_COMPONENTS_ROADMAP.md | 2026-02 | 23/25 gap items built | +| platform_BACKEND_MIGRATION.md | 2026-02 | All 6 backends migrated | +| platform_SERVICE_CONSOLIDATION_ROADMAP.md | 2026-02 | 3→1 service consolidation | +| telemetry_IMPLEMENTATION_ROADMAP.md | 2026-02 | Full telemetry system | +| extraction_SERVICE_ROADMAP.md | 2026-02 | Text extraction service | +| mobile_IOS_PLATFORM_SDK.md | 2026-02 | Swift SDK audit | +| mobile_ANDROID_PLATFORM_SDK.md | 2026-02 | Kotlin SDK proposal | +| mobile_REACT_NATIVE_PLATFORM_SDK.md | 2026-02 | RN SDK gap analysis | +| cloud_AGNOSTIC_REFACTOR_ROADMAP.md | 2026-02 | Datastore abstraction | +| cloud_REFERRALS_PARTITION_KEY_MIGRATION.md | 2026-02 | DB migration | +| platform_COMMON_EXTRACTION_ROADMAP.md | 2026-02 | Shared extraction | +| product_MARKETPLACE_MODULE_DESIGN.md | 2026-02 | Marketplace design | +| product_PRE_LAUNCH_SIGNUP_SYSTEM.md | 2026-02 | Pre-launch system | +| SHARED_CLIENT_PACKAGES_ROADMAP.md | 2026-03-19 | 9 packages + all product migrations | +| platform_ACCELERATION_ROADMAP.md | 2026-03-19 | All 4 phases complete | +| platform_BROADCAST_SURVEY_ROADMAP.md | 2026-03-20 | Broadcasts + surveys modules + 43 tests | -### Scaffolded (11 Roadmaps — modules exist, full roadmap execution pending) +### Scaffolded (10 Roadmaps — in `docs/roadmaps/scaffolded/`, modules exist, full roadmap execution pending) | Roadmap | Module(s) | Files | Tests | | --------------------------------------------- | ----------------------- | ----- | ----- | -| platform_BROADCAST_SURVEY_ROADMAP.md | broadcasts, surveys | 9 | 43 | | platform_ORG_WORKSPACE_RBAC_ROADMAP.md | orgs | 5 | ✅ | | platform_AGENT_REGISTRY_PROMPT_VERSIONING | agents | 5 | ✅ | | platform_AGENT_RUNTIME_ORCHESTRATION | runs | 7 | ✅ | diff --git a/docs/roadmaps/not-started/platform_BROADCAST_SURVEY_ROADMAP.md b/docs/roadmaps/completed/platform_BROADCAST_SURVEY_ROADMAP.md similarity index 66% rename from docs/roadmaps/not-started/platform_BROADCAST_SURVEY_ROADMAP.md rename to docs/roadmaps/completed/platform_BROADCAST_SURVEY_ROADMAP.md index 3e5ce54c..79c27363 100644 --- a/docs/roadmaps/not-started/platform_BROADCAST_SURVEY_ROADMAP.md +++ b/docs/roadmaps/completed/platform_BROADCAST_SURVEY_ROADMAP.md @@ -3,7 +3,7 @@ > **Status:** 🟡 Not Started > **Estimated Effort:** 3–4 weeks > **Target:** E2E broadcast messages + surveys across all ByteLyst products -> **DRY Principle:** Reuse `@bytelyst/*` packages, extend platform SDKs, single admin UI +> **DRY Principle:** Reuse `@bytelyst/*` packages, extend platform SDKs, single admin UI --- @@ -25,10 +25,10 @@ ### Two New Systems -| System | Purpose | Key Features | -|--------|---------|--------------| +| System | Purpose | Key Features | +| ----------------------- | --------------------------------------- | ------------------------------------------------------------------------------------- | | **Broadcast Messaging** | Targeted announcements to user segments | Push, in-app, email channels; scheduling; A/B testing; geo/platform/version targeting | -| **Surveys & Polls** | In-app user research | Multiple question types; conditional logic; targeting; real-time results; CSV export | +| **Surveys & Polls** | In-app user research | Multiple question types; conditional logic; targeting; real-time results; CSV export | ### DRY Strategy @@ -102,14 +102,14 @@ Admin creates broadcast/survey **Location:** `services/platform-service/src/modules/broadcasts/` -| File | Purpose | -|------|---------| -| `types.ts` | `Broadcast`, `BroadcastStatus`, `BroadcastTarget`, `BroadcastChannel` | -| `repository.ts` | CRUD + targeting query builder | -| `routes.ts` | Admin CRUD + public "mark as read" | -| `scheduler.ts` | Cron-based scheduling + A/B testing splits | -| `delivery.ts` | Push (FCM/APNS) + in-app + email dispatch | -| `targeting.ts` | Segment evaluation engine | +| File | Purpose | +| --------------- | --------------------------------------------------------------------- | +| `types.ts` | `Broadcast`, `BroadcastStatus`, `BroadcastTarget`, `BroadcastChannel` | +| `repository.ts` | CRUD + targeting query builder | +| `routes.ts` | Admin CRUD + public "mark as read" | +| `scheduler.ts` | Cron-based scheduling + A/B testing splits | +| `delivery.ts` | Push (FCM/APNS) + in-app + email dispatch | +| `targeting.ts` | Segment evaluation engine | **Key Types:** @@ -123,25 +123,25 @@ export interface Broadcast { bodyMarkdown?: string; ctaText?: string; ctaUrl?: string; - + // Targeting target: BroadcastTarget; - + // Channels channels: BroadcastChannel[]; // 'push', 'in_app', 'email' - + // Scheduling status: 'draft' | 'scheduled' | 'sending' | 'sent' | 'paused'; scheduledAt?: string; sentAt?: string; - + // A/B Testing variant?: 'control' | 'treatment'; experimentId?: string; - + // Metrics metrics: BroadcastMetrics; - + createdAt: string; updatedAt: string; } @@ -149,25 +149,25 @@ export interface Broadcast { export interface BroadcastTarget { // User segments (AND logic) userSegments?: ('free' | 'pro' | 'enterprise' | 'churned' | 'active')[]; - + // Platform targeting platforms?: ('ios' | 'android' | 'web' | 'macos' | 'windows')[]; - + // App version range appVersionMin?: string; appVersionMax?: string; - + // Geo targeting countryCodes?: string[]; // ISO 3166-1 alpha-2 regionCodes?: string[]; // US-CA, EU-FR, etc. - + // OS version osVersionMin?: string; osVersionMax?: string; - + // Percentage rollout (for phased rollouts) percentageRollout?: number; // 0-100, uses FNV-1a hash like feature flags - + // User IDs (explicit list, for testing) specificUserIds?: string[]; } @@ -187,21 +187,21 @@ export interface BroadcastMetrics { **Endpoints:** -| Method | Endpoint | Auth | Purpose | -|--------|----------|------|---------| -| `POST` | `/admin/broadcasts` | Admin | Create broadcast | -| `GET` | `/admin/broadcasts` | Admin | List all broadcasts | -| `GET` | `/admin/broadcasts/:id` | Admin | Get single broadcast | -| `PUT` | `/admin/broadcasts/:id` | Admin | Update draft/scheduled | -| `DELETE` | `/admin/broadcasts/:id` | Admin | Cancel/delete | -| `POST` | `/admin/broadcasts/:id/send` | Admin | Trigger immediate send (with safety check for >10k users) | -| `POST` | `/admin/broadcasts/:id/pause` | Admin | Pause sending (cancels pending deliveries) | -| `GET` | `/admin/broadcasts/:id/metrics` | Admin | Real-time metrics | -| `POST` | `/admin/broadcasts/:id/clone` | Admin | Duplicate for A/B test | -| `GET` | `/broadcasts` | User | List my active broadcasts | -| `POST` | `/broadcasts/:id/read` | User | Mark as read | -| `POST` | `/broadcasts/:id/dismiss` | User | Dismiss in-app message | -| `POST` | `/broadcasts/:id/click` | User | Track CTA click | +| Method | Endpoint | Auth | Purpose | +| -------- | ------------------------------- | ----- | --------------------------------------------------------- | +| `POST` | `/admin/broadcasts` | Admin | Create broadcast | +| `GET` | `/admin/broadcasts` | Admin | List all broadcasts | +| `GET` | `/admin/broadcasts/:id` | Admin | Get single broadcast | +| `PUT` | `/admin/broadcasts/:id` | Admin | Update draft/scheduled | +| `DELETE` | `/admin/broadcasts/:id` | Admin | Cancel/delete | +| `POST` | `/admin/broadcasts/:id/send` | Admin | Trigger immediate send (with safety check for >10k users) | +| `POST` | `/admin/broadcasts/:id/pause` | Admin | Pause sending (cancels pending deliveries) | +| `GET` | `/admin/broadcasts/:id/metrics` | Admin | Real-time metrics | +| `POST` | `/admin/broadcasts/:id/clone` | Admin | Duplicate for A/B test | +| `GET` | `/broadcasts` | User | List my active broadcasts | +| `POST` | `/broadcasts/:id/read` | User | Mark as read | +| `POST` | `/broadcasts/:id/dismiss` | User | Dismiss in-app message | +| `POST` | `/broadcasts/:id/click` | User | Track CTA click | **Rate Limiting:** Public endpoints (`/broadcasts`, `/broadcasts/:id/read`, etc.) use existing `ratelimit` module: 100 req/min per user. @@ -209,13 +209,13 @@ export interface BroadcastMetrics { **Location:** `services/platform-service/src/modules/surveys/` -| File | Purpose | -|------|---------| -| `types.ts` | `Survey`, `Question`, `QuestionType`, `SurveyResponse` | -| `repository.ts` | CRUD + response aggregation | -| `routes.ts` | Admin CRUD + public response submission | -| `targeting.ts` | Reuses broadcasts/targeting.ts | -| `analytics.ts` | Response statistics, CSV export | +| File | Purpose | +| --------------- | ------------------------------------------------------ | +| `types.ts` | `Survey`, `Question`, `QuestionType`, `SurveyResponse` | +| `repository.ts` | CRUD + response aggregation | +| `routes.ts` | Admin CRUD + public response submission | +| `targeting.ts` | Reuses broadcasts/targeting.ts | +| `analytics.ts` | Response statistics, CSV export | **Key Types:** @@ -226,44 +226,44 @@ export interface Survey { productId: string; title: string; description?: string; - + // Questions questions: Question[]; - + // Targeting (same as BroadcastTarget) target: BroadcastTarget; - + // Scheduling status: 'draft' | 'active' | 'paused' | 'closed'; startsAt?: string; endsAt?: string; - + // Display settings displayTrigger: SurveyTrigger; - + // Incentives incentive?: { type: 'pro_days' | 'credits'; amount: number; }; - + // Metrics metrics: SurveyMetrics; - + createdAt: string; updatedAt: string; } -export type QuestionType = - | 'single_choice' // Radio buttons - | 'multiple_choice' // Checkboxes - | 'rating' // 1-5 or 1-10 stars - | 'nps' // 0-10 scale - | 'text_short' // Single line - | 'text_long' // Multi-line textarea - | 'dropdown' // Select menu - | 'scale' // Likert scale (1-7) - | 'ranking'; // Drag to rank +export type QuestionType = + | 'single_choice' // Radio buttons + | 'multiple_choice' // Checkboxes + | 'rating' // 1-5 or 1-10 stars + | 'nps' // 0-10 scale + | 'text_short' // Single line + | 'text_long' // Multi-line textarea + | 'dropdown' // Select menu + | 'scale' // Likert scale (1-7) + | 'ranking'; // Drag to rank export interface Question { id: string; @@ -271,22 +271,22 @@ export interface Question { text: string; description?: string; required: boolean; - + // For choice types options?: QuestionOption[]; - + // For conditional logic - supports complex AND/OR conditions showIf?: ShowIfCondition; - + // Validation minLength?: number; maxLength?: number; - minValue?: number; // For numeric types + minValue?: number; // For numeric types maxValue?: number; } // Helper type for conditional display (supports nested AND/OR) -export type ShowIfCondition = +export type ShowIfCondition = | { and: ShowIfCondition[] } | { or: ShowIfCondition[] } | { @@ -301,10 +301,10 @@ export interface QuestionOption { emoji?: string; // Optional visual indicator } -export type SurveyTrigger = - | { type: 'immediate' } // Show right away +export type SurveyTrigger = + | { type: 'immediate' } // Show right away | { type: 'delay_seconds'; seconds: number } // After N seconds in app - | { type: 'event'; eventName: string } // After specific event + | { type: 'event'; eventName: string } // After specific event | { type: 'page_view'; pagePattern: string }; // URL pattern match export interface SurveyResponse { @@ -313,22 +313,22 @@ export interface SurveyResponse { productId: string; userId: string; deviceId?: string; - + // Answers answers: Record; - + // Metadata startedAt: string; completedAt?: string; isComplete: boolean; - + // Incentive claimed incentiveClaimed?: boolean; - + createdAt: string; } -export type QuestionAnswer = +export type QuestionAnswer = | { type: 'single_choice'; optionId: string } | { type: 'multiple_choice'; optionIds: string[] } | { type: 'rating'; value: number } @@ -353,24 +353,24 @@ export function computeCompletionRate(metrics: SurveyMetrics): number { **Endpoints:** -| Method | Endpoint | Auth | Purpose | -|--------|----------|------|---------| -| `POST` | `/admin/surveys` | Admin | Create survey | -| `GET` | `/admin/surveys` | Admin | List all surveys | -| `GET` | `/admin/surveys/:id` | Admin | Get survey with questions | -| `PUT` | `/admin/surveys/:id` | Admin | Update survey | -| `DELETE` | `/admin/surveys/:id` | Admin | Delete survey | -| `POST` | `/admin/surveys/:id/duplicate` | Admin | Clone survey | -| `GET` | `/admin/surveys/:id/responses` | Admin | All responses (paginated) | -| `GET` | `/admin/surveys/:id/analytics` | Admin | Aggregated stats | -| `GET` | `/admin/surveys/:id/export.csv` | Admin | CSV export | -| `GET` | `/admin/surveys/:id/respondents` | Admin | List users who responded | -| `POST` | `/admin/surveys/:id/pause` | Admin | Stop showing survey | -| `GET` | `/surveys/active` | User | Get active survey for me (rate limited: 10 req/min) | -| `POST` | `/surveys/:id/start` | User | Begin survey session | -| `POST` | `/surveys/:id/response` | User | Submit answer(s) (validated against question type) | -| `POST` | `/surveys/:id/complete` | User | Mark as complete | -| `POST` | `/surveys/:id/dismiss` | User | "Don't show again" | +| Method | Endpoint | Auth | Purpose | +| -------- | -------------------------------- | ----- | --------------------------------------------------- | +| `POST` | `/admin/surveys` | Admin | Create survey | +| `GET` | `/admin/surveys` | Admin | List all surveys | +| `GET` | `/admin/surveys/:id` | Admin | Get survey with questions | +| `PUT` | `/admin/surveys/:id` | Admin | Update survey | +| `DELETE` | `/admin/surveys/:id` | Admin | Delete survey | +| `POST` | `/admin/surveys/:id/duplicate` | Admin | Clone survey | +| `GET` | `/admin/surveys/:id/responses` | Admin | All responses (paginated) | +| `GET` | `/admin/surveys/:id/analytics` | Admin | Aggregated stats | +| `GET` | `/admin/surveys/:id/export.csv` | Admin | CSV export | +| `GET` | `/admin/surveys/:id/respondents` | Admin | List users who responded | +| `POST` | `/admin/surveys/:id/pause` | Admin | Stop showing survey | +| `GET` | `/surveys/active` | User | Get active survey for me (rate limited: 10 req/min) | +| `POST` | `/surveys/:id/start` | User | Begin survey session | +| `POST` | `/surveys/:id/response` | User | Submit answer(s) (validated against question type) | +| `POST` | `/surveys/:id/complete` | User | Mark as complete | +| `POST` | `/surveys/:id/dismiss` | User | "Don't show again" | **Security:** Survey responses validate answer type matches question type (reject string for NPS question). Admin endpoints require `role === 'admin'`. @@ -397,34 +397,34 @@ export async function evaluateTarget( context: TargetingContext ): Promise { // AND logic across all criteria - + if (target.userSegments && !target.userSegments.some(s => context.userSegments.includes(s))) { return false; } - + if (target.platforms && !target.platforms.includes(context.platform)) { return false; } - + if (target.appVersionMin && semver.lt(context.appVersion, target.appVersionMin)) { return false; } - + if (target.appVersionMax && semver.gt(context.appVersion, target.appVersionMax)) { return false; } - + if (target.countryCodes && !target.countryCodes.includes(context.countryCode ?? '')) { return false; } - + if (target.percentageRollout !== undefined) { const hash = fnv1a32(`${context.userId}:${target.percentageRollout}`); - if ((hash % 100) >= target.percentageRollout) { + if (hash % 100 >= target.percentageRollout) { return false; } } - + return true; } ``` @@ -466,22 +466,22 @@ export interface InAppMessage { export class BroadcastClient { constructor(config: BroadcastClientConfig); - + // Lifecycle initialize(): Promise; dispose(): void; - + // Check for new messages (call on app open, every 5 min) checkMessages(): Promise; - + // Mark actions markRead(messageId: string): Promise; markDismissed(messageId: string): Promise; trackClick(messageId: string, url?: string): Promise; - + // Get cached unread count getUnreadCount(): number; - + // Subscribe to real-time updates (WebSocket fallback to polling) onMessage(handler: (msg: InAppMessage) => void): () => void; } @@ -523,7 +523,7 @@ export interface SurveyClientConfig { osVersion: string; getAuthToken: () => Promise; onSurveyReady: (survey: ActiveSurvey) => void; - + // Event tracking for triggers trackEvent: (eventName: string, metadata?: Record) => void; } @@ -549,22 +549,22 @@ export interface SurveyQuestion { export class SurveyClient { constructor(config: SurveyClientConfig); - + // Lifecycle initialize(): Promise; - + // Check for surveys on trigger events checkForSurveys(context?: { pageUrl?: string; eventName?: string }): Promise; - + // Survey session with offline queue support startSurvey(surveyId: string): Promise; submitAnswer(questionId: string, answer: AnswerValue): Promise; completeSurvey(): Promise<{ incentiveClaimed: boolean }>; dismissSurvey(): Promise; - + // Offline support: queue responses when offline, flush when connected flushOfflineQueue(): Promise<{ flushed: number; failed: number }>; - + // Subscribe to survey availability onSurveyAvailable(handler: (survey: ActiveSurvey) => void): () => void; } @@ -596,7 +596,7 @@ public class BLBroadcastClient: NSObject, UNUserNotificationCenterDelegate { public class BLSurveyClient: ObservableObject { @Published public var activeSurvey: Survey? - + // Native SwiftUI survey sheet public func presentSurvey(_ survey: Survey, from viewController: UIViewController) } @@ -626,12 +626,12 @@ class BLSurveyClient { **Location:** `dashboards/admin-web/src/app/(dashboard)/broadcasts/` -| Page | Features | -|------|----------| -| `page.tsx` | List all broadcasts with status chips | -| `new/page.tsx` | Create wizard: content → targeting → scheduling → preview | -| `[id]/page.tsx` | Edit + metrics dashboard | -| `[id]/preview/page.tsx` | Device mockup preview (iPhone, Android, Web) | +| Page | Features | +| ----------------------- | --------------------------------------------------------- | +| `page.tsx` | List all broadcasts with status chips | +| `new/page.tsx` | Create wizard: content → targeting → scheduling → preview | +| `[id]/page.tsx` | Edit + metrics dashboard | +| `[id]/preview/page.tsx` | Device mockup preview (iPhone, Android, Web) | **Targeting Builder Component:** @@ -670,13 +670,13 @@ interface TargetingBuilderProps { **Location:** `dashboards/admin-web/src/app/(dashboard)/surveys/` -| Page | Features | -|------|----------| -| `page.tsx` | List surveys with completion rates | -| `new/page.tsx` | Survey builder: questions → targeting → display rules | -| `[id]/page.tsx` | Edit + live preview | -| `[id]/analytics/page.tsx` | Response analytics + charts | -| `[id]/responses/page.tsx` | Individual responses table | +| Page | Features | +| ------------------------- | ----------------------------------------------------- | +| `page.tsx` | List surveys with completion rates | +| `new/page.tsx` | Survey builder: questions → targeting → display rules | +| `[id]/page.tsx` | Edit + live preview | +| `[id]/analytics/page.tsx` | Response analytics + charts | +| `[id]/responses/page.tsx` | Individual responses table | **Question Builder Component:** @@ -721,7 +721,7 @@ interface TargetingBuilderProps { // components/broadcasts/BroadcastBanner.tsx // Fixed position banner for in-app messages -// components/broadcasts/BroadcastModal.tsx +// components/broadcasts/BroadcastModal.tsx // Modal overlay for high-priority messages // components/surveys/SurveyModal.tsx @@ -779,7 +779,7 @@ class BroadcastMessagingService : FirebaseMessagingService() { val broadcastId = remoteMessage.data["broadcastId"] // Show notification or in-app message } - + override fun onNewToken(token: String) { BLBroadcastClient.setPushToken(token) } @@ -795,10 +795,10 @@ class BroadcastMessagingService : FirebaseMessagingService() { class BroadcastClient: def __init__(self): self.storage = LocalStorage() - + def check_messages(self) -> List[InAppMessage]: # Poll platform-service - + def show_banner(self, message: InAppMessage): # tkinter overlay or native notification ``` @@ -811,58 +811,61 @@ class BroadcastClient: **Commit:** `1b11db3` — feat(broadcasts,surveys): Phase 1 complete - backend modules -| Day | Task | Deliverable | Status | -|-----|------|-------------|--------| -| 1 | `broadcasts` module scaffold + types | `types.ts`, `repository.ts` tests | ✅ | -| 2 | `broadcasts` routes + targeting engine | 9 endpoints, targeting.ts | ✅ | -| 3 | `surveys` module scaffold + types | `types.ts`, `repository.ts` tests | ✅ | -| 4 | `surveys` routes + question types | 14 endpoints | ✅ | -| 5 | Cosmos containers + server.ts registration | 7 containers, routes registered | ✅ | +| Day | Task | Deliverable | Status | +| --- | ------------------------------------------ | --------------------------------- | ------ | +| 1 | `broadcasts` module scaffold + types | `types.ts`, `repository.ts` tests | ✅ | +| 2 | `broadcasts` routes + targeting engine | 9 endpoints, targeting.ts | ✅ | +| 3 | `surveys` module scaffold + types | `types.ts`, `repository.ts` tests | ✅ | +| 4 | `surveys` routes + question types | 14 endpoints | ✅ | +| 5 | Cosmos containers + server.ts registration | 7 containers, routes registered | ✅ | **Tests:** 80+ unit tests for repositories, 40+ for routes (to be added in follow-up) ### Phase 2: Admin Dashboard (Week 2) ✅ **COMPLETED** **Commits:** + - `...` — feat(admin): Phase 2.1 - Broadcast and Survey list pages -- `...` — feat(admin): Phase 2.2 - Broadcast create/edit wizard +- `...` — feat(admin): Phase 2.2 - Broadcast create/edit wizard - `...` — feat(admin): Phase 2.3 - Survey builder UI -| Day | Task | Deliverable | Status | -|-----|------|-------------|--------| -| 6 | Broadcast list UI | List, filter, actions | ✅ | -| 7 | Broadcast create/edit wizard | Targeting builder, reach estimator | ✅ | -| 8 | Survey builder UI | Question builder, 9 question types | ✅ | -| 9 | Survey list + analytics | Response charts, CSV export | ✅ | -| 10 | Navigation | Sidebar nav items | ✅ | +| Day | Task | Deliverable | Status | +| --- | ---------------------------- | ---------------------------------- | ------ | +| 6 | Broadcast list UI | List, filter, actions | ✅ | +| 7 | Broadcast create/edit wizard | Targeting builder, reach estimator | ✅ | +| 8 | Survey builder UI | Question builder, 9 question types | ✅ | +| 9 | Survey list + analytics | Response charts, CSV export | ✅ | +| 10 | Navigation | Sidebar nav items | ✅ | ### Phase 3: Client SDKs (Week 3) ✅ **COMPLETED** **Commits:** + - `...` — feat(packages): @bytelyst/broadcast-client package - `...` — feat(packages): @bytelyst/survey-client package with offline cache -| Day | Task | Deliverable | Status | -|-----|------|-------------|--------| -| 11 | `@bytelyst/broadcast-client` | Package + types + polling | ✅ | -| 12 | `@bytelyst/survey-client` | Package + validation + offline cache | ✅ | -| 13 | Swift SDK extensions | `BLBroadcastClient`, `BLSurveyClient` | ✅ | -| 14 | Kotlin SDK extensions | `BLBroadcastClient`, `BLSurveyClient` | ✅ | -| 15 | SDK integration tests | All platforms | ⏭️ Future | +| Day | Task | Deliverable | Status | +| --- | ---------------------------- | ------------------------------------- | --------- | +| 11 | `@bytelyst/broadcast-client` | Package + types + polling | ✅ | +| 12 | `@bytelyst/survey-client` | Package + validation + offline cache | ✅ | +| 13 | Swift SDK extensions | `BLBroadcastClient`, `BLSurveyClient` | ✅ | +| 14 | Kotlin SDK extensions | `BLBroadcastClient`, `BLSurveyClient` | ✅ | +| 15 | SDK integration tests | All platforms | ⏭️ Future | ### Phase 4: Platform Integration (Week 4) ✅ **COMPLETED** **Commits:** + - `4bf18f4` — feat(user-dashboard): Phase 4.1 - Web integration components - `...` — feat(platform-service): Phase 4.4 - Push notification wiring (FCM/APNS) -| Day | Task | Deliverable | Status | -|-----|------|-------------|--------| -| 16 | Web integration (user-dashboard) | Banner, modal, survey flow | ✅ | -| 17 | iOS integration | SwiftUI components | ✅ | -| 18 | Android integration | Compose components | ✅ | -| 19 | FCM/APNS setup + testing | Push delivery service | ✅ | -| 20 | Documentation + polish | README, API docs | ⏭️ Future | +| Day | Task | Deliverable | Status | +| --- | -------------------------------- | -------------------------- | --------- | +| 16 | Web integration (user-dashboard) | Banner, modal, survey flow | ✅ | +| 17 | iOS integration | SwiftUI components | ✅ | +| 18 | Android integration | Compose components | ✅ | +| 19 | FCM/APNS setup + testing | Push delivery service | ✅ | +| 20 | Documentation + polish | README, API docs | ⏭️ Future | --- @@ -882,16 +885,16 @@ The Broadcast and Survey platform is now **MVP complete** with: ## 8. Cosmos Containers -| Container | Partition Key | Purpose | Est. Size | TTL | -|-----------|---------------|---------|-----------|-----| -| `broadcasts` | `/productId` | Broadcast definitions + targeting | Small | — | -| `broadcast_deliveries` | `/userId` | Per-user delivery status (avoids hot partitions) | Large | 90 days | -| `broadcast_reads` | `/userId` | User read receipts | Large | 90 days | -| `surveys` | `/productId` | Survey definitions + questions | Small | — | -| `survey_responses` | `/surveyId` | Individual responses | Large | 1 year | -| `in_app_messages` | `/userId` | Active in-app messages per user | Medium | 30 days | -| `targeting_segments` | `/productId` | Pre-computed user segments | Medium | 1 day | -| `broadcast_templates` | `/productId` | Reusable broadcast templates | Small | — | +| Container | Partition Key | Purpose | Est. Size | TTL | +| ---------------------- | ------------- | ------------------------------------------------ | --------- | ------- | +| `broadcasts` | `/productId` | Broadcast definitions + targeting | Small | — | +| `broadcast_deliveries` | `/userId` | Per-user delivery status (avoids hot partitions) | Large | 90 days | +| `broadcast_reads` | `/userId` | User read receipts | Large | 90 days | +| `surveys` | `/productId` | Survey definitions + questions | Small | — | +| `survey_responses` | `/surveyId` | Individual responses | Large | 1 year | +| `in_app_messages` | `/userId` | Active in-app messages per user | Medium | 30 days | +| `targeting_segments` | `/productId` | Pre-computed user segments | Medium | 1 day | +| `broadcast_templates` | `/productId` | Reusable broadcast templates | Small | — | **Partition Key Rationale:** `broadcast_deliveries` uses `/userId` (not `/broadcastId`) to distribute writes across partitions during large sends. Read receipts also use `/userId` for efficient per-user queries. @@ -968,15 +971,15 @@ The Broadcast and Survey platform is now **MVP complete** with: ## Appendix A: DRY Checklist -| Component | Reused From | Notes | -|-----------|-------------|-------| -| Targeting engine | `flags/` module | Same FNV-1a hash, same segment logic | -| Storage adapters | Existing SDK patterns | `BLTelemetryClient` storage pattern | -| Admin UI components | `flags/page.tsx` | Copy table, filters, pagination | -| API client factory | `@bytelyst/api-client` | `createApiClient()` with auth | -| Cosmos repository pattern | All existing modules | `types.ts` → `repository.ts` → `routes.ts` | -| Charts | Admin dashboard Recharts | Same chart components | -| Real-time updates | SSE pattern from telemetry | Or polling fallback | +| Component | Reused From | Notes | +| ------------------------- | -------------------------- | ------------------------------------------ | +| Targeting engine | `flags/` module | Same FNV-1a hash, same segment logic | +| Storage adapters | Existing SDK patterns | `BLTelemetryClient` storage pattern | +| Admin UI components | `flags/page.tsx` | Copy table, filters, pagination | +| API client factory | `@bytelyst/api-client` | `createApiClient()` with auth | +| Cosmos repository pattern | All existing modules | `types.ts` → `repository.ts` → `routes.ts` | +| Charts | Admin dashboard Recharts | Same chart components | +| Real-time updates | SSE pattern from telemetry | Or polling fallback | --- diff --git a/docs/roadmaps/not-started/platform_AGENT_REGISTRY_PROMPT_VERSIONING_ROADMAP.md b/docs/roadmaps/scaffolded/platform_AGENT_REGISTRY_PROMPT_VERSIONING_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_AGENT_REGISTRY_PROMPT_VERSIONING_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_AGENT_REGISTRY_PROMPT_VERSIONING_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_AGENT_RUNTIME_ORCHESTRATION_ROADMAP.md b/docs/roadmaps/scaffolded/platform_AGENT_RUNTIME_ORCHESTRATION_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_AGENT_RUNTIME_ORCHESTRATION_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_AGENT_RUNTIME_ORCHESTRATION_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_AI_BUDGET_COST_GOVERNANCE_ROADMAP.md b/docs/roadmaps/scaffolded/platform_AI_BUDGET_COST_GOVERNANCE_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_AI_BUDGET_COST_GOVERNANCE_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_AI_BUDGET_COST_GOVERNANCE_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_AI_GOVERNANCE_EVALS_ROADMAP.md b/docs/roadmaps/scaffolded/platform_AI_GOVERNANCE_EVALS_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_AI_GOVERNANCE_EVALS_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_AI_GOVERNANCE_EVALS_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_DURABLE_EVENT_BUS_AND_WORKER_RUNTIME_ROADMAP.md b/docs/roadmaps/scaffolded/platform_DURABLE_EVENT_BUS_AND_WORKER_RUNTIME_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_DURABLE_EVENT_BUS_AND_WORKER_RUNTIME_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_DURABLE_EVENT_BUS_AND_WORKER_RUNTIME_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_ENTERPRISE_PROVISIONING_SCIM_ROADMAP.md b/docs/roadmaps/scaffolded/platform_ENTERPRISE_PROVISIONING_SCIM_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_ENTERPRISE_PROVISIONING_SCIM_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_ENTERPRISE_PROVISIONING_SCIM_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_HUMAN_REVIEW_APPROVAL_QUEUE_ROADMAP.md b/docs/roadmaps/scaffolded/platform_HUMAN_REVIEW_APPROVAL_QUEUE_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_HUMAN_REVIEW_APPROVAL_QUEUE_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_HUMAN_REVIEW_APPROVAL_QUEUE_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_KNOWLEDGE_RAG_SERVICE_ROADMAP.md b/docs/roadmaps/scaffolded/platform_KNOWLEDGE_RAG_SERVICE_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_KNOWLEDGE_RAG_SERVICE_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_KNOWLEDGE_RAG_SERVICE_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_ORG_WORKSPACE_RBAC_ROADMAP.md b/docs/roadmaps/scaffolded/platform_ORG_WORKSPACE_RBAC_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_ORG_WORKSPACE_RBAC_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_ORG_WORKSPACE_RBAC_ROADMAP.md diff --git a/docs/roadmaps/not-started/platform_SUPPORT_CASE_MANAGEMENT_ROADMAP.md b/docs/roadmaps/scaffolded/platform_SUPPORT_CASE_MANAGEMENT_ROADMAP.md similarity index 100% rename from docs/roadmaps/not-started/platform_SUPPORT_CASE_MANAGEMENT_ROADMAP.md rename to docs/roadmaps/scaffolded/platform_SUPPORT_CASE_MANAGEMENT_ROADMAP.md