docs: thorough review of service consolidation roadmap — 12 critical gaps identified
- Gap 1: Product ID naming inconsistency (tracker uses DEFAULT_PRODUCT_ID) - Gap 2: Missing deps in platform-service (stripe, @bytelyst/auth, @fastify/rate-limit) - Gap 3: Billing internal key auth must be scoped (not global hook) - Gap 4-5: Growth webhooks lib + Stripe key config - Gap 6: 17+ consumer files need URL updates across LysnrAI repo - Gap 7: Ops status health check route references old ports - Gap 8: Stripe webhook test hardcodes port 4002 - Gap 9-10: Load tests + Stripe docs reference old ports - Gap 11: LysnrAI services/ env stubs need cleanup - Gap 12: Mobile apps — no changes needed (confirmed) - Route collision check: verified no conflicts - Added Python client updates, Phase 0 baseline steps, pnpm install verification
This commit is contained in:
parent
e4b55a0424
commit
9f6c12043c
@ -3,7 +3,8 @@
|
||||
> **Goal:** Merge `billing-service`, `growth-service`, and `tracker-service` into `platform-service` so we have one unified Fastify service for all common platform concerns. `extraction-service` stays separate (Python sidecar).
|
||||
>
|
||||
> **Created:** 2026-02-14
|
||||
> **Estimated effort:** 3–4 days
|
||||
> **Reviewed:** 2026-02-14 (thorough gap analysis — see Critical Gaps section)
|
||||
> **Estimated effort:** 4–5 days
|
||||
> **Blocked by:** Nothing — can start immediately
|
||||
|
||||
---
|
||||
@ -22,6 +23,138 @@
|
||||
|
||||
---
|
||||
|
||||
## Critical Gaps Found During Review
|
||||
|
||||
> These MUST be addressed during the merge or features/tests will break.
|
||||
|
||||
### Gap 1: Product ID Naming Inconsistency
|
||||
|
||||
Services export product ID differently — modules reference different names:
|
||||
|
||||
| Service | Export Name | Source |
|
||||
|---------|-----------|--------|
|
||||
| **platform-service** | `PRODUCT_ID` | `loadProductIdentity().productId` from `@bytelyst/config` |
|
||||
| **growth-service** | `PRODUCT_ID` | same as platform ✅ |
|
||||
| **billing-service** | `PRODUCT_ID` | same as platform ✅ |
|
||||
| **tracker-service** | `DEFAULT_PRODUCT_ID` | `process.env.DEFAULT_PRODUCT_ID \|\| getProductId()` — **different name** ⚠️ |
|
||||
|
||||
**Fix:** When merging tracker modules, change all `DEFAULT_PRODUCT_ID` imports to `PRODUCT_ID` in the copied module files, and add `DEFAULT_PRODUCT_ID` env var support to platform-service's `product-config.ts` for backward compat.
|
||||
|
||||
### Gap 2: Missing Dependencies in Platform-Service
|
||||
|
||||
Platform-service `package.json` is **missing** these deps needed by merged modules:
|
||||
|
||||
| Dep | Needed By | Currently In |
|
||||
|-----|-----------|-------------|
|
||||
| `stripe` (^17.5.0) | billing modules (stripe webhooks, checkout) | billing-service, growth-service |
|
||||
| `@bytelyst/auth` (workspace:*) | tracker modules (`extractAuth`) | tracker-service |
|
||||
| `@fastify/rate-limit` (^10.3.0) | tracker rate limiting | tracker-service |
|
||||
|
||||
### Gap 3: Billing Internal Key Auth (Global Hook)
|
||||
|
||||
`billing-service/src/server.ts` has a **global** `onRequest` hook:
|
||||
```typescript
|
||||
app.addHook('onRequest', async (req, reply) => {
|
||||
if (path === '/health' || path.includes('/stripe/webhook')) return;
|
||||
const key = req.headers['x-internal-key'];
|
||||
if (key !== INTERNAL_KEY) reply.code(401).send(...)
|
||||
});
|
||||
```
|
||||
This **cannot** be a global hook after merge — it would block auth, audit, tracker, etc. routes.
|
||||
|
||||
**Fix:** Convert to a Fastify plugin registered only on billing route prefixes, or add `x-internal-key` check inside each billing route handler.
|
||||
|
||||
### Gap 4: Growth Webhooks Library
|
||||
|
||||
`growth-service/src/lib/webhooks.ts` dispatches fire-and-forget HTTP callbacks on invitation redeem. References env vars:
|
||||
- `WEBHOOK_INVITATION_REDEEMED_URL`
|
||||
- `WEBHOOK_REFERRAL_STATUS_URL`
|
||||
|
||||
**Fix:** Copy `webhooks.ts` to platform-service `src/lib/`, add both env vars to config schema.
|
||||
|
||||
### Gap 5: Growth Config Requires `STRIPE_SECRET_KEY`
|
||||
|
||||
Growth-service config requires `STRIPE_SECRET_KEY` as **required** (not optional). Platform-service doesn't currently need Stripe at all.
|
||||
|
||||
**Fix:** Add `STRIPE_SECRET_KEY` to platform-service config. Make it **optional** with validation only when billing/growth routes are hit (or make it required after merge since billing always needs it).
|
||||
|
||||
### Gap 6: 17+ Consumer Files Need URL Updates (LysnrAI Repo)
|
||||
|
||||
**Dashboard API clients (TypeScript):**
|
||||
|
||||
| File | Current Env Var | Current Default |
|
||||
|------|----------------|-----------------|
|
||||
| `admin-dashboard-web/src/lib/billing-client.ts` | `BILLING_SERVICE_URL` | `http://localhost:4002` |
|
||||
| `admin-dashboard-web/src/lib/growth-client.ts` | `GROWTH_SERVICE_URL` | `http://localhost:4001` |
|
||||
| `user-dashboard-web/src/lib/billing-client.ts` | `BILLING_SERVICE_URL` | `http://localhost:4002` |
|
||||
| `user-dashboard-web/src/lib/growth-client.ts` | `GROWTH_SERVICE_URL` | `http://localhost:4001` |
|
||||
| `user-dashboard-web/src/app/api/stripe/webhook/route.ts` | `BILLING_SERVICE_URL` | `http://localhost:4002` |
|
||||
| `admin-dashboard-web/src/app/api/stripe/config/route.ts` | — | `http://localhost:4002` inline |
|
||||
| `admin-dashboard-web/src/lib/stripe-context.tsx` | — | `http://localhost:4002` (3 places) |
|
||||
| `tracker-dashboard-web/src/app/api/tracker/[...path]/route.ts` | `TRACKER_API_URL` | `http://localhost:4004` |
|
||||
| `tracker-dashboard-web/src/app/api/auth/login/route.ts` | `PLATFORM_API_URL` | `http://localhost:4003` ✅ |
|
||||
| `tracker-dashboard-web/src/app/api/auth/me/route.ts` | `PLATFORM_API_URL` | `http://localhost:4003` ✅ |
|
||||
|
||||
**Python clients (desktop + backend):**
|
||||
|
||||
| File | Current Env Var | Current Default |
|
||||
|------|----------------|-----------------|
|
||||
| `backend/src/clients/billing_client.py` | `BILLING_SERVICE_URL` | `http://localhost:4002` |
|
||||
| `src/cloud/api_sync.py` | `BILLING_SERVICE_URL` | `http://localhost:4002` |
|
||||
| `src/cloud/plan_resolver.py` | `BILLING_SERVICE_URL` | `http://localhost:4002` |
|
||||
|
||||
All these must change to `PLATFORM_SERVICE_URL` / `http://localhost:4003`.
|
||||
|
||||
### Gap 7: Ops Status Health Check Route
|
||||
|
||||
`admin-dashboard-web/src/app/api/ops/status/route.ts` checks health of 5 individual services on separate ports. After consolidation, billing/growth/tracker entries must be removed — they'll all respond on platform-service's `/health`.
|
||||
|
||||
### Gap 8: Stripe Webhook Test Hardcodes Port
|
||||
|
||||
`user-dashboard-web/src/__tests__/stripe-webhook.test.ts` sets:
|
||||
```typescript
|
||||
process.env.BILLING_SERVICE_URL = 'http://localhost:4002';
|
||||
expect(url).toBe('http://localhost:4002/api/stripe/webhook');
|
||||
```
|
||||
Must update to port 4003.
|
||||
|
||||
### Gap 9: Load Test Scripts
|
||||
|
||||
- `tests/load/billing-service.js` — `BASE_URL || "http://localhost:4002"`
|
||||
- `tests/load/growth-service.js` — `BASE_URL || "http://localhost:4001"`
|
||||
|
||||
Must update defaults to port 4003.
|
||||
|
||||
### Gap 10: Stripe Documentation
|
||||
|
||||
- `docs/STRIPE_SETUP_GUIDE.md` — references `localhost:4002/api/stripe/webhook`
|
||||
- `docs/BILLING_GAPS_ANALYSIS.md` — references `localhost:4002/api/stripe/webhook`
|
||||
|
||||
### Gap 11: LysnrAI Services Stubs
|
||||
|
||||
`learning_voice_ai_agent/services/` contains `.env.example` stubs for each service:
|
||||
- `services/billing-service/.env.example`
|
||||
- `services/growth-service/.env.example`
|
||||
- `services/tracker-service/.env.example`
|
||||
- `services/platform-service/.env.example`
|
||||
|
||||
After consolidation, remove billing/growth/tracker stubs, keep platform-service with merged env vars.
|
||||
|
||||
### Gap 12: Mobile Apps
|
||||
|
||||
No references to old service ports found in `mobile_app/` — **no changes needed**. ✅
|
||||
Mobile apps call the Python backend (`localhost:8000`), which calls billing-service. The Python backend client (Gap 6) handles the redirection.
|
||||
|
||||
### Route Path Collision Check ✅
|
||||
|
||||
All services use unique route prefixes — **no collisions**:
|
||||
- platform: `/auth/*`, `/audit/*`, `/notifications/*`, `/flags/*`, `/ratelimit/*`, `/blob/*`, `/devices/*`
|
||||
- billing: `/subscriptions/*`, `/usage/*`, `/plans/*`, `/licenses/*`, `/payments/*`, `/stripe/*`
|
||||
- growth: `/invitations/*`, `/referrals/*`, `/promos/*`
|
||||
- tracker: `/items/*`, `/comments/*`, `/votes/*`, `/public/*`
|
||||
|
||||
---
|
||||
|
||||
## Current State
|
||||
|
||||
```
|
||||
@ -75,13 +208,14 @@ All containers served by one Cosmos client in platform-service:
|
||||
|
||||
## Phase 0 — Preparation
|
||||
|
||||
> **Goal:** Backup, verify tests pass before any changes.
|
||||
> **Goal:** Backup, verify tests pass, baseline everything before any changes.
|
||||
|
||||
- [ ] **0.1** Backup all 3 repos via `/repo_backup-main-branch`
|
||||
- [ ] **0.2** Verify all services build: `pnpm build`
|
||||
- [ ] **0.3** Verify all tests pass: `pnpm test`
|
||||
- [ ] **0.4** Document current test counts per service (baseline)
|
||||
- [ ] **0.5** Create `consolidation` branch (or work on main with incremental commits)
|
||||
- [ ] **0.3** Verify all tests pass: `pnpm test` (record exact counts per service)
|
||||
- [ ] **0.4** Baseline test counts: platform ~55, billing ~11, growth ~14, tracker ~45 = **~125 total**
|
||||
- [ ] **0.5** Run `npx tsc --noEmit` in all 3 dashboards — confirm clean
|
||||
- [ ] **0.6** Run `python -m pytest tests/ -q` in LysnrAI — confirm Python tests pass
|
||||
|
||||
---
|
||||
|
||||
@ -95,34 +229,45 @@ All containers served by one Cosmos client in platform-service:
|
||||
- [ ] **1.1.2** Copy `growth-service/src/modules/referrals/` → `platform-service/src/modules/referrals/`
|
||||
- [ ] **1.1.3** Copy `growth-service/src/modules/promos/` → `platform-service/src/modules/promos/`
|
||||
|
||||
### 1.2 Fix imports
|
||||
### 1.2 Copy lib files
|
||||
|
||||
- [ ] **1.2.1** Update import paths in copied modules: `../../lib/errors.js`, `../../lib/product-config.js`, `../../lib/cosmos.js`
|
||||
- [ ] **1.2.2** Copy `growth-service/src/lib/webhooks.ts` → `platform-service/src/lib/webhooks.ts` (used by invitation redeem)
|
||||
- [ ] **1.2.3** Verify no growth-specific lib files are missed
|
||||
- [ ] **1.2.1** Copy `growth-service/src/lib/webhooks.ts` → `platform-service/src/lib/webhooks.ts` **(Gap 4)**
|
||||
- [ ] **1.2.2** Verify growth `product-config.ts` uses same `PRODUCT_ID` export name as platform ✅
|
||||
|
||||
### 1.3 Register routes
|
||||
### 1.3 Fix imports in copied modules
|
||||
|
||||
- [ ] **1.3.1** Add imports to `platform-service/src/server.ts`: `invitationRoutes`, `referralRoutes`, `promoRoutes`
|
||||
- [ ] **1.3.2** Register routes with `/api` prefix (same as growth-service)
|
||||
- [ ] **1.3.1** Update all `../../lib/errors.js` → verify same re-export exists in platform-service
|
||||
- [ ] **1.3.2** Update all `../../lib/product-config.js` → verify `PRODUCT_ID` export matches
|
||||
- [ ] **1.3.3** Update all `../../lib/cosmos.js` → verify same pattern
|
||||
- [ ] **1.3.4** Update `../../lib/webhooks.js` references
|
||||
|
||||
### 1.4 Merge config
|
||||
### 1.4 Merge config **(Gap 5)**
|
||||
|
||||
- [ ] **1.4.1** Add any growth-specific env vars to `platform-service/src/lib/config.ts` (check for `WEBHOOK_URL`, etc.)
|
||||
- [ ] **1.4.2** Add growth Cosmos containers to platform-service container registry
|
||||
- [ ] **1.4.1** Add to `platform-service/src/lib/config.ts`:
|
||||
- `STRIPE_SECRET_KEY: z.string().optional()` (was required in growth — make optional for now)
|
||||
- `WEBHOOK_INVITATION_REDEEMED_URL: z.string().optional()`
|
||||
- `WEBHOOK_REFERRAL_STATUS_URL: z.string().optional()`
|
||||
- [ ] **1.4.2** Add `stripe` (^17.5.0) to `platform-service/package.json` dependencies
|
||||
- [ ] **1.4.3** Add growth Cosmos containers to platform-service container registry
|
||||
|
||||
### 1.5 Copy tests
|
||||
### 1.5 Register routes
|
||||
|
||||
- [ ] **1.5.1** Copy `growth-service/src/modules/invitations/invitations.test.ts` → platform-service
|
||||
- [ ] **1.5.2** Copy any other test files from growth-service modules
|
||||
- [ ] **1.5.3** Fix test import paths
|
||||
- [ ] **1.5.1** Add imports to `platform-service/src/server.ts`: `invitationRoutes`, `referralRoutes`, `promoRoutes`
|
||||
- [ ] **1.5.2** Register routes with `/api` prefix (same as growth-service)
|
||||
|
||||
### 1.6 Verify
|
||||
### 1.6 Copy + fix tests
|
||||
|
||||
- [ ] **1.6.1** `pnpm --filter @lysnrai/platform-service build` — clean
|
||||
- [ ] **1.6.2** `pnpm --filter @lysnrai/platform-service test` — all tests pass (existing + growth)
|
||||
- [ ] **1.6.3** Remove `services/growth-service/` directory
|
||||
- [ ] **1.6.4** Commit: `refactor: merge growth-service into platform-service`
|
||||
- [ ] **1.6.1** Copy all growth test files to platform-service
|
||||
- [ ] **1.6.2** Fix test import paths
|
||||
- [ ] **1.6.3** Run tests: `pnpm --filter @lysnrai/platform-service test` — **growth tests must pass**
|
||||
|
||||
### 1.7 Verify + remove
|
||||
|
||||
- [ ] **1.7.1** `pnpm --filter @lysnrai/platform-service build` — clean
|
||||
- [ ] **1.7.2** `pnpm --filter @lysnrai/platform-service test` — all tests pass (existing + growth ≥ 69)
|
||||
- [ ] **1.7.3** Remove `services/growth-service/` directory
|
||||
- [ ] **1.7.4** `pnpm install` — workspace resolution updated (no broken refs)
|
||||
- [ ] **1.7.5** Commit: `refactor: merge growth-service into platform-service`
|
||||
|
||||
---
|
||||
|
||||
@ -138,35 +283,61 @@ All containers served by one Cosmos client in platform-service:
|
||||
- [ ] **2.1.4** Copy `billing-service/src/modules/licenses/` → `platform-service/src/modules/licenses/`
|
||||
- [ ] **2.1.5** Copy `billing-service/src/modules/stripe/` → `platform-service/src/modules/stripe/`
|
||||
|
||||
### 2.2 Fix imports
|
||||
### 2.2 Handle billing internal key auth **(Gap 3 — CRITICAL)**
|
||||
|
||||
- [ ] **2.2.1** Update all import paths in copied modules
|
||||
- [ ] **2.2.2** Handle billing-specific internal key auth — convert `BILLING_INTERNAL_KEY` hook to route-level guard on billing endpoints (instead of global onRequest hook)
|
||||
- [ ] **2.2.1** Do NOT copy the global `onRequest` hook from billing-service `server.ts`
|
||||
- [ ] **2.2.2** Create `platform-service/src/lib/billing-auth.ts` — a Fastify plugin that checks `x-internal-key` header
|
||||
- [ ] **2.2.3** Register the billing auth plugin ONLY on billing route prefixes:
|
||||
```typescript
|
||||
// In server.ts — wrap billing routes with internal key check
|
||||
await app.register(async (billingScope) => {
|
||||
billingScope.addHook('onRequest', billingKeyGuard);
|
||||
await billingScope.register(subscriptionRoutes, { prefix: '/api' });
|
||||
await billingScope.register(usageRoutes, { prefix: '/api' });
|
||||
await billingScope.register(planRoutes, { prefix: '/api' });
|
||||
await billingScope.register(licenseRoutes, { prefix: '/api' });
|
||||
// Note: stripeRoutes has its own webhook signature check — skip internal key
|
||||
});
|
||||
await app.register(stripeRoutes, { prefix: '/api' }); // Outside billing scope
|
||||
```
|
||||
- [ ] **2.2.4** Verify: auth, audit, tracker, etc. routes are NOT affected by billing key check
|
||||
|
||||
### 2.3 Merge config
|
||||
### 2.3 Fix imports in copied modules
|
||||
|
||||
- [ ] **2.3.1** Add billing env vars to `platform-service/src/lib/config.ts`:
|
||||
- `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRICE_PRO`, `STRIPE_PRICE_ENTERPRISE`
|
||||
- `BILLING_INTERNAL_KEY`, `BACKEND_URL`, `PLAN_LIMITS_JSON`, `USAGE_WARN_THRESHOLD`
|
||||
- [ ] **2.3.2** Add billing Cosmos containers to platform-service container registry
|
||||
- [ ] **2.3.3** Add `stripe` to platform-service `package.json` dependencies
|
||||
- [ ] **2.3.1** Update all import paths in copied modules
|
||||
- [ ] **2.3.2** Verify `PRODUCT_ID` export name matches (billing uses same as platform ✅)
|
||||
|
||||
### 2.4 Register routes
|
||||
### 2.4 Merge config
|
||||
|
||||
- [ ] **2.4.1** Add imports to `platform-service/src/server.ts`
|
||||
- [ ] **2.4.2** Register: `subscriptionRoutes`, `usageRoutes`, `planRoutes`, `licenseRoutes`, `stripeRoutes`
|
||||
- [ ] **2.4.1** Add billing env vars to `platform-service/src/lib/config.ts`:
|
||||
- `STRIPE_SECRET_KEY` — upgrade from optional (Phase 1) to required
|
||||
- `STRIPE_WEBHOOK_SECRET: z.string().optional()`
|
||||
- `STRIPE_PRICE_PRO: z.string().optional()`
|
||||
- `STRIPE_PRICE_ENTERPRISE: z.string().optional()`
|
||||
- `BILLING_INTERNAL_KEY: z.string().optional()`
|
||||
- `BACKEND_URL: z.string().default('http://localhost:8000')`
|
||||
- `PLAN_LIMITS_JSON: z.string().optional()`
|
||||
- `USAGE_WARN_THRESHOLD: z.coerce.number().default(0.8)`
|
||||
- [ ] **2.4.2** Add billing Cosmos containers to container registry
|
||||
|
||||
### 2.5 Copy tests
|
||||
### 2.5 Register routes
|
||||
|
||||
- [ ] **2.5.1** Copy all billing test files to platform-service
|
||||
- [ ] **2.5.2** Fix test import paths
|
||||
- [ ] **2.5.1** Add imports to `platform-service/src/server.ts`
|
||||
- [ ] **2.5.2** Register routes with billing auth scope (see 2.2.3)
|
||||
|
||||
### 2.6 Verify
|
||||
### 2.6 Copy + fix tests
|
||||
|
||||
- [ ] **2.6.1** `pnpm --filter @lysnrai/platform-service build` — clean
|
||||
- [ ] **2.6.2** `pnpm --filter @lysnrai/platform-service test` — all tests pass
|
||||
- [ ] **2.6.3** Remove `services/billing-service/` directory
|
||||
- [ ] **2.6.4** Commit: `refactor: merge billing-service into platform-service`
|
||||
- [ ] **2.6.1** Copy all billing test files to platform-service
|
||||
- [ ] **2.6.2** Fix test import paths
|
||||
- [ ] **2.6.3** Run tests: billing tests must pass
|
||||
|
||||
### 2.7 Verify + remove
|
||||
|
||||
- [ ] **2.7.1** `pnpm --filter @lysnrai/platform-service build` — clean
|
||||
- [ ] **2.7.2** `pnpm --filter @lysnrai/platform-service test` — all tests pass (≥ 80)
|
||||
- [ ] **2.7.3** Remove `services/billing-service/` directory
|
||||
- [ ] **2.7.4** `pnpm install` — workspace resolution updated
|
||||
- [ ] **2.7.5** Commit: `refactor: merge billing-service into platform-service`
|
||||
|
||||
---
|
||||
|
||||
@ -181,82 +352,138 @@ All containers served by one Cosmos client in platform-service:
|
||||
- [ ] **3.1.3** Copy `tracker-service/src/modules/votes/` → `platform-service/src/modules/votes/`
|
||||
- [ ] **3.1.4** Copy `tracker-service/src/modules/public/` → `platform-service/src/modules/public/`
|
||||
|
||||
### 3.2 Fix imports
|
||||
### 3.2 Fix Product ID naming **(Gap 1 — CRITICAL)**
|
||||
|
||||
- [ ] **3.2.1** Update all import paths in copied modules
|
||||
- [ ] **3.2.2** Copy `tracker-service/src/lib/auth.ts` → merge into platform-service's existing auth helper (both use `extractAuth` from `@bytelyst/auth`)
|
||||
- [ ] **3.2.1** In all 4 copied module dirs, replace `DEFAULT_PRODUCT_ID` → `PRODUCT_ID` in imports
|
||||
- [ ] **3.2.2** Update `../../lib/product-config.js` imports to match platform-service pattern
|
||||
- [ ] **3.2.3** Add `DEFAULT_PRODUCT_ID` env var support to `platform-service/src/lib/config.ts` for backward compat
|
||||
- [ ] **3.2.4** In `product-config.ts`, add: `export const DEFAULT_PRODUCT_ID = PRODUCT_ID;` (alias for tracker compat)
|
||||
|
||||
### 3.3 Merge config
|
||||
### 3.3 Fix auth import
|
||||
|
||||
- [ ] **3.3.1** No new env vars needed (tracker uses same Cosmos + JWT vars as platform)
|
||||
- [ ] **3.3.2** Add tracker Cosmos containers to container registry
|
||||
- [ ] **3.3.1** Tracker modules import `extractAuth` from `../../lib/auth.js` — verify platform-service has this file
|
||||
- [ ] **3.3.2** If missing, create `platform-service/src/lib/auth.ts` re-exporting from `@bytelyst/auth`
|
||||
- [ ] **3.3.3** Add `@bytelyst/auth` (workspace:*) to platform-service `package.json` **(Gap 2)**
|
||||
- [ ] **3.3.4** Add `@fastify/rate-limit` (^10.3.0) to platform-service `package.json` **(Gap 2)**
|
||||
- [ ] **3.3.5** Add `jose` if not already present (tracker uses it for JWT — already in platform ✅)
|
||||
|
||||
### 3.4 Register routes
|
||||
### 3.4 Merge config
|
||||
|
||||
- [ ] **3.4.1** Add imports to `platform-service/src/server.ts`
|
||||
- [ ] **3.4.2** Register: `itemRoutes`, `commentRoutes`, `voteRoutes`, `publicRoutes`
|
||||
- [ ] **3.4.3** Ensure public routes skip auth (they already do internally — verify)
|
||||
- [ ] **3.4.1** Add `DEFAULT_PRODUCT_ID: z.string().default('lysnrai')` to config schema
|
||||
- [ ] **3.4.2** Add tracker Cosmos containers to container registry
|
||||
|
||||
### 3.5 Copy tests
|
||||
### 3.5 Register routes
|
||||
|
||||
- [ ] **3.5.1** Copy all tracker test files to platform-service
|
||||
- [ ] **3.5.2** Fix test import paths
|
||||
- [ ] **3.5.3** Verify: 45+ tracker tests pass
|
||||
- [ ] **3.5.1** Add imports to `platform-service/src/server.ts`
|
||||
- [ ] **3.5.2** Register: `itemRoutes`, `commentRoutes`, `voteRoutes`, `publicRoutes`
|
||||
- [ ] **3.5.3** Public routes must NOT be behind any auth middleware — register at top-level (not inside a scoped plugin)
|
||||
|
||||
### 3.6 Verify
|
||||
### 3.6 Copy + fix tests
|
||||
|
||||
- [ ] **3.6.1** `pnpm --filter @lysnrai/platform-service build` — clean
|
||||
- [ ] **3.6.2** `pnpm --filter @lysnrai/platform-service test` — all 125+ tests pass
|
||||
- [ ] **3.6.3** Remove `services/tracker-service/` directory
|
||||
- [ ] **3.6.4** Commit: `refactor: merge tracker-service into platform-service`
|
||||
- [ ] **3.6.1** Copy all tracker test files to platform-service
|
||||
- [ ] **3.6.2** Fix test import paths
|
||||
- [ ] **3.6.3** Fix any `DEFAULT_PRODUCT_ID` references in tests
|
||||
- [ ] **3.6.4** Run tests: 45+ tracker tests must pass
|
||||
|
||||
### 3.7 Verify + remove
|
||||
|
||||
- [ ] **3.7.1** `pnpm --filter @lysnrai/platform-service build` — clean
|
||||
- [ ] **3.7.2** `pnpm --filter @lysnrai/platform-service test` — **all 125+ tests pass**
|
||||
- [ ] **3.7.3** Remove `services/tracker-service/` directory
|
||||
- [ ] **3.7.4** `pnpm install` — workspace resolution updated
|
||||
- [ ] **3.7.5** Commit: `refactor: merge tracker-service into platform-service`
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Update Consumers
|
||||
## Phase 4 — Update Consumers (LysnrAI Repo)
|
||||
|
||||
> **Goal:** Update all dashboards, scripts, configs, and docker files that reference the old services.
|
||||
> **Goal:** Update all dashboards, Python clients, scripts, configs, and docker files that reference the old service ports/URLs.
|
||||
|
||||
### 4.1 Dashboard API clients
|
||||
### 4.1 Dashboard API clients **(Gap 6)**
|
||||
|
||||
- [ ] **4.1.1** `admin-dashboard-web/src/lib/billing-client.ts` — change `BILLING_API_URL` → `PLATFORM_API_URL` (port 4003)
|
||||
- [ ] **4.1.2** `admin-dashboard-web/src/lib/growth-client.ts` — change `GROWTH_API_URL` → `PLATFORM_API_URL`
|
||||
- [ ] **4.1.3** `user-dashboard-web/src/lib/billing-client.ts` — same change
|
||||
- [ ] **4.1.4** `tracker-dashboard-web/src/lib/tracker-client.ts` — change `TRACKER_API_URL` → `PLATFORM_API_URL`
|
||||
- [ ] **4.1.5** Update all dashboard `env.local.example` files — remove old service URLs, add note that everything goes through `PLATFORM_API_URL`
|
||||
- [ ] **4.1.1** `admin-dashboard-web/src/lib/billing-client.ts` — `BILLING_SERVICE_URL` → `PLATFORM_SERVICE_URL`, default `http://localhost:4003`
|
||||
- [ ] **4.1.2** `admin-dashboard-web/src/lib/growth-client.ts` — `GROWTH_SERVICE_URL` → `PLATFORM_SERVICE_URL`, default `http://localhost:4003`
|
||||
- [ ] **4.1.3** `user-dashboard-web/src/lib/billing-client.ts` — same
|
||||
- [ ] **4.1.4** `user-dashboard-web/src/lib/growth-client.ts` — same
|
||||
- [ ] **4.1.5** `tracker-dashboard-web/src/app/api/tracker/[...path]/route.ts` — `TRACKER_API_URL` → `PLATFORM_API_URL`, default `http://localhost:4003`
|
||||
|
||||
### 4.2 Docker Compose
|
||||
### 4.2 Stripe proxy + context **(Gap 6)**
|
||||
|
||||
- [ ] **4.2.1** `learning_ai_common_plat/docker-compose.yml` — remove billing, growth, tracker service entries; keep platform + extraction
|
||||
- [ ] **4.2.2** `learning_voice_ai_agent/docker-compose.yml` — same cleanup
|
||||
- [ ] **4.2.3** Update Traefik labels (all routes go to platform-service)
|
||||
- [ ] **4.2.1** `user-dashboard-web/src/app/api/stripe/webhook/route.ts` — `BILLING_SERVICE_URL` → `PLATFORM_SERVICE_URL`
|
||||
- [ ] **4.2.2** `admin-dashboard-web/src/app/api/stripe/config/route.ts` — `billingServiceUrl` default to port 4003
|
||||
- [ ] **4.2.3** `admin-dashboard-web/src/lib/stripe-context.tsx` — update all 3 `localhost:4002` references to `localhost:4003`
|
||||
|
||||
### 4.3 Run scripts
|
||||
### 4.3 Ops status route **(Gap 7)**
|
||||
|
||||
- [ ] **4.3.1** `learning_voice_ai_agent/run-local-all-services.sh` — remove billing/growth/tracker start commands; update health checks
|
||||
- [ ] **4.3.2** `.windsurf/workflows/start-all-services.md` — update to reflect 2 services
|
||||
- [ ] **4.3.1** `admin-dashboard-web/src/app/api/ops/status/route.ts` — remove billing/growth/tracker entries from `SERVICES` array; keep backend + platform + extraction
|
||||
|
||||
### 4.4 Environment files
|
||||
### 4.4 Stripe webhook test **(Gap 8)**
|
||||
|
||||
- [ ] **4.4.1** `learning_ai_common_plat/.env.example` — consolidate all env vars into one section for platform-service
|
||||
- [ ] **4.4.2** Remove references to ports 4001, 4002, 4004
|
||||
- [ ] **4.4.1** `user-dashboard-web/src/__tests__/stripe-webhook.test.ts` — change `http://localhost:4002` → `http://localhost:4003` in all 3 places
|
||||
|
||||
### 4.5 CI
|
||||
### 4.5 Python clients **(Gap 6)**
|
||||
|
||||
- [ ] **4.5.1** `.github/workflows/ci.yml.disabled` — remove billing/growth/tracker from matrix; only platform + extraction
|
||||
- [ ] **4.5.2** Delete individual CI workflows: `ci-billing-service.yml`, `ci-growth-service.yml`, `ci-tracker-service.yml` (if they exist)
|
||||
- [ ] **4.5.1** `backend/src/clients/billing_client.py` — `BILLING_SERVICE_URL` → `PLATFORM_SERVICE_URL`, default `http://localhost:4003`
|
||||
- [ ] **4.5.2** `src/cloud/api_sync.py` — same
|
||||
- [ ] **4.5.3** `src/cloud/plan_resolver.py` — same
|
||||
|
||||
### 4.6 Verify consumers
|
||||
### 4.6 Environment files
|
||||
|
||||
- [ ] **4.6.1** `npx tsc --noEmit` in admin-dashboard-web
|
||||
- [ ] **4.6.2** `npx tsc --noEmit` in user-dashboard-web
|
||||
- [ ] **4.6.3** `npx tsc --noEmit` in tracker-dashboard-web
|
||||
- [ ] **4.6.4** Commit: `refactor: update consumers for consolidated platform-service`
|
||||
- [ ] **4.6.1** `learning_voice_ai_agent/.env.example` — replace `BILLING_SERVICE_URL=http://localhost:4002` with `PLATFORM_SERVICE_URL=http://localhost:4003`
|
||||
- [ ] **4.6.2** `admin-dashboard-web/.env.example` — remove `BILLING_SERVICE_URL`, `GROWTH_SERVICE_URL`; ensure `PLATFORM_SERVICE_URL` present
|
||||
- [ ] **4.6.3** `admin-dashboard-web/.env.local.example` — same
|
||||
- [ ] **4.6.4** `user-dashboard-web/.env.example` — same
|
||||
- [ ] **4.6.5** `user-dashboard-web/.env.local.example` — same
|
||||
- [ ] **4.6.6** `tracker-dashboard-web/.env.example` — remove `TRACKER_API_URL`, use `PLATFORM_API_URL`
|
||||
- [ ] **4.6.7** `tracker-dashboard-web/.env.local.example` — same
|
||||
|
||||
### 4.7 LysnrAI service stubs **(Gap 11)**
|
||||
|
||||
- [ ] **4.7.1** Remove `services/billing-service/` directory (just .env.example stub)
|
||||
- [ ] **4.7.2** Remove `services/growth-service/` directory
|
||||
- [ ] **4.7.3** Remove `services/tracker-service/` directory
|
||||
- [ ] **4.7.4** Update `services/platform-service/.env.example` with merged env vars
|
||||
|
||||
### 4.8 Docker Compose (both repos)
|
||||
|
||||
- [ ] **4.8.1** `learning_ai_common_plat/docker-compose.yml` — remove billing, growth, tracker service entries
|
||||
- [ ] **4.8.2** `learning_voice_ai_agent/docker-compose.yml` — same cleanup
|
||||
- [ ] **4.8.3** Update Traefik labels (all routes go to platform-service on 4003)
|
||||
- [ ] **4.8.4** Remove healthcheck entries for ports 4001, 4002, 4004
|
||||
|
||||
### 4.9 Run scripts + workflows
|
||||
|
||||
- [ ] **4.9.1** `learning_voice_ai_agent/run-local-all-services.sh` — remove billing/growth/tracker start commands; update health checks
|
||||
- [ ] **4.9.2** `.windsurf/workflows/start-all-services.md` — update to reflect 2 services (platform + extraction)
|
||||
|
||||
### 4.10 Load tests **(Gap 9)**
|
||||
|
||||
- [ ] **4.10.1** `tests/load/billing-service.js` — change default URL to `http://localhost:4003`
|
||||
- [ ] **4.10.2** `tests/load/growth-service.js` — same
|
||||
|
||||
### 4.11 Stripe docs **(Gap 10)**
|
||||
|
||||
- [ ] **4.11.1** `docs/STRIPE_SETUP_GUIDE.md` — change `localhost:4002` → `localhost:4003`
|
||||
- [ ] **4.11.2** `docs/BILLING_GAPS_ANALYSIS.md` — same
|
||||
|
||||
### 4.12 CI
|
||||
|
||||
- [ ] **4.12.1** `.github/workflows/ci.yml.disabled` (common-plat) — remove billing/growth/tracker from matrix
|
||||
- [ ] **4.12.2** Delete individual disabled CI workflows if they exist
|
||||
|
||||
### 4.13 Verify consumers
|
||||
|
||||
- [ ] **4.13.1** `npx tsc --noEmit` in admin-dashboard-web — clean
|
||||
- [ ] **4.13.2** `npx tsc --noEmit` in user-dashboard-web — clean
|
||||
- [ ] **4.13.3** `npx tsc --noEmit` in tracker-dashboard-web — clean
|
||||
- [ ] **4.13.4** Run `vitest` in user-dashboard-web — stripe webhook test passes with new port
|
||||
- [ ] **4.13.5** Commit in LysnrAI repo: `refactor: update all consumers for consolidated platform-service`
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Documentation & Cleanup
|
||||
## Phase 5 — Documentation & Final Cleanup
|
||||
|
||||
> **Goal:** Update all docs, AGENTS.md, and clean up dead references.
|
||||
> **Goal:** Update all docs, AGENTS.md, and verify nothing is broken.
|
||||
|
||||
### 5.1 Documentation
|
||||
|
||||
@ -265,40 +492,41 @@ All containers served by one Cosmos client in platform-service:
|
||||
- [ ] **5.1.3** Update `docs/MIGRATION_GUIDE.md` — single service URL for all API calls
|
||||
- [ ] **5.1.4** Update `docs/ROADMAP.md` — add consolidation as completed item
|
||||
|
||||
### 5.2 Package cleanup
|
||||
### 5.2 Platform-service cleanup
|
||||
|
||||
- [ ] **5.2.1** Remove `services/billing-service/` from git (already deleted in Phase 2)
|
||||
- [ ] **5.2.2** Remove `services/growth-service/` from git (already deleted in Phase 1)
|
||||
- [ ] **5.2.3** Remove `services/tracker-service/` from git (already deleted in Phase 3)
|
||||
- [ ] **5.2.4** Run `pnpm install` — workspace resolution updated
|
||||
- [ ] **5.2.5** Verify `pnpm build` passes across entire workspace
|
||||
- [ ] **5.2.1** Update `platform-service/package.json` description — include all domains
|
||||
- [ ] **5.2.2** Update `platform-service/src/server.ts` — description comment lists all 18 modules
|
||||
- [ ] **5.2.3** Swagger description reflects all modules
|
||||
- [ ] **5.2.4** Update platform-service `.env.example` — includes Stripe, webhook, billing key vars
|
||||
|
||||
### 5.3 Platform-service cleanup
|
||||
### 5.3 Workspace cleanup
|
||||
|
||||
- [ ] **5.3.1** Update `platform-service/package.json` — description, add any missing deps
|
||||
- [ ] **5.3.2** Update `platform-service/src/server.ts` — description comment
|
||||
- [ ] **5.3.3** Swagger description reflects all 18 modules
|
||||
- [ ] **5.3.1** `pnpm install` — no broken workspace refs
|
||||
- [ ] **5.3.2** Grep entire workspace for `localhost:4001`, `localhost:4002`, `localhost:4004` — must return 0 results
|
||||
- [ ] **5.3.3** Grep entire workspace for `billing-service`, `growth-service`, `tracker-service` — only docs/history references remain
|
||||
|
||||
### 5.4 Final verification
|
||||
|
||||
- [ ] **5.4.1** `pnpm build` — all packages + platform-service + extraction-service build
|
||||
- [ ] **5.4.2** `pnpm test` — all 125+ tests pass
|
||||
- [ ] **5.4.3** `pnpm typecheck` — clean across workspace
|
||||
- [ ] **5.4.4** Commit: `docs: update all documentation for consolidated platform-service`
|
||||
- [ ] **5.4.2** `pnpm test` — all 125+ tests pass in platform-service
|
||||
- [ ] **5.4.3** `pnpm typecheck` — clean across common-plat workspace
|
||||
- [ ] **5.4.4** `npx tsc --noEmit` — clean across all 3 LysnrAI dashboards
|
||||
- [ ] **5.4.5** `python -m pytest tests/ -q` — Python tests still pass (billing client URL changed)
|
||||
- [ ] **5.4.6** Commit: `docs: update all documentation for consolidated platform-service`
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Phase | What | Effort | Tests Moved |
|
||||
|-------|------|--------|-------------|
|
||||
| **0** | Preparation & backup | 30 min | — |
|
||||
| **1** | Merge growth-service (3 modules) | 2–3 hrs | ~14 |
|
||||
| **2** | Merge billing-service (5 modules) | 3–4 hrs | ~11 |
|
||||
| **3** | Merge tracker-service (4 modules) | 3–4 hrs | ~45 |
|
||||
| **4** | Update consumers (dashboards, docker, scripts, CI) | 2–3 hrs | — |
|
||||
| **5** | Documentation & cleanup | 1–2 hrs | — |
|
||||
| **Total** | **5 services → 2** | **~3 days** | **~125+ tests** |
|
||||
| Phase | What | Effort | Tests Moved | Critical Gaps Addressed |
|
||||
|-------|------|--------|-------------|------------------------|
|
||||
| **0** | Preparation & backup | 30 min | — | — |
|
||||
| **1** | Merge growth-service (3 modules) | 2–3 hrs | ~14 | Gap 4 (webhooks), Gap 5 (Stripe key) |
|
||||
| **2** | Merge billing-service (5 modules) | 4–5 hrs | ~11 | Gap 3 (internal key auth) |
|
||||
| **3** | Merge tracker-service (4 modules) | 3–4 hrs | ~45 | Gap 1 (product ID), Gap 2 (deps) |
|
||||
| **4** | Update consumers (17+ files across repos) | 3–4 hrs | — | Gaps 6–11 |
|
||||
| **5** | Documentation & final verification | 2–3 hrs | — | — |
|
||||
| **Total** | **5 services → 2** | **~4–5 days** | **~125+ tests** | **12 gaps addressed** |
|
||||
|
||||
## Port Allocation (After)
|
||||
|
||||
@ -316,13 +544,17 @@ Each phase has its own commit. If a phase breaks something:
|
||||
1. `git revert <commit>` to undo that phase
|
||||
2. The old service code is in git history
|
||||
3. Backup branches created in Phase 0
|
||||
4. Consumers (Phase 4) are updated LAST — services work on old ports until Phase 4
|
||||
|
||||
## Risks & Mitigations
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|-----------|
|
||||
| Route path collisions between services | All services already use unique prefixes (`/auth/*`, `/subscriptions/*`, `/items/*`, etc.) |
|
||||
| Config schema gets large | Group env vars by domain in config.ts with clear comments |
|
||||
| Stripe webhook handler needs raw body | Fastify already handles this — just verify after move |
|
||||
| Billing internal key auth | Convert from global hook to route-level guard on billing endpoints only |
|
||||
| Public tracker routes skip auth | They already handle auth internally — just verify |
|
||||
| Route path collisions | Verified ✅ — all services use unique prefixes |
|
||||
| Config schema gets large | Group env vars by domain with clear section comments |
|
||||
| Stripe webhook raw body | Fastify handles this — verify after move |
|
||||
| Billing internal key blocks other routes | Scoped Fastify plugin (Phase 2.2) isolates key check to billing prefixes only |
|
||||
| Public tracker routes skip auth | Register outside scoped plugins — verify in Phase 3.5.3 |
|
||||
| Python billing client breaks | Change env var name, keep same API paths — transparent to Python code |
|
||||
| Stripe webhook test fails | Explicit port update in Phase 4.4 |
|
||||
| Product ID mismatch | Alias `DEFAULT_PRODUCT_ID = PRODUCT_ID` in Phase 3.2.4 |
|
||||
|
||||
Loading…
Reference in New Issue
Block a user