learning_ai_common_plat/AGENTS.md
saravanakumardb1 90b9cf93d8 fix(common): configure ESLint 9 and fix lint issues
- Added @eslint/js dependency
- Updated eslint.config.js for ESLint 9 compatibility
- Added required globals (crypto, localStorage, React, etc.)
- Fixed unused imports and variables
- Disabled sort-imports temporarily
- Formatted all files with Prettier
2026-02-12 16:37:30 -08:00

304 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AGENTS.md — AI Coding Agent Instructions
> **For:** Claude Code, OpenAI Codex, Cursor, GitHub Copilot, Windsurf Cascade, and any AI coding agent.
> **Repo:** `learning_ai_common_plat` — Shared platform packages + microservices for the ByteLyst ecosystem.
> **See also:** [`README.md`](README.md) for quick start, [`docs/ECOSYSTEM_ARCHITECTURE.md`](docs/ECOSYSTEM_ARCHITECTURE.md) for full architecture.
---
## 1. Project Identity
| Key | Value |
| --------------------- | --------------------------------------------------------------------------------------- |
| **Root package** | `@bytelyst/root` |
| **Library scope** | `@bytelyst/*` (packages/) |
| **Service scope** | `@lysnrai/*` (services/) |
| **Product consumers** | [LysnrAI](../learning_voice_ai_agent), [MindLyst](../learning_multimodal_memory_agents) |
| **Product-agnostic** | Yes — every Cosmos doc includes `productId` |
| **Runtime** | Node.js (ESM), TypeScript 5.7+ |
| **Package manager** | pnpm (workspace) |
| **Test runner** | Vitest |
## 2. Monorepo Layout
```
learning_ai_common_plat/
├── packages/ # @bytelyst/* shared libraries
│ ├── errors/ # Typed HTTP service errors (400429)
│ ├── cosmos/ # Azure Cosmos DB client singleton + container registry
│ ├── config/ # Zod-based env loader + product identity (loadProductIdentity)
│ ├── auth/ # JWT utilities, auth middleware, password hashing
│ ├── api-client/ # Configurable fetch wrapper with auth token injection
│ ├── react-auth/ # React auth context factory (typed provider + hook)
│ └── design-tokens/ # Cross-platform tokens (JSON → CSS/TS/Kotlin/Swift)
│ ├── tokens/bytelyst.tokens.json # ← CANONICAL SOURCE
│ ├── scripts/generate.ts # Token generator
│ └── generated/ # Output: tokens.css, tokens.ts, MindLystTokens.kt, MindLystTheme.swift
├── services/ # @lysnrai/* product-agnostic microservices
│ ├── platform-service/ # Auth, audit, flags, notifications, blob (port 4003)
│ ├── billing-service/ # Subscriptions, Stripe, usage, licenses (port 4002)
│ ├── growth-service/ # Invitations, referrals, promos (port 4001)
│ ├── tracker-service/ # Items, comments, votes, public roadmap (port 4004)
│ └── monitoring/ # Loki + Grafana config, health-check script
├── docs/ # Architecture docs, roadmap, analysis
├── package.json # Root scripts: build, test, typecheck, clean
├── pnpm-workspace.yaml # Workspace: packages/* + services/*
├── tsconfig.base.json # Shared TS config (ES2022, NodeNext, strict)
├── vitest.config.ts # Root vitest config (passWithNoTests)
├── docker-compose.yml # Full service stack + Loki + Grafana + Traefik
├── .env.example # Required env vars template
└── .editorconfig # Editor settings
```
## 3. Tech Stack Rules
### TypeScript (all packages + services)
- **Module system:** ESM (`"type": "module"` everywhere)
- **TS target:** ES2022, `moduleResolution: NodeNext`
- **Base config:** All packages/services extend `../../tsconfig.base.json`
- **Builds:** `tsc` — outputs to `dist/`
- **Tests:** Vitest with `passWithNoTests: true` at root
### Service framework (Fastify)
- **Framework:** Fastify 5 with Zod validation
- **Module pattern:** `types.ts``repository.ts``routes.ts` per module
- **Auth:** JWT via `jose` — platform-service issues, all others validate
- **Database:** Azure Cosmos DB via `@azure/cosmos`
- **Logging:** Fastify built-in `req.log` / `app.log` (never `console.log`)
- **Health:** Every service exposes `GET /health``{ status: "ok", service, requestId }`
- **Request tracing:** `x-request-id` header propagated across all services
- **Dev mode:** `tsx watch src/server.ts`
### Package conventions
- All packages export from `src/index.ts``dist/index.js`
- Use `exports` field in `package.json` (not just `main`)
- Peer dependencies for heavy/shared deps (`@azure/cosmos`, `jose`, `bcryptjs`, `react`, `zod`)
- Workspace deps: `"@bytelyst/errors": "workspace:*"`
## 4. Coding Conventions
### MUST follow
- Every Cosmos document MUST include a `productId` field
- Every REST endpoint MUST validate input with Zod schemas
- Every service MUST propagate `x-request-id` headers
- Use `PRODUCT_ID` from `@bytelyst/config` (`loadProductIdentity()`) — never hardcode
- Services use self-contained Zod config schemas in `src/lib/config.ts` (avoids zod version mismatch with shared packages)
- Services re-export from `@bytelyst/*` in their `src/lib/` files (`errors.ts`, `cosmos.ts`, `product-config.ts`)
- Commit messages: `type(scope): description` — types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`
### MUST NOT do
- Never use `console.log` in production code — use `req.log` or `app.log` in Fastify
- Never use `any` type — use Zod inference or explicit types
- Never hardcode secrets or API keys
- Never modify tests to make them pass — fix the actual code
- Never delete existing comments or documentation unless explicitly asked
- Never add emojis to code unless explicitly asked
## 5. File Ownership Map
| Domain | Location | Key Files |
| ----------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Errors** | `packages/errors/` | `src/index.ts``BadRequestError`, `UnauthorizedError`, `ForbiddenError`, `NotFoundError`, `ConflictError`, `RateLimitError` |
| **Cosmos client** | `packages/cosmos/` | `src/index.ts``getCosmosClient()`, `getContainer()`, container registry |
| **Config / Product ID** | `packages/config/` | `src/index.ts``loadEnvConfig()`, `loadProductIdentity()`, `getProductId()` |
| **JWT / Auth** | `packages/auth/` | `src/index.ts``signJwt()`, `verifyJwt()`, `hashPassword()`, `verifyPassword()`, auth middleware |
| **API client** | `packages/api-client/` | `src/index.ts``createApiClient()` with token injection |
| **React auth** | `packages/react-auth/` | `src/index.ts``createAuthContext()` factory (provider + hook) |
| **Design tokens** | `packages/design-tokens/` | `tokens/bytelyst.tokens.json` (source), `scripts/generate.ts` (generator), `generated/` (output) |
| **Auth / JWT issue** | `services/platform-service/` | `src/modules/auth/` |
| **Feature flags** | `services/platform-service/` | `src/modules/flags/` — FNV-1a hash for deterministic rollout |
| **Blob storage** | `services/platform-service/` | `src/modules/blob/`, `src/lib/blob.ts` — SAS tokens, CRUD |
| **Audit log** | `services/platform-service/` | `src/modules/audit/` |
| **Notifications** | `services/platform-service/` | `src/modules/notifications/` |
| **Rate limiting** | `services/platform-service/` | `src/modules/rate-limit/` |
| **Subscriptions** | `services/billing-service/` | `src/modules/subscriptions/` |
| **Stripe webhooks** | `services/billing-service/` | `src/modules/stripe/` |
| **Usage tracking** | `services/billing-service/` | `src/modules/usage/` |
| **Plans** | `services/billing-service/` | `src/modules/plans/` |
| **Licenses** | `services/billing-service/` | `src/modules/licenses/` |
| **Invitations** | `services/growth-service/` | `src/modules/invitations/` |
| **Referrals** | `services/growth-service/` | `src/modules/referrals/` |
| **Promos** | `services/growth-service/` | `src/modules/promos/` |
| **Tracker items** | `services/tracker-service/` | `src/modules/items/` |
| **Public roadmap** | `services/tracker-service/` | `src/modules/public/` |
| **Tracker comments** | `services/tracker-service/` | `src/modules/comments/` |
| **Tracker votes** | `services/tracker-service/` | `src/modules/votes/` |
| **Monitoring** | `services/monitoring/` | `health-check.ts`, `loki/`, `grafana/` |
### Dashboard Consumers (via `file:` refs)
The following dashboards in `../learning_voice_ai_agent/` consume `@bytelyst/*` packages:
| Dashboard | Packages Used |
| ----------------------- | ---------------------------------------- |
| `admin-dashboard-web` | api-client, auth, config, cosmos, errors |
| `user-dashboard-web` | api-client, auth, config, cosmos, errors |
| `tracker-dashboard-web` | api-client, errors |
**Prerequisite:** Run `pnpm build` in this repo before running `npm install` in any dashboard.
## 6. How to Run Things
```bash
# ── Install ────────────────────────────────────────
pnpm install
# ── Build all packages + services ──────────────────
pnpm build
# ── Run all tests (20 test files across all workspaces) ─
pnpm test
# ── Type-check everything ──────────────────────────
pnpm typecheck
# ── Clean dist/ in all packages ────────────────────
pnpm clean
# ── Run a specific service in dev mode ─────────────
pnpm --filter @lysnrai/platform-service dev
pnpm --filter @lysnrai/billing-service dev
pnpm --filter @lysnrai/growth-service dev
pnpm --filter @lysnrai/tracker-service dev
# ── Run tests for one workspace ────────────────────
pnpm --filter @lysnrai/platform-service test
pnpm --filter @bytelyst/errors test
# ── Generate design tokens ─────────────────────────
pnpm --filter @bytelyst/design-tokens generate
# ── Docker Compose (all services + monitoring) ─────
docker compose up -d
docker compose down
# ── Health check all services ──────────────────────
pnpm --filter @lysnrai/monitoring check
```
## 7. Common Patterns
### Adding a new Fastify module
1. Create `services/<service>/src/modules/<name>/types.ts` — Zod schemas + TS interfaces
2. Create `services/<service>/src/modules/<name>/repository.ts` — Cosmos CRUD
3. Create `services/<service>/src/modules/<name>/routes.ts` — REST endpoints
4. Register in `services/<service>/src/server.ts`: `await app.register(routes, { prefix: "/api" })`
5. Add tests: `services/<service>/src/modules/<name>/<name>.test.ts`
### Adding a new shared package
1. Create `packages/<name>/` with `package.json` (`name: "@bytelyst/<name>"`)
2. Add `src/index.ts` with exports
3. Add `tsconfig.json` extending `../../tsconfig.base.json`
4. Heavy deps go in `peerDependencies`, not `dependencies`
5. Consumer services add `"@bytelyst/<name>": "workspace:*"` to their `dependencies`
### Using shared packages in services
Services re-export from `@bytelyst/*` in `src/lib/` for clean internal imports:
```typescript
// src/lib/errors.ts
export { BadRequestError, NotFoundError, ConflictError } from '@bytelyst/errors';
// src/lib/cosmos.ts
export { getCosmosClient, getContainer } from '@bytelyst/cosmos';
// src/lib/product-config.ts
import { loadProductIdentity } from '@bytelyst/config';
const identity = loadProductIdentity();
export const PRODUCT_ID = identity.productId;
```
### Design token workflow
1. Edit `packages/design-tokens/tokens/bytelyst.tokens.json`
2. Run `pnpm --filter @bytelyst/design-tokens generate`
3. Copy generated files to consumer repos:
- `MindLystTokens.kt``mindlyst-native/shared/.../theme/`
- `MindLystTheme.swift``mindlyst-native/iosApp/`
- Token CSS → `design-system/web/mindlyst.css` (token section only)
## 8. Environment Variables
Required by all services (see `.env.example`):
```
COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
COSMOS_KEY=<primary-key>
COSMOS_DATABASE=lysnrai
JWT_SECRET=<shared-secret>
```
Additional per-service:
```
# billing-service + growth-service
STRIPE_SECRET_KEY=<stripe-key>
STRIPE_WEBHOOK_SECRET=<webhook-secret>
# platform-service (blob storage)
AZURE_BLOB_CONNECTION_STRING=<connection-string>
AZURE_BLOB_ACCOUNT_NAME=bytelystblobs
AZURE_BLOB_ACCOUNT_KEY=<account-key>
# All services
DEFAULT_PRODUCT_ID=lysnrai
```
## 9. Dependency Graph
```
@bytelyst/errors ← no deps (foundation)
@bytelyst/cosmos ← peers: @azure/cosmos
@bytelyst/config ← peers: zod
@bytelyst/auth ← peers: jose, bcryptjs
@bytelyst/api-client ← no deps
@bytelyst/react-auth ← deps: @bytelyst/api-client; peers: react
@bytelyst/design-tokens ← no deps (standalone generator)
@lysnrai/platform-service ← @bytelyst/{config, cosmos, errors}
@lysnrai/billing-service ← @bytelyst/{config, cosmos, errors}
@lysnrai/growth-service ← @bytelyst/{config, cosmos, errors}
@lysnrai/tracker-service ← @bytelyst/{config, cosmos, errors}
```
Build order: packages first (they have no inter-deps), then services. `pnpm build` handles this automatically via workspace topology.
## 10. Key Documents
| When you need to... | Read this |
| -------------------------------- | -------------------------------------------------------------------------------------------------- |
| Understand the full architecture | [`docs/ECOSYSTEM_ARCHITECTURE.md`](docs/ECOSYSTEM_ARCHITECTURE.md) |
| See the extraction roadmap | [`docs/ROADMAP.md`](docs/ROADMAP.md) |
| Understand why this repo exists | [`docs/COMMON_PLATFORM_ANALYSIS.md`](docs/COMMON_PLATFORM_ANALYSIS.md) |
| Quick start / consuming packages | [`README.md`](README.md) |
| LysnrAI product repo conventions | [`../learning_voice_ai_agent/AGENTS.md`](../learning_voice_ai_agent/AGENTS.md) |
| MindLyst native repo conventions | [`../learning_multimodal_memory_agents/AGENTS.md`](../learning_multimodal_memory_agents/AGENTS.md) |
## 11. Service Test Counts
| Service / Package | Tests | Runner |
| ----------------- | -------- | ------ |
| platform-service | 55 | vitest |
| tracker-service | 45 | vitest |
| growth-service | 33 | vitest |
| billing-service | 32 | vitest |
| **Total** | **165+** | |
## 12. Common Pitfalls
1. **Don't import `zod` from `@bytelyst/config` in services** — services bundle their own zod version. Use self-contained Zod schemas in `src/lib/config.ts`.
2. **Don't forget `productId`** — every Cosmos document must include it.
3. **Don't use `dependencies` for heavy libs in packages** — use `peerDependencies` so consumers control the version.
4. **Don't mix up package scopes** — libraries are `@bytelyst/*`, services are `@lysnrai/*`.
5. **Don't run `npm` commands** — this is a pnpm workspace. Always use `pnpm`.
6. **Don't modify generated files directly** — edit `bytelyst.tokens.json` and re-run the generator.
7. **Build packages before testing services** — service tests may import from `@bytelyst/*` dist. Run `pnpm build` first if you get import errors.