# Cross-Repo DRY Audit — Migration & Integration Candidates > **Date:** 2026-03-20 > **Scope:** 9 product backends + web dashboards vs. 53 `@bytelyst/*` shared packages > **Goal:** Identify duplicated patterns across product repos that should be consolidated into common platform packages. --- ## Executive Summary Audited all 9 product repos with Fastify backends. Found **6 high-priority** and **4 medium-priority** duplication patterns across backends and web clients. The most impactful candidates involve backend `lib/` files that are **copy-pasted identically** (or near-identically) across all repos — differing only by product ID, port number, or service name. **Estimated LOC savings:** ~2,400 lines backend + ~1,800 lines web = **~4,200 lines** of duplicated code that could be replaced by shared packages. --- ## HIGH Priority — Backend `lib/` Duplication (9 repos × 6 files) ### 1. `auth.ts` — JWT verification + JWKS + role checking **Status:** Identical across all 9 repos (60-90 lines each = ~700 LOC total) **Pattern:** RS256 JWKS verification → HS256 fallback → `extractAuth()` + `requireRole()` **Only difference:** imports `config` from local `./config.js` **Recommendation:** Create `@bytelyst/fastify-auth` package: ```ts // New package: packages/fastify-auth/ export function createAuthPlugin(opts: { jwtSecret: string; jwksUrl?: string }) { ... } export function extractAuth(req: FastifyRequest): Promise { ... } export function requireRole(req: FastifyRequest, ...roles: string[]): Promise { ... } ``` **Affected repos:** LysnrAI, MindLyst, ChronoMind, JarvisJr, NomGap, PeakPulse, FlowMonk, NoteLett, ActionTrail --- ### 2. `request-context.ts` — productId validation + getUserId() **Status:** Nearly identical across all 9 repos (~30-50 lines each = ~350 LOC total) **Only difference:** `const PRODUCT_ID = ''` string literal **Recommendation:** Add to `@bytelyst/fastify-auth` or new `@bytelyst/request-context`: ```ts export function createRequestContext(productId: string) { return { getRequestProductId(req: FastifyRequest): string { ... }, getUserId(req: FastifyRequest): string { ... }, }; } ``` **Affected repos:** All 9 backends --- ### 3. `errors.ts` — Re-export of `@bytelyst/errors` **Status:** Identical in 8/9 repos (FlowMonk imports directly) **Pattern:** 7-12 line file that just re-exports from `@bytelyst/errors` **Recommendation:** **DELETE these files.** Product repos should import `@bytelyst/errors` directly in their modules — the re-export layer adds no value. **Affected repos:** LysnrAI, MindLyst, ChronoMind, JarvisJr, NomGap, PeakPulse, NoteLett, ActionTrail --- ### 4. `config.ts` — Zod env schema **Status:** 80% identical across all 9 repos (~15-30 lines each = ~200 LOC total) **Common fields:** PORT, HOST, NODE*ENV, CORS_ORIGIN, SERVICE_NAME, DB_PROVIDER, COSMOS*\*, JWT_SECRET, PLATFORM_JWKS_URL **Product-specific fields:** PLATFORM_SERVICE_URL, EXTRACTION_SERVICE_URL, WEBHOOK_SECRET, LLM_API_KEY, etc. **Recommendation:** Create `@bytelyst/backend-config` with a composable schema: ```ts import { createBackendConfig } from '@bytelyst/backend-config'; export const config = createBackendConfig({ serviceName: 'nomgap-backend', defaultPort: 4013, extraSchema: z.object({ EXTRACTION_SERVICE_URL: z.string().default('http://localhost:4005'), }), }); ``` **Affected repos:** All 9 backends --- ### 5. `datastore.ts` — DB_PROVIDER switch (Cosmos vs Memory) **Status:** Identical in 6/9 repos; 3 older repos use direct Cosmos without the provider abstraction **Pattern:** Import `@bytelyst/datastore`, configure based on `DB_PROVIDER` env var **Recommendation:** Already have `@bytelyst/datastore` package. The 3 older repos (LysnrAI, MindLyst, ChronoMind) should be **migrated** to use `@bytelyst/datastore` with `DB_PROVIDER` support instead of direct `@azure/cosmos` calls. **Migration needed:** LysnrAI, MindLyst, ChronoMind backends --- ### 6. `product-config.ts` — Backend product identity **Status:** Present in 4/9 repos (FlowMonk, ActionTrail, NoteLett, NomGap), hardcoded in others **Pattern:** Read `shared/product.json`, export `PRODUCT_ID`, `productConfig` **Recommendation:** Already solved by `@bytelyst/config` (loadProductIdentity). The 5 repos without `product-config.ts` should adopt `@bytelyst/config/product-identity` instead of hardcoding product IDs. **Migration needed:** LysnrAI, MindLyst, ChronoMind, JarvisJr, PeakPulse --- ## MEDIUM Priority — Backend Patterns (2-3 repos) ### 7. `events.ts` — Domain event bus + SSE + webhook dispatch **Status:** FlowMonk and ActionTrail have near-identical event bus infrastructure (~150 lines each) **Pattern:** `@bytelyst/event-store` + `@bytelyst/fastify-sse` + `@bytelyst/webhook-dispatch` wired together with typed domain events + SSE hub + webhook targets **Recommendation:** Create `@bytelyst/domain-events` factory: ```ts export function createDomainEventBus(opts: { productId: string; eventTypes: TEvent['type'][]; webhookSecret?: string; }) { ... } ``` Product repos would only define their event type interfaces and call `createDomainEventBus()`. **Affected repos:** FlowMonk, ActionTrail (and future products that need real-time events) --- ### 8. `feature-flags.ts` — Backend in-memory flag registry **Status:** FlowMonk and ActionTrail have **identical** implementations (25 lines each) **Pattern:** `Map` with `isFeatureEnabled()`, `getAllFlags()`, `setFlag()` **Recommendation:** Create `@bytelyst/backend-flags`: ```ts export function createFlagRegistry(defaults: Record) { ... } ``` **Affected repos:** FlowMonk, ActionTrail (expandable to all backends) --- ### 9. `telemetry.ts` — Backend telemetry buffer **Status:** FlowMonk and ActionTrail have **byte-for-byte identical** implementations (33 lines each) **Pattern:** In-memory buffer with `trackEvent()`, `getBufferedEvents()`, `flushEvents()` **Recommendation:** Add to existing `@bytelyst/events` or new `@bytelyst/backend-telemetry`: ```ts export function createTelemetryBuffer(opts: { enabled: boolean }) { ... } ``` **Affected repos:** FlowMonk, ActionTrail --- ### 10. `scheduler.ts` — In-process job scheduler **Status:** ActionTrail has a full scheduler; FlowMonk has a scheduling engine **Pattern:** Cron parsing, job registry, runner with diagnostics **Recommendation:** ActionTrail's scheduler could generalize to `@bytelyst/cron-scheduler` for any product needing periodic jobs. Currently `@bytelyst/queue` exists but is a different pattern (durable job queue). **Affected repos:** ActionTrail (FlowMonk's scheduler is domain-specific — planning, not cron) --- ## HIGH Priority — Web `lib/` Duplication (5+ repos) ### 11. `telemetry.ts` — Web telemetry init **Status:** NomGap, NoteLett, ChronoMind, JarvisJr have near-identical wrappers (~35 lines each) **Only difference:** `channel` name string **Recommendation:** The `@bytelyst/telemetry-client` package already provides `createTelemetryClient()`. Products should call it directly in their `providers.tsx` instead of maintaining a wrapper file. Alternatively, add a `createWebTelemetry(productId, channel)` convenience to the package. **Affected repos:** NomGap, NoteLett, ChronoMind, JarvisJr web apps --- ### 12. `diagnostics.ts` — Web diagnostics init **Status:** NomGap, NoteLett, ChronoMind, JarvisJr have near-identical wrappers (~40 lines each) **Only difference:** `channel` name, auth token retrieval method **Recommendation:** Add `createWebDiagnostics(opts)` convenience to `@bytelyst/diagnostics-client` that handles install ID generation, localStorage auth token, and default config. **Affected repos:** NomGap, NoteLett, ChronoMind, JarvisJr web apps --- ### 13. `feature-flags.ts` + `kill-switch.ts` — Web client wrappers **Status:** NomGap and NoteLett have identical wrappers; ChronoMind has similar **Recommendation:** These are thin wrappers around `@bytelyst/feature-flag-client` and `@bytelyst/kill-switch-client`. Consider adding React hook convenience exports directly to the packages. --- ### 14. `product-config.ts` — Web product identity **Status:** 5 different patterns across repos: - NomGap/NoteLett: import `shared/product.json` + env var overrides - FlowMonk/ActionTrail: inline object literal - JarvisJr/ChronoMind: custom exports **Recommendation:** Standardize on `shared/product.json` import pattern. Could add `@bytelyst/web-config` convenience that reads product.json and provides typed exports with NEXT*PUBLIC* env var overrides. --- ## Migration Priority Matrix | # | Candidate | LOC Saved | Repos | Effort | Priority | | --- | -------------------------------------------------------- | --------- | ----- | -------- | -------- | | 1 | `auth.ts` → `@bytelyst/fastify-auth` | ~700 | 9 | 2 days | **P0** | | 2 | `request-context.ts` → merge into fastify-auth | ~350 | 9 | 1 day | **P0** | | 3 | `errors.ts` → delete (import directly) | ~100 | 8 | 0.5 day | **P0** | | 4 | `config.ts` → `@bytelyst/backend-config` | ~200 | 9 | 2 days | **P1** | | 5 | Older repos → `@bytelyst/datastore` | ~300 | 3 | 1 day | **P1** | | 6 | Hardcoded productId → `@bytelyst/config` | ~50 | 5 | 0.5 day | **P1** | | 7 | `events.ts` → `@bytelyst/domain-events` | ~300 | 2 | 1.5 days | **P2** | | 8 | `feature-flags.ts` → `@bytelyst/backend-flags` | ~50 | 2 | 0.5 day | **P2** | | 9 | `telemetry.ts` → `@bytelyst/backend-telemetry` | ~70 | 2 | 0.5 day | **P2** | | 10 | Web telemetry/diagnostics wrappers → package convenience | ~400 | 4 | 1 day | **P2** | | 11 | Web `product-config.ts` → standardize pattern | ~200 | 5+ | 1 day | **P2** | **Total estimated effort: ~11 days for full DRY migration** **Total LOC eliminated: ~2,700+ duplicated lines** --- ## Repos NOT Yet Using Common Platform ### `learning_ai_local_memory_gpt` - Standalone Express + SQLite app — no Cosmos, no auth, no platform-service - **No integration needed** — this is intentionally a standalone local tool ### `learning_ai_productivity_web` - No backend directory found - Needs investigation to determine if it should adopt platform patterns --- ## Recommended Execution Order ### Sprint 1 (P0 — 3.5 days) 1. Create `@bytelyst/fastify-auth` package with `extractAuth()`, `requireRole()`, `createRequestContext()` 2. Migrate all 9 backends to use it (delete local `auth.ts` + `request-context.ts`) 3. Delete all `errors.ts` re-export files, update imports to `@bytelyst/errors` directly ### Sprint 2 (P1 — 3.5 days) 4. Create `@bytelyst/backend-config` with composable Zod schema factory 5. Migrate LysnrAI, MindLyst, ChronoMind backends to `@bytelyst/datastore` 6. Migrate 5 repos to `@bytelyst/config/product-identity` for productId ### Sprint 3 (P2 — 4 days) 7. Create `@bytelyst/domain-events` factory (from FlowMonk/ActionTrail pattern) 8. Create `@bytelyst/backend-flags` and `@bytelyst/backend-telemetry` 9. Add convenience functions to web-side shared packages 10. Standardize web `product-config.ts` pattern