/** * @fileoverview Deprecation Policy - Explicit Lifecycle Management * v0.18.0 Enhancement: Clear deprecation timeline and warning system * Purpose: Predictable migration path, no zombie endpoints */ import { z } from 'zod'; // Deprecation status export const DeprecationStatus = z.enum(['active', 'deprecated', 'removed']); // Deprecation timeline export const DeprecationPolicy = z.object({ endpoint: z.string(), status: DeprecationStatus, deprecated_in: z.string().optional(), // Version when deprecated removed_in: z.string().optional(), // Version when removed replacement: z.string().optional(), // Canonical replacement endpoint reason: z.string().optional() // Why deprecated }).strict(); // Deprecation status values export const DeprecationStatusValueSchema = z.enum(['dual_support', 'deprecation_warnings', 'legacy_removed']); // Legacy route deprecation schedule with Zod schema validation export const LegacyDeprecationScheduleSchema = z.record( z.string(), // Version string z.object({ status: DeprecationStatusValueSchema, legacy_routes_active: z.boolean(), canonical_routes_active: z.boolean(), warnings_enabled: z.boolean(), warning_header: z.string().optional() }).strict() ).describe('Version-based deprecation schedule'); export const LEGACY_DEPRECATION_SCHEDULE = { // v0.18.4 → Dual support (no warnings) 'v0.18.4': { status: 'dual_support' as const, legacy_routes_active: true, canonical_routes_active: true, warnings_enabled: false }, // v0.19.0 → Warnings added 'v0.19.0': { status: 'deprecation_warnings' as const, legacy_routes_active: true, canonical_routes_active: true, warnings_enabled: true, warning_header: 'X-Deprecated-Endpoint' }, // v0.20.0 → Legacy removed 'v0.20.0': { status: 'legacy_removed' as const, legacy_routes_active: false, canonical_routes_active: true, warnings_enabled: false } } as const satisfies z.infer; // Deprecation warning response enhancement export const DeprecationWarning = z.object({ deprecated: z.literal(true), deprecated_since: z.string(), // Version removal_date: z.string(), // Version when removed replacement_endpoint: z.string(), // Canonical endpoint to use migration_guide: z.string().url().optional() // Link to migration docs }).strict(); // Enhanced response envelope with deprecation support export const EnhancedResponseEnvelope = z.object({ success: z.boolean(), data: z.any().optional(), error: z.object({ code: z.string(), message: z.string(), details: z.record(z.any()).optional(), timestamp: z.string().datetime() }).strict().optional(), // Standard metadata requestId: z.string(), timestamp: z.string().datetime(), // Enhanced metadata (Management improvement #5) meta: z.object({ contractsVersion: z.string(), traceId: z.string().optional(), // Distributed tracing latencyMs: z.number().int().nonnegative().optional(), source: z.string().optional(), // 'infra-api', 'cache', etc. // Deprecation warnings deprecation: DeprecationWarning.optional() }).strict().optional() }).strict(); // Legacy route mapping schema export const LegacyRouteMappingSchema = z.object({ canonical: z.string().min(1), deprecated_in: z.string().optional(), removed_in: z.string().optional() }).strict().describe('Legacy route to canonical mapping'); // Specific legacy route mappings with Zod schema validation export const LegacyRouteMappingsSchema = z.record( z.string(), // Route path LegacyRouteMappingSchema ).describe('Legacy route mappings to canonical endpoints'); export const LEGACY_ROUTE_MAPPINGS = { // Portfolio legacy → canonical '/api/portfolio/summary': { canonical: '/api/infra/portfolio/summary', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, '/api/portfolio/investments': { canonical: '/api/infra/portfolio/investments', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, // Market legacy → canonical '/api/marketdata/ohlcv': { canonical: '/api/infra/market/data/ohlcv', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, '/api/marketdata/indicators': { canonical: '/api/infra/market/data/indicators', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, // ML legacy → canonical '/api/signals/store': { canonical: '/api/infra/ml/signals/store', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, '/api/signals/latest': { canonical: '/api/infra/ml/signals/latest', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, '/api/models': { canonical: '/api/infra/ml/models', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, // Trading legacy → canonical '/api/trading/positions': { canonical: '/api/infra/trading/positions', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' }, '/api/trading/trades': { canonical: '/api/infra/trading/trades', deprecated_in: 'v0.19.0', removed_in: 'v0.20.0' } } as const satisfies z.infer; // Helper functions export function getCanonicalEndpoint(legacyPath: string): string | null { const mapping = LEGACY_ROUTE_MAPPINGS[legacyPath as keyof typeof LEGACY_ROUTE_MAPPINGS]; return mapping?.canonical || null; } export function createDeprecationWarning(legacyPath: string, currentVersion: string = '0.18.4'): z.infer | null { const mapping = LEGACY_ROUTE_MAPPINGS[legacyPath as keyof typeof LEGACY_ROUTE_MAPPINGS]; if (!mapping) return null; return { deprecated: true, deprecated_since: mapping.deprecated_in, removal_date: mapping.removed_in, replacement_endpoint: mapping.canonical, migration_guide: 'https://docs.neuronetiq.ai/contracts/migration-v0.18.4' }; } // Type exports export type DeprecationStatusType = z.infer; export type DeprecationStatusValueType = z.infer; export type LegacyDeprecationScheduleType = z.infer; export type LegacyRouteMappingType = z.infer; export type LegacyRouteMappingsType = z.infer; export type DeprecationPolicyType = z.infer; export type DeprecationWarningType = z.infer; export type EnhancedResponseEnvelopeType = z.infer;