learning_ai_common_plat/docs/UNIFIED_BYTELYST_PORTAL_PRD.md
saravanakumardb1 7a4cca034c docs: add Unified ByteLyst Portal PRD + phased roadmap with 124 tasks
- PRD: product identity, architecture (BFF + web), data model, 10 pages,
  21 widgets, cross-product feed/search, security, resilience, telemetry
- Roadmap: 8 phases (scaffold, auth, feed, widgets, search, billing,
  security, polish), dependency graph, ~21 days estimated
- Builds on CROSS_PRODUCT_USER_DASHBOARD.md design + DASHBOARD_UI_GAP_ANALYSIS.md findings
2026-03-21 20:49:55 -07:00

27 KiB
Raw Blame History

Unified ByteLyst Portal — Product Requirements Document

Date: 2026-03-21 · Status: Draft · Author: AI-assisted
Depends on: SmartAuth OneAuth (Phase 5), @bytelyst/dashboard-shell, platform-service
See also: CROSS_PRODUCT_USER_DASHBOARD.md, DASHBOARD_UI_GAP_ANALYSIS.md


1. Product Identity

Key Value
Product ByteLyst Portal
Product ID portal
Domain portal.bytelyst.com
Repo learning_ai_portal (new)
Ecosystem ByteLyst (consumes platform-service + all 11 product backends)
Port (web) 3010
Port (BFF) 4020

2. Problem Statement

The ByteLyst ecosystem has grown to 11 products (LysnrAI, MindLyst, ChronoMind, JarvisJr, NomGap, PeakPulse, FlowMonk, NoteLett, ActionTrail, LocalMemGPT, ByteLyst Auth), each with its own web dashboard, login, and settings. Users who use multiple products face:

  1. Separate logins — even though OneAuth shares identity, users still open different URLs per product
  2. No unified view — no way to see "what's happening across all my ByteLyst apps"
  3. Fragmented settings — notification preferences, theme, timezone set per-product
  4. No cross-product search — can't search across notes, timers, sessions, tasks from one place
  5. No unified billing — subscriptions managed per-product with no combined view

Meanwhile, the admin dashboard has grown to 43+ backend modules with 511+ endpoints, but the gap analysis shows 55 features are hidden or underexposed in the UI. The admin console is becoming unmanageable — it needs to evolve alongside the user-facing portal.


3. Goals

3.1 User-Facing Portal Goals

# Goal Success Metric
G1 Single login, all products — one URL, one session, access everything 100% of products accessible from portal
G2 Cross-product activity feed — timeline of recent actions across all products Feed renders within 2s for users with 5+ products
G3 Unified search — search notes, timers, tasks, sessions, memories from one bar Cross-product search returns results in <1s
G4 Product launcher — app-switcher grid (like Google's waffle menu) All 11 products launchable with deep links
G5 Combined billing — single view of all subscriptions, invoices, usage Zero billing queries to support about "which product charges what"
G6 Global settings — theme, timezone, notification prefs apply cross-product Settings changes propagate to all products within 30s
G7 Cross-product widgets — composable dashboard with pinnable product widgets Users can customize their portal home with ≥10 widget types

3.2 Platform Goals

# Goal Success Metric
P1 Reusable shell — portal built on @bytelyst/dashboard-shell Shell package consumed without forking
P2 BFF pattern — portal has its own Backend-For-Frontend that aggregates data from product backends No direct browser→product-backend calls
P3 Progressive rollout — portal works even if some product backends are down Graceful degradation for unavailable products
P4 Extensible product cards — each product registers a "portal card" config New products auto-appear in portal via product.json

3.3 Non-Goals (Explicit)

  • Not replacing product dashboards — portal is a hub, not a replacement. Deep actions still happen in product UIs.
  • Not an admin console — portal is user-facing. Admin features stay in admin-web.
  • Not a mobile app — web-only for v1. Native portal is a future consideration.
  • Not real-time collaboration — this is a personal dashboard, not a shared workspace.

4. Architecture

4.1 High-Level Architecture

┌─────────────────────────────────────────────────────────────┐
│                    ByteLyst Portal (web)                      │
│                     Next.js 16 · port 3010                   │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐   │
│  │ Product   │ │ Activity │ │ Search   │ │ Settings     │   │
│  │ Launcher  │ │ Feed     │ │ Bar      │ │ & Billing    │   │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘   │
│       │             │            │               │           │
│       └─────────────┴────────────┴───────────────┘           │
│                          │                                    │
│              Portal BFF (Fastify 5 · port 4020)              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ /api/portal/products    — product registry            │   │
│  │ /api/portal/feed        — aggregated activity         │   │
│  │ /api/portal/search      — cross-product search        │   │
│  │ /api/portal/widgets     — widget data aggregation     │   │
│  │ /api/portal/preferences — global user preferences     │   │
│  │ /api/portal/billing     — combined billing summary    │   │
│  └──────────────────────────────────────────────────────┘   │
│                          │                                    │
└──────────────────────────┼──────────────────────────────────┘
                           │
        ┌──────────────────┼──────────────────────┐
        ▼                  ▼                       ▼
   platform-service   product backends        product backends
     (port 4003)      (ports 4010-4019)      (ports 4010-4019)
   ┌──────────┐      ┌───────────────┐      ┌───────────────┐
   │ auth     │      │ LysnrAI 4015  │      │ FlowMonk 4017 │
   │ billing  │      │ MindLyst 4014 │      │ NoteLett 4016  │
   │ flags    │      │ ChronoMind4011│      │ ActionTrail4018│
   │ telemetry│      │ JarvisJr 4012 │      │ LocalMem  4019 │
   │ usage    │      │ NomGap   4013 │      │ PeakPulse 4010 │
   └──────────┘      └───────────────┘      └───────────────┘

4.2 Data Model

4.2.1 UserDoc Enhancement (already in place via OneAuth)

interface UserDoc {
  id: string;
  email: string;
  primaryProductId: string;
  memberships: ProductMembership[]; // ← from SmartAuth Phase 5
  globalPreferences?: GlobalPreferences; // ← NEW for portal
}

interface ProductMembership {
  productId: string;
  role: 'user' | 'admin';
  plan: 'free' | 'pro' | 'enterprise';
  firstAccessAt: string;
  subscriptionId?: string;
  licenseId?: string;
}

interface GlobalPreferences {
  theme: 'light' | 'dark' | 'system';
  timezone: string;
  locale: string;
  notifications: {
    email: boolean;
    push: boolean;
    inApp: boolean;
    digest: 'none' | 'daily' | 'weekly';
  };
  portalLayout: WidgetLayout[];
}

4.2.2 Portal Widget Config

interface WidgetLayout {
  widgetId: string; // e.g. 'lysnrai:recent-transcripts'
  productId: string;
  position: { row: number; col: number; width: number; height: number };
  config?: Record<string, unknown>;
}

interface PortalWidgetDefinition {
  id: string;
  productId: string;
  name: string;
  description: string;
  icon: string;
  sizes: ('small' | 'medium' | 'large')[];
  dataEndpoint: string; // BFF endpoint that fetches widget data
}

4.2.3 Product Registry (from existing product.json files)

Each product already has a product.json with:

  • id, name, displayName, domain, description
  • theme (colors)
  • features (capability flags)
  • ports (service + dashboard)

The BFF reads all products/*/product.json at startup to build the product registry. No new schema needed.

4.3 BFF API Endpoints

Method Path Description Source
GET /api/portal/products List products user has access to platform-service /auth/me
GET /api/portal/feed Cross-product activity feed (last 7d) Fan-out to product backends
GET /api/portal/search?q=... Cross-product search Fan-out to product search endpoints
GET /api/portal/widgets/:widgetId Fetch data for a specific widget Product backend endpoint
GET /api/portal/preferences Get global preferences platform-service
PATCH /api/portal/preferences Update global preferences platform-service
GET /api/portal/billing/summary Combined billing across products platform-service subscriptions
GET /api/portal/billing/invoices All invoices across products platform-service stripe
POST /api/portal/products/:id/switch Switch active product context JWT re-issue
GET /api/portal/notifications Aggregated notifications platform-service
GET /api/portal/quick-actions Available quick actions per product Product registrations

4.4 JWT Enhancement

Current JWT (already includes memberships via OneAuth):

{
  "sub": "user-123",
  "productId": "lysnrai",
  "primaryProductId": "lysnrai",
  "memberships": [
    { "productId": "lysnrai", "role": "user" },
    { "productId": "mindlyst", "role": "admin" }
  ]
}

Portal JWT adds a scope: "portal" claim so product backends know the request comes from the portal BFF:

{
  "sub": "user-123",
  "scope": "portal",
  "primaryProductId": "lysnrai",
  "memberships": [...]
}

4.5 Tech Stack

Layer Technology
Web Next.js 16 (App Router), React 19, TailwindCSS v4, @bytelyst/dashboard-shell, Zustand, Recharts, Lucide icons
BFF Fastify 5, TypeScript ESM, @bytelyst/fastify-core, @bytelyst/api-client, @bytelyst/auth
Auth JWT via jose, cookie-based session, @bytelyst/react-auth
Shared packages @bytelyst/config, @bytelyst/errors, @bytelyst/logger, @bytelyst/design-tokens, @bytelyst/telemetry-client, @bytelyst/feature-flag-client, @bytelyst/kill-switch-client
Database Azure Cosmos DB (productId: "portal") for portal-specific data (widget layouts, preferences)
Tests Vitest (BFF), Playwright (E2E)

5. Pages & UI

5.1 Page Map

Page Route Description
Home / Dashboard / Customizable widget grid + activity feed
Products /products Product launcher grid with status badges
Activity /activity Full cross-product activity timeline with filters
Search /search Cross-product search results grouped by product
Billing /billing Combined subscriptions, invoices, usage
Settings /settings Global preferences (theme, timezone, notifications)
Security /security MFA, passkeys, devices, sessions (from SmartAuth)
Profile /profile User profile, connected accounts (OAuth link/unlink)
Product Detail /products/[id] Deep link into product with embedded iframe or redirect
Support /support Cross-product support ticket creation and tracking

5.2 Product Launcher (Home)

The home page has three zones:

  1. Product Grid (top) — 3×4 grid of product cards. Each card shows:

    • Product icon + name
    • Status badge (active/trial/free)
    • Last activity timestamp
    • Quick action button (e.g., "New Timer" for ChronoMind, "Dictate" for LysnrAI)
    • Click → opens product dashboard in new tab or embedded view
  2. Activity Feed (left 60%) — chronological feed of recent events:

    • "You completed a 25-min Pomodoro in ChronoMind"
    • "New note created in NoteLett: 'Meeting Notes'"
    • "JarvisJr coaching session: 3 insights extracted"
    • Each item has product icon, timestamp, and deep link
  3. Widgets (right 40%) — user-configurable widget stack:

    • ChronoMind: next timer countdown
    • NomGap: current fast progress
    • FlowMonk: today's schedule
    • MindLyst: brain activity heatmap
    • LysnrAI: recent transcripts
    • PeakPulse: weekly stats

Global search bar in the top bar (Cmd+K). Results grouped by product:

🔍 "meeting notes"

📝 NoteLett (3 results)
  - Meeting Notes — Project Alpha (2h ago)
  - Weekly Standup Notes (yesterday)
  - Client Meeting Follow-up (3d ago)

🎤 LysnrAI (2 results)
  - Meeting transcript — 03/21 (today)
  - Meeting transcript — 03/18

🧠 MindLyst (1 result)
  - Memory: "Meeting with design team" in Work brain

5.4 Widget System

Widgets are the portal's core differentiator. Each product registers widget definitions:

Widget ID Product Size Description
lysnrai:recent-transcripts LysnrAI Medium Last 5 transcripts with duration
lysnrai:usage-chart LysnrAI Large Weekly transcription minutes chart
chronomind:next-timer ChronoMind Small Countdown to next timer/alarm
chronomind:today-schedule ChronoMind Medium Today's timers and routines
nomgap:fast-progress NomGap Small Current fast elapsed/remaining
nomgap:streak NomGap Small Fasting streak count
mindlyst:brain-activity MindLyst Medium Brain captures heatmap (7d)
mindlyst:recent-captures MindLyst Medium Last 5 captures with brain tags
jarvisjr:coaching-streak JarvisJr Small Coaching session streak
jarvisjr:recent-sessions JarvisJr Medium Last 3 agent sessions
flowmonk:today-schedule FlowMonk Medium Today's planned flow slots
flowmonk:task-summary FlowMonk Small Tasks: pending/done/overdue
notelett:recent-notes NoteLett Medium Last 5 notes with tags
notelett:workspace-summary NoteLett Small Workspace note counts
actiontrail:recent-actions ActionTrail Medium Last 10 agent actions
actiontrail:risk-summary ActionTrail Small Risk level distribution
peakpulse:weekly-stats PeakPulse Medium Distance, elevation, sessions
peakpulse:recent-sessions PeakPulse Medium Last 3 adventure sessions
localmemgpt:recent-chats LocalMemGPT Medium Last 5 conversations
portal:billing-summary Portal Small Combined monthly cost
portal:security-status Portal Small MFA status, device count

6. Cross-Product Activity Feed

6.1 Feed Event Schema

interface FeedEvent {
  id: string;
  productId: string;
  productName: string;
  productIcon: string;
  userId: string;
  type: string; // product-specific event type
  title: string; // human-readable summary
  description?: string;
  deepLink?: string; // URL to the item in the product dashboard
  metadata?: Record<string, unknown>;
  createdAt: string;
}

6.2 Event Sources per Product

Product Event Types Source
LysnrAI transcript.created, session.completed GET /api/transcripts?limit=10
MindLyst capture.created, triage.completed GET /api/memory-items?limit=10
ChronoMind timer.completed, routine.finished, pomodoro.done GET /api/timers/recent
JarvisJr session.completed, memory.created GET /api/jarvis-sessions?limit=10
NomGap fast.started, fast.completed, milestone.reached GET /api/fasting-sessions?limit=10
PeakPulse session.recorded, goal.achieved, badge.unlocked GET /api/sessions?limit=10
FlowMonk task.completed, schedule.generated, entry.done GET /api/schedule-entries?limit=10
NoteLett note.created, note.updated, task.extracted GET /api/notes?limit=10
ActionTrail action.ingested, alert.fired, approval.decided GET /api/actions?limit=10
LocalMemGPT conversation.created, document.uploaded GET /api/conversations?limit=10

6.3 Aggregation Strategy

The BFF fetches from all product backends in parallel with:

  • Timeout: 3s per product (fail-open — missing products show "temporarily unavailable")
  • Caching: 60s TTL in-memory cache per user
  • Pagination: Feed returns 50 items max, sorted by createdAt desc
  • Circuit breaker: After 3 consecutive failures, skip product for 5 minutes

7. Security & Auth

7.1 Authentication Flow

  1. User visits portal.bytelyst.com
  2. If no session, redirect to /login (uses platform-service /auth/login)
  3. On success, BFF issues a portal-scoped JWT with all memberships
  4. JWT stored as httpOnly cookie (not localStorage)
  5. BFF proxies requests to product backends using service-to-service auth

7.2 Authorization

  • Portal BFF has a service API key for each product backend
  • When fetching product data, BFF sends x-user-id + x-portal-token headers
  • Product backends validate the portal service key and scope data to the user
  • Users can only see data for products they have memberships in

7.3 Security Page Features

Leverages existing SmartAuth infrastructure:

  • MFA management — TOTP setup/disable, recovery codes
  • Passkey management — register/remove WebAuthn credentials
  • Device management — view trusted devices, revoke sessions
  • Login history — recent login events with IP/location
  • Connected accounts — link/unlink Google, Microsoft, Apple OAuth

8. Offline & Resilience

8.1 Graceful Degradation

The portal must work even when some product backends are down:

Scenario Behavior
Product backend down Widget shows "Temporarily unavailable" with retry button
Platform-service down Portal shows cached data, auth redirects to maintenance page
BFF down Static Next.js pages with "Service connecting..." message
Slow product backend (>3s) Widget shows skeleton, loads async when available

8.2 Caching Strategy

Data Cache TTL Storage
Product registry 1 hour BFF memory
User memberships 5 minutes BFF memory
Activity feed 60 seconds BFF memory per user
Widget data 30 seconds BFF memory per widget
Global preferences 10 minutes BFF memory per user
Search results No cache Real-time fan-out

9. Telemetry & Analytics

9.1 Portal-Specific Events

Event Properties
portal.product_launched productId, source (grid/feed/search/widget)
portal.search_executed query, resultCount, productHits[]
portal.widget_interacted widgetId, action
portal.layout_customized widgetCount, widgetIds[]
portal.preference_changed key, oldValue, newValue
portal.feed_scrolled depth, productsVisible[]

9.2 Cross-Product Insights (Admin)

The portal BFF can provide admin-web with:

  • Cross-product adoption: How many users use 1, 2, 3+ products
  • Product affinity: Which products are commonly used together
  • Portal engagement: Time spent in portal vs. direct product access
  • Widget popularity: Most/least configured widgets

10. Open Questions

# Question Options Recommendation
Q1 Standalone repo or inside common-plat? Standalone learning_ai_portal vs. dashboards/portal-web/ Standalone repo — it has its own BFF, making it more than a dashboard
Q2 Embedded product views or redirect? iframe embed vs. open in new tab New tab for v1, embedded for v2
Q3 Should BFF own its own Cosmos containers? Yes (portal-specific) vs. use platform-service only Yes — for widget layouts, portal preferences, feed cache
Q4 Widget data: pull or push? BFF polls products vs. products push events Pull for v1 (simpler), SSE push for v2
Q5 How does portal handle products user hasn't signed up for? Hide vs. show with "Get Started" CTA Show with CTA — drives cross-product adoption

11. Dependencies

Dependency Status Blocker?
OneAuth memberships[] on UserDoc Implemented No
/auth/me returns product list Implemented No
@bytelyst/dashboard-shell Published No
@bytelyst/react-auth Published No
Product backends expose recent-items APIs ⚠️ Partial — most have list endpoints Non-blocking (graceful degradation)
product.json files for all 11 products 7 exist, 4 need creation Non-blocking
Service-to-service auth (portal BFF → product backends) Needs implementation Phase 1 blocker
Global preferences on UserDoc Needs implementation Phase 2 blocker

This PRD should be reviewed and updated as implementation progresses.