learning_ai_common_plat/docs/CROSS_REPO_DRY_AUDIT.md
saravanakumardb1 d10322095a docs: fix 10 inaccuracies in DRY audit + roadmap after thorough review
Verified claims against actual codebase. Key corrections:

Audit (CROSS_REPO_DRY_AUDIT.md):
- Fix #5: all 9 repos already use @bytelyst/datastore — issue is only
  DB_PROVIDER missing from config.ts in 3 older repos (not a full migration)
- Fix #6: only 3 repos have product-config.ts (not 4) — NomGap was wrong
- Fix #11: web telemetry.ts is in NomGap+NoteLett+ChronoMind+LysnrAI (not JarvisJr)
- Fix #12: web diagnostics.ts includes LysnrAI user-dashboard-web (5 repos total)
- Fix auth.ts LOC: exactly 79 lines × 9 repos = 711 (was '60-90')
- Fix request-context.ts LOC: 30-49 lines range (was '~30-50')
- Fix package count: 50 packages (not 53)
- Add items 15-16: web auth.ts + billing-client.ts (noted as keep-as-is)
- Fix LOC math: ~2,700 total (was inflated ~4,200)
- Add cosmos-init.ts note (5 repos, product-specific, not consolidation candidates)

Roadmap (CROSS_REPO_DRY_MIGRATION_ROADMAP.md):
- Phase 0.2: 6 repos need product-config.ts (add NomGap)
- Phase 2.3: rewritten from 'migrate to datastore' to 'add DB_PROVIDER to config'
- Phase 4: add LysnrAI user-dashboard-web to affected repos, remove JarvisJr from telemetry
- Fix product-config.ts template path (was ../../../../, now ../../../ with depth note)
- Fix success metrics: packages 50→55, product-config 3→9, LOC ~1,760
- Fix overview table: Phase 2 name, Phase 4 repo count
2026-03-20 07:15:07 -07:00

13 KiB
Raw Blame History

Cross-Repo DRY Audit — Migration & Integration Candidates

Date: 2026-03-20 Scope: 9 product backends + web dashboards vs. 50 @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 + 5 Next.js web dashboards. Found 6 high-priority and 4 medium-priority backend duplication patterns, plus 6 web-side duplication patterns. 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: ~1,700 lines backend + ~1,000 lines web = ~2,700 lines of duplicated code that could be replaced by shared packages or eliminated entirely.


HIGH Priority — Backend lib/ Duplication (9 repos × 6 files)

1. auth.ts — JWT verification + JWKS + role checking

Status: Identical across all 9 repos (79 lines each = 711 LOC total) Pattern: RS256 JWKS verification → HS256 fallback → extractAuth() + requireRole() Only difference: imports config from local ./config.js

Recommendation: Create @bytelyst/fastify-auth package:

// New package: packages/fastify-auth/
export function createAuthPlugin(opts: { jwtSecret: string; jwksUrl?: string }) { ... }
export function extractAuth(req: FastifyRequest): Promise<AuthPayload> { ... }
export function requireRole(req: FastifyRequest, ...roles: string[]): Promise<AuthPayload> { ... }

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-49 lines each = ~315 LOC total) Only difference: const PRODUCT_ID = '<product>' string literal

Recommendation: Add to @bytelyst/fastify-auth or new @bytelyst/request-context:

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, NODEENV, 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:

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 in config vs. hardcoded env read

Status: All 9 repos already use @bytelyst/datastore (CosmosDatastoreProvider / MemoryDatastoreProvider). However, 3 older repos (LysnrAI, MindLyst, ChronoMind) read DB_PROVIDER directly from process.env inside datastore.ts instead of declaring it in their Zod config.ts schema. The 6 newer repos properly declare DB_PROVIDER in config. Pattern: Import @bytelyst/datastore, configure based on DB_PROVIDER env var

Recommendation: Add DB_PROVIDER to the Zod config schema in the 3 older repos so it's validated at startup like other env vars. This is a minor cleanup (not a full migration).

Cleanup needed: LysnrAI, MindLyst, ChronoMind — add DB_PROVIDER to config.ts

Note: 5 repos also have a supplementary cosmos-init.ts file (MindLyst, ChronoMind, JarvisJr, FlowMonk, NoteLett) that registers Cosmos containers. These are product-specific and NOT candidates for consolidation — each repo registers different containers.


6. product-config.ts — Backend product identity

Status: Present in 3/9 repos (FlowMonk, ActionTrail, NoteLett). The other 6 repos hardcode const PRODUCT_ID = '<name>' in request-context.ts. Pattern: Read shared/product.json, export PRODUCT_ID, productConfig

Recommendation: The 6 repos without product-config.ts should add one that reads from shared/product.json (all repos have this file). This eliminates hardcoded product IDs and ensures consistency.

Migration needed: LysnrAI, MindLyst, ChronoMind, JarvisJr, NomGap, 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:

export function createDomainEventBus<TEvent extends BaseEvent>(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<string, boolean> with isFeatureEnabled(), getAllFlags(), setFlag()

Recommendation: Create @bytelyst/backend-flags:

export function createFlagRegistry(defaults: Record<string, boolean>) { ... }

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:

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, LysnrAI (user-dashboard-web) have near-identical wrappers (~35 lines each). JarvisJr does NOT have this file. 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, LysnrAI web apps


12. diagnostics.ts — Web diagnostics init

Status: NomGap, NoteLett, ChronoMind, JarvisJr, LysnrAI (user-dashboard-web) 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, LysnrAI 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 (best pattern)
  • FlowMonk/ActionTrail: inline object literal
  • JarvisJr: custom getPlatformBaseURL() function
  • ChronoMind: product config embedded in auth-api.ts (PRODUCT_ID + getBaseUrl())
  • LysnrAI user-dashboard: uses @bytelyst/config loadProductIdentity() (slightly different)

Recommendation: Standardize on shared/product.json import pattern (NomGap/NoteLett style). This reads the canonical shared/product.json and provides typed exports with NEXT_PUBLIC_* env var overrides.


15. auth.ts — Web auth provider wrapper

Status: NomGap and NoteLett have near-identical auth.ts files (~40 lines each) wrapping createAuthProvider() from @bytelyst/react-auth with product-specific types. Only difference: LoginResponse type shape varies slightly.

Recommendation: Minor duplication — keep as-is since each product may have different user types. Not worth a shared package.

Affected repos: NomGap, NoteLett (ChronoMind uses @bytelyst/auth-client instead)


16. billing-client.ts — Web subscription/billing wrapper

Status: NomGap and ChronoMind wrap @bytelyst/subscription-client; LysnrAI wraps @bytelyst/api-client. Three different approaches to the same problem.

Recommendation: Minor duplication — keep as-is since each product has different billing UI needs. The shared @bytelyst/subscription-client already handles the heavy lifting.


Migration Priority Matrix

# Candidate LOC Saved Repos Effort Priority
1 auth.ts@bytelyst/fastify-auth ~711 9 2 days P0
2 request-context.ts → merge into fastify-auth ~315 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 DB_PROVIDER cleanup in older config.ts ~15 3 0.5 day P1
6 Hardcoded productId → product-config.ts ~50 6 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 5 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,435+ duplicated lines

Note: Items 15-16 (web auth.ts, billing-client.ts) are intentionally NOT in this matrix — the duplication is minor and each product legitimately needs different types/behavior.


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

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)

  1. Create @bytelyst/backend-config with composable Zod schema factory
  2. Migrate LysnrAI, MindLyst, ChronoMind backends to @bytelyst/datastore
  3. Migrate 5 repos to @bytelyst/config/product-identity for productId

Sprint 3 (P2 — 4 days)

  1. Create @bytelyst/domain-events factory (from FlowMonk/ActionTrail pattern)
  2. Create @bytelyst/backend-flags and @bytelyst/backend-telemetry
  3. Add convenience functions to web-side shared packages
  4. Standardize web product-config.ts pattern