learning_ai_common_plat/docs/CROSS_REPO_DRY_AUDIT.md
saravanakumardb1 a769f671e2 docs: cross-repo DRY audit + end-to-end migration roadmap
- CROSS_REPO_DRY_AUDIT.md: identified 14 duplication patterns across
  9 product backends + web clients (~4,200 LOC duplicated)
- CROSS_REPO_DRY_MIGRATION_ROADMAP.md: 5-phase execution plan with
  concrete file lists, migration steps, verification checkpoints,
  rollback strategy, and success metrics
- Phase 0: quick wins (delete errors.ts re-exports, standardize product-config)
- Phase 1: @bytelyst/fastify-auth (auth + request-context for 9 repos)
- Phase 2: @bytelyst/backend-config + datastore migration for 3 older repos
- Phase 3: backend-flags, backend-telemetry, domain-events (FlowMonk + ActionTrail)
- Phase 4: web client DRY (telemetry, diagnostics, product-config conveniences)
- Estimated: 11 days, 5 new packages, ~3,260 LOC eliminated
2026-03-20 07:04:46 -07:00

11 KiB
Raw Blame History

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:

// 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-50 lines each = ~350 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 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:

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, 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 NEXTPUBLIC 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

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