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
This commit is contained in:
parent
0b8e45a9b0
commit
7a4cca034c
477
docs/UNIFIED_BYTELYST_PORTAL_PRD.md
Normal file
477
docs/UNIFIED_BYTELYST_PORTAL_PRD.md
Normal file
@ -0,0 +1,477 @@
|
||||
# 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`](design/CROSS_PRODUCT_USER_DASHBOARD.md), [`DASHBOARD_UI_GAP_ANALYSIS.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)
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
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):
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
### 5.3 Cross-Product Search
|
||||
|
||||
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
|
||||
|
||||
```typescript
|
||||
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._
|
||||
275
docs/UNIFIED_BYTELYST_PORTAL_ROADMAP.md
Normal file
275
docs/UNIFIED_BYTELYST_PORTAL_ROADMAP.md
Normal file
@ -0,0 +1,275 @@
|
||||
# Unified ByteLyst Portal — Roadmap & Task List
|
||||
|
||||
> **Date:** 2026-03-21 · **Companion to:** [`UNIFIED_BYTELYST_PORTAL_PRD.md`](UNIFIED_BYTELYST_PORTAL_PRD.md)
|
||||
> **Estimated total:** 8 phases · ~124 tasks · 6-8 weeks
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Repo Scaffold & Foundations (2 days)
|
||||
|
||||
> **Goal:** Repo exists, builds, deploys to dev. BFF starts and returns health check. Web renders shell.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ----------------------------------------------------------------------------------------- | ------- | --- | --------------------------------------------------------- |
|
||||
| 0.1 | Create `learning_ai_portal` repo with standard structure | infra | 1h | `backend/`, `web/`, `shared/`, `docs/`, `AGENTS.md` |
|
||||
| 0.2 | Create `shared/product.json` (id: `portal`, port: 4020/3010) | config | 15m | Follow existing product.json pattern |
|
||||
| 0.3 | Create `products/portal/product.json` in common-plat | config | 15m | Register portal in product registry |
|
||||
| 0.4 | Scaffold BFF with `@bytelyst/fastify-core` (port 4020) | backend | 1h | `createServiceApp()` + health endpoint |
|
||||
| 0.5 | Add `lib/config.ts` -- Zod-validated env (JWT_SECRET, PLATFORM_URL, product backend URLs) | backend | 30m | |
|
||||
| 0.6 | Add `lib/product-config.ts` -- load from `shared/product.json` | backend | 15m | |
|
||||
| 0.7 | Add `lib/auth.ts` -- JWT extraction + portal scope validation | backend | 30m | |
|
||||
| 0.8 | Add `lib/request-context.ts` -- `getUserId(req)`, `getUserMemberships(req)` | backend | 30m | |
|
||||
| 0.9 | Add `lib/product-registry.ts` -- load all product.json files, build registry | backend | 1h | Read from `../../products/*/product.json` or env-injected |
|
||||
| 0.10 | Add `lib/product-client.ts` -- service-to-service HTTP client for product backends | backend | 1h | Timeout, circuit breaker, x-user-id header |
|
||||
| 0.11 | Scaffold web with Next.js 16 + `@bytelyst/dashboard-shell` (port 3010) | web | 1h | App Router, TailwindCSS v4, `--portal-*` CSS props |
|
||||
| 0.12 | Add `web/src/lib/product-config.ts` -- product identity + API URLs | web | 15m | |
|
||||
| 0.13 | Add `web/src/lib/auth.ts` -- `@bytelyst/react-auth` provider | web | 30m | Cookie-based auth |
|
||||
| 0.14 | Add `web/src/lib/api.ts` -- typed fetch client for BFF | web | 30m | |
|
||||
| 0.15 | Add `web/src/app/layout.tsx` + `providers.tsx` -- shell + auth + telemetry | web | 30m | |
|
||||
| 0.16 | Create `AGENTS.md` with project conventions | docs | 30m | |
|
||||
| 0.17 | Create `.github/workflows/ci.yml` -- typecheck + test for backend + web | infra | 30m | |
|
||||
| 0.18 | Verify: `cd backend && npm test && npm run typecheck` passes | test | 15m | |
|
||||
| 0.19 | Verify: `cd web && npm run typecheck && npm run build` passes | test | 15m | |
|
||||
|
||||
**Phase 0 deliverable:** Repo builds, BFF returns `GET /health`, web renders empty shell with sidebar.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Product Launcher & Auth (3 days)
|
||||
|
||||
> **Goal:** User can log in, see all their products, and launch any product dashboard.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ----------------------------------------------------------------------------------------------------------------------------- | ------- | --- | ------------------------------------------------------------------------------------ |
|
||||
| 1.1 | BFF: `GET /api/portal/products` -- fetch user memberships from platform-service `/auth/me`, enrich with product.json metadata | backend | 2h | Returns `{ products: [{ id, name, icon, plan, role, dashboardUrl, lastActiveAt }] }` |
|
||||
| 1.2 | BFF: `POST /api/portal/products/:id/switch` -- re-issue JWT with new active productId | backend | 1h | |
|
||||
| 1.3 | BFF: service-to-service auth setup -- API key registration for portal-to-product-backend calls | backend | 2h | Register `portal` as a service consumer in platform-service |
|
||||
| 1.4 | Web: `/login` page -- email/password + OAuth buttons via `@bytelyst/react-auth` | web | 2h | Redirect to `/` on success |
|
||||
| 1.5 | Web: `(app)/layout.tsx` -- authenticated route group with `DashboardShell` | web | 1h | Sidebar nav: Home, Products, Activity, Search, Billing, Settings, Security |
|
||||
| 1.6 | Web: `Sidebar.tsx` -- portal sidebar with product icons + nav sections | web | 1h | |
|
||||
| 1.7 | Web: `/products` page -- product launcher grid | web | 3h | Card per product: icon, name, plan badge, last active, "Open" button |
|
||||
| 1.8 | Web: `ProductCard.tsx` component -- product card with theme colors from product.json | web | 1h | |
|
||||
| 1.9 | Web: `/` redirect to `/products` (temporary, until dashboard is built in Phase 3) | web | 15m | |
|
||||
| 1.10 | Web: product launch handler -- opens product dashboard in new tab with session context | web | 1h | Deep link: `https://{domain}/?portal=true` |
|
||||
| 1.11 | Web: show "Get Started" CTA for products user hasn't signed up for | web | 1h | Links to product landing page |
|
||||
| 1.12 | Test: BFF products endpoint returns correct memberships | test | 1h | Vitest |
|
||||
| 1.13 | Test: Login flow to product grid to launch works E2E | test | 1h | Playwright |
|
||||
|
||||
**Phase 1 deliverable:** User logs in, sees grid of their products with status, can open any product in a new tab.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Activity Feed & Notifications (3 days)
|
||||
|
||||
> **Goal:** User sees a chronological feed of recent actions across all products.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ---------------------------------------------------------------------------------------------------- | ------- | --- | -------------------------------------------------------------- |
|
||||
| 2.1 | BFF: `lib/feed-aggregator.ts` -- parallel fan-out to product backends with timeout + circuit breaker | backend | 3h | 3s timeout per product, fail-open |
|
||||
| 2.2 | BFF: Define `FeedEvent` schema + product-specific event mappers | backend | 2h | One mapper per product that normalizes response into FeedEvent |
|
||||
| 2.3 | BFF: `GET /api/portal/feed` -- aggregated feed with pagination (`?cursor=&limit=50`) | backend | 2h | Merge-sort by createdAt desc |
|
||||
| 2.4 | BFF: In-memory cache (60s TTL per user) for feed data | backend | 1h | |
|
||||
| 2.5 | BFF: `GET /api/portal/notifications` -- aggregate from platform-service notifications | backend | 1h | |
|
||||
| 2.6 | Web: `/activity` page -- full-page activity timeline | web | 3h | Filter by product, date range, event type |
|
||||
| 2.7 | Web: `FeedCard.tsx` -- event card with product icon, title, timestamp, deep link | web | 1h | |
|
||||
| 2.8 | Web: `FeedFilters.tsx` -- product multi-select, date range picker | web | 1h | |
|
||||
| 2.9 | Web: Activity feed widget on `/` home page (compact view, last 10 items) | web | 1h | |
|
||||
| 2.10 | Web: Notification bell in top bar -- badge count + dropdown | web | 2h | |
|
||||
| 2.11 | Product backends: Verify each backend has a "recent items" list endpoint | backend | 2h | Add missing endpoints where needed |
|
||||
| 2.12 | Test: Feed aggregation with 3 products up, 2 down | test | 1h | Circuit breaker test |
|
||||
| 2.13 | Test: Feed pagination, sorting, filtering | test | 1h | |
|
||||
|
||||
**Phase 2 deliverable:** `/activity` page shows chronological feed from all products. Home page shows compact feed.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Widget Dashboard (4 days)
|
||||
|
||||
> **Goal:** Home page is a customizable widget grid. Users can add/remove/resize widgets.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --- | --------------------------------------------------------- |
|
||||
| 3.1 | BFF: `modules/widgets/types.ts` -- WidgetDefinition, WidgetLayout schemas | backend | 1h | |
|
||||
| 3.2 | BFF: `modules/widgets/repository.ts` -- CRUD for user widget layouts in Cosmos | backend | 2h | Container: `portal_widget_layouts`, partition: `/userId` |
|
||||
| 3.3 | BFF: `modules/widgets/routes.ts` -- GET/PUT layout, GET widget definitions | backend | 2h | |
|
||||
| 3.4 | BFF: `GET /api/portal/widgets/:widgetId/data` -- fetch widget data from product backend | backend | 2h | Route to correct product backend based on widgetId prefix |
|
||||
| 3.5 | BFF: Register 20+ widget definitions (from PRD section 5.4) | backend | 2h | Static definitions loaded at startup |
|
||||
| 3.6 | BFF: Cosmos container registration for `portal_widget_layouts` | backend | 30m | |
|
||||
| 3.7 | Web: `/` home page with widget grid layout (CSS Grid) | web | 3h | Fixed grid for v1, drag-and-drop in Phase 8 |
|
||||
| 3.8 | Web: `WidgetShell.tsx` -- generic widget wrapper (header, loading, error, resize) | web | 2h | |
|
||||
| 3.9 | Web: `WidgetPicker.tsx` -- modal to add widgets from catalog | web | 2h | Grouped by product |
|
||||
| 3.10 | Web: Implement 5 priority widgets: ChronoMind next-timer, NomGap fast-progress, FlowMonk today-schedule, NoteLett recent-notes, Portal billing-summary | web | 4h | ~45m each |
|
||||
| 3.11 | Web: Implement 5 more widgets: LysnrAI recent-transcripts, MindLyst recent-captures, JarvisJr coaching-streak, ActionTrail recent-actions, PeakPulse weekly-stats | web | 4h | |
|
||||
| 3.12 | Web: Implement remaining 11 widgets | web | 5h | |
|
||||
| 3.13 | Web: `useWidgetData(widgetId)` hook -- fetch + cache + loading/error states | web | 1h | |
|
||||
| 3.14 | Web: Default widget layout for new users (6 widgets: feed + 5 most-active products) | web | 1h | |
|
||||
| 3.15 | Web: Save layout changes to BFF via PUT /api/portal/widgets/layout | web | 1h | Debounced save |
|
||||
| 3.16 | Test: Widget CRUD, layout persistence | test | 1h | |
|
||||
| 3.17 | Test: Widget data fetch with product backend down (graceful degradation) | test | 1h | |
|
||||
|
||||
**Phase 3 deliverable:** Home page has customizable widget grid. Each widget fetches live data.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Cross-Product Search (2 days)
|
||||
|
||||
> **Goal:** Cmd+K opens a global search bar that searches across all products.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ------------------------------------------------------------------------------ | ------- | --- | --------------------------------------------------------------------------- |
|
||||
| 4.1 | BFF: `lib/search-aggregator.ts` -- parallel search fan-out to product backends | backend | 2h | Same circuit-breaker pattern as feed |
|
||||
| 4.2 | BFF: `GET /api/portal/search?q=...&products=...` -- cross-product search | backend | 2h | Returns results grouped by product |
|
||||
| 4.3 | BFF: Product search endpoint mapping -- which endpoint to call per product | backend | 1h | e.g., NoteLett: `GET /api/notes?search=`, LocalMemGPT: `GET /api/search?q=` |
|
||||
| 4.4 | Web: `/search` page -- full search results grouped by product | web | 3h | Product sections, result cards with deep links |
|
||||
| 4.5 | Web: `SearchBar.tsx` -- Cmd+K global search overlay | web | 2h | Debounced input, recent searches, keyboard nav |
|
||||
| 4.6 | Web: `SearchResultCard.tsx` -- generic result card with product badge | web | 1h | |
|
||||
| 4.7 | Web: Add `use-keyboard-shortcuts.ts` -- Cmd+K to open search | web | 30m | |
|
||||
| 4.8 | Product backends: Verify search/filter endpoints exist for each product | backend | 2h | Add missing search endpoints |
|
||||
| 4.9 | Test: Search across 3 products, results merge correctly | test | 1h | |
|
||||
| 4.10 | Test: Search with one product down, others still return | test | 30m | |
|
||||
|
||||
**Phase 4 deliverable:** Cmd+K opens cross-product search. Results grouped by product with deep links.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Billing & Settings (2 days)
|
||||
|
||||
> **Goal:** User manages billing and global preferences from the portal.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ------------------------------------------------------------------------------------------------ | ------- | --- | -------------------------------------------- |
|
||||
| 5.1 | BFF: `GET /api/portal/billing/summary` -- aggregate from platform-service subscriptions + stripe | backend | 2h | Combined monthly cost, per-product breakdown |
|
||||
| 5.2 | BFF: `GET /api/portal/billing/invoices` -- all invoices across products | backend | 1h | |
|
||||
| 5.3 | BFF: `GET /api/portal/preferences` -- user global preferences | backend | 1h | From UserDoc.globalPreferences |
|
||||
| 5.4 | BFF: `PATCH /api/portal/preferences` -- update preferences | backend | 1h | Validate with Zod, save to platform-service |
|
||||
| 5.5 | Platform-service: Add `globalPreferences` field to UserDoc schema | backend | 1h | Optional, backward-compatible |
|
||||
| 5.6 | Platform-service: Add `PATCH /auth/preferences` endpoint | backend | 1h | |
|
||||
| 5.7 | Web: `/billing` page -- subscription cards per product, combined total, invoice list | web | 3h | |
|
||||
| 5.8 | Web: `/settings` page -- theme toggle, timezone picker, locale, notification prefs | web | 3h | |
|
||||
| 5.9 | Web: Theme toggle (dark/light/system) applies to portal immediately | web | 1h | |
|
||||
| 5.10 | Web: Notification preferences -- email/push/in-app toggles, digest frequency | web | 1h | |
|
||||
| 5.11 | Test: Billing aggregation with mixed plan types | test | 1h | |
|
||||
| 5.12 | Test: Preferences save and reload correctly | test | 1h | |
|
||||
|
||||
**Phase 5 deliverable:** `/billing` shows combined costs. `/settings` manages cross-product preferences.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Security & Profile (2 days)
|
||||
|
||||
> **Goal:** Full SmartAuth security management from the portal.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ---------------------------------------------------------------------------------------- | ------- | --- | ------------------------------------------- |
|
||||
| 6.1 | BFF: Proxy security endpoints to platform-service (MFA, passkeys, devices, login-events) | backend | 2h | Same catch-all proxy pattern |
|
||||
| 6.2 | Web: `/security` page -- MFA status, TOTP setup/disable, recovery codes | web | 3h | Reuse patterns from admin-web security page |
|
||||
| 6.3 | Web: `/security` -- passkey management (register, list, remove) | web | 2h | WebAuthn browser API integration |
|
||||
| 6.4 | Web: `/security` -- device list with trust levels, session revocation | web | 2h | |
|
||||
| 6.5 | Web: `/security` -- login history timeline | web | 1h | |
|
||||
| 6.6 | Web: `/profile` page -- name, email, avatar, connected OAuth accounts | web | 2h | |
|
||||
| 6.7 | Web: Connected accounts section -- link/unlink Google, Microsoft, Apple | web | 2h | |
|
||||
| 6.8 | Web: `/support` page -- create/track support tickets via platform-service support-cases | web | 2h | |
|
||||
| 6.9 | Test: MFA setup flow E2E | test | 1h | |
|
||||
| 6.10 | Test: Device revocation works from portal | test | 30m | |
|
||||
|
||||
**Phase 6 deliverable:** Full security management. Profile with OAuth link/unlink. Support ticket creation.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Telemetry, Polish & Launch (3 days)
|
||||
|
||||
> **Goal:** Production-ready portal with telemetry, error handling, and polished UI.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ----------------------------------------------------------------------------------------------- | ------- | --- | ----- |
|
||||
| 7.1 | BFF: Telemetry event buffer -- portal-specific events (product_launched, search_executed, etc.) | backend | 1h | |
|
||||
| 7.2 | BFF: Feature flags integration -- `@bytelyst/feature-flag-client` | backend | 30m | |
|
||||
| 7.3 | BFF: Kill switch integration -- `@bytelyst/kill-switch-client` | backend | 30m | |
|
||||
| 7.4 | BFF: Rate limiting on search and feed endpoints | backend | 1h | |
|
||||
| 7.5 | BFF: Request logging with structured context | backend | 30m | |
|
||||
| 7.6 | Web: Telemetry client -- track portal events via `@bytelyst/telemetry-client` | web | 1h | |
|
||||
| 7.7 | Web: Error boundaries -- per-widget and per-page | web | 1h | |
|
||||
| 7.8 | Web: Loading skeletons for all pages | web | 2h | |
|
||||
| 7.9 | Web: Empty states for zero-product users (onboarding CTA) | web | 1h | |
|
||||
| 7.10 | Web: Responsive design -- mobile-friendly sidebar collapse | web | 2h | |
|
||||
| 7.11 | Web: PWA manifest + service worker for offline shell | web | 1h | |
|
||||
| 7.12 | Web: `--portal-*` design tokens from `@bytelyst/design-tokens` | web | 1h | |
|
||||
| 7.13 | Web: Keyboard shortcuts -- Cmd+K (search), Cmd+1-9 (product launch) | web | 1h | |
|
||||
| 7.14 | Docs: Update `AGENTS.md` with final architecture | docs | 1h | |
|
||||
| 7.15 | Docs: Write `README.md` with setup instructions | docs | 30m | |
|
||||
| 7.16 | Docker: `Dockerfile` for BFF + web | infra | 1h | |
|
||||
| 7.17 | Docker: Add to `docker-compose.yml` in common-plat | infra | 30m | |
|
||||
| 7.18 | CI: Playwright E2E test suite (10 core flows) | test | 3h | |
|
||||
| 7.19 | CI: Add portal to `run-local-all-services.sh` | infra | 15m | |
|
||||
| 7.20 | Final: Typecheck + test + build green across BFF + web | test | 1h | |
|
||||
|
||||
**Phase 7 deliverable:** Production-ready portal. All tests pass. Docker-deployable. Telemetry wired.
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Post-Launch Enhancements (Ongoing)
|
||||
|
||||
> **Goal:** Iterative improvements based on usage data.
|
||||
|
||||
| # | Task | Type | Est | Notes |
|
||||
| ---- | ------------------------------------------------------------- | ------- | --- | --------------------------------------------------- |
|
||||
| 8.1 | Drag-and-drop widget reordering (react-dnd or dnd-kit) | web | 3h | |
|
||||
| 8.2 | Embedded product views (iframe) with postMessage auth | web | 4h | v2 of product launcher |
|
||||
| 8.3 | SSE-based real-time feed updates | backend | 3h | `@bytelyst/fastify-sse` |
|
||||
| 8.4 | Cross-product quick actions (e.g., "Start Timer" from portal) | web+bff | 4h | Product backends expose action endpoints |
|
||||
| 8.5 | Mobile-responsive PWA optimization | web | 2h | |
|
||||
| 8.6 | Admin analytics -- portal engagement metrics in admin-web | web | 3h | Cross-product adoption charts |
|
||||
| 8.7 | Smart widget suggestions based on user activity patterns | backend | 2h | "You use ChronoMind daily -- add the timer widget?" |
|
||||
| 8.8 | Unified notification center with mark-read, filters | web | 3h | |
|
||||
| 8.9 | Product health badges -- show backend status in product cards | bff | 1h | Poll health endpoints |
|
||||
| 8.10 | Custom widget themes -- user sets accent color per widget | web | 1h | |
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Phase | Name | Duration | Tasks | Key Deliverable |
|
||||
| ----- | ------------------------------- | ------------ | ------- | ----------------------------------- |
|
||||
| **0** | Repo Scaffold and Foundations | 2 days | 19 | Repo builds, shell renders |
|
||||
| **1** | Product Launcher and Auth | 3 days | 13 | Login, product grid, launch |
|
||||
| **2** | Activity Feed and Notifications | 3 days | 13 | Cross-product activity timeline |
|
||||
| **3** | Widget Dashboard | 4 days | 17 | Customizable widget grid |
|
||||
| **4** | Cross-Product Search | 2 days | 10 | Cmd+K global search |
|
||||
| **5** | Billing and Settings | 2 days | 12 | Combined billing + global prefs |
|
||||
| **6** | Security and Profile | 2 days | 10 | Full SmartAuth security from portal |
|
||||
| **7** | Polish and Launch | 3 days | 20 | Production-ready, Docker, E2E |
|
||||
| **8** | Post-Launch | Ongoing | 10 | Drag-drop, SSE, quick actions |
|
||||
| | **Total** | **~21 days** | **124** | |
|
||||
|
||||
---
|
||||
|
||||
## Dependency Graph
|
||||
|
||||
```
|
||||
Phase 0 (scaffold)
|
||||
|
|
||||
v
|
||||
Phase 1 (auth + products)
|
||||
|
|
||||
+---> Phase 2 (feed) ---> Phase 3 (widgets)
|
||||
|
|
||||
+---> Phase 4 (search)
|
||||
|
|
||||
+---> Phase 5 (billing + settings)
|
||||
|
|
||||
+---> Phase 6 (security + profile)
|
||||
|
|
||||
v
|
||||
Phase 7 (polish + launch) <-- all above complete
|
||||
|
|
||||
v
|
||||
Phase 8 (post-launch enhancements)
|
||||
```
|
||||
|
||||
**Critical path:** Phase 0 -> Phase 1 -> Phase 2 -> Phase 3 -> Phase 7
|
||||
|
||||
Phases 4, 5, 6 can be parallelized after Phase 1.
|
||||
|
||||
---
|
||||
|
||||
_This roadmap should be reviewed after each phase. Estimates are in ideal developer-hours._
|
||||
Loading…
Reference in New Issue
Block a user