@forklaunch/core 1.3.12 → 1.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/{apiDefinition.types-CPWnG8GH.d.mts → apiDefinition.types-CCeDOt57.d.mts} +1 -1
- package/lib/{apiDefinition.types-BNRPj2PT.d.ts → apiDefinition.types-CKd_mi4-.d.ts} +1 -1
- package/lib/http/index.d.mts +7 -22
- package/lib/http/index.d.ts +7 -22
- package/lib/http/index.js +38 -29
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +38 -29
- package/lib/http/index.mjs.map +1 -1
- package/lib/{openTelemetryCollector-DXGXRvQP.d.mts → openTelemetryCollector-BS-ej09T.d.mts} +22 -3
- package/lib/{openTelemetryCollector-DXGXRvQP.d.ts → openTelemetryCollector-BS-ej09T.d.ts} +22 -3
- package/lib/persistence/index.d.mts +2 -2
- package/lib/persistence/index.d.ts +2 -2
- package/lib/persistence/index.js +45 -1
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +46 -2
- package/lib/persistence/index.mjs.map +1 -1
- package/lib/services/index.d.mts +3 -2
- package/lib/services/index.d.ts +3 -2
- package/lib/services/index.js.map +1 -1
- package/lib/services/index.mjs.map +1 -1
- package/lib/ws/index.d.mts +3 -2
- package/lib/ws/index.d.ts +3 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/index.ts","../../src/environment/loadCascadingEnv.ts","../../src/services/configInjector.ts","../../src/services/guards/isConstructed.ts","../../src/services/types/configInjector.types.ts","../../src/services/guards/isConstructedSingleton.ts","../../src/services/guards/isConstructor.ts","../../src/persistence/complianceTypes.ts","../../src/services/retentionService.ts","../../src/services/complianceDataService.ts","../../src/services/runRetentionEnforcement.ts"],"sourcesContent":["export { getEnvVar } from '@forklaunch/common';\nexport * from '../environment';\nexport { createConfigInjector } from './configInjector';\nexport type { ConfigInjector, ValidConfigInjector } from './configInjector';\nexport * from './types/configInjector.types';\nexport * from './types/entityManager.types';\nexport * from './types/service.types';\nexport {\n RetentionService,\n type EnforcementOptions,\n type EnforcementResult\n} from './retentionService';\nexport {\n ComplianceDataService,\n type EraseResult,\n type ExportResult,\n type UserIdFieldOverrides\n} from './complianceDataService';\nexport { runRetentionEnforcement } from './runRetentionEnforcement';\n","import dotenv from 'dotenv';\nimport { existsSync } from 'fs';\nimport { dirname, resolve } from 'path';\n\n/**\n * Gets cascading environment file paths: collects all .env.local files from project directory up to root\n * Root detection uses: .forklaunch/manifest.toml\n */\nexport function getCascadingEnvPaths(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvExists: boolean;\n projectEnvExists: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n loadOrder: string[];\n} {\n const result = {\n rootEnvExists: false,\n projectEnvExists: false,\n rootEnvPath: undefined as string | undefined,\n projectEnvFilePath: undefined as string | undefined,\n loadOrder: [] as string[]\n };\n\n const applicationRoot = findApplicationRoot(projectRoot);\n\n const envLocalFiles = collectEnvLocalFiles(projectRoot, applicationRoot);\n result.loadOrder.push(...envLocalFiles);\n\n const rootEnvPath = resolve(applicationRoot, '.env.local');\n if (envLocalFiles.includes(rootEnvPath)) {\n result.rootEnvExists = true;\n result.rootEnvPath = rootEnvPath;\n }\n\n if (projectEnvPath) {\n const fullProjectEnvPath = resolve(projectRoot, projectEnvPath);\n if (existsSync(fullProjectEnvPath)) {\n result.projectEnvExists = true;\n result.projectEnvFilePath = fullProjectEnvPath;\n if (!result.loadOrder.includes(fullProjectEnvPath)) {\n result.loadOrder.push(fullProjectEnvPath);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Loads environment variables with cascading precedence: all .env.local files from root to project, then project env file\n */\nexport function loadCascadingEnv(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvLoaded: boolean;\n projectEnvLoaded: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n envFilesLoaded: string[];\n totalEnvFilesLoaded: number;\n} {\n const paths = getCascadingEnvPaths(projectEnvPath, projectRoot);\n const result = {\n rootEnvLoaded: false,\n projectEnvLoaded: false,\n rootEnvPath: paths.rootEnvPath,\n projectEnvFilePath: paths.projectEnvFilePath,\n envFilesLoaded: [] as string[],\n totalEnvFilesLoaded: 0\n };\n\n const seen = new Set<string>();\n for (const envPath of paths.loadOrder) {\n if (seen.has(envPath)) {\n continue;\n }\n seen.add(envPath);\n\n const envResult = dotenv.config({\n path: envPath,\n override: true\n });\n\n if (!envResult?.error) {\n result.envFilesLoaded.push(envPath);\n result.totalEnvFilesLoaded++;\n\n if (envPath === paths.rootEnvPath) {\n result.rootEnvLoaded = true;\n }\n if (envPath === paths.projectEnvFilePath) {\n result.projectEnvLoaded = true;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Collects all .env.local files from project directory up to application root\n * Returns paths in order from root to project (for proper precedence)\n */\nfunction collectEnvLocalFiles(\n projectRoot: string,\n applicationRoot: string\n): string[] {\n const envLocalPaths: string[] = [];\n\n let currentPath = resolve(projectRoot);\n const normalizedAppRoot = resolve(applicationRoot);\n\n while (currentPath.length >= normalizedAppRoot.length) {\n const envLocalPath = resolve(currentPath, '.env.local');\n if (existsSync(envLocalPath)) {\n envLocalPaths.push(envLocalPath);\n }\n\n if (currentPath === normalizedAppRoot) {\n break;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n }\n\n return envLocalPaths.reverse();\n}\n\n/**\n * Finds application root by looking for .forklaunch/manifest.toml\n */\nexport function findApplicationRoot(startPath: string): string {\n let currentPath = resolve(startPath);\n const originalStart = currentPath;\n const maxDepth = 10;\n let depth = 0;\n\n while (depth < maxDepth) {\n const forklaunchManifest = resolve(\n currentPath,\n '.forklaunch',\n 'manifest.toml'\n );\n if (existsSync(forklaunchManifest)) {\n return currentPath;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n depth++;\n }\n\n return originalStart;\n}\n","import { extractArgumentNames, isNever } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n IdiomaticSchema,\n ParseResult,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { isConstructed } from './guards/isConstructed';\nimport { isConstructedSingleton } from './guards/isConstructedSingleton';\nimport { isConstructor } from './guards/isConstructor';\nimport {\n ConfigValidator,\n Constructed,\n ConstructedSingleton,\n Lifetime,\n ResolvedConfigValidator,\n SchemaConstructor,\n SchemaFunction,\n Singleton\n} from './types/configInjector.types';\n\nexport function createConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n>(\n schemaValidator: SV,\n dependenciesDefinition: {\n [K in keyof CV]:\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >;\n }\n) {\n return new ConfigInjector<SV, CV>(\n schemaValidator,\n dependenciesDefinition\n ).load();\n}\n\nexport class ConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> {\n instances: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n } = {};\n\n readonly configShapes: CV;\n\n load(inheritedScopeInstances?: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n }): this {\n for (const token in inheritedScopeInstances) {\n this.instances[token] = inheritedScopeInstances[token];\n }\n\n for (const token in this.dependenciesDefinition) {\n const definition = this.dependenciesDefinition[token];\n if (\n definition.lifetime === Lifetime.Singleton &&\n !this.instances[token]\n ) {\n if (\n isConstructedSingleton<\n CV[typeof token],\n Omit<ResolvedConfigValidator<SV, CV>, typeof token>,\n ResolvedConfigValidator<SV, CV>[typeof token]\n >(definition)\n ) {\n this.instances[token] = this.resolveInstance<typeof token>(\n token,\n definition\n );\n } else {\n this.instances[token] = definition.value;\n }\n }\n }\n return this;\n }\n\n private resolveInstance<T extends keyof CV>(\n token: T,\n definition:\n | ConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >\n | Constructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n if (process.env.FORKLAUNCH_MODE === 'openapi') {\n const noopProxy: Record<string, unknown> = new Proxy(\n function () {} as unknown as Record<string, unknown>,\n {\n get(_target, prop) {\n if (prop === Symbol.toPrimitive) return () => '';\n if (prop === 'toString' || prop === 'valueOf') return () => '';\n if (prop === 'then') return undefined;\n if (prop === Symbol.iterator) return function* () {};\n if (prop === Symbol.asyncIterator) return async function* () {};\n return noopProxy;\n },\n set() {\n return true;\n },\n has() {\n return true;\n },\n deleteProperty() {\n return true;\n },\n ownKeys() {\n return ['prototype'];\n },\n getOwnPropertyDescriptor(_target, prop) {\n if (prop === 'prototype') {\n return { configurable: false, enumerable: false, writable: true };\n }\n return { configurable: true, enumerable: true };\n },\n apply() {\n return noopProxy;\n },\n construct() {\n return noopProxy as object;\n }\n }\n );\n return noopProxy as ResolvedConfigValidator<SV, CV>[T];\n }\n\n const rawInjectorArgument = extractArgumentNames(definition.factory)[0];\n // short circuit as no args\n if (!rawInjectorArgument || rawInjectorArgument === '_args') {\n return definition.factory(\n {} as Omit<ResolvedConfigValidator<SV, CV>, T>,\n context ?? {},\n this.resolve.bind(this)\n );\n }\n\n // Normalize whitespace to handle both single-line and multiline formatting\n const injectorArgument = rawInjectorArgument.replace(/\\s+/g, '');\n\n if (!injectorArgument.startsWith('{') || !injectorArgument.endsWith('}')) {\n throw new Error(\n `Invalid injector argument for ${String(\n token\n )}: ${injectorArgument}. Please use object destructuring syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment.`\n );\n }\n const resolvedArguments = Object.fromEntries(\n injectorArgument\n .slice(1, -1)\n .split(',')\n .filter((arg) => arg.length > 0)\n .map((arg) => arg.split(':')[0].trim())\n .map((arg) => {\n const newResolutionPath = [...resolutionPath, token];\n if (resolutionPath.includes(arg)) {\n throw new Error(\n `Circular dependency detected: ${newResolutionPath.join(\n ' -> '\n )} -> ${arg}`\n );\n }\n const resolvedArg = this.resolve(arg, context, newResolutionPath);\n return [arg, resolvedArg];\n })\n ) as unknown as Omit<ResolvedConfigValidator<SV, CV>, T>;\n return definition.factory(\n resolvedArguments,\n context ?? {},\n this.resolve.bind(this)\n );\n }\n\n constructor(\n private schemaValidator: SV,\n private dependenciesDefinition: {\n [K in keyof CV]: (\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n ) & {\n type: CV[K];\n };\n }\n ) {\n this.configShapes = Object.entries(this.dependenciesDefinition).reduce(\n (acc, [key, { type }]) => ({\n ...acc,\n [key]: type\n }),\n {} as Record<keyof CV, CV[keyof CV]>\n ) as CV;\n }\n\n safeValidateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>> {\n const validNonSchemaSingletons = Object.entries(this.configShapes).reduce<\n ParseResult<ResolvedConfigValidator<SV, CV>>\n >(\n (acc, [key, value]) => {\n if (\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n !(this.schemaValidator as SchemaValidator).isSchema<\n SchemaFunction<SV> | SchemaConstructor<SV> | IdiomaticSchema<SV>\n >(value) &&\n isConstructor(value)\n ) {\n if (!(this.instances[key] instanceof value)) {\n const expected = value.name;\n const receivedValue: unknown = this.instances[key];\n const received = isConstructed(receivedValue)\n ? receivedValue.constructor.name\n : typeof receivedValue;\n\n if (acc.ok) {\n acc = {\n ok: false,\n errors: []\n };\n }\n acc.errors?.push({\n message: `Expected ${expected}, received ${received}`,\n path: [key]\n });\n } else {\n if (acc.ok) {\n acc = {\n ok: true,\n value: {\n ...acc.value,\n [key]: this.instances[key]\n }\n };\n }\n }\n return acc;\n }\n return acc;\n },\n {\n ok: true,\n value: {} as ResolvedConfigValidator<SV, CV>\n }\n );\n\n const singletons = Object.fromEntries(\n Object.entries(this.configShapes).filter(\n ([key, value]) =>\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n (this.schemaValidator as SchemaValidator).isSchema(value)\n )\n );\n const schemaSingletonParseResult = (\n this.schemaValidator as SchemaValidator\n ).parse(\n (this.schemaValidator as SchemaValidator).schemify(singletons),\n Object.fromEntries(\n Object.keys(singletons).map((key) => {\n const dependency = this.dependenciesDefinition[key];\n return [\n key,\n dependency.lifetime === Lifetime.Singleton\n ? this.instances[key]\n : undefined\n ];\n })\n )\n );\n\n const configKeys = Object.keys(this.configShapes);\n\n return validNonSchemaSingletons.ok && schemaSingletonParseResult.ok\n ? {\n ok: true as const,\n value: new ValidConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).load({ ...this.instances })\n }\n : {\n ok: false as const,\n errors: [\n ...(!validNonSchemaSingletons.ok && validNonSchemaSingletons.errors\n ? validNonSchemaSingletons.errors\n : []),\n ...(!schemaSingletonParseResult.ok &&\n schemaSingletonParseResult.errors\n ? schemaSingletonParseResult.errors\n : [])\n ].sort(\n (a, b) =>\n configKeys.indexOf(a.path[0]) - configKeys.indexOf(b.path[0])\n )\n };\n }\n\n validateConfigSingletons(configName: string): ValidConfigInjector<SV, CV> {\n if (process.env.FORKLAUNCH_MODE === 'openapi') {\n return this.createScope() as ValidConfigInjector<SV, CV>;\n }\n\n const safeValidateResult = this.safeValidateConfigSingletons();\n\n if (safeValidateResult.ok) {\n return safeValidateResult.value;\n }\n\n throw new Error(\n prettyPrintParseErrors(safeValidateResult.errors, configName)\n );\n }\n\n resolve<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n const instance = this.instances[token];\n if (!instance) {\n const definition = this.dependenciesDefinition[token];\n\n if (!definition) {\n throw new Error(`Unable to resolve dependency ${String(token)}`);\n }\n\n switch (definition.lifetime) {\n case Lifetime.Singleton: {\n if (\n isConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition) &&\n !this.instances[token]\n ) {\n this.instances[token] = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n return this.instances[token] as ResolvedConfigValidator<SV, CV>[T];\n }\n case Lifetime.Scoped: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n const scopedInstance = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n this.instances[token] = scopedInstance;\n return scopedInstance;\n }\n case Lifetime.Transient: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n return this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n default: {\n isNever(definition);\n throw new Error(\n `Unable to resolve lifetime for dependency ${String(\n token\n )}, ${resolutionPath}`\n );\n }\n }\n } else {\n return instance;\n }\n }\n\n scopedResolver<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): (options?: {\n scope?: ConfigInjector<SV, CV>;\n context?: Record<string, unknown>;\n }) => ResolvedConfigValidator<SV, CV>[T] {\n return (options) =>\n (options?.scope ?? this.createScope()).resolve<T>(\n token,\n options?.context ? { ...context, ...options.context } : context,\n resolutionPath\n );\n }\n\n createScope(): ConfigInjector<SV, CV> {\n const singletons: Record<string, unknown> = {};\n for (const dependency in this.dependenciesDefinition) {\n if (\n this.dependenciesDefinition[dependency].lifetime === Lifetime.Singleton\n ) {\n singletons[dependency] = this.instances[dependency];\n }\n }\n return new ConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).load(singletons as ResolvedConfigValidator<SV, CV>);\n }\n\n dispose(): void {\n this.instances = {};\n this.load();\n }\n\n chain<ChainedCV extends ConfigValidator<SV>>(dependenciesDefinition: {\n [K in keyof ChainedCV]: {\n type: ChainedCV[K];\n } & (\n | Singleton<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n | Constructed<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n );\n }): ConfigInjector<SV, CV & ChainedCV> {\n return new ConfigInjector<SV, CV>(this.schemaValidator, {\n ...this.dependenciesDefinition,\n ...dependenciesDefinition\n }).load({ ...this.instances }) as unknown as ConfigInjector<\n SV,\n CV & ChainedCV\n >;\n }\n\n tokens(): {\n [K in keyof CV]: K;\n } {\n return Object.fromEntries(\n Object.keys(this.dependenciesDefinition).map((key) => [key, key])\n ) as {\n [K in keyof CV]: K;\n };\n }\n}\n\nexport class ValidConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> extends ConfigInjector<SV, CV> {\n validConfigInjector!: void;\n}\n","import { Constructed } from '../types/configInjector.types';\n\nexport function isConstructed<Type, Args, Return>(\n value: unknown\n): value is Constructed<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'constructor' in value &&\n value.constructor != null\n );\n}\n","import {\n AnySchemaValidator,\n IdiomaticSchema,\n Schema\n} from '@forklaunch/validator';\nimport { ConfigInjector } from '../configInjector';\n\nexport const Lifetime = {\n Singleton: 0,\n Transient: 1,\n Scoped: 2\n} as const;\nexport type Lifetime = (typeof Lifetime)[keyof typeof Lifetime];\n\nexport type Singleton<Type, Args, Value> =\n | {\n lifetime: typeof Lifetime.Singleton;\n type: Type;\n value: Value;\n }\n | ConstructedSingleton<Type, Args, Value>;\n\nexport type ConstructedSingleton<Type, Args, Return> = {\n lifetime: typeof Lifetime.Singleton;\n type: Type;\n factory: (\n args: Args,\n context: Record<string, unknown>,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T]\n ) => Return;\n};\n\nexport type Constructed<Type, Args, Return> = {\n lifetime: typeof Lifetime.Transient | typeof Lifetime.Scoped;\n type: Type;\n factory: (\n args: Args,\n context: Record<string, unknown>,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T]\n ) => Return;\n};\n\nexport type Constructor = new (...args: never[]) => unknown;\nexport type SchemaConstructor<SV extends AnySchemaValidator> = new (\n ...args: unknown[]\n) => IdiomaticSchema<SV>;\nexport type Function = (...args: never[]) => unknown;\nexport type FunctionToConstructor = (\n ...args: never[]\n) => new (...args: never[]) => unknown;\nexport type SchemaFunction<SV extends AnySchemaValidator> = (\n args: unknown\n) => IdiomaticSchema<SV>;\n\nexport type ConfigTypes<SV extends AnySchemaValidator> =\n | Function\n | SchemaFunction<SV>\n | Constructor\n | SchemaConstructor<SV>\n | IdiomaticSchema<SV>;\n\nexport type ConfigValidator<SV extends AnySchemaValidator> = Record<\n string,\n ConfigTypes<SV> | Record<string, ConfigTypes<SV>>\n>;\n\ntype ResolveConfigValue<SV extends AnySchemaValidator, T> =\n T extends SchemaConstructor<SV>\n ? Schema<InstanceType<T>, SV>\n : T extends SchemaFunction<SV>\n ? (...args: Parameters<T>) => Schema<ReturnType<T>, SV>\n : T extends FunctionToConstructor\n ? (...args: Parameters<T>) => InstanceType<ReturnType<T>>\n : T extends Function\n ? (...args: Parameters<T>) => ReturnType<T>\n : T extends Constructor\n ? InstanceType<T>\n : T extends IdiomaticSchema<SV>\n ? Schema<T, SV>\n : T extends Record<string, ConfigTypes<SV>>\n ? {\n [K in keyof T]: ResolveConfigValue<SV, T[K]>;\n }\n : Schema<T, SV>;\n\nexport type ResolvedConfigValidator<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> = {\n [M in keyof CV]: ResolveConfigValue<SV, CV[M]>;\n};\n\nexport type ScopedDependencyFactory<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>,\n M extends keyof CV\n> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];\n","import { ConstructedSingleton, Lifetime } from '../types/configInjector.types';\n\nexport function isConstructedSingleton<Type, Args, Return>(\n value: unknown\n): value is ConstructedSingleton<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'lifetime' in value &&\n value.lifetime === Lifetime.Singleton &&\n 'factory' in value\n );\n}\n","import { Constructor } from '../types/configInjector.types';\n\nexport function isConstructor(value: unknown): value is Constructor {\n return (\n typeof value === 'function' &&\n value.constructor != null &&\n value.prototype != null\n );\n}\n","export const ComplianceLevel = {\n pii: 'pii',\n phi: 'phi',\n pci: 'pci',\n none: 'none'\n} as const;\nexport type ComplianceLevel =\n (typeof ComplianceLevel)[keyof typeof ComplianceLevel];\n\nexport const COMPLIANCE_KEY = '~compliance' as const;\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\nconst complianceRegistry = new Map<string, Map<string, ComplianceLevel>>();\n\nexport function registerEntityCompliance(\n entityName: string,\n fields: Map<string, ComplianceLevel>\n): void {\n complianceRegistry.set(entityName, fields);\n}\n\nexport function getComplianceMetadata(\n entityName: string,\n fieldName: string\n): ComplianceLevel {\n return complianceRegistry.get(entityName)?.get(fieldName) ?? 'none';\n}\n\nexport function getEntityComplianceFields(\n entityName: string\n): Map<string, ComplianceLevel> | undefined {\n return complianceRegistry.get(entityName);\n}\n\nexport function entityHasEncryptedFields(entityName: string): boolean {\n const fields = complianceRegistry.get(entityName);\n if (!fields) return false;\n for (const level of fields.values()) {\n if (level === 'phi' || level === 'pci') return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Retention types and registry\n// ---------------------------------------------------------------------------\n\nexport const RetentionAction = {\n delete: 'delete',\n anonymize: 'anonymize'\n} as const;\nexport type RetentionAction =\n (typeof RetentionAction)[keyof typeof RetentionAction];\n\nexport interface RetentionPolicy {\n duration: string;\n action: RetentionAction;\n}\n\nexport const RetentionDuration = {\n days: (n: number): string => `P${n}D`,\n months: (n: number): string => `P${n}M`,\n years: (n: number): string => `P${n}Y`\n} as const;\n\nexport interface ParsedDuration {\n years: number;\n months: number;\n days: number;\n}\n\nconst DURATION_REGEX = /^P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)D)?$/;\n\n/**\n * Parse an ISO 8601 duration string into calendar units.\n * Returns structured units to enable calendar-aware date arithmetic.\n */\nexport function parseDuration(iso: string): ParsedDuration {\n const match = DURATION_REGEX.exec(iso);\n if (!match) {\n throw new Error(\n `Invalid ISO 8601 duration: '${iso}'. Expected format: P[n]Y[n]M[n]D`\n );\n }\n const years = parseInt(match[1] || '0', 10);\n const months = parseInt(match[2] || '0', 10);\n const days = parseInt(match[3] || '0', 10);\n\n // Approximate total days for minimum validation only\n const approxDays = years * 365 + months * 30 + days;\n if (approxDays < 1) {\n throw new Error(\n `Retention duration must be >= 1 day (P1D). Got: '${iso}' (${approxDays} approx days)`\n );\n }\n\n return { years, months, days };\n}\n\n/**\n * Subtract a parsed duration from a date using calendar-aware arithmetic.\n * Handles month-end clamping and leap years correctly.\n */\nexport function subtractDuration(from: Date, duration: ParsedDuration): Date {\n const result = new Date(from);\n result.setFullYear(result.getFullYear() - duration.years);\n result.setMonth(result.getMonth() - duration.months);\n result.setDate(result.getDate() - duration.days);\n return result;\n}\n\nconst retentionRegistry = new Map<string, RetentionPolicy>();\n\n// ---------------------------------------------------------------------------\n// User ID field registry — maps entity name to the field linking records to a user\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_USER_ID_FIELD = 'userId';\nconst userIdFieldRegistry = new Map<string, string>();\n\nexport function registerEntityUserIdField(\n entityName: string,\n field: string\n): void {\n userIdFieldRegistry.set(entityName, field);\n}\n\nexport function getEntityUserIdField(entityName: string): string {\n return userIdFieldRegistry.get(entityName) ?? DEFAULT_USER_ID_FIELD;\n}\n\nexport function getAllUserIdFields(): ReadonlyMap<string, string> {\n return userIdFieldRegistry;\n}\n\nexport function registerEntityRetention(\n entityName: string,\n policy: RetentionPolicy\n): void {\n retentionRegistry.set(entityName, policy);\n}\n\nexport function getEntityRetention(\n entityName: string\n): RetentionPolicy | undefined {\n return retentionRegistry.get(entityName);\n}\n\nexport function getAllRetentionPolicies(): ReadonlyMap<\n string,\n RetentionPolicy\n> {\n return retentionRegistry;\n}\n\n// ---------------------------------------------------------------------------\n// Module augmentation — adds .compliance() via PropertyOptions\n// ---------------------------------------------------------------------------\n\n/**\n * Adds `compliance` to PropertyOptions, which flows into IncludeKeys\n * for all scalar/enum/embedded builders (PropertyOptions is extended by\n * EnumOptions and EmbeddedOptions). Relation builders use ReferenceOptions\n * instead, so they don't get .compliance() — which is what we want.\n */\ndeclare module '@mikro-orm/core' {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n interface PropertyOptions<Owner> {\n compliance?: ComplianceLevel;\n }\n\n interface UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys> {\n compliance(\n level: ComplianceLevel\n ): Pick<\n UniversalPropertyOptionsBuilder<\n Value,\n Options & { readonly '~c': true },\n IncludeKeys\n >,\n IncludeKeys & keyof UniversalPropertyOptionsBuilder<never, never, never>\n >;\n }\n}\n","import type { MikroORM } from '@mikro-orm/core';\nimport type { OpenTelemetryCollector } from '../http/telemetry/openTelemetryCollector';\nimport {\n getAllRetentionPolicies,\n getEntityComplianceFields,\n parseDuration,\n subtractDuration,\n type RetentionPolicy\n} from '../persistence/complianceTypes';\n\nexport interface EnforcementOptions {\n /** Filter to specific entity names (default: all with retention policies) */\n entities?: string[];\n /** Records per batch (default: 1000) */\n batchSize?: number;\n /** Log what would happen without mutating */\n dryRun?: boolean;\n}\n\nexport interface EnforcementResult {\n processed: number;\n deleted: number;\n anonymized: number;\n errors: number;\n byEntity: Record<\n string,\n { deleted: number; anonymized: number; errors: number }\n >;\n durationMs: number;\n}\n\nexport class RetentionService {\n private readonly DEFAULT_BATCH_SIZE = 1000;\n\n constructor(\n private readonly orm: MikroORM,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly otel: OpenTelemetryCollector<any>\n ) {}\n\n async enforce(options?: EnforcementOptions): Promise<EnforcementResult> {\n const start = Date.now();\n const batchSize = options?.batchSize ?? this.DEFAULT_BATCH_SIZE;\n const dryRun = options?.dryRun ?? false;\n const policies = getAllRetentionPolicies();\n const result: EnforcementResult = {\n processed: 0,\n deleted: 0,\n anonymized: 0,\n errors: 0,\n byEntity: {},\n durationMs: 0\n };\n\n if (policies.size === 0) {\n this.otel.info('[RetentionService] No retention policies registered');\n result.durationMs = Date.now() - start;\n return result;\n }\n\n this.otel.info('[RetentionService] Starting enforcement', {\n entityCount: policies.size,\n batchSize,\n dryRun\n });\n\n for (const [entityName, policy] of policies) {\n if (options?.entities && !options.entities.includes(entityName)) continue;\n\n const entityResult = { deleted: 0, anonymized: 0, errors: 0 };\n\n try {\n await this.enforceEntity(\n entityName,\n policy,\n batchSize,\n entityResult,\n dryRun\n );\n } catch (err) {\n entityResult.errors++;\n this.otel.error('[RetentionService] Entity-level failure', {\n entityName,\n error: String(err)\n });\n }\n\n result.byEntity[entityName] = entityResult;\n result.deleted += entityResult.deleted;\n result.anonymized += entityResult.anonymized;\n result.errors += entityResult.errors;\n result.processed += entityResult.deleted + entityResult.anonymized;\n }\n\n result.durationMs = Date.now() - start;\n this.otel.info('[RetentionService] Enforcement complete', {\n processed: result.processed,\n deleted: result.deleted,\n anonymized: result.anonymized,\n errors: result.errors,\n durationMs: result.durationMs\n });\n\n return result;\n }\n\n private async enforceEntity(\n entityName: string,\n policy: RetentionPolicy,\n batchSize: number,\n stats: { deleted: number; anonymized: number; errors: number },\n dryRun: boolean\n ): Promise<void> {\n const metadata = [...this.orm.getMetadata().getAll().values()].find(\n (m) => m.className === entityName\n );\n\n if (!metadata) {\n this.otel.warn(\n '[RetentionService] Entity not in MikroORM metadata — skipping',\n { entityName }\n );\n return;\n }\n\n const duration = parseDuration(policy.duration);\n const cutoff = subtractDuration(new Date(), duration);\n const entityClass = metadata.class ?? metadata.className;\n\n // For anonymize: only null out PII/PHI/PCI fields that are nullable.\n // Non-nullable fields are skipped to avoid flush errors.\n const piiFieldNames: string[] = [];\n if (policy.action === 'anonymize') {\n const complianceFields = getEntityComplianceFields(entityName);\n if (complianceFields) {\n for (const [fieldName, level] of complianceFields) {\n if (level === 'none') continue;\n const prop = metadata.properties[fieldName];\n if (prop && prop.nullable) {\n piiFieldNames.push(fieldName);\n } else {\n this.otel.warn(\n '[RetentionService] Skipping non-nullable PII field for anonymize',\n { entityName, fieldName, level }\n );\n }\n }\n }\n }\n\n const filter: Record<string, unknown> = {\n createdAt: { $lt: cutoff }\n };\n if (policy.action === 'anonymize') {\n filter['retentionAnonymizedAt'] = null;\n }\n\n // Dry run: use count instead of fetching records\n if (dryRun) {\n const em = this.orm.em.fork();\n try {\n const count = await em.count(entityClass, filter);\n this.otel.info('[RetentionService] Dry run — would process', {\n entityName,\n action: policy.action,\n count\n });\n if (policy.action === 'delete') stats.deleted += count;\n else stats.anonymized += count;\n } catch (err) {\n stats.errors++;\n this.otel.error('[RetentionService] Dry run count failed', {\n entityName,\n error: String(err)\n });\n }\n return;\n }\n\n let batchNum = 0;\n\n while (true) {\n batchNum++;\n const em = this.orm.em.fork();\n\n try {\n const records = await em.find(entityClass, filter, {\n limit: batchSize,\n orderBy: { createdAt: 'ASC' }\n });\n\n if (records.length === 0) break;\n\n if (policy.action === 'delete') {\n records.forEach((r) => em.remove(r));\n await em.flush();\n stats.deleted += records.length;\n } else {\n for (const record of records) {\n const rec = record as Record<string, unknown>;\n for (const field of piiFieldNames) {\n rec[field] = null;\n }\n rec['retentionAnonymizedAt'] = new Date();\n }\n await em.flush();\n stats.anonymized += records.length;\n }\n\n this.otel.info('[RetentionService] Batch processed', {\n entityName,\n action: policy.action,\n batch: batchNum,\n count: records.length\n });\n } catch (err) {\n stats.errors++;\n this.otel.error('[RetentionService] Batch failed', {\n entityName,\n batch: batchNum,\n error: String(err)\n });\n break; // stop batching this entity, continue to next\n }\n }\n }\n}\n","import type { MikroORM } from '@mikro-orm/core';\nimport type { OpenTelemetryCollector } from '../http/telemetry/openTelemetryCollector';\nimport { MetricsDefinition } from '../http/types/openTelemetryCollector.types';\nimport {\n getEntityComplianceFields,\n getEntityUserIdField\n} from '../persistence/complianceTypes';\n\nexport interface EraseResult {\n entitiesAffected: string[];\n recordsDeleted: number;\n}\n\nexport interface ExportResult {\n userId: string;\n entities: Record<string, unknown[]>;\n}\n\n/**\n * Per-entity userIdField overrides.\n * Keys are entity names, values are the field name linking records to a user.\n *\n * @example\n * {\n * User: 'id', // the User entity IS the user record\n * Subscription: 'partyId', // billing links via partyId\n * Account: 'userId', // default, can be omitted\n * }\n */\nexport type UserIdFieldOverrides = Record<string, string>;\n\n/**\n * Common field names that link an entity to a user, tried in order.\n * Used for optimistic search when no explicit userIdField is configured.\n */\nconst CANDIDATE_USER_FIELDS = [\n 'userId',\n 'user',\n 'id',\n 'partyId',\n 'customerId',\n 'ownerId',\n 'createdBy',\n 'email'\n];\n\n/**\n * Generic compliance data service that walks all compliance-registered entities\n * and erases or exports PII/PHI/PCI data for a given user.\n *\n * Resolution order for userIdField per entity:\n * 1. Constructor overrides (highest priority)\n * 2. defineComplianceEntity({ userIdField }) registry\n * 3. Optimistic search: first CANDIDATE_USER_FIELDS match in entity metadata\n * 4. Skip entity (no user link found)\n */\nexport class ComplianceDataService {\n private readonly userIdFieldOverrides: UserIdFieldOverrides;\n\n constructor(\n private readonly orm: MikroORM,\n private readonly otel: OpenTelemetryCollector<MetricsDefinition>,\n userIdFieldOverrides?: UserIdFieldOverrides\n ) {\n this.userIdFieldOverrides = userIdFieldOverrides ?? {};\n }\n\n /**\n * Resolve the field linking an entity to a user.\n * Returns undefined if no link can be determined.\n */\n private resolveUserIdField(\n entityName: string,\n entityProperties: Record<string, unknown>\n ): string | undefined {\n // 1. Constructor override\n const override = this.userIdFieldOverrides[entityName];\n if (override) return override;\n\n // 2. Registry (from defineComplianceEntity({ userIdField }))\n const registered = getEntityUserIdField(entityName);\n if (registered !== 'userId' || entityProperties['userId']) {\n // Registry returned a non-default value, or the default 'userId' exists\n if (entityProperties[registered]) return registered;\n }\n\n // 3. Optimistic search\n for (const candidate of CANDIDATE_USER_FIELDS) {\n if (entityProperties[candidate]) return candidate;\n }\n\n // 4. No link found\n return undefined;\n }\n\n async erase(userId: string): Promise<EraseResult> {\n const em = this.orm.em.fork();\n const entitiesAffected: string[] = [];\n let recordsDeleted = 0;\n\n const allMetadata = [...this.orm.getMetadata().getAll().values()];\n\n for (const metadata of allMetadata) {\n const entityName = metadata.className;\n const fields = getEntityComplianceFields(entityName);\n if (!fields) continue;\n\n const hasPii = [...fields.values()].some(\n (level) => level === 'pii' || level === 'phi' || level === 'pci'\n );\n if (!hasPii) continue;\n\n const userIdField = this.resolveUserIdField(\n entityName,\n metadata.properties\n );\n\n if (!userIdField) {\n this.otel.warn(\n '[ComplianceDataService] No user-linking field found — skipping',\n { entityName, candidates: CANDIDATE_USER_FIELDS }\n );\n continue;\n }\n\n try {\n const entityClass = metadata.class ?? metadata.className;\n const records = await em.find(entityClass, {\n [userIdField]: userId\n });\n\n if (records.length > 0) {\n entitiesAffected.push(entityName);\n recordsDeleted += records.length;\n records.forEach((r) => em.remove(r));\n }\n } catch (err) {\n this.otel.error('[ComplianceDataService] Failed to erase entity', {\n entityName,\n userIdField,\n error: String(err)\n });\n }\n }\n\n if (recordsDeleted > 0) {\n await em.flush();\n }\n\n this.otel.info('[ComplianceDataService] Erase complete', {\n userId,\n entitiesAffected: entitiesAffected.join(','),\n recordsDeleted\n });\n\n return { entitiesAffected, recordsDeleted };\n }\n\n async export(userId: string): Promise<ExportResult> {\n const em = this.orm.em.fork();\n const entities: Record<string, unknown[]> = {};\n\n const allMetadata = [...this.orm.getMetadata().getAll().values()];\n\n for (const metadata of allMetadata) {\n const entityName = metadata.className;\n const fields = getEntityComplianceFields(entityName);\n if (!fields) continue;\n\n const hasPii = [...fields.values()].some(\n (level) => level === 'pii' || level === 'phi' || level === 'pci'\n );\n if (!hasPii) continue;\n\n const userIdField = this.resolveUserIdField(\n entityName,\n metadata.properties\n );\n\n if (!userIdField) {\n continue;\n }\n\n try {\n const entityClass = metadata.class ?? metadata.className;\n const records = await em.find(entityClass, {\n [userIdField]: userId\n });\n\n if (records.length > 0) {\n const piiFieldNames = [...fields.entries()]\n .filter(([, level]) => level !== 'none')\n .map(([name]) => name);\n\n entities[entityName] = records.map((record) => {\n const filtered: Record<string, unknown> = {};\n filtered['id'] = (record as Record<string, unknown>)['id'];\n for (const fieldName of piiFieldNames) {\n filtered[fieldName] = (record as Record<string, unknown>)[\n fieldName\n ];\n }\n return filtered;\n });\n }\n } catch (err) {\n this.otel.error('[ComplianceDataService] Failed to export entity', {\n entityName,\n userIdField,\n error: String(err)\n });\n }\n }\n\n this.otel.info('[ComplianceDataService] Export complete', {\n userId,\n entityCount: Object.keys(entities).length\n });\n\n return { userId, entities };\n }\n}\n","import type { OpenTelemetryCollector } from '../http/telemetry/openTelemetryCollector';\nimport type { RetentionService } from './retentionService';\n\n/**\n * Shared retention enforcement runner.\n * Designed to be called from a one-shot script (ECS RunTask / cron).\n *\n * @example\n * ```ts\n * import { ci, tokens } from '../bootstrapper';\n * import { runRetentionEnforcement } from '@myapp/core';\n *\n * runRetentionEnforcement(\n * ci.resolve(tokens.RetentionService),\n * ci.resolve(tokens.OpenTelemetryCollector)\n * );\n * ```\n */\nexport async function runRetentionEnforcement(\n retentionService: RetentionService,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n otel: OpenTelemetryCollector<any>\n): Promise<void> {\n const dryRun = process.argv.includes('--dry-run');\n\n otel.info('[RetentionEnforcement] Starting', { dryRun });\n\n const result = await retentionService.enforce({ dryRun });\n\n otel.info('[RetentionEnforcement] Complete', {\n processed: result.processed,\n deleted: result.deleted,\n anonymized: result.anonymized,\n errors: result.errors,\n durationMs: result.durationMs\n });\n\n if (result.errors > 0) {\n otel.warn('[RetentionEnforcement] Completed with errors', {\n errors: result.errors,\n byEntity: result.byEntity\n });\n process.exit(1);\n }\n\n process.exit(0);\n}\n"],"mappings":"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","names":["import_common","dotenv"]}
|
|
1
|
+
{"version":3,"sources":["../../src/services/index.ts","../../src/environment/loadCascadingEnv.ts","../../src/services/configInjector.ts","../../src/services/guards/isConstructed.ts","../../src/services/types/configInjector.types.ts","../../src/services/guards/isConstructedSingleton.ts","../../src/services/guards/isConstructor.ts","../../src/persistence/complianceTypes.ts","../../src/services/retentionService.ts","../../src/services/complianceDataService.ts","../../src/services/runRetentionEnforcement.ts"],"sourcesContent":["export { getEnvVar } from '@forklaunch/common';\nexport * from '../environment';\nexport { createConfigInjector } from './configInjector';\nexport type { ConfigInjector, ValidConfigInjector } from './configInjector';\nexport * from './types/configInjector.types';\nexport * from './types/entityManager.types';\nexport * from './types/service.types';\nexport {\n RetentionService,\n type EnforcementOptions,\n type EnforcementResult\n} from './retentionService';\nexport {\n ComplianceDataService,\n type EraseResult,\n type ExportResult,\n type UserIdFieldOverrides\n} from './complianceDataService';\nexport { runRetentionEnforcement } from './runRetentionEnforcement';\n","import dotenv from 'dotenv';\nimport { existsSync } from 'fs';\nimport { dirname, resolve } from 'path';\n\n/**\n * Gets cascading environment file paths: collects all .env.local files from project directory up to root\n * Root detection uses: .forklaunch/manifest.toml\n */\nexport function getCascadingEnvPaths(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvExists: boolean;\n projectEnvExists: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n loadOrder: string[];\n} {\n const result = {\n rootEnvExists: false,\n projectEnvExists: false,\n rootEnvPath: undefined as string | undefined,\n projectEnvFilePath: undefined as string | undefined,\n loadOrder: [] as string[]\n };\n\n const applicationRoot = findApplicationRoot(projectRoot);\n\n const envLocalFiles = collectEnvLocalFiles(projectRoot, applicationRoot);\n result.loadOrder.push(...envLocalFiles);\n\n const rootEnvPath = resolve(applicationRoot, '.env.local');\n if (envLocalFiles.includes(rootEnvPath)) {\n result.rootEnvExists = true;\n result.rootEnvPath = rootEnvPath;\n }\n\n if (projectEnvPath) {\n const fullProjectEnvPath = resolve(projectRoot, projectEnvPath);\n if (existsSync(fullProjectEnvPath)) {\n result.projectEnvExists = true;\n result.projectEnvFilePath = fullProjectEnvPath;\n if (!result.loadOrder.includes(fullProjectEnvPath)) {\n result.loadOrder.push(fullProjectEnvPath);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Loads environment variables with cascading precedence: all .env.local files from root to project, then project env file\n */\nexport function loadCascadingEnv(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvLoaded: boolean;\n projectEnvLoaded: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n envFilesLoaded: string[];\n totalEnvFilesLoaded: number;\n} {\n const paths = getCascadingEnvPaths(projectEnvPath, projectRoot);\n const result = {\n rootEnvLoaded: false,\n projectEnvLoaded: false,\n rootEnvPath: paths.rootEnvPath,\n projectEnvFilePath: paths.projectEnvFilePath,\n envFilesLoaded: [] as string[],\n totalEnvFilesLoaded: 0\n };\n\n const seen = new Set<string>();\n for (const envPath of paths.loadOrder) {\n if (seen.has(envPath)) {\n continue;\n }\n seen.add(envPath);\n\n const envResult = dotenv.config({\n path: envPath,\n override: true\n });\n\n if (!envResult?.error) {\n result.envFilesLoaded.push(envPath);\n result.totalEnvFilesLoaded++;\n\n if (envPath === paths.rootEnvPath) {\n result.rootEnvLoaded = true;\n }\n if (envPath === paths.projectEnvFilePath) {\n result.projectEnvLoaded = true;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Collects all .env.local files from project directory up to application root\n * Returns paths in order from root to project (for proper precedence)\n */\nfunction collectEnvLocalFiles(\n projectRoot: string,\n applicationRoot: string\n): string[] {\n const envLocalPaths: string[] = [];\n\n let currentPath = resolve(projectRoot);\n const normalizedAppRoot = resolve(applicationRoot);\n\n while (currentPath.length >= normalizedAppRoot.length) {\n const envLocalPath = resolve(currentPath, '.env.local');\n if (existsSync(envLocalPath)) {\n envLocalPaths.push(envLocalPath);\n }\n\n if (currentPath === normalizedAppRoot) {\n break;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n }\n\n return envLocalPaths.reverse();\n}\n\n/**\n * Finds application root by looking for .forklaunch/manifest.toml\n */\nexport function findApplicationRoot(startPath: string): string {\n let currentPath = resolve(startPath);\n const originalStart = currentPath;\n const maxDepth = 10;\n let depth = 0;\n\n while (depth < maxDepth) {\n const forklaunchManifest = resolve(\n currentPath,\n '.forklaunch',\n 'manifest.toml'\n );\n if (existsSync(forklaunchManifest)) {\n return currentPath;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n depth++;\n }\n\n return originalStart;\n}\n","import { extractArgumentNames, isNever } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n IdiomaticSchema,\n ParseResult,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { isConstructed } from './guards/isConstructed';\nimport { isConstructedSingleton } from './guards/isConstructedSingleton';\nimport { isConstructor } from './guards/isConstructor';\nimport {\n ConfigValidator,\n Constructed,\n ConstructedSingleton,\n Lifetime,\n ResolvedConfigValidator,\n SchemaConstructor,\n SchemaFunction,\n Singleton\n} from './types/configInjector.types';\n\nexport function createConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n>(\n schemaValidator: SV,\n dependenciesDefinition: {\n [K in keyof CV]:\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >;\n }\n) {\n return new ConfigInjector<SV, CV>(\n schemaValidator,\n dependenciesDefinition\n ).load();\n}\n\nexport class ConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> {\n instances: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n } = {};\n\n readonly configShapes: CV;\n\n load(inheritedScopeInstances?: {\n [K in keyof CV]?: ResolvedConfigValidator<SV, CV>[K];\n }): this {\n for (const token in inheritedScopeInstances) {\n this.instances[token] = inheritedScopeInstances[token];\n }\n\n for (const token in this.dependenciesDefinition) {\n const definition = this.dependenciesDefinition[token];\n if (\n definition.lifetime === Lifetime.Singleton &&\n !this.instances[token]\n ) {\n if (\n isConstructedSingleton<\n CV[typeof token],\n Omit<ResolvedConfigValidator<SV, CV>, typeof token>,\n ResolvedConfigValidator<SV, CV>[typeof token]\n >(definition)\n ) {\n this.instances[token] = this.resolveInstance<typeof token>(\n token,\n definition\n );\n } else {\n this.instances[token] = definition.value;\n }\n }\n }\n return this;\n }\n\n private resolveInstance<T extends keyof CV>(\n token: T,\n definition:\n | ConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >\n | Constructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n if (process.env.FORKLAUNCH_MODE === 'openapi') {\n const noopProxy: Record<string, unknown> = new Proxy(\n function () {} as unknown as Record<string, unknown>,\n {\n get(_target, prop) {\n if (prop === Symbol.toPrimitive) return () => '';\n if (prop === 'toString' || prop === 'valueOf') return () => '';\n if (prop === 'then') return undefined;\n if (prop === Symbol.iterator) return function* () {};\n if (prop === Symbol.asyncIterator) return async function* () {};\n return noopProxy;\n },\n set() {\n return true;\n },\n has() {\n return true;\n },\n deleteProperty() {\n return true;\n },\n ownKeys() {\n return ['prototype'];\n },\n getOwnPropertyDescriptor(_target, prop) {\n if (prop === 'prototype') {\n return { configurable: false, enumerable: false, writable: true };\n }\n return { configurable: true, enumerable: true };\n },\n apply() {\n return noopProxy;\n },\n construct() {\n return noopProxy as object;\n }\n }\n );\n return noopProxy as ResolvedConfigValidator<SV, CV>[T];\n }\n\n const rawInjectorArgument = extractArgumentNames(definition.factory)[0];\n // short circuit as no args\n if (!rawInjectorArgument || rawInjectorArgument === '_args') {\n return definition.factory(\n {} as Omit<ResolvedConfigValidator<SV, CV>, T>,\n context ?? {},\n this.resolve.bind(this)\n );\n }\n\n // Normalize whitespace to handle both single-line and multiline formatting\n const injectorArgument = rawInjectorArgument.replace(/\\s+/g, '');\n\n if (!injectorArgument.startsWith('{') || !injectorArgument.endsWith('}')) {\n throw new Error(\n `Invalid injector argument for ${String(\n token\n )}: ${injectorArgument}. Please use object destructuring syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment.`\n );\n }\n const resolvedArguments = Object.fromEntries(\n injectorArgument\n .slice(1, -1)\n .split(',')\n .filter((arg) => arg.length > 0)\n .map((arg) => arg.split(':')[0].trim())\n .map((arg) => {\n const newResolutionPath = [...resolutionPath, token];\n if (resolutionPath.includes(arg)) {\n throw new Error(\n `Circular dependency detected: ${newResolutionPath.join(\n ' -> '\n )} -> ${arg}`\n );\n }\n const resolvedArg = this.resolve(arg, context, newResolutionPath);\n return [arg, resolvedArg];\n })\n ) as unknown as Omit<ResolvedConfigValidator<SV, CV>, T>;\n return definition.factory(\n resolvedArguments,\n context ?? {},\n this.resolve.bind(this)\n );\n }\n\n constructor(\n private schemaValidator: SV,\n private dependenciesDefinition: {\n [K in keyof CV]: (\n | Singleton<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n | Constructed<\n CV[K],\n Omit<ResolvedConfigValidator<SV, CV>, K>,\n ResolvedConfigValidator<SV, CV>[K]\n >\n ) & {\n type: CV[K];\n };\n }\n ) {\n this.configShapes = Object.entries(this.dependenciesDefinition).reduce(\n (acc, [key, { type }]) => ({\n ...acc,\n [key]: type\n }),\n {} as Record<keyof CV, CV[keyof CV]>\n ) as CV;\n }\n\n safeValidateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>> {\n const validNonSchemaSingletons = Object.entries(this.configShapes).reduce<\n ParseResult<ResolvedConfigValidator<SV, CV>>\n >(\n (acc, [key, value]) => {\n if (\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n !(this.schemaValidator as SchemaValidator).isSchema<\n SchemaFunction<SV> | SchemaConstructor<SV> | IdiomaticSchema<SV>\n >(value) &&\n isConstructor(value)\n ) {\n if (!(this.instances[key] instanceof value)) {\n const expected = value.name;\n const receivedValue: unknown = this.instances[key];\n const received = isConstructed(receivedValue)\n ? receivedValue.constructor.name\n : typeof receivedValue;\n\n if (acc.ok) {\n acc = {\n ok: false,\n errors: []\n };\n }\n acc.errors?.push({\n message: `Expected ${expected}, received ${received}`,\n path: [key]\n });\n } else {\n if (acc.ok) {\n acc = {\n ok: true,\n value: {\n ...acc.value,\n [key]: this.instances[key]\n }\n };\n }\n }\n return acc;\n }\n return acc;\n },\n {\n ok: true,\n value: {} as ResolvedConfigValidator<SV, CV>\n }\n );\n\n const singletons = Object.fromEntries(\n Object.entries(this.configShapes).filter(\n ([key, value]) =>\n this.dependenciesDefinition[key].lifetime === Lifetime.Singleton &&\n (this.schemaValidator as SchemaValidator).isSchema(value)\n )\n );\n const schemaSingletonParseResult = (\n this.schemaValidator as SchemaValidator\n ).parse(\n (this.schemaValidator as SchemaValidator).schemify(singletons),\n Object.fromEntries(\n Object.keys(singletons).map((key) => {\n const dependency = this.dependenciesDefinition[key];\n return [\n key,\n dependency.lifetime === Lifetime.Singleton\n ? this.instances[key]\n : undefined\n ];\n })\n )\n );\n\n const configKeys = Object.keys(this.configShapes);\n\n return validNonSchemaSingletons.ok && schemaSingletonParseResult.ok\n ? {\n ok: true as const,\n value: new ValidConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).load({ ...this.instances })\n }\n : {\n ok: false as const,\n errors: [\n ...(!validNonSchemaSingletons.ok && validNonSchemaSingletons.errors\n ? validNonSchemaSingletons.errors\n : []),\n ...(!schemaSingletonParseResult.ok &&\n schemaSingletonParseResult.errors\n ? schemaSingletonParseResult.errors\n : [])\n ].sort(\n (a, b) =>\n configKeys.indexOf(a.path[0]) - configKeys.indexOf(b.path[0])\n )\n };\n }\n\n validateConfigSingletons(configName: string): ValidConfigInjector<SV, CV> {\n if (process.env.FORKLAUNCH_MODE === 'openapi') {\n return this.createScope() as ValidConfigInjector<SV, CV>;\n }\n\n const safeValidateResult = this.safeValidateConfigSingletons();\n\n if (safeValidateResult.ok) {\n return safeValidateResult.value;\n }\n\n throw new Error(\n prettyPrintParseErrors(safeValidateResult.errors, configName)\n );\n }\n\n resolve<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): ResolvedConfigValidator<SV, CV>[T] {\n const instance = this.instances[token];\n if (!instance) {\n const definition = this.dependenciesDefinition[token];\n\n if (!definition) {\n throw new Error(`Unable to resolve dependency ${String(token)}`);\n }\n\n switch (definition.lifetime) {\n case Lifetime.Singleton: {\n if (\n isConstructedSingleton<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition) &&\n !this.instances[token]\n ) {\n this.instances[token] = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n return this.instances[token] as ResolvedConfigValidator<SV, CV>[T];\n }\n case Lifetime.Scoped: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n const scopedInstance = this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n this.instances[token] = scopedInstance;\n return scopedInstance;\n }\n case Lifetime.Transient: {\n if (\n !isConstructed<\n CV[T],\n Omit<ResolvedConfigValidator<SV, CV>, T>,\n ResolvedConfigValidator<SV, CV>[T]\n >(definition)\n ) {\n throw new Error(\n `Invalid dependency definition for ${String(token)}`\n );\n }\n\n return this.resolveInstance<T>(\n token,\n definition,\n context,\n resolutionPath\n );\n }\n default: {\n isNever(definition);\n throw new Error(\n `Unable to resolve lifetime for dependency ${String(\n token\n )}, ${resolutionPath}`\n );\n }\n }\n } else {\n return instance;\n }\n }\n\n scopedResolver<T extends keyof CV>(\n token: T,\n context?: Record<string, unknown>,\n resolutionPath: (keyof CV)[] = []\n ): (options?: {\n scope?: ConfigInjector<SV, CV>;\n context?: Record<string, unknown>;\n }) => ResolvedConfigValidator<SV, CV>[T] {\n return (options) =>\n (options?.scope ?? this.createScope()).resolve<T>(\n token,\n options?.context ? { ...context, ...options.context } : context,\n resolutionPath\n );\n }\n\n createScope(): ConfigInjector<SV, CV> {\n const singletons: Record<string, unknown> = {};\n for (const dependency in this.dependenciesDefinition) {\n if (\n this.dependenciesDefinition[dependency].lifetime === Lifetime.Singleton\n ) {\n singletons[dependency] = this.instances[dependency];\n }\n }\n return new ConfigInjector<SV, CV>(\n this.schemaValidator,\n this.dependenciesDefinition\n ).load(singletons as ResolvedConfigValidator<SV, CV>);\n }\n\n dispose(): void {\n this.instances = {};\n this.load();\n }\n\n chain<ChainedCV extends ConfigValidator<SV>>(dependenciesDefinition: {\n [K in keyof ChainedCV]: {\n type: ChainedCV[K];\n } & (\n | Singleton<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n | Constructed<\n ChainedCV[K],\n Omit<ResolvedConfigValidator<SV, CV & ChainedCV>, K>,\n ResolvedConfigValidator<SV, ChainedCV>[K]\n >\n );\n }): ConfigInjector<SV, CV & ChainedCV> {\n return new ConfigInjector<SV, CV>(this.schemaValidator, {\n ...this.dependenciesDefinition,\n ...dependenciesDefinition\n }).load({ ...this.instances }) as unknown as ConfigInjector<\n SV,\n CV & ChainedCV\n >;\n }\n\n tokens(): {\n [K in keyof CV]: K;\n } {\n return Object.fromEntries(\n Object.keys(this.dependenciesDefinition).map((key) => [key, key])\n ) as {\n [K in keyof CV]: K;\n };\n }\n}\n\nexport class ValidConfigInjector<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> extends ConfigInjector<SV, CV> {\n validConfigInjector!: void;\n}\n","import { Constructed } from '../types/configInjector.types';\n\nexport function isConstructed<Type, Args, Return>(\n value: unknown\n): value is Constructed<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'constructor' in value &&\n value.constructor != null\n );\n}\n","import {\n AnySchemaValidator,\n IdiomaticSchema,\n Schema\n} from '@forklaunch/validator';\nimport { ConfigInjector } from '../configInjector';\n\nexport const Lifetime = {\n Singleton: 0,\n Transient: 1,\n Scoped: 2\n} as const;\nexport type Lifetime = (typeof Lifetime)[keyof typeof Lifetime];\n\nexport type Singleton<Type, Args, Value> =\n | {\n lifetime: typeof Lifetime.Singleton;\n type: Type;\n value: Value;\n }\n | ConstructedSingleton<Type, Args, Value>;\n\nexport type ConstructedSingleton<Type, Args, Return> = {\n lifetime: typeof Lifetime.Singleton;\n type: Type;\n factory: (\n args: Args,\n context: Record<string, unknown>,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T]\n ) => Return;\n};\n\nexport type Constructed<Type, Args, Return> = {\n lifetime: typeof Lifetime.Transient | typeof Lifetime.Scoped;\n type: Type;\n factory: (\n args: Args,\n context: Record<string, unknown>,\n resolve: <T extends keyof Args>(\n token: T,\n context?: Record<string, unknown>\n ) => Args[T]\n ) => Return;\n};\n\nexport type Constructor = new (...args: never[]) => unknown;\nexport type SchemaConstructor<SV extends AnySchemaValidator> = new (\n ...args: unknown[]\n) => IdiomaticSchema<SV>;\nexport type Function = (...args: never[]) => unknown;\nexport type FunctionToConstructor = (\n ...args: never[]\n) => new (...args: never[]) => unknown;\nexport type SchemaFunction<SV extends AnySchemaValidator> = (\n args: unknown\n) => IdiomaticSchema<SV>;\n\nexport type ConfigTypes<SV extends AnySchemaValidator> =\n | Function\n | SchemaFunction<SV>\n | Constructor\n | SchemaConstructor<SV>\n | IdiomaticSchema<SV>;\n\nexport type ConfigValidator<SV extends AnySchemaValidator> = Record<\n string,\n ConfigTypes<SV> | Record<string, ConfigTypes<SV>>\n>;\n\ntype ResolveConfigValue<SV extends AnySchemaValidator, T> =\n T extends SchemaConstructor<SV>\n ? Schema<InstanceType<T>, SV>\n : T extends SchemaFunction<SV>\n ? (...args: Parameters<T>) => Schema<ReturnType<T>, SV>\n : T extends FunctionToConstructor\n ? (...args: Parameters<T>) => InstanceType<ReturnType<T>>\n : T extends Function\n ? (...args: Parameters<T>) => ReturnType<T>\n : T extends Constructor\n ? InstanceType<T>\n : T extends IdiomaticSchema<SV>\n ? Schema<T, SV>\n : T extends Record<string, ConfigTypes<SV>>\n ? {\n [K in keyof T]: ResolveConfigValue<SV, T[K]>;\n }\n : Schema<T, SV>;\n\nexport type ResolvedConfigValidator<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>\n> = {\n [M in keyof CV]: ResolveConfigValue<SV, CV[M]>;\n};\n\nexport type ScopedDependencyFactory<\n SV extends AnySchemaValidator,\n CV extends ConfigValidator<SV>,\n M extends keyof CV\n> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];\n","import { ConstructedSingleton, Lifetime } from '../types/configInjector.types';\n\nexport function isConstructedSingleton<Type, Args, Return>(\n value: unknown\n): value is ConstructedSingleton<Type, Args, Return> {\n return (\n typeof value === 'object' &&\n value != null &&\n 'lifetime' in value &&\n value.lifetime === Lifetime.Singleton &&\n 'factory' in value\n );\n}\n","import { Constructor } from '../types/configInjector.types';\n\nexport function isConstructor(value: unknown): value is Constructor {\n return (\n typeof value === 'function' &&\n value.constructor != null &&\n value.prototype != null\n );\n}\n","export const ComplianceLevel = {\n pii: 'pii',\n phi: 'phi',\n pci: 'pci',\n none: 'none'\n} as const;\nexport type ComplianceLevel =\n (typeof ComplianceLevel)[keyof typeof ComplianceLevel];\n\nexport const COMPLIANCE_KEY = '~compliance' as const;\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\nconst complianceRegistry = new Map<string, Map<string, ComplianceLevel>>();\n\nexport function registerEntityCompliance(\n entityName: string,\n fields: Map<string, ComplianceLevel>\n): void {\n complianceRegistry.set(entityName, fields);\n}\n\nexport function getComplianceMetadata(\n entityName: string,\n fieldName: string\n): ComplianceLevel {\n return complianceRegistry.get(entityName)?.get(fieldName) ?? 'none';\n}\n\nexport function getEntityComplianceFields(\n entityName: string\n): Map<string, ComplianceLevel> | undefined {\n return complianceRegistry.get(entityName);\n}\n\nexport function entityHasEncryptedFields(entityName: string): boolean {\n const fields = complianceRegistry.get(entityName);\n if (!fields) return false;\n for (const level of fields.values()) {\n if (level === 'phi' || level === 'pci') return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Retention types and registry\n// ---------------------------------------------------------------------------\n\nexport const RetentionAction = {\n delete: 'delete',\n anonymize: 'anonymize'\n} as const;\nexport type RetentionAction =\n (typeof RetentionAction)[keyof typeof RetentionAction];\n\nexport interface RetentionPolicy {\n duration: string;\n action: RetentionAction;\n}\n\nexport const RetentionDuration = {\n days: (n: number): string => `P${n}D`,\n months: (n: number): string => `P${n}M`,\n years: (n: number): string => `P${n}Y`\n} as const;\n\nexport interface ParsedDuration {\n years: number;\n months: number;\n days: number;\n}\n\nconst DURATION_REGEX = /^P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)D)?$/;\n\n/**\n * Parse an ISO 8601 duration string into calendar units.\n * Returns structured units to enable calendar-aware date arithmetic.\n */\nexport function parseDuration(iso: string): ParsedDuration {\n const match = DURATION_REGEX.exec(iso);\n if (!match) {\n throw new Error(\n `Invalid ISO 8601 duration: '${iso}'. Expected format: P[n]Y[n]M[n]D`\n );\n }\n const years = parseInt(match[1] || '0', 10);\n const months = parseInt(match[2] || '0', 10);\n const days = parseInt(match[3] || '0', 10);\n\n // Approximate total days for minimum validation only\n const approxDays = years * 365 + months * 30 + days;\n if (approxDays < 1) {\n throw new Error(\n `Retention duration must be >= 1 day (P1D). Got: '${iso}' (${approxDays} approx days)`\n );\n }\n\n return { years, months, days };\n}\n\n/**\n * Subtract a parsed duration from a date using calendar-aware arithmetic.\n * Handles month-end clamping and leap years correctly.\n */\nexport function subtractDuration(from: Date, duration: ParsedDuration): Date {\n const result = new Date(from);\n result.setFullYear(result.getFullYear() - duration.years);\n result.setMonth(result.getMonth() - duration.months);\n result.setDate(result.getDate() - duration.days);\n return result;\n}\n\nconst retentionRegistry = new Map<string, RetentionPolicy>();\n\n// ---------------------------------------------------------------------------\n// User ID field registry — maps entity name to the field linking records to a user\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_USER_ID_FIELD = 'userId';\nconst userIdFieldRegistry = new Map<string, string>();\n\nexport function registerEntityUserIdField(\n entityName: string,\n field: string\n): void {\n userIdFieldRegistry.set(entityName, field);\n}\n\nexport function getEntityUserIdField(entityName: string): string {\n return userIdFieldRegistry.get(entityName) ?? DEFAULT_USER_ID_FIELD;\n}\n\nexport function getAllUserIdFields(): ReadonlyMap<string, string> {\n return userIdFieldRegistry;\n}\n\nexport function registerEntityRetention(\n entityName: string,\n policy: RetentionPolicy\n): void {\n retentionRegistry.set(entityName, policy);\n}\n\nexport function getEntityRetention(\n entityName: string\n): RetentionPolicy | undefined {\n return retentionRegistry.get(entityName);\n}\n\nexport function getAllRetentionPolicies(): ReadonlyMap<\n string,\n RetentionPolicy\n> {\n return retentionRegistry;\n}\n\n// ---------------------------------------------------------------------------\n// Module augmentation — adds .compliance() via PropertyOptions\n// ---------------------------------------------------------------------------\n\n/**\n * Adds `compliance` to PropertyOptions, which flows into IncludeKeys\n * for all scalar/enum/embedded builders (PropertyOptions is extended by\n * EnumOptions and EmbeddedOptions). Relation builders use ReferenceOptions\n * instead, so they don't get .compliance() — which is what we want.\n */\ndeclare module '@mikro-orm/core' {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n interface PropertyOptions<Owner> {\n compliance?: ComplianceLevel;\n }\n\n interface UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys> {\n compliance(\n level: ComplianceLevel\n ): Pick<\n UniversalPropertyOptionsBuilder<\n Value,\n Options & { readonly '~c': true },\n IncludeKeys\n >,\n IncludeKeys & keyof UniversalPropertyOptionsBuilder<never, never, never>\n >;\n }\n}\n","import type { MikroORM } from '@mikro-orm/core';\nimport type { OpenTelemetryCollector } from '../http/telemetry/openTelemetryCollector';\nimport {\n getAllRetentionPolicies,\n getEntityComplianceFields,\n parseDuration,\n subtractDuration,\n type RetentionPolicy\n} from '../persistence/complianceTypes';\n\nexport interface EnforcementOptions {\n /** Filter to specific entity names (default: all with retention policies) */\n entities?: string[];\n /** Records per batch (default: 1000) */\n batchSize?: number;\n /** Log what would happen without mutating */\n dryRun?: boolean;\n}\n\nexport interface EnforcementResult {\n processed: number;\n deleted: number;\n anonymized: number;\n errors: number;\n byEntity: Record<\n string,\n { deleted: number; anonymized: number; errors: number }\n >;\n durationMs: number;\n}\n\nexport class RetentionService {\n private readonly DEFAULT_BATCH_SIZE = 1000;\n\n constructor(\n private readonly orm: MikroORM,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly otel: OpenTelemetryCollector<any>\n ) {}\n\n async enforce(options?: EnforcementOptions): Promise<EnforcementResult> {\n const start = Date.now();\n const batchSize = options?.batchSize ?? this.DEFAULT_BATCH_SIZE;\n const dryRun = options?.dryRun ?? false;\n const policies = getAllRetentionPolicies();\n const result: EnforcementResult = {\n processed: 0,\n deleted: 0,\n anonymized: 0,\n errors: 0,\n byEntity: {},\n durationMs: 0\n };\n\n if (policies.size === 0) {\n this.otel.info('[RetentionService] No retention policies registered');\n result.durationMs = Date.now() - start;\n return result;\n }\n\n this.otel.info('[RetentionService] Starting enforcement', {\n entityCount: policies.size,\n batchSize,\n dryRun\n });\n\n for (const [entityName, policy] of policies) {\n if (options?.entities && !options.entities.includes(entityName)) continue;\n\n const entityResult = { deleted: 0, anonymized: 0, errors: 0 };\n\n try {\n await this.enforceEntity(\n entityName,\n policy,\n batchSize,\n entityResult,\n dryRun\n );\n } catch (err) {\n entityResult.errors++;\n this.otel.error('[RetentionService] Entity-level failure', {\n entityName,\n error: String(err)\n });\n }\n\n result.byEntity[entityName] = entityResult;\n result.deleted += entityResult.deleted;\n result.anonymized += entityResult.anonymized;\n result.errors += entityResult.errors;\n result.processed += entityResult.deleted + entityResult.anonymized;\n }\n\n result.durationMs = Date.now() - start;\n this.otel.info('[RetentionService] Enforcement complete', {\n processed: result.processed,\n deleted: result.deleted,\n anonymized: result.anonymized,\n errors: result.errors,\n durationMs: result.durationMs\n });\n\n return result;\n }\n\n private async enforceEntity(\n entityName: string,\n policy: RetentionPolicy,\n batchSize: number,\n stats: { deleted: number; anonymized: number; errors: number },\n dryRun: boolean\n ): Promise<void> {\n const metadata = [...this.orm.getMetadata().getAll().values()].find(\n (m) => m.className === entityName\n );\n\n if (!metadata) {\n this.otel.warn(\n '[RetentionService] Entity not in MikroORM metadata — skipping',\n { entityName }\n );\n return;\n }\n\n const duration = parseDuration(policy.duration);\n const cutoff = subtractDuration(new Date(), duration);\n const entityClass = metadata.class ?? metadata.className;\n\n // For anonymize: only null out PII/PHI/PCI fields that are nullable.\n // Non-nullable fields are skipped to avoid flush errors.\n const piiFieldNames: string[] = [];\n if (policy.action === 'anonymize') {\n const complianceFields = getEntityComplianceFields(entityName);\n if (complianceFields) {\n for (const [fieldName, level] of complianceFields) {\n if (level === 'none') continue;\n const prop = metadata.properties[fieldName];\n if (prop && prop.nullable) {\n piiFieldNames.push(fieldName);\n } else {\n this.otel.warn(\n '[RetentionService] Skipping non-nullable PII field for anonymize',\n { entityName, fieldName, level }\n );\n }\n }\n }\n }\n\n const filter: Record<string, unknown> = {\n createdAt: { $lt: cutoff }\n };\n if (policy.action === 'anonymize') {\n filter['retentionAnonymizedAt'] = null;\n }\n\n // Dry run: use count instead of fetching records\n if (dryRun) {\n const em = this.orm.em.fork();\n try {\n const count = await em.count(entityClass, filter);\n this.otel.info('[RetentionService] Dry run — would process', {\n entityName,\n action: policy.action,\n count\n });\n if (policy.action === 'delete') stats.deleted += count;\n else stats.anonymized += count;\n } catch (err) {\n stats.errors++;\n this.otel.error('[RetentionService] Dry run count failed', {\n entityName,\n error: String(err)\n });\n }\n return;\n }\n\n let batchNum = 0;\n\n while (true) {\n batchNum++;\n const em = this.orm.em.fork();\n\n try {\n const records = await em.find(entityClass, filter, {\n limit: batchSize,\n orderBy: { createdAt: 'ASC' }\n });\n\n if (records.length === 0) break;\n\n if (policy.action === 'delete') {\n records.forEach((r) => em.remove(r));\n await em.flush();\n stats.deleted += records.length;\n } else {\n for (const record of records) {\n const rec = record as Record<string, unknown>;\n for (const field of piiFieldNames) {\n rec[field] = null;\n }\n rec['retentionAnonymizedAt'] = new Date();\n }\n await em.flush();\n stats.anonymized += records.length;\n }\n\n this.otel.info('[RetentionService] Batch processed', {\n entityName,\n action: policy.action,\n batch: batchNum,\n count: records.length\n });\n } catch (err) {\n stats.errors++;\n this.otel.error('[RetentionService] Batch failed', {\n entityName,\n batch: batchNum,\n error: String(err)\n });\n break; // stop batching this entity, continue to next\n }\n }\n }\n}\n","import type { MikroORM } from '@mikro-orm/core';\nimport type { OpenTelemetryCollector } from '../http/telemetry/openTelemetryCollector';\nimport { MetricsDefinition } from '../http/types/openTelemetryCollector.types';\nimport {\n getEntityComplianceFields,\n getEntityUserIdField\n} from '../persistence/complianceTypes';\n\nexport interface EraseResult {\n entitiesAffected: string[];\n recordsDeleted: number;\n}\n\nexport interface ExportResult {\n userId: string;\n entities: Record<string, unknown[]>;\n}\n\n/**\n * Per-entity userIdField overrides.\n * Keys are entity names, values are the field name linking records to a user.\n *\n * @example\n * {\n * User: 'id', // the User entity IS the user record\n * Subscription: 'partyId', // billing links via partyId\n * Account: 'userId', // default, can be omitted\n * }\n */\nexport type UserIdFieldOverrides = Record<string, string>;\n\n/**\n * Common field names that link an entity to a user, tried in order.\n * Used for optimistic search when no explicit userIdField is configured.\n */\nconst CANDIDATE_USER_FIELDS = [\n 'userId',\n 'user',\n 'id',\n 'partyId',\n 'customerId',\n 'ownerId',\n 'createdBy',\n 'email'\n];\n\n/**\n * Generic compliance data service that walks all compliance-registered entities\n * and erases or exports PII/PHI/PCI data for a given user.\n *\n * Resolution order for userIdField per entity:\n * 1. Constructor overrides (highest priority)\n * 2. defineComplianceEntity({ userIdField }) registry\n * 3. Optimistic search: first CANDIDATE_USER_FIELDS match in entity metadata\n * 4. Skip entity (no user link found)\n */\nexport class ComplianceDataService {\n private readonly userIdFieldOverrides: UserIdFieldOverrides;\n\n constructor(\n private readonly orm: MikroORM,\n private readonly otel: OpenTelemetryCollector<MetricsDefinition>,\n userIdFieldOverrides?: UserIdFieldOverrides\n ) {\n this.userIdFieldOverrides = userIdFieldOverrides ?? {};\n }\n\n /**\n * Resolve the field linking an entity to a user.\n * Returns undefined if no link can be determined.\n */\n private resolveUserIdField(\n entityName: string,\n entityProperties: Record<string, unknown>\n ): string | undefined {\n // 1. Constructor override\n const override = this.userIdFieldOverrides[entityName];\n if (override) return override;\n\n // 2. Registry (from defineComplianceEntity({ userIdField }))\n const registered = getEntityUserIdField(entityName);\n if (registered !== 'userId' || entityProperties['userId']) {\n // Registry returned a non-default value, or the default 'userId' exists\n if (entityProperties[registered]) return registered;\n }\n\n // 3. Optimistic search\n for (const candidate of CANDIDATE_USER_FIELDS) {\n if (entityProperties[candidate]) return candidate;\n }\n\n // 4. No link found\n return undefined;\n }\n\n async erase(userId: string): Promise<EraseResult> {\n const em = this.orm.em.fork();\n const entitiesAffected: string[] = [];\n let recordsDeleted = 0;\n\n const allMetadata = [...this.orm.getMetadata().getAll().values()];\n\n for (const metadata of allMetadata) {\n const entityName = metadata.className;\n const fields = getEntityComplianceFields(entityName);\n if (!fields) continue;\n\n const hasPii = [...fields.values()].some(\n (level) => level === 'pii' || level === 'phi' || level === 'pci'\n );\n if (!hasPii) continue;\n\n const userIdField = this.resolveUserIdField(\n entityName,\n metadata.properties\n );\n\n if (!userIdField) {\n this.otel.warn(\n '[ComplianceDataService] No user-linking field found — skipping',\n { entityName, candidates: CANDIDATE_USER_FIELDS }\n );\n continue;\n }\n\n try {\n const entityClass = metadata.class ?? metadata.className;\n const records = await em.find(entityClass, {\n [userIdField]: userId\n });\n\n if (records.length > 0) {\n entitiesAffected.push(entityName);\n recordsDeleted += records.length;\n records.forEach((r) => em.remove(r));\n }\n } catch (err) {\n this.otel.error('[ComplianceDataService] Failed to erase entity', {\n entityName,\n userIdField,\n error: String(err)\n });\n }\n }\n\n if (recordsDeleted > 0) {\n await em.flush();\n }\n\n this.otel.info('[ComplianceDataService] Erase complete', {\n userId,\n entitiesAffected: entitiesAffected.join(','),\n recordsDeleted\n });\n\n return { entitiesAffected, recordsDeleted };\n }\n\n async export(userId: string): Promise<ExportResult> {\n const em = this.orm.em.fork();\n const entities: Record<string, unknown[]> = {};\n\n const allMetadata = [...this.orm.getMetadata().getAll().values()];\n\n for (const metadata of allMetadata) {\n const entityName = metadata.className;\n const fields = getEntityComplianceFields(entityName);\n if (!fields) continue;\n\n const hasPii = [...fields.values()].some(\n (level) => level === 'pii' || level === 'phi' || level === 'pci'\n );\n if (!hasPii) continue;\n\n const userIdField = this.resolveUserIdField(\n entityName,\n metadata.properties\n );\n\n if (!userIdField) {\n continue;\n }\n\n try {\n const entityClass = metadata.class ?? metadata.className;\n const records = await em.find(entityClass, {\n [userIdField]: userId\n });\n\n if (records.length > 0) {\n const piiFieldNames = [...fields.entries()]\n .filter(([, level]) => level !== 'none')\n .map(([name]) => name);\n\n entities[entityName] = records.map((record) => {\n const filtered: Record<string, unknown> = {};\n filtered['id'] = (record as Record<string, unknown>)['id'];\n for (const fieldName of piiFieldNames) {\n filtered[fieldName] = (record as Record<string, unknown>)[\n fieldName\n ];\n }\n return filtered;\n });\n }\n } catch (err) {\n this.otel.error('[ComplianceDataService] Failed to export entity', {\n entityName,\n userIdField,\n error: String(err)\n });\n }\n }\n\n this.otel.info('[ComplianceDataService] Export complete', {\n userId,\n entityCount: Object.keys(entities).length\n });\n\n return { userId, entities };\n }\n}\n","import type { OpenTelemetryCollector } from '../http/telemetry/openTelemetryCollector';\nimport type { RetentionService } from './retentionService';\n\n/**\n * Shared retention enforcement runner.\n * Designed to be called from a one-shot script (ECS RunTask / cron).\n *\n * @example\n * ```ts\n * import { ci, tokens } from '../bootstrapper';\n * import { runRetentionEnforcement } from '@myapp/core';\n *\n * runRetentionEnforcement(\n * ci.resolve(tokens.RetentionService),\n * ci.resolve(tokens.OtelCollector)\n * );\n * ```\n */\nexport async function runRetentionEnforcement(\n retentionService: RetentionService,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n otel: OpenTelemetryCollector<any>\n): Promise<void> {\n const dryRun = process.argv.includes('--dry-run');\n\n otel.info('[RetentionEnforcement] Starting', { dryRun });\n\n const result = await retentionService.enforce({ dryRun });\n\n otel.info('[RetentionEnforcement] Complete', {\n processed: result.processed,\n deleted: result.deleted,\n anonymized: result.anonymized,\n errors: result.errors,\n durationMs: result.durationMs\n });\n\n if (result.errors > 0) {\n otel.warn('[RetentionEnforcement] Completed with errors', {\n errors: result.errors,\n byEntity: result.byEntity\n });\n process.exit(1);\n }\n\n process.exit(0);\n}\n"],"mappings":"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","names":["import_common","dotenv"]}
|