# ByteLyst Platform — Best Practices & New Product Playbook

> **For:** Founders, engineers, and AI coding agents building products on the ByteLyst shared platform.
>
> **Last updated:** 2026-03-01 · **Ecosystem:** 6 products, 21 shared packages, 25 platform modules + 5 product backends, 1400+ service tests.

---

## Table of Contents

1. [Platform Philosophy](#1-platform-philosophy)
2. [What You Get for Free](#2-what-you-get-for-free)
3. [New Product Playbook — Step by Step](#3-new-product-playbook--step-by-step)
4. [Expected Velocity](#4-expected-velocity)
5. [Architecture Best Practices](#5-architecture-best-practices)
6. [Coding Conventions](#6-coding-conventions)
7. [Data & Cosmos DB Practices](#7-data--cosmos-db-practices)
8. [Auth & Security Practices](#8-auth--security-practices)
9. [Testing Practices](#9-testing-practices)
10. [Deployment & CI Practices](#10-deployment--ci-practices)
11. [AI Agent Collaboration](#11-ai-agent-collaboration)
12. [Anti-Patterns to Avoid](#12-anti-patterns-to-avoid)
13. [Real-World Examples](#13-real-world-examples)

---

## 1. Platform Philosophy

The ByteLyst platform follows a **"build once, ship five"** model:

- **Product-agnostic core** — every shared package and service works for any product via the `productId` field
- **Thin product shells** — product repos contain only UI and product-specific logic; all infrastructure is shared
- **Convention over configuration** — follow the patterns, get auth/billing/telemetry/flags/audit for free
- **Offline-first** — clients work without connectivity and sync when online

### The Three Layers

```
┌─────────────────────────────────────────────────────────────┐
│  PRODUCT REPO          UI + product-specific logic only     │
│  (your new app)        Next.js / SwiftUI / Compose / RN    │
└────────────────────────────┬────────────────────────────────┘
                             │  file: refs / REST API
┌────────────────────────────┴────────────────────────────────┐
│  COMMON PLATFORM           @bytelyst/* packages             │
│  (learning_ai_common_plat) platform-service (port 4003)     │
│                            extraction-service (port 4005)   │
└────────────────────────────┬────────────────────────────────┘
                             │
┌────────────────────────────┴────────────────────────────────┐
│  AZURE INFRASTRUCTURE      Cosmos DB · Blob · Key Vault     │
│                            Speech · OpenAI · Stripe         │
└─────────────────────────────────────────────────────────────┘
```

---

## 2. What You Get for Free

### 2.1 Shared Packages (21)

Every package is `npm install`-able via `file:` refs to the sibling common-plat repo.

**Server-side packages (Node.js / Fastify):**

| Package                    | What It Does                                         | You Write                |
| -------------------------- | ---------------------------------------------------- | ------------------------ |
| **@bytelyst/auth**         | JWT sign/verify, password hash, auth middleware      | Nothing — just call it   |
| **@bytelyst/cosmos**       | Cosmos DB client singleton, container registry       | Register your containers |
| **@bytelyst/config**       | Zod env loader, product identity, Key Vault resolver | Your product's `.env`    |
| **@bytelyst/api-client**   | Fetch wrapper with auth injection, timeout, retry    | Your service URLs        |
| **@bytelyst/errors**       | Typed HTTP errors (400–429)                          | Throw them               |
| **@bytelyst/fastify-core** | `createServiceApp()` + `startService()` factory      | Your route plugins       |
| **@bytelyst/logger**       | Pino-based structured logging                        | `req.log.info(...)`      |
| **@bytelyst/events**       | Typed in-memory event bus with error isolation       | Emit/subscribe           |
| **@bytelyst/blob**         | Azure Blob Storage client + SAS token helpers        | Your container names     |
| **@bytelyst/extraction**   | AI text extraction client                            | Your extraction tasks    |
| **@bytelyst/monitoring**   | Health-check utilities, Loki/Grafana helpers         | Your service name        |
| **@bytelyst/testing**      | Shared test mocks, Fastify inject helpers            | Import in tests          |

**Client-side packages (Browser / React Native / Mobile):**

| Package                           | What It Does                                                 | You Write             |
| --------------------------------- | ------------------------------------------------------------ | --------------------- |
| **@bytelyst/auth-client**         | Client-side auth (login, register, token refresh, SSO)       | Wire to your login UI |
| **@bytelyst/platform-client**     | Typed fetch wrapper with auth injection, x-request-id, retry | Your base URL         |
| **@bytelyst/feature-flag-client** | Feature flag polling client with caching                     | Init + `isEnabled()`  |
| **@bytelyst/kill-switch-client**  | Kill switch check (force-update, maintenance mode)           | Init at app launch    |
| **@bytelyst/offline-queue**       | Persistent retry queue with max retries and queue size       | Storage adapter       |
| **@bytelyst/react-auth**          | `createAuthContext()` → typed Provider + useAuth hook        | Wrap your app         |
| **@bytelyst/telemetry-client**    | Browser/RN telemetry SDK (queue, flush, beacon)              | `trackEvent()`        |
| **@bytelyst/design-tokens**       | JSON → CSS/TS/Kotlin/Swift token generator                   | Your color overrides  |
| **@bytelyst/blob-client**         | SAS URL upload/download via platform-service blob endpoints  | Container + file data |

### 2.2 Platform Service Modules (25 — product-agnostic)

The consolidated platform-service (port 4003) provides REST endpoints for shared infrastructure:

| Category          | Modules                                               | What You Get                                                                       |
| ----------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------- |
| **Identity**      | auth, sessions                                        | JWT auth, login/register, SSO, password reset, email verification, device sessions |
| **Billing**       | subscriptions, plans, licenses, stripe, promos        | Stripe integration, plan management, promo codes, license keys                     |
| **Growth**        | invitations, referrals                                | Invite links, referral tracking, reward attribution                                |
| **Ops**           | flags, maintenance, status, ip-rules, ratelimit, jobs | Feature flags with rollout %, maintenance mode, public status page, scheduled jobs |
| **Data**          | audit, exports, settings, notifications, delivery     | Audit log, GDPR export, user preferences, email/push delivery with templates       |
| **Content**       | items, comments, votes, public, changelog, feedback   | Tracker/roadmap items, comments, voting, public roadmap, in-app feedback           |
| **Telemetry**     | telemetry, analytics, experiments                     | Event ingestion, error clustering, geo distribution, A/B experiments               |
| **Storage**       | blob, products                                        | Blob SAS tokens, product registry/cache                                            |
| **Impersonation** | impersonation                                         | Admin user impersonation for debugging                                             |

### 2.3 Product-Specific Backends (NEW — migrated from platform-service)

Product-specific modules now live in each product repo's `backend/` directory. This keeps domain logic close to the product code and platform-service product-agnostic.

| Product        | Port | Modules                                                                                   | Tests |
| -------------- | ---- | ----------------------------------------------------------------------------------------- | ----- |
| **PeakPulse**  | 4010 | peak-sessions, peak-routes                                                                | 32    |
| **ChronoMind** | 4011 | timers, routines, shared-timers, households, webhooks                                     | 174   |
| **JarvisJr**   | 4012 | jarvis-agents, jarvis-sessions, jarvis-memory, jarvis-teams, marketplace                  | 198   |
| **NomGap**     | 4013 | fasting-sessions, fasting-protocols, body-stages, social-fasting, meal-log, push-triggers | 152   |
| **MindLyst**   | 4014 | brains, memory, reflections, daily-briefs, streaks                                        | 59    |
| **LysnrAI**    | 8000 | _(Python FastAPI backend — kept as-is, not migrated to Fastify)_                          | 53    |

Each backend uses:

- `@bytelyst/fastify-core` for app factory
- `@bytelyst/cosmos` for Cosmos DB
- `@bytelyst/auth` for JWT verification (same `JWT_SECRET` as platform-service)
- `@bytelyst/errors` for typed HTTP errors
- Validated env config via Zod (never read `process.env` directly for secrets)

### 2.4 Dashboards (Product-Agnostic)

| Dashboard       | Port | What It Does                                                                                   |
| --------------- | ---- | ---------------------------------------------------------------------------------------------- |
| **admin-web**   | 3001 | User management, audit logs, feature flags, telemetry viewer, secrets manager, mission control |
| **tracker-web** | 3003 | Issue tracker, public roadmap, voting, changelog                                               |

Both work for any product — they read `productId` from env and filter accordingly.

### 2.5 Infrastructure

- **Azure Cosmos DB** — multi-tenant via `productId` partition
- **Azure Blob Storage** — 6 containers (audio, transcripts, attachments, avatars, releases, backups)
- **Azure Key Vault** — secrets resolution at startup via `@bytelyst/config`
- **Docker Compose** — full stack with Traefik, Loki, Grafana
- **GitHub Actions** — CI templates (lint, test, typecheck, build)
- **Husky + lint-staged** — pre-commit secret scanning, linting

---

## 3. New Product Playbook — Step by Step

### Day 0: Identity & Repo Setup (1 hour)

```bash
# 1. Create your product repo
mkdir learning_ai_<codename>
cd learning_ai_<codename>
git init

# 2. Choose your product identity
PRODUCT_ID="yourapp"       # lowercase, no hyphens (e.g. "nomgap", "chronomind")
BUNDLE_ID="com.saravana.${PRODUCT_ID}"
DOMAIN="${PRODUCT_ID}.app"
```

Create the scaffolding:

```
learning_ai_<codename>/
├── docs/
│   ├── PRD.md                  # Product requirements
│   └── roadmap.md              # Implementation roadmap
├── scripts/
│   └── docker-prep.sh          # Copy from any existing product repo
├── AGENTS.md                   # AI agent instructions (hand-maintained; canonical pointer auto-prepended)
├── .github/
│   └── copilot-instructions.md # Thin pointer (auto-generated by update-agent-docs.sh)
├── .aider.conf.yml             # Aider config (auto-generated)
├── .editorconfig               # Editor config (auto-generated)
├── .gitignore
├── .env.example
└── README.md
```

### Day 0: Register Product in Platform (30 minutes)

1. **Add product to platform-service products module:**

   ```
   POST /products
   {
     "id": "<PRODUCT_ID>",
     "name": "Your App Name",
     "description": "One-liner",
     "domain": "yourapp.app",
     "bundleId": "com.saravana.yourapp"
   }
   ```

2. **Seed default feature flags** — already automatic (see `flags/seed.ts`), just add your product's flags to the seed file.

3. **Add to backup/push workflows** — update `scripts/backup-main.sh` and `.windsurf/workflows/repo_*.md` to include the new repo.

### Day 1: Web App (Next.js) — 2–4 hours

```bash
mkdir web && cd web
npx create-next-app@latest . --app --typescript --tailwind --eslint
npm install zustand zod date-fns recharts
```

Wire the shared packages:

```json
// package.json — add file: refs
{
  "dependencies": {
    "@bytelyst/api-client": "file:../../learning_ai_common_plat/packages/api-client",
    "@bytelyst/auth-client": "file:../../learning_ai_common_plat/packages/auth-client",
    "@bytelyst/config": "file:../../learning_ai_common_plat/packages/config",
    "@bytelyst/cosmos": "file:../../learning_ai_common_plat/packages/cosmos",
    "@bytelyst/react-auth": "file:../../learning_ai_common_plat/packages/react-auth",
    "@bytelyst/telemetry-client": "file:../../learning_ai_common_plat/packages/telemetry-client",
    "@bytelyst/errors": "file:../../learning_ai_common_plat/packages/errors"
  }
}
```

Create the standard `src/lib/` wiring files (copy from any existing product):

| File                     | Purpose                         | Source Package               |
| ------------------------ | ------------------------------- | ---------------------------- |
| `lib/cosmos.ts`          | Register Cosmos containers      | `@bytelyst/cosmos`           |
| `lib/auth-server.ts`     | JWT utils for API routes        | `@bytelyst/auth`             |
| `lib/product-config.ts`  | Product identity                | `@bytelyst/config`           |
| `lib/platform-client.ts` | API client for platform-service | `@bytelyst/api-client`       |
| `lib/telemetry.ts`       | Client telemetry init           | `@bytelyst/telemetry-client` |
| `app/providers.tsx`      | AuthProvider + telemetry init   | `@bytelyst/react-auth`       |

**What you DON'T write:** auth flows, JWT handling, token refresh, Cosmos client setup, error types, API client with retry/timeout, telemetry pipeline, feature flag polling.

### Day 1: Native App (choose your framework) — 4–8 hours

| Option                    | Best For                          | Stack                                      |
| ------------------------- | --------------------------------- | ------------------------------------------ |
| **Expo (React Native)**   | Fast cross-platform, JS ecosystem | Expo SDK, expo-router, Zustand + MMKV      |
| **KMP + SwiftUI/Compose** | Maximum native performance        | Shared Kotlin, native UI shells            |
| **Pure Native**           | Single platform focus             | SwiftUI (iOS) or Jetpack Compose (Android) |

For any native app, use the shared platform SDKs:

**iOS / macOS / watchOS — ByteLystPlatformSDK (Swift Package):**

1. Add `../learning_ai_common_plat/packages/swift-platform-sdk/` as a local SPM dependency
2. Create `Platform/` directory with thin wrappers (Config, KeychainHelper, TelemetryService, AuthService, etc.)
3. Wire `PlatformSyncManager` for cloud sync
4. Use design tokens from `@bytelyst/design-tokens` (auto-generated `*Theme.swift`)

**Android — kotlin-platform-sdk (Gradle module):**

1. Add `../learning_ai_common_plat/packages/kotlin-platform-sdk` as a project dependency
2. Create a Hilt `PlatformModule` (or Koin `platformModule`) providing `BLPlatformConfig`, `BLAuthClient`, `BLTelemetryClient`, `BLFeatureFlagClient`, `BLKillSwitchClient`
3. Wire sync via `PlatformApiClient` + `SyncRepository`

**React Native (Expo) — @bytelyst/\* TS packages:**

1. Wire `@bytelyst/platform-client`, `@bytelyst/auth-client`, `@bytelyst/feature-flag-client`, `@bytelyst/kill-switch-client`, `@bytelyst/offline-queue`
2. Use MMKV as storage adapter for offline queue
3. Use design tokens from `@bytelyst/design-tokens` (auto-generated `tokens.ts`)

### Day 2: Product-Specific Backend (2–4 hours per module)

> **Key change (2026-03-01):** Product-specific modules now live in the product repo's `backend/` directory, NOT in platform-service. This keeps domain logic close to the product and platform-service product-agnostic.

Scaffold the backend (copy from any existing product repo):

```
your-product/backend/
├── src/
│   ├── lib/
│   │   ├── config.ts           # Zod env schema (PORT, HOST, JWT_SECRET, COSMOS_*)
│   │   ├── cosmos.ts           # Re-export from @bytelyst/cosmos
│   │   ├── cosmos-init.ts      # Register + initialize Cosmos containers
│   │   ├── auth.ts             # Re-export from @bytelyst/auth
│   │   ├── errors.ts           # Re-export from @bytelyst/errors
│   │   └── request-context.ts  # productId validation from JWT/headers
│   ├── modules/
│   │   └── <your-module>/
│   │       ├── types.ts        # Zod schemas + TypeScript interfaces
│   │       ├── repository.ts   # Cosmos DB CRUD
│   │       ├── routes.ts       # Fastify REST endpoints
│   │       └── <module>.test.ts # Vitest tests
│   └── server.ts               # Entry point
├── package.json                # file: refs to @bytelyst/* packages
├── tsconfig.json
├── vitest.config.ts
└── .env.example
```

**Template (server.ts):**

```typescript
import { createServiceApp, startService } from '@bytelyst/fastify-core';
import { jwtVerify } from 'jose';
import { yourRoutes } from './modules/your-module/routes.js';
import { initCosmosIfNeeded } from './lib/cosmos-init.js';
import { config } from './lib/config.js';

// ⚠️ Always use validated config — never process.env directly for secrets
const jwtSecret = new TextEncoder().encode(config.JWT_SECRET);

await initCosmosIfNeeded();
const app = await createServiceApp({ name: 'yourapp-backend', version: '0.1.0' });

app.addHook('onRequest', async req => {
  const auth = req.headers.authorization;
  if (!auth?.startsWith('Bearer ')) return;
  try {
    const { payload } = await jwtVerify(auth.slice(7), jwtSecret, { issuer: 'bytelyst-platform' });
    req.jwtPayload = payload;
  } catch {
    /* token invalid — leave undefined */
  }
});

await app.register(yourRoutes, { prefix: '/api' });
await startService(app, { port: config.PORT, host: config.HOST });
```

**Template (routes.ts):**

```typescript
import type { FastifyInstance } from 'fastify';
import { extractAuth } from '../../lib/auth.js';
import { BadRequestError, NotFoundError } from '../../lib/errors.js';
import * as repo from './repository.js';
import { CreateYourDocSchema } from './types.js';

const PRODUCT_ID = 'yourapp';

export async function yourRoutes(app: FastifyInstance) {
  app.get('/your-resource', async req => {
    const auth = await extractAuth(req);
    return { items: await repo.list(auth.sub, PRODUCT_ID) };
  });
  // ... POST, PUT, DELETE
}
```

### Day 3: User Dashboard (optional) — 4–6 hours

If your product needs a user-facing web portal, create a Next.js app in your product repo:

```
your-product/
└── user-dashboard-web/
    ├── src/
    │   ├── app/           # App Router pages
    │   ├── lib/           # Standard wiring files (copy pattern)
    │   └── components/    # shadcn/ui + custom
    ├── package.json       # file: refs to @bytelyst/*
    └── .env.example
```

The admin dashboard and tracker dashboard are **already built and product-agnostic** — just point them at your productId.

---

## 4. Expected Velocity

### What Took Months, Now Takes Days

Based on actual delivery across 6 products (LysnrAI, MindLyst, ChronoMind, NomGap, JarvisJr, PeakPulse):

| Capability                                       | Without Platform | With Platform               | Savings |
| ------------------------------------------------ | ---------------- | --------------------------- | ------- |
| Auth (JWT, login, register, SSO, password reset) | 2–3 weeks        | 0 days (already built)      | 100%    |
| Billing (Stripe, plans, subscriptions)           | 2–3 weeks        | 0 days                      | 100%    |
| Feature flags with rollout                       | 1 week           | 0 days                      | 100%    |
| Telemetry pipeline                               | 1–2 weeks        | 1 hour (wire client)        | 95%     |
| Admin dashboard                                  | 3–4 weeks        | 0 days (shared)             | 100%    |
| Audit logging                                    | 3–5 days         | 0 days                      | 100%    |
| GDPR data export                                 | 3–5 days         | 0 days                      | 100%    |
| Email delivery (templates, SendGrid)             | 1 week           | 0 days                      | 100%    |
| Rate limiting + IP rules                         | 3–5 days         | 0 days                      | 100%    |
| Blob storage (uploads, SAS tokens)               | 1 week           | 0 days                      | 100%    |
| Public roadmap + issue tracker                   | 2 weeks          | 0 days                      | 100%    |
| Client offline sync queue                        | 1 week           | 2 hours (copy pattern)      | 90%     |
| Design system (tokens across platforms)          | 1–2 weeks        | 1 hour (add product colors) | 90%     |
| **New product-specific CRUD module**             | —                | **2–4 hours**               | —       |
| **Full MVP (web + mobile shell)**                | 6–10 weeks       | **3–5 days**                | ~85%    |

### Realistic Timeline for a New Product

| Day       | Milestone                                                             |
| --------- | --------------------------------------------------------------------- |
| **Day 0** | Repo created, product registered, AGENTS.md written                   |
| **Day 1** | Web app scaffolded with auth, telemetry, feature flags wired          |
| **Day 2** | 2–3 product-specific backend modules, Cosmos containers registered    |
| **Day 3** | Core UI screens built, offline sync queue, user dashboard (if needed) |
| **Day 4** | Native app shells (iOS/Android) with auth + sync wired                |
| **Day 5** | Polish, tests, CI, first deploy                                       |

**By Day 5 you have:** a fully authenticated, multi-platform app with billing, telemetry, feature flags, admin dashboard, audit logging, GDPR export, public roadmap, and offline sync — all production-grade.

---

## 5. Architecture Best Practices

### 5.1 Product Repo Structure

```
your-product/
├── web/                    # Next.js (App Router) or Expo
│   ├── src/
│   │   ├── app/            # Pages + API routes
│   │   ├── components/     # UI components
│   │   └── lib/            # Engine logic (pure TS, no framework imports)
│   └── package.json        # file: refs to @bytelyst/*
├── backend/                # Product-specific Fastify backend (NEW)
│   ├── src/
│   │   ├── lib/            # config, cosmos, auth, errors re-exports
│   │   ├── modules/        # Domain modules (types, repo, routes, tests)
│   │   └── server.ts       # Entry point
│   └── package.json        # file: refs to @bytelyst/* server packages
├── ios/                    # SwiftUI (if native)
│   └── <App>/Platform/     # Thin wrappers over ByteLystPlatformSDK
├── android/                # Jetpack Compose (if native)
│   └── app/.../platform/   # Hilt/Koin module for kotlin-platform-sdk
├── docs/                   # PRD, roadmap, research
├── scripts/                # Build/deploy scripts
├── AGENTS.md               # AI agent instructions
└── .env.example
```

### 5.2 Engine Logic Separation

**Critical rule:** Keep business logic in pure TypeScript/Kotlin/Swift files with zero framework dependencies.

```
✅ web/src/lib/fasting-timer.ts    → pure TS, testable without DOM
✅ web/src/lib/body-stages.ts      → pure TS, imported by components

❌ web/src/components/Timer.tsx     → business logic mixed with React
❌ web/src/lib/timer.ts            → imports from 'react'
```

This enables:

- Unit testing without mocking React/RN
- Sharing logic between web and native (via ports)
- AI agents can modify engine logic confidently

### 5.3 Sync Architecture

Every client follows the same offline-first pattern:

```
Local Store (Zustand/MMKV/UserDefaults)
    │
    ├── Immediate: update local state
    ├── Fire-and-forget: POST/PUT to platform-service
    └── On failure: enqueue to offline queue
                        │
                        └── On next online: flush queue → pull remote → merge
```

**Shared packages for sync:**

- `@bytelyst/offline-queue` — persistent retry queue with max retries and queue size (TS/RN)
- `@bytelyst/platform-client` — typed fetch wrapper with auth injection, x-request-id, auto-retry on 401 (TS/RN)
- `ByteLystPlatformSDK.BLSyncEngine` — offline-first sync engine (Swift/iOS)
- `kotlin-platform-sdk` — platform API client + secure store (Kotlin/Android)

**Reference implementations:**

- `PlatformSyncManager.swift` (ChronoMind) — bidirectional sync with conflict detection, offline queue
- `PlatformSyncManager.swift` (PeakPulse) — BLSyncEngine-based upload/download
- `src/api/client.ts` (NomGap) — `@bytelyst/platform-client` wrapper with auth token injection

---

## 6. Coding Conventions

### Must Follow

| Rule                                           | Why                                     |
| ---------------------------------------------- | --------------------------------------- |
| Every Cosmos document includes `productId`     | Multi-tenant isolation                  |
| Every REST endpoint validates with Zod schemas | Type safety + auto documentation        |
| Every service propagates `x-request-id`        | Distributed tracing                     |
| Use `req.log` / `app.log` in Fastify           | Structured logging with request context |
| Use `structlog` in Python                      | Same — never `print()`                  |
| Use theme tokens, never hardcode colors        | Cross-platform consistency              |
| Commit messages: `type(scope): description`    | Changelog generation                    |
| Imports always at top of file                  | Code style consistency                  |

### Must Not Do

| Anti-Pattern                     | Do Instead                             |
| -------------------------------- | -------------------------------------- |
| `console.log` in production      | `req.log.info(...)` or analytics stub  |
| `any` type in TypeScript         | Zod inference or explicit types        |
| Hardcode secrets                 | `@bytelyst/config` + Key Vault         |
| Hardcode API URLs                | Environment variables                  |
| `Math.random()` for IDs in loops | `crypto.randomUUID()` or include index |
| Modify tests to make them pass   | Fix the actual code                    |
| `npm` in common-plat             | `pnpm` (workspace)                     |

---

## 7. Data & Cosmos DB Practices

### Container Naming

```
✅ fasting_sessions       (snake_case, plural)
✅ feature_flags
❌ FastingSessions        (no PascalCase)
❌ fasting-session        (no hyphens, no singular)
```

### Document Shape

Every document must include:

```typescript
{
  id: string; // Unique ID (e.g. "session_1709234567890")
  productId: string; // ALWAYS — multi-tenant key
  // ... your fields
  createdAt: string; // ISO 8601
  updatedAt: string; // ISO 8601
}
```

### Partition Key Strategy

- Use `productId` as partition key for shared collections
- Use `id` as partition key for product-specific collections with low cross-product queries
- For high-volume telemetry: composite key like `productId:yyyyMM:platform`

### Query Patterns

```typescript
// ✅ Always filter by productId first
'SELECT * FROM c WHERE c.productId = @pid AND c.userId = @uid ORDER BY c.createdAt DESC';

// ❌ Full scan — never do this
'SELECT * FROM c';
```

---

## 8. Auth & Security Practices

### JWT Flow

```
Client → POST /auth/login → platform-service → JWT (access + refresh)
Client → Authorization: Bearer <jwt> → platform-service validates
Client → 401 → silent refresh via refresh token → retry
```

### Server-Side (Next.js API Routes)

```typescript
// lib/auth-server.ts — copy from existing product
import { createJwtUtils } from '@bytelyst/auth';

// ⚠️ For product backends (Fastify): use validated Zod config, never process.env directly
// For Next.js API routes: process.env is acceptable since Next.js validates at build time
export const { verifyToken, signToken, hashPassword, verifyPassword } = createJwtUtils({
  secret: process.env.JWT_SECRET!,
});
```

### Client-Side

```typescript
// lib/auth-client.ts — copy from existing product
import { createAuthClient } from '@bytelyst/auth-client';
export const authClient = createAuthClient({
  baseUrl: process.env.NEXT_PUBLIC_PLATFORM_URL!,
  storage: { getItem, setItem, removeItem }, // localStorage or MMKV
});
```

### Security Checklist

- [ ] Husky pre-commit: secret scan (`scripts/secret-scan-staged.sh`)
- [ ] Husky pre-push: full repo scan (`scripts/secret-scan-repo.sh`)
- [ ] No secrets in `.env.example` — only placeholder keys
- [ ] All real secrets in Azure Key Vault
- [ ] `@bytelyst/config` resolves secrets at startup
- [ ] Rate limiting on all public endpoints
- [ ] Edge middleware blocks unauthenticated API requests

---

## 9. Testing Practices

### Test Structure

```
# Service tests (Vitest)
services/platform-service/src/modules/<module>/<module>.test.ts

# Web engine tests (Vitest)
web/src/lib/<module>.test.ts

# Native tests
ios/<Project>Tests/         # XCTest
android/app/src/test/       # JUnit5

# E2E tests (Playwright)
web/e2e/
```

### Testing Rules

1. **Engine logic gets unit tests** — pure functions, no mocking needed
2. **API routes get integration tests** — use `@bytelyst/testing` Fastify inject helpers
3. **Never modify tests to make them pass** — fix the code
4. **Test the module pattern** — `types.ts` (schema validation), `repository.ts` (CRUD), `routes.ts` (HTTP)
5. **Mock external services** — Cosmos, Stripe, SendGrid
6. **Run all tests before pushing:**

   ```bash
   # Common platform
   cd learning_ai_common_plat && pnpm test

   # Your product web
   cd your-product/web && npm test

   # Typecheck
   cd your-product/web && npx tsc --noEmit
   ```

### Current Test Counts (for reference)

**Platform (common-plat):**

| Repo             | Tests | Test Files |
| ---------------- | ----- | ---------- |
| Platform-service | 766   | 66         |
| Shared packages  | ~120  | 21         |

**Product backends (Fastify):**

| Repo               | Tests | Port |
| ------------------ | ----- | ---- |
| JarvisJr backend   | 198   | 4012 |
| ChronoMind backend | 174   | 4011 |
| NomGap backend     | 152   | 4013 |
| MindLyst backend   | 59    | 4014 |
| PeakPulse backend  | 32    | 4010 |
| LysnrAI backend    | 53    | 8000 |

**Product frontends:**

| Repo               | Tests | Framework |
| ------------------ | ----- | --------- |
| NomGap (RN)        | 430   | Vitest    |
| ChronoMind web     | 394   | Vitest    |
| JarvisJr web       | 32    | Vitest    |
| ChronoMind iOS     | 129   | XCTest    |
| ChronoMind Android | 30    | JUnit5    |

---

## 10. Deployment & CI Practices

### Local Development

```bash
# Start platform-service (required for all products)
cd learning_ai_common_plat/services/platform-service
npm run dev    # port 4003

# Start your product
cd your-product/web
npm run dev    # port 3000 (or custom)
```

### Docker / CI Builds

Product repos use `file:` refs to `@bytelyst/*` packages. These break in Docker/CI where the sibling repo isn't available. Use the tarball prep workflow:

```bash
# 1. Build packages
cd learning_ai_common_plat && pnpm build

# 2. Pack tarballs + rewrite package.json
./scripts/docker-prep.sh

# 3. Now Docker build works (no sibling repo needed)
docker build your-product/web/

# 4. Restore original package.json
./scripts/docker-prep.sh --restore
```

### Environment Variables

```bash
# Required for every product
COSMOS_ENDPOINT=https://your-cosmos.documents.azure.com:443
COSMOS_KEY=...
JWT_SECRET=...
PRODUCT_ID=yourapp

# Platform-service URL (for client API calls)
PLATFORM_SERVICE_URL=http://localhost:4003
NEXT_PUBLIC_PLATFORM_URL=http://localhost:4003

# Optional but recommended
AZURE_BLOB_CONNECTION_STRING=...
STRIPE_SECRET_KEY=...
```

---

## 11. AI Agent Collaboration

### AGENTS.md Is Your Contract

Every product repo MUST have an `AGENTS.md` at root. This is the onboarding doc for all AI coding agents (Claude, Cursor, Copilot, Windsurf, Codex). Include:

1. **Project identity** — product name, ID, bundle ID, repo name
2. **Repo layout** — directory tree with descriptions
3. **Tech stack** — frameworks, versions, patterns
4. **Coding conventions** — must-follow and must-not-do rules
5. **File ownership map** — which files to touch for which domain
6. **Build & test commands** — copy-pastable verification steps
7. **Common pitfalls** — things agents frequently get wrong

### Windsurf Workflows

Create `.windsurf/workflows/` for repeatable multi-step tasks:

```yaml
---
description: Build and deploy the app
---
1. Run tests
// turbo
2. Build the app
// turbo
3. Deploy to staging
```

### Key Agent Rules

- Agents should **read AGENTS.md first** before making any changes
- Agents should **never modify tests to make them pass**
- Agents should **use `req.log` not `console.log`**
- Agents should **always include `productId`** in Cosmos documents
- Agents should **run typecheck + tests** after making changes

---

## 12. Anti-Patterns to Avoid

### Architecture Anti-Patterns

| Don't                                         | Do Instead                                              |
| --------------------------------------------- | ------------------------------------------------------- |
| Build a custom auth system                    | Use `@bytelyst/auth` + `@bytelyst/auth-client`          |
| Create a new microservice for each feature    | Add a module to platform-service                        |
| Inline `fetch()` wrappers in dashboard code   | Use `@bytelyst/api-client` factory                      |
| Put business logic in React components        | Pure TS in `src/lib/`, React in `src/components/`       |
| Create a separate Cosmos database per product | Share one database, partition by `productId`            |
| Write your own feature flag system            | Use `flags/poll` endpoint + existing polling client     |
| Skip offline queue                            | Copy `offline-queue.ts` pattern — users will be offline |

### Code Anti-Patterns

| Don't                                                  | Do Instead                                      |
| ------------------------------------------------------ | ----------------------------------------------- |
| `import { something } from '../../../common_plat/...'` | `import { something } from '@bytelyst/package'` |
| `const id = Math.random().toString()`                  | `const id = crypto.randomUUID()`                |
| `catch (e: any)`                                       | `catch (e: unknown)` with type narrowing        |
| `if (process.env.NODE_ENV === 'production')`           | Feature flags via `flags/poll`                  |
| Copy-paste an entire module and rename                 | Use the module template pattern in §3           |

### Process Anti-Patterns

| Don't                                              | Do Instead                                   |
| -------------------------------------------------- | -------------------------------------------- |
| Make a giant PR across 5 repos                     | Commit incrementally per repo, push in order |
| Skip typecheck before pushing                      | `npx tsc --noEmit` is mandatory              |
| Forget to update AGENTS.md                         | Keep it current — it's the agent contract    |
| Use `npm` in common-plat                           | `pnpm` — workspace protocol requires it      |
| Forget `pnpm build` before dashboard `npm install` | Always build packages first                  |

---

## 13. Real-World Examples

### Example: How NomGap Was Built

NomGap (fasting visualization app) was built on this platform in ~1 week:

1. **Day 0:** Created `learning_ai_fastgap`, wrote PRD, wrote AGENTS.md
2. **Day 1:** Expo (React Native) app scaffolded with:
   - Zustand + MMKV for state
   - `@bytelyst/auth-client` for auth
   - `@bytelyst/telemetry-client` for telemetry
   - Feature flag polling from platform-service
3. **Day 2:** Pure engine modules in `src/lib/` — fasting timer, body stages, autophagy meter, safety checks, gamification (283 tests)
4. **Day 3:** Platform-service modules added — `fasting-sessions`, `fasting-protocols`, `body-stages`, `social-fasting`, `meal-log`
5. **Day 4:** Offline queue, sync, native extensions (widgets, watch app stubs)
6. **Day 5:** Store assets, CI, polish

**What was NOT built from scratch:** Auth, billing, telemetry, feature flags, admin dashboard, audit logging, rate limiting, email delivery — all inherited from the platform.

### Example: How ChronoMind Was Built

ChronoMind (AI clock/timer) spans web (Next.js PWA), iOS (SwiftUI), Android (Compose), watchOS, macOS:

1. **Web:** Next.js 16 + Zustand + Serwist (PWA). 16 pure engine modules in `web/src/lib/`, 12 React components, 394 tests
2. **iOS:** SwiftUI with 20+ shared modules in `ios/ChronoMind/Shared/`, `Platform/` wrappers over ByteLystPlatformSDK, WidgetKit, Live Activities, Siri Shortcuts
3. **Android:** Jetpack Compose + Room + Hilt + kotlin-platform-sdk, Glance widgets, foreground service
4. **Backend:** Product-specific Fastify backend (port 4011) with 5 modules (timers, routines, shared-timers, households, webhooks) — 198 tests
5. **Sync:** Bidirectional sync with offline queue, conflict detection, Keychain-based auth token storage

**Total product backend modules:** 5. Everything else (auth, billing, flags, telemetry, admin, tracker) was inherited from platform-service.

---

## Quick Reference: Copy-Paste Checklist for New Products

```
□ Create repo: learning_ai_<codename>
□ Write AGENTS.md (copy template, customize)
□ Create .env.example with required vars
□ Register product: POST /products to platform-service
□ Add flags to services/platform-service/src/modules/flags/seed.ts
□ Add design tokens to packages/design-tokens/ (optional)
□ Scaffold web app with file: refs to @bytelyst/*
□ Create lib/ wiring: cosmos.ts, auth-server.ts, product-config.ts, platform-client.ts
□ Scaffold product backend in backend/ (copy from existing product repo)
□   — lib/config.ts with Zod env validation (JWT_SECRET from config, NOT process.env)
□   — lib/cosmos-init.ts to register + initialize Cosmos containers
□   — 1–3 domain modules (types.ts, repository.ts, routes.ts, *.test.ts)
□ Wire native SDKs:
□   — iOS: ByteLystPlatformSDK → Platform/ wrappers
□   — Android: kotlin-platform-sdk → Hilt/Koin module
□   — RN: @bytelyst/platform-client, auth-client, feature-flag-client, kill-switch-client, offline-queue
□ Wire telemetry client
□ Wire feature flag polling
□ Add offline queue for sync
□ Write tests for engine logic
□ Run typecheck + tests
□ Add to backup/push workflows
□ Push to origin
```
