@objectstack/core 15.1.0 → 16.0.0-rc.0

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/kernel-base.ts","../src/logger.ts","../src/kernel.ts","../src/security/plugin-config-validator.ts","../src/security/plugin-artifact-signature.ts","../src/plugin-loader.ts","../src/utils/env.ts","../src/fallbacks/memory-cache.ts","../src/fallbacks/memory-queue.ts","../src/fallbacks/memory-job.ts","../src/fallbacks/memory-i18n.ts","../src/fallbacks/memory-metadata.ts","../src/fallbacks/authored-translation-sync.ts","../src/fallbacks/index.ts","../src/lite-kernel.ts","../src/api-registry.ts","../src/api-registry-plugin.ts","../src/qa/index.ts","../src/qa/runner.ts","../src/qa/http-adapter.ts","../src/security/plugin-signature-verifier.ts","../src/security/plugin-permission-enforcer.ts","../src/security/permission-manager.ts","../src/security/sandbox-runtime.ts","../src/security/security-scanner.ts","../src/security/api-key.ts","../src/security/resolve-authz-context.ts","../src/security/grant-validity.ts","../src/security/posture-ladder.ts","../src/security/auth-gate.ts","../src/security/anonymous-deny.ts","../src/utils/datetime.ts","../src/utils/bulk-write.ts","../src/health-monitor.ts","../src/hot-reload.ts","../src/dependency-resolver.ts","../src/namespace-resolver.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/core\n * \n * Core runtime for ObjectStack microkernel architecture.\n * Provides plugin system, dependency injection, and lifecycle management.\n */\n\nexport * from './kernel-base.js';\nexport * from './kernel.js';\nexport * from './lite-kernel.js';\nexport * from './types.js';\nexport * from './logger.js';\nexport * from './plugin-loader.js';\nexport * from './api-registry.js';\nexport * from './api-registry-plugin.js';\nexport * as QA from './qa/index.js';\n\n// Export security utilities\nexport * from './security/index.js';\n\n// Export environment utilities\nexport * from './utils/env.js';\n\n// Export timezone-aware calendar utilities (ADR-0053 Phase 2)\nexport * from './utils/datetime.js';\n\n// Export the shared batched-write helper (framework#2678)\nexport * from './utils/bulk-write.js';\n\n// Export in-memory fallbacks for core-criticality services\nexport * from './fallbacks/index.js';\n\n// Export Phase 2 components - Advanced lifecycle management\nexport * from './health-monitor.js';\nexport * from './hot-reload.js';\nexport * from './dependency-resolver.js';\n\n// Export Phase 3 components - Package lifecycle management\nexport * from './namespace-resolver.js';\n\n// Re-export contracts from @objectstack/spec for backward compatibility\nexport type { \n Logger,\n IHttpServer,\n IHttpRequest,\n IHttpResponse,\n RouteHandler,\n Middleware,\n IDataEngine,\n IDataDriver,\n} from '@objectstack/spec/contracts';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from './types.js';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { IServiceRegistry } from '@objectstack/spec/contracts';\n\n/**\n * Kernel state machine\n */\nexport type KernelState = 'idle' | 'initializing' | 'running' | 'stopping' | 'stopped';\n\n/**\n * ObjectKernelBase - Abstract Base Class for Microkernel\n * \n * Provides common functionality for ObjectKernel and LiteKernel:\n * - Plugin management (Map storage)\n * - Dependency resolution (topological sort)\n * - Hook/Event system\n * - Context creation\n * - State validation\n * \n * This eliminates code duplication between the implementations.\n */\nexport abstract class ObjectKernelBase {\n protected plugins: Map<string, Plugin> = new Map();\n protected services: IServiceRegistry | Map<string, any> = new Map();\n protected hooks: Map<string, Array<(...args: any[]) => void | Promise<void>>> = new Map();\n protected state: KernelState = 'idle';\n protected logger: Logger;\n protected context!: PluginContext;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n /**\n * Validate kernel state\n * @param requiredState - Required state for the operation\n * @throws Error if current state doesn't match\n */\n protected validateState(requiredState: KernelState): void {\n if (this.state !== requiredState) {\n throw new Error(\n `[Kernel] Invalid state: expected '${requiredState}', got '${this.state}'`\n );\n }\n }\n\n /**\n * Validate kernel is in idle state (for plugin registration)\n */\n protected validateIdle(): void {\n if (this.state !== 'idle') {\n throw new Error('[Kernel] Cannot register plugins after bootstrap has started');\n }\n }\n\n /**\n * Create the plugin context\n * Subclasses can override to customize context creation\n */\n protected createContext(): PluginContext {\n return {\n registerService: (name, service) => {\n if (this.services instanceof Map) {\n if (this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' already registered`);\n }\n this.services.set(name, service);\n } else {\n // IServiceRegistry implementation\n this.services.register(name, service);\n }\n this.logger.info(`Service '${name}' registered`, { service: name });\n },\n getService: <T>(name: string): T => {\n if (this.services instanceof Map) {\n const service = this.services.get(name);\n if (!service) {\n throw new Error(`[Kernel] Service '${name}' not found`);\n }\n return service as T;\n } else {\n // IServiceRegistry implementation\n return this.services.get<T>(name);\n }\n },\n replaceService: <T>(name: string, implementation: T): void => {\n if (this.services instanceof Map) {\n if (!this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' not found. Use registerService() to add new services.`);\n }\n this.services.set(name, implementation);\n } else {\n // IServiceRegistry implementation\n if (!this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' not found. Use registerService() to add new services.`);\n }\n this.services.register(name, implementation);\n }\n this.logger.info(`Service '${name}' replaced`, { service: name });\n },\n hook: (name, handler) => {\n if (!this.hooks.has(name)) {\n this.hooks.set(name, []);\n }\n this.hooks.get(name)!.push(handler);\n },\n trigger: async (name, ...args) => {\n const handlers = this.hooks.get(name) || [];\n for (const handler of handlers) {\n await handler(...args);\n }\n },\n getServices: () => {\n if (this.services instanceof Map) {\n return new Map(this.services);\n } else {\n // For IServiceRegistry, we need to return the underlying Map\n // This is a compatibility method\n return new Map();\n }\n },\n logger: this.logger,\n getKernel: () => this as any,\n registerServiceFactory: (_name, _factory, _lifecycle, _dependencies) => {\n throw new Error('[KernelBase] registerServiceFactory not supported — use ObjectKernel');\n },\n getServiceScoped: async <T>(_name: string, _scopeId: string): Promise<T> => {\n throw new Error('[KernelBase] getServiceScoped not supported — use ObjectKernel');\n },\n };\n }\n\n /**\n * Resolve plugin dependencies using topological sort\n * @returns Ordered list of plugins (dependencies first)\n */\n protected resolveDependencies(): Plugin[] {\n const resolved: Plugin[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (pluginName: string) => {\n if (visited.has(pluginName)) return;\n \n if (visiting.has(pluginName)) {\n throw new Error(`[Kernel] Circular dependency detected: ${pluginName}`);\n }\n\n const plugin = this.plugins.get(pluginName);\n if (!plugin) {\n throw new Error(`[Kernel] Plugin '${pluginName}' not found`);\n }\n\n visiting.add(pluginName);\n\n // Visit dependencies first\n const deps = plugin.dependencies || [];\n for (const dep of deps) {\n if (!this.plugins.has(dep)) {\n throw new Error(\n `[Kernel] Dependency '${dep}' not found for plugin '${pluginName}'`\n );\n }\n visit(dep);\n }\n\n visiting.delete(pluginName);\n visited.add(pluginName);\n resolved.push(plugin);\n };\n\n // Visit all plugins\n for (const pluginName of this.plugins.keys()) {\n visit(pluginName);\n }\n\n return resolved;\n }\n\n /**\n * Run plugin init phase\n * @param plugin - Plugin to initialize\n */\n protected async runPluginInit(plugin: Plugin): Promise<void> {\n const pluginName = plugin.name;\n this.logger.info(`Initializing plugin: ${pluginName}`);\n \n try {\n await plugin.init(this.context);\n this.logger.info(`Plugin initialized: ${pluginName}`);\n } catch (error) {\n this.logger.error(`Plugin init failed: ${pluginName}`, error as Error);\n throw error;\n }\n }\n\n /**\n * Run plugin start phase\n * @param plugin - Plugin to start\n */\n protected async runPluginStart(plugin: Plugin): Promise<void> {\n if (!plugin.start) return;\n \n const pluginName = plugin.name;\n this.logger.info(`Starting plugin: ${pluginName}`);\n \n try {\n await plugin.start(this.context);\n this.logger.info(`Plugin started: ${pluginName}`);\n } catch (error) {\n this.logger.error(`Plugin start failed: ${pluginName}`, error as Error);\n throw error;\n }\n }\n\n /**\n * Run plugin destroy phase\n * @param plugin - Plugin to destroy\n */\n protected async runPluginDestroy(plugin: Plugin): Promise<void> {\n if (!plugin.destroy) return;\n \n const pluginName = plugin.name;\n this.logger.info(`Destroying plugin: ${pluginName}`);\n \n try {\n await plugin.destroy();\n this.logger.info(`Plugin destroyed: ${pluginName}`);\n } catch (error) {\n this.logger.error(`Plugin destroy failed: ${pluginName}`, error as Error);\n throw error;\n }\n }\n\n /**\n * Trigger a hook with all registered handlers\n * @param name - Hook name\n * @param args - Arguments to pass to handlers\n */\n protected async triggerHook(name: string, ...args: any[]): Promise<void> {\n const handlers = this.hooks.get(name) || [];\n this.logger.debug(`Triggering hook: ${name}`, { \n hook: name, \n handlerCount: handlers.length \n });\n \n for (const handler of handlers) {\n try {\n await handler(...args);\n } catch (error) {\n this.logger.error(`Hook handler failed: ${name}`, error as Error);\n // Continue with other handlers even if one fails\n }\n }\n }\n\n /**\n * Get current kernel state\n */\n getState(): KernelState {\n return this.state;\n }\n\n /**\n * Get all registered plugins\n */\n getPlugins(): Map<string, Plugin> {\n return new Map(this.plugins);\n }\n\n /**\n * Abstract methods to be implemented by subclasses\n */\n abstract use(plugin: Plugin): this | Promise<this>;\n abstract bootstrap(): Promise<void>;\n abstract destroy(): Promise<void>;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { LoggerConfig, LogLevel } from '@objectstack/spec/system';\nimport type { Logger } from '@objectstack/spec/contracts';\n\n// Re-export the contract type so consumers can do\n// `import type { Logger } from '@objectstack/core/logger'` without also\n// pulling `@objectstack/spec` into their bundle graph manually.\nexport type { Logger };\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 4,\n silent: 5,\n};\n\nconst LEVEL_COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m',\n info: '\\x1b[32m',\n warn: '\\x1b[33m',\n error: '\\x1b[31m',\n fatal: '\\x1b[35m',\n silent: '',\n};\n\nconst RESET = '\\x1b[0m';\n\nexport class ObjectLogger implements Logger {\n private config: Required<Omit<LoggerConfig, 'file' | 'rotation' | 'name'>> & {\n file?: string;\n rotation?: { maxSize: string; maxFiles: number };\n name?: string;\n };\n private bindings: Record<string, any>;\n private fileStream?: any;\n\n constructor(config: Partial<LoggerConfig> = {}, bindings: Record<string, any> = {}) {\n this.config = {\n name: config.name,\n level: config.level ?? 'info',\n format: config.format ?? 'pretty',\n redact: config.redact ?? ['password', 'token', 'secret', 'key'],\n sourceLocation: config.sourceLocation ?? false,\n file: config.file,\n rotation: config.rotation ?? { maxSize: '10m', maxFiles: 5 },\n };\n this.bindings = bindings;\n\n if (this.config.file && typeof process !== 'undefined') {\n this.openFileStream(this.config.file);\n }\n }\n\n private openFileStream(path: string) {\n try {\n // Lazy require to avoid bundling issues\n const fs = require('fs');\n const dir = require('path').dirname(path);\n fs.mkdirSync(dir, { recursive: true });\n this.fileStream = fs.createWriteStream(path, { flags: 'a' });\n } catch {\n // ignore — file logging is optional\n }\n }\n\n private isEnabled(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[this.config.level];\n }\n\n private redactSensitive(obj: any): any {\n if (!obj || typeof obj !== 'object') return obj;\n const redacted = Array.isArray(obj) ? [...obj] : { ...obj };\n for (const key in redacted) {\n const lower = key.toLowerCase();\n if (this.config.redact.some((p: string) => lower.includes(p.toLowerCase()))) {\n redacted[key] = '***REDACTED***';\n } else if (typeof redacted[key] === 'object' && redacted[key] !== null) {\n redacted[key] = this.redactSensitive(redacted[key]);\n }\n }\n return redacted;\n }\n\n private write(level: LogLevel, message: string, meta?: Record<string, any>, error?: Error) {\n if (!this.isEnabled(level)) return;\n\n const context = this.redactSensitive({\n ...this.bindings,\n ...meta,\n ...(error ? { error: { message: error.message, stack: error.stack } } : {}),\n });\n\n const hasContext = Object.keys(context).length > 0;\n const ts = new Date().toISOString();\n\n let line: string;\n\n if (this.config.format === 'json') {\n line = JSON.stringify({\n time: ts,\n level,\n ...(this.config.name ? { name: this.config.name } : {}),\n msg: message,\n ...context,\n });\n } else if (this.config.format === 'text') {\n const parts = [ts, level.toUpperCase(), message];\n if (hasContext) parts.push(JSON.stringify(context));\n line = parts.join(' | ');\n } else {\n // pretty\n const color = LEVEL_COLORS[level] || '';\n const label = this.config.name ? `[${this.config.name}] ` : '';\n line = `${color}${ts} ${level.toUpperCase()}${RESET} ${label}${message}`;\n if (hasContext) line += ` ${JSON.stringify(context)}`;\n }\n\n const out = line + '\\n';\n\n // Browser-safe output: prefer process streams when available, otherwise\n // fall back to console. The previous unguarded `process.stderr?.write`\n // throws `ReferenceError: process is not defined` in browsers because\n // `process` itself is the missing global, not just its `stderr` field.\n if (typeof process !== 'undefined' && (process as any).stderr) {\n if (level === 'error' || level === 'fatal') {\n (process as any).stderr.write(out);\n } else {\n (process as any).stdout?.write(out);\n }\n } else if (typeof console !== 'undefined') {\n const fn =\n level === 'error' || level === 'fatal' ? console.error\n : level === 'warn' ? console.warn\n : level === 'debug' ? console.debug\n : console.log;\n fn(line);\n }\n\n if (this.fileStream) {\n this.fileStream.write(out);\n }\n }\n\n debug(message: string, meta?: Record<string, any>): void {\n this.write('debug', message, meta);\n }\n\n info(message: string, meta?: Record<string, any>): void {\n this.write('info', message, meta);\n }\n\n warn(message: string, meta?: Record<string, any>): void {\n this.write('warn', message, meta);\n }\n\n error(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void {\n if (errorOrMeta instanceof Error) {\n this.write('error', message, meta, errorOrMeta);\n } else {\n this.write('error', message, errorOrMeta);\n }\n }\n\n fatal(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void {\n if (errorOrMeta instanceof Error) {\n this.write('fatal', message, meta, errorOrMeta);\n } else {\n this.write('fatal', message, errorOrMeta);\n }\n }\n\n log(message: string, ...args: any[]): void {\n this.info(message, args.length > 0 ? { args } : undefined);\n }\n\n child(context: Record<string, any>): ObjectLogger {\n const child = new ObjectLogger(this.config, { ...this.bindings, ...context });\n // Share the file stream — no double-open\n child.fileStream = this.fileStream;\n return child;\n }\n\n withTrace(traceId: string, spanId?: string): ObjectLogger {\n return this.child({ traceId, spanId });\n }\n\n async destroy(): Promise<void> {\n if (this.fileStream) {\n await new Promise<void>((resolve) => this.fileStream.end(resolve));\n this.fileStream = undefined;\n }\n }\n}\n\nexport function createLogger(config?: Partial<LoggerConfig>): ObjectLogger {\n return new ObjectLogger(config);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext } from './types.js';\nimport { createLogger, ObjectLogger } from './logger.js';\nimport type { LoggerConfig } from '@objectstack/spec/system';\nimport { ServiceRequirementDef } from '@objectstack/spec/system';\nimport { PluginLoader, PluginMetadata, ServiceLifecycle, ServiceFactory, PluginStartupResult } from './plugin-loader.js';\nimport { isNode, safeExit } from './utils/env.js';\nimport { CORE_FALLBACK_FACTORIES } from './fallbacks/index.js';\n\n/**\n * Enhanced Kernel Configuration\n */\nexport interface ObjectKernelConfig {\n logger?: Partial<LoggerConfig>;\n \n /** Default plugin startup timeout in milliseconds */\n defaultStartupTimeout?: number;\n \n /** Whether to enable graceful shutdown */\n gracefulShutdown?: boolean;\n \n /** Graceful shutdown timeout in milliseconds */\n shutdownTimeout?: number;\n \n /** Whether to rollback on startup failure */\n rollbackOnFailure?: boolean;\n \n /** Whether to skip strict system requirement validation (Critical for testing) */\n skipSystemValidation?: boolean;\n}\n\n/**\n * Enhanced ObjectKernel with Advanced Plugin Management\n * \n * Extends the basic ObjectKernel with:\n * - Async plugin loading with validation\n * - Version compatibility checking\n * - Plugin signature verification\n * - Configuration validation (Zod)\n * - Factory-based dependency injection\n * - Service lifecycle management (singleton/transient/scoped)\n * - Circular dependency detection\n * - Lazy loading services\n * - Graceful shutdown\n * - Plugin startup timeout control\n * - Startup failure rollback\n * - Plugin health checks\n */\nexport class ObjectKernel {\n private plugins: Map<string, PluginMetadata> = new Map();\n private services: Map<string, any> = new Map();\n private hooks: Map<string, Array<(...args: any[]) => void | Promise<void>>> = new Map();\n private state: 'idle' | 'initializing' | 'running' | 'stopping' | 'stopped' = 'idle';\n private logger: ObjectLogger;\n private context: PluginContext;\n private pluginLoader: PluginLoader;\n private config: ObjectKernelConfig;\n private startedPlugins: Set<string> = new Set();\n private pluginStartTimes: Map<string, number> = new Map();\n private shutdownHandlers: Array<() => Promise<void>> = [];\n\n constructor(config: ObjectKernelConfig = {}) {\n this.config = {\n defaultStartupTimeout: 30000, // 30 seconds\n gracefulShutdown: true,\n shutdownTimeout: 60000, // 60 seconds\n rollbackOnFailure: true,\n ...config,\n };\n\n this.logger = createLogger(config.logger);\n this.pluginLoader = new PluginLoader(this.logger);\n \n // Initialize context\n this.context = {\n registerService: (name, service) => {\n this.registerService(name, service);\n },\n registerServiceFactory: (name, factory, lifecycle, dependencies) => {\n this.registerServiceFactory(name, factory, lifecycle, dependencies);\n },\n getService: <T>(name: string) => {\n // 1. Try direct service map first (synchronous cache)\n const service = this.services.get(name);\n if (service) {\n return service as T;\n }\n\n // 2. Try to get from plugin loader cache (Sync access to factories)\n const loaderService = this.pluginLoader.getServiceInstance<T>(name);\n if (loaderService) {\n // Cache it locally for faster next access\n this.services.set(name, loaderService);\n return loaderService;\n }\n\n // 3. Try to get from plugin loader (support async factories)\n try {\n const service = this.pluginLoader.getService(name);\n if (service instanceof Promise) {\n // If we found it in the loader but not in the sync map, it's likely a factory-based service or still loading\n // We must silence any potential rejection from this promise since we are about to throw our own error\n // and abandon the promise. Without this, Node.js will crash with \"Unhandled Promise Rejection\".\n service.catch(() => {});\n throw new Error(`Service '${name}' is async - use await`);\n }\n return service as T;\n } catch (error: any) {\n if (error.message?.includes('is async')) {\n throw error;\n }\n \n // Re-throw critical factory errors instead of masking them as \"not found\"\n // If the error came from the factory execution (e.g. database connection failed), we must see it.\n // \"Service '${name}' not found\" comes from PluginLoader.getService fallback.\n const isNotFoundError = error.message === `Service '${name}' not found`;\n \n if (!isNotFoundError) {\n throw error;\n }\n\n throw new Error(`[Kernel] Service '${name}' not found`);\n }\n },\n replaceService: <T>(name: string, implementation: T): void => {\n const hasService = this.services.has(name) || this.pluginLoader.hasService(name);\n if (!hasService) {\n throw new Error(`[Kernel] Service '${name}' not found. Use registerService() to add new services.`);\n }\n this.services.set(name, implementation);\n this.pluginLoader.replaceService(name, implementation);\n this.logger.info(`Service '${name}' replaced`, { service: name });\n },\n hook: (name, handler) => {\n if (!this.hooks.has(name)) {\n this.hooks.set(name, []);\n }\n this.hooks.get(name)!.push(handler);\n },\n trigger: async (name, ...args) => {\n const handlers = this.hooks.get(name) || [];\n for (const handler of handlers) {\n await handler(...args);\n }\n },\n getServices: () => {\n return new Map(this.services);\n },\n getServiceScoped: <T>(name: string, scopeId: string): Promise<T> => {\n return this.pluginLoader.getService<T>(name, scopeId);\n },\n logger: this.logger,\n getKernel: () => this as any, // Type compatibility\n };\n\n this.pluginLoader.setContext(this.context);\n\n // Register shutdown handler\n if (this.config.gracefulShutdown) {\n this.registerShutdownSignals();\n }\n }\n\n /**\n * Register a plugin with enhanced validation\n */\n async use(plugin: Plugin): Promise<this> {\n if (this.state !== 'idle') {\n throw new Error('[Kernel] Cannot register plugins after bootstrap has started');\n }\n\n // Load plugin through enhanced loader\n const result = await this.pluginLoader.loadPlugin(plugin);\n \n if (!result.success || !result.plugin) {\n throw new Error(`Failed to load plugin: ${plugin.name} - ${result.error?.message}`);\n }\n\n const pluginMeta = result.plugin;\n this.plugins.set(pluginMeta.name, pluginMeta);\n \n this.logger.info(`Plugin registered: ${pluginMeta.name}@${pluginMeta.version}`, {\n plugin: pluginMeta.name,\n version: pluginMeta.version,\n });\n\n return this;\n }\n\n /**\n * Register a service instance directly\n */\n registerService<T>(name: string, service: T): this {\n if (this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' already registered`);\n }\n this.services.set(name, service);\n this.pluginLoader.registerService(name, service);\n this.logger.info(`Service '${name}' registered`, { service: name });\n return this;\n }\n\n /**\n * Register a service factory with lifecycle management\n */\n registerServiceFactory<T>(\n name: string,\n factory: ServiceFactory<T>,\n lifecycle: ServiceLifecycle = ServiceLifecycle.SINGLETON,\n dependencies?: string[]\n ): this {\n this.pluginLoader.registerServiceFactory({\n name,\n factory,\n lifecycle,\n dependencies,\n });\n return this;\n }\n\n /**\n * Pre-inject in-memory fallbacks for 'core' services that were not registered\n * by plugins during Phase 1. Called before Phase 2 so that all core services\n * (e.g. 'metadata', 'cache', 'queue') are resolvable via ctx.getService()\n * when plugin start() methods execute.\n */\n private preInjectCoreFallbacks() {\n if (this.config.skipSystemValidation) return;\n for (const [serviceName, criticality] of Object.entries(ServiceRequirementDef)) {\n if (criticality !== 'core') continue;\n const hasService = this.services.has(serviceName) || this.pluginLoader.hasService(serviceName);\n if (!hasService) {\n const factory = CORE_FALLBACK_FACTORIES[serviceName];\n if (factory) {\n const fallback = factory();\n this.registerService(serviceName, fallback);\n this.logger.debug(`[Kernel] Pre-injected in-memory fallback for '${serviceName}' before Phase 2`);\n }\n }\n }\n }\n\n /**\n * Validate Critical System Requirements\n */\n private validateSystemRequirements() {\n if (this.config.skipSystemValidation) {\n this.logger.debug('System requirement validation skipped');\n return;\n }\n\n this.logger.debug('Validating system service requirements...');\n const missingServices: string[] = [];\n const missingCoreServices: string[] = [];\n \n // Iterate through all defined requirements\n for (const [serviceName, criticality] of Object.entries(ServiceRequirementDef)) {\n const hasService = this.services.has(serviceName) || this.pluginLoader.hasService(serviceName);\n \n if (!hasService) {\n if (criticality === 'required') {\n this.logger.error(`CRITICAL: Required service missing: ${serviceName}`);\n missingServices.push(serviceName);\n } else if (criticality === 'core') {\n // Auto-inject in-memory fallback if available\n const factory = CORE_FALLBACK_FACTORIES[serviceName];\n if (factory) {\n const fallback = factory();\n this.registerService(serviceName, fallback);\n this.logger.warn(`Service '${serviceName}' not provided — using in-memory fallback`);\n } else {\n this.logger.warn(`CORE: Core service missing, functionality may be degraded: ${serviceName}`);\n missingCoreServices.push(serviceName);\n }\n } else {\n this.logger.info(`Info: Optional service not present: ${serviceName}`);\n }\n }\n }\n\n if (missingServices.length > 0) {\n const errorMsg = `System failed to start. Missing critical services: ${missingServices.join(', ')}`;\n this.logger.error(errorMsg);\n throw new Error(errorMsg);\n }\n\n if (missingCoreServices.length > 0) {\n this.logger.warn(`System started with degraded capabilities. Missing core services: ${missingCoreServices.join(', ')}`);\n }\n \n this.logger.info('System requirement check passed');\n }\n\n /**\n * Bootstrap the kernel with enhanced features\n */\n async bootstrap(): Promise<void> {\n if (this.state !== 'idle') {\n throw new Error('[Kernel] Kernel already bootstrapped');\n }\n\n this.state = 'initializing';\n this.logger.info('Bootstrap started');\n\n try {\n // Check for circular dependencies\n const cycles = this.pluginLoader.detectCircularDependencies();\n if (cycles.length > 0) {\n this.logger.warn('Circular service dependencies detected:', { cycles });\n }\n\n // Resolve plugin dependencies\n const orderedPlugins = this.resolveDependencies();\n\n // Phase 1: Init - Plugins register services\n this.logger.info('Phase 1: Init plugins');\n for (const plugin of orderedPlugins) {\n await this.initPluginWithTimeout(plugin);\n }\n\n // Pre-inject in-memory fallbacks for 'core' services that were not\n // registered by any plugin during Phase 1. This ensures services like\n // 'metadata', 'cache', 'queue', etc. are always available when plugins\n // call ctx.getService() during their start() methods.\n this.preInjectCoreFallbacks();\n\n // Phase 2: Start - Plugins execute business logic\n this.logger.info('Phase 2: Start plugins');\n this.state = 'running';\n \n for (const plugin of orderedPlugins) {\n const result = await this.startPluginWithTimeout(plugin);\n \n if (!result.success) {\n this.logger.error(`Plugin startup failed: ${plugin.name}`, result.error);\n const origMsg = result.error instanceof Error ? result.error.message : String(result.error);\n const origStack = result.error instanceof Error ? result.error.stack : '';\n console.error(`[Kernel] Plugin startup failed: ${plugin.name}`, origMsg, origStack);\n\n if (this.config.rollbackOnFailure) {\n this.logger.warn('Rolling back started plugins...');\n await this.rollbackStartedPlugins();\n // Propagate the original cause through the thrown error\n // so callers (e.g. cloud auth-proxy) can surface the\n // real failure instead of an opaque \"rollback complete\"\n // string. Without this, every kernel-boot failure looks\n // identical from the outside.\n const err: any = new Error(\n `Plugin ${plugin.name} failed to start - rollback complete: ${origMsg}`,\n );\n if (result.error instanceof Error) {\n err.cause = result.error;\n err.originalStack = origStack;\n }\n throw err;\n }\n }\n }\n\n // Phase 3: Trigger kernel:ready hook\n this.validateSystemRequirements(); // Final check before ready\n this.logger.debug('Triggering kernel:ready hook');\n await this.context.trigger('kernel:ready');\n\n // Phase 3.5: Trigger kernel:bootstrapped AFTER every kernel:ready\n // handler has settled — the \"all synchronous bootstrap has settled\"\n // anchor. Reconcile/backfill work that consumes data produced by a\n // later-starting plugin's kernel:ready handler belongs here, not in\n // kernel:ready (where handler order would race the data). NOTE: this\n // does NOT guarantee background app seed data has settled (an inline\n // seed that overruns OS_INLINE_SEED_BUDGET_MS finishes later) —\n // subscribe `app:seeded` for that. See\n // packages/spec/src/contracts/plugin-lifecycle-events.ts.\n this.logger.debug('Triggering kernel:bootstrapped hook');\n await this.context.trigger('kernel:bootstrapped');\n\n // Phase 4: Trigger kernel:listening hook AFTER all kernel:ready\n // handlers have completed. This is the cue for HTTP server\n // plugins to actually open the listening socket — by now every\n // other plugin has finished registering routes/middleware.\n // See `kernel:listening` docs in\n // packages/spec/src/contracts/plugin-lifecycle-events.ts\n // for the race-condition rationale.\n this.logger.debug('Triggering kernel:listening hook');\n await this.context.trigger('kernel:listening');\n\n this.logger.info('✅ Bootstrap complete');\n } catch (error) {\n this.state = 'stopped';\n throw error;\n }\n }\n\n /**\n * Graceful shutdown with timeout\n */\n async shutdown(): Promise<void> {\n if (this.state === 'stopped' || this.state === 'stopping') {\n this.logger.warn('Kernel already stopped or stopping');\n return;\n }\n\n if (this.state !== 'running') {\n throw new Error('[Kernel] Kernel not running');\n }\n\n this.state = 'stopping';\n this.logger.info('Graceful shutdown started');\n\n try {\n const shutdownPromise = this.performShutdown();\n const timeoutPromise = new Promise<void>((_, reject) => {\n const t = setTimeout(() => {\n reject(new Error('Shutdown timeout exceeded'));\n }, this.config.shutdownTimeout);\n // Don't let this timer keep the event loop alive\n if (t.unref) t.unref();\n });\n\n await Promise.race([shutdownPromise, timeoutPromise]);\n\n this.state = 'stopped';\n this.logger.info('✅ Graceful shutdown complete');\n } catch (error) {\n this.logger.error('Shutdown timed out — forcing exit', error as Error);\n this.state = 'stopped';\n // Flush logger then hard-exit; the process would otherwise hang\n await this.logger.destroy();\n process.exit(1);\n } finally {\n await this.logger.destroy();\n }\n }\n\n /**\n * Check health of a specific plugin\n */\n async checkPluginHealth(pluginName: string): Promise<any> {\n return await this.pluginLoader.checkPluginHealth(pluginName);\n }\n\n /**\n * Check health of all plugins\n */\n async checkAllPluginsHealth(): Promise<Map<string, any>> {\n const results = new Map();\n \n for (const pluginName of this.plugins.keys()) {\n const health = await this.checkPluginHealth(pluginName);\n results.set(pluginName, health);\n }\n \n return results;\n }\n\n /**\n * Get plugin startup metrics\n */\n getPluginMetrics(): Map<string, number> {\n return new Map(this.pluginStartTimes);\n }\n\n /**\n * Get a service (sync helper)\n */\n getService<T>(name: string): T {\n return this.context.getService<T>(name);\n }\n\n /**\n * Get a service asynchronously (supports factories)\n */\n async getServiceAsync<T>(name: string, scopeId?: string): Promise<T> {\n return await this.pluginLoader.getService<T>(name, scopeId);\n }\n\n /**\n * Clear all scoped service instances for a given scope (e.g., environmentId).\n * Releases driver connections and metadata caches for idle projects.\n */\n clearScope(scopeId: string): void {\n this.pluginLoader.clearScope(scopeId);\n }\n\n /**\n * Check if kernel is running\n */\n isRunning(): boolean {\n return this.state === 'running';\n }\n\n /**\n * Get kernel state\n */\n getState(): string {\n return this.state;\n }\n\n // Private methods\n\n private async initPluginWithTimeout(plugin: PluginMetadata): Promise<void> {\n const timeout = plugin.startupTimeout || this.config.defaultStartupTimeout!;\n \n this.logger.debug(`Init: ${plugin.name}`, { plugin: plugin.name });\n \n const initPromise = plugin.init(this.context);\n const timeoutPromise = new Promise<void>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Plugin ${plugin.name} init timeout after ${timeout}ms`));\n }, timeout);\n });\n\n await Promise.race([initPromise, timeoutPromise]);\n }\n\n private async startPluginWithTimeout(plugin: PluginMetadata): Promise<PluginStartupResult> {\n if (!plugin.start) {\n return { success: true, pluginName: plugin.name };\n }\n\n const timeout = plugin.startupTimeout || this.config.defaultStartupTimeout!;\n const startTime = Date.now();\n \n this.logger.debug(`Start: ${plugin.name}`, { plugin: plugin.name });\n \n try {\n const startPromise = plugin.start(this.context);\n const timeoutPromise = new Promise<void>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Plugin ${plugin.name} start timeout after ${timeout}ms`));\n }, timeout);\n });\n\n await Promise.race([startPromise, timeoutPromise]);\n \n const duration = Date.now() - startTime;\n this.startedPlugins.add(plugin.name);\n this.pluginStartTimes.set(plugin.name, duration);\n \n this.logger.debug(`Plugin started: ${plugin.name} (${duration}ms)`);\n \n return {\n success: true,\n pluginName: plugin.name,\n startTime: duration,\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n const isTimeout = (error as Error).message.includes('timeout');\n \n return {\n success: false,\n pluginName: plugin.name,\n error: error as Error,\n startTime: duration,\n timedOut: isTimeout,\n };\n }\n }\n\n private async rollbackStartedPlugins(): Promise<void> {\n const pluginsToRollback = Array.from(this.startedPlugins).reverse();\n \n for (const pluginName of pluginsToRollback) {\n const plugin = this.plugins.get(pluginName);\n if (plugin?.destroy) {\n try {\n this.logger.debug(`Rollback: ${pluginName}`);\n await plugin.destroy();\n } catch (error) {\n this.logger.error(`Rollback failed for ${pluginName}`, error as Error);\n }\n }\n }\n \n this.startedPlugins.clear();\n }\n\n private async performShutdown(): Promise<void> {\n // Trigger shutdown hook\n await this.context.trigger('kernel:shutdown');\n\n // Destroy plugins in reverse order\n const orderedPlugins = Array.from(this.plugins.values()).reverse();\n for (const plugin of orderedPlugins) {\n if (plugin.destroy) {\n this.logger.debug(`Destroy: ${plugin.name}`, { plugin: plugin.name });\n try {\n await plugin.destroy();\n } catch (error) {\n this.logger.error(`Error destroying plugin ${plugin.name}`, error as Error);\n }\n }\n }\n\n // Execute custom shutdown handlers\n for (const handler of this.shutdownHandlers) {\n try {\n await handler();\n } catch (error) {\n this.logger.error('Shutdown handler error', error as Error);\n }\n }\n }\n\n private resolveDependencies(): PluginMetadata[] {\n const resolved: PluginMetadata[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (pluginName: string) => {\n if (visited.has(pluginName)) return;\n \n if (visiting.has(pluginName)) {\n throw new Error(`[Kernel] Circular dependency detected: ${pluginName}`);\n }\n\n const plugin = this.plugins.get(pluginName);\n if (!plugin) {\n throw new Error(`[Kernel] Plugin '${pluginName}' not found`);\n }\n\n visiting.add(pluginName);\n\n // Visit dependencies first\n const deps = plugin.dependencies || [];\n for (const dep of deps) {\n if (!this.plugins.has(dep)) {\n throw new Error(`[Kernel] Dependency '${dep}' not found for plugin '${pluginName}'`);\n }\n visit(dep);\n }\n\n visiting.delete(pluginName);\n visited.add(pluginName);\n resolved.push(plugin);\n };\n\n // Visit all plugins\n for (const pluginName of this.plugins.keys()) {\n visit(pluginName);\n }\n\n return resolved;\n }\n\n private registerShutdownSignals(): void {\n const signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGQUIT'];\n let shutdownInProgress = false;\n \n const handleShutdown = async (signal: string) => {\n if (shutdownInProgress) {\n this.logger.warn(`Shutdown already in progress, ignoring ${signal}`);\n return;\n }\n \n shutdownInProgress = true;\n this.logger.info(`Received ${signal} - initiating graceful shutdown`);\n \n try {\n await this.shutdown();\n safeExit(0);\n } catch (error) {\n this.logger.error('Shutdown failed', error as Error);\n safeExit(1);\n }\n };\n \n if (isNode) {\n for (const signal of signals) {\n process.on(signal, () => handleShutdown(signal));\n }\n }\n }\n\n /**\n * Register a custom shutdown handler\n */\n onShutdown(handler: () => Promise<void>): void {\n this.shutdownHandlers.push(handler);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { z } from 'zod';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { PluginMetadata } from '../plugin-loader.js';\n\n/**\n * Plugin Configuration Validator\n * \n * Validates plugin configurations against Zod schemas to ensure:\n * 1. Type safety - all config values have correct types\n * 2. Business rules - values meet constraints (min/max, regex, etc.)\n * 3. Required fields - all mandatory configuration is provided\n * 4. Default values - missing optional fields get defaults\n * \n * Architecture:\n * - Uses Zod for runtime validation\n * - Provides detailed error messages with field paths\n * - Supports nested configuration objects\n * - Allows partial validation for incremental updates\n * \n * Usage:\n * ```typescript\n * const validator = new PluginConfigValidator(logger);\n * const validConfig = validator.validatePluginConfig(plugin, userConfig);\n * ```\n */\nexport class PluginConfigValidator {\n private logger: Logger;\n \n constructor(logger: Logger) {\n this.logger = logger;\n }\n \n /**\n * Validate plugin configuration against its Zod schema\n * \n * @param plugin - Plugin metadata with configSchema\n * @param config - User-provided configuration\n * @returns Validated and typed configuration\n * @throws Error with detailed validation errors\n */\n validatePluginConfig<T = any>(plugin: PluginMetadata, config: any): T {\n if (!plugin.configSchema) {\n this.logger.debug(`Plugin ${plugin.name} has no config schema - skipping validation`);\n return config as T;\n }\n \n try {\n // Use Zod to parse and validate\n const validatedConfig = plugin.configSchema.parse(config);\n \n this.logger.debug(`✅ Plugin config validated: ${plugin.name}`, {\n plugin: plugin.name,\n configKeys: Object.keys(config || {}).length,\n });\n \n return validatedConfig as T;\n } catch (error) {\n if (error instanceof z.ZodError) {\n const formattedErrors = this.formatZodErrors(error);\n const errorMessage = [\n `Plugin ${plugin.name} configuration validation failed:`,\n ...formattedErrors.map(e => ` - ${e.path}: ${e.message}`),\n ].join('\\n');\n \n this.logger.error(errorMessage, undefined, {\n plugin: plugin.name,\n errors: formattedErrors,\n });\n \n throw new Error(errorMessage);\n }\n \n // Re-throw other errors\n throw error;\n }\n }\n \n /**\n * Validate partial configuration (for incremental updates)\n * \n * @param plugin - Plugin metadata\n * @param partialConfig - Partial configuration to validate\n * @returns Validated partial configuration\n */\n validatePartialConfig<T = any>(plugin: PluginMetadata, partialConfig: any): Partial<T> {\n if (!plugin.configSchema) {\n return partialConfig as Partial<T>;\n }\n \n try {\n // Use Zod's partial() method for partial validation\n // Cast to ZodObject to access partial() method\n const partialSchema = (plugin.configSchema as any).partial();\n const validatedConfig = partialSchema.parse(partialConfig);\n \n this.logger.debug(`✅ Partial config validated: ${plugin.name}`);\n return validatedConfig as Partial<T>;\n } catch (error) {\n if (error instanceof z.ZodError) {\n const formattedErrors = this.formatZodErrors(error);\n const errorMessage = [\n `Plugin ${plugin.name} partial configuration validation failed:`,\n ...formattedErrors.map(e => ` - ${e.path}: ${e.message}`),\n ].join('\\n');\n \n throw new Error(errorMessage);\n }\n \n throw error;\n }\n }\n \n /**\n * Get default configuration from schema\n * \n * @param plugin - Plugin metadata\n * @returns Default configuration object\n */\n getDefaultConfig<T = any>(plugin: PluginMetadata): T | undefined {\n if (!plugin.configSchema) {\n return undefined;\n }\n \n try {\n // Parse empty object to get defaults\n const defaults = plugin.configSchema.parse({});\n this.logger.debug(`Default config extracted: ${plugin.name}`);\n return defaults as T;\n } catch (error) {\n // Schema may require some fields - return undefined\n this.logger.debug(`No default config available: ${plugin.name}`);\n return undefined;\n }\n }\n \n /**\n * Check if configuration is valid without throwing\n * \n * @param plugin - Plugin metadata\n * @param config - Configuration to check\n * @returns True if valid, false otherwise\n */\n isConfigValid(plugin: PluginMetadata, config: any): boolean {\n if (!plugin.configSchema) {\n return true;\n }\n \n const result = plugin.configSchema.safeParse(config);\n return result.success;\n }\n \n /**\n * Get configuration errors without throwing\n * \n * @param plugin - Plugin metadata\n * @param config - Configuration to check\n * @returns Array of validation errors, or empty array if valid\n */\n getConfigErrors(plugin: PluginMetadata, config: any): Array<{path: string; message: string}> {\n if (!plugin.configSchema) {\n return [];\n }\n \n const result = plugin.configSchema.safeParse(config);\n \n if (result.success) {\n return [];\n }\n \n return this.formatZodErrors(result.error);\n }\n \n // Private methods\n \n private formatZodErrors(error: z.ZodError<any>): Array<{path: string; message: string}> {\n return error.issues.map((e: z.ZodIssue) => ({\n path: e.path.join('.') || 'root',\n message: e.message,\n }));\n }\n}\n\n/**\n * Create a plugin config validator\n * \n * @param logger - Logger instance\n * @returns Plugin config validator\n */\nexport function createPluginConfigValidator(logger: Logger): PluginConfigValidator {\n return new PluginConfigValidator(logger);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Plugin artifact signing & verification (ADR-0025 §3.4–§3.7, framework F3).\n *\n * This is the CANONICAL Ed25519 detached-signature contract shared by the\n * whole plugin distribution pipeline. It is intentionally byte-for-byte\n * compatible with the cloud control plane's `package-signing.ts` so the\n * two never drift:\n *\n * - signature string format: `ed25519:<keyId>:<base64url(signature)>`\n * - publisher signature: Ed25519 over the raw `.osplugin` artifact bytes,\n * produced by `os plugin sign`, verified by cloud at publish time and by\n * the runtime when it materializes the artifact.\n * - platform counter-signature: Ed25519 over {@link counterSignPayload}\n * (the version identity), produced by cloud at approval, verified by the\n * runtime at load time as the marketplace's \"reviewed + approved\" attest.\n *\n * Algorithm: Ed25519 via node:crypto (`sign(null, …)` / `verify(null, …)`):\n * short, deterministic, no padding ambiguity. The `keyId` is an opaque\n * rotation handle used to resolve the verifying public key.\n *\n * The two trust chains the runtime checks before loading a third-party\n * plugin are combined in {@link verifyPluginArtifact}.\n */\n\nimport {\n sign as cryptoSign,\n verify as cryptoVerify,\n createPublicKey,\n createPrivateKey,\n generateKeyPairSync,\n type KeyObject,\n} from 'node:crypto';\n\nexport const SIGNATURE_ALG = 'ed25519';\nconst SIG_PREFIX = 'ed25519:';\n\nexport type KeyInput = string | KeyObject;\n\nfunction toPrivateKey(key: KeyInput): KeyObject {\n return typeof key === 'string' ? createPrivateKey(key) : key;\n}\nfunction toPublicKey(key: KeyInput): KeyObject {\n return typeof key === 'string' ? createPublicKey(key) : key;\n}\nfunction toBytes(payload: string | Uint8Array): Uint8Array {\n return typeof payload === 'string' ? new TextEncoder().encode(payload) : payload;\n}\n\n/** Generate an Ed25519 keypair as PEM strings (publisher bootstrap / tests). */\nexport function generateEd25519KeyPair(): { publicKeyPem: string; privateKeyPem: string } {\n const { publicKey, privateKey } = generateKeyPairSync('ed25519');\n return {\n publicKeyPem: publicKey.export({ type: 'spki', format: 'pem' }).toString(),\n privateKeyPem: privateKey.export({ type: 'pkcs8', format: 'pem' }).toString(),\n };\n}\n\n/**\n * Sign `payload` with an Ed25519 private key, returning the formatted\n * signature string `ed25519:<keyId>:<base64url(sig)>`.\n */\nexport function signPayload(\n payload: string | Uint8Array,\n privateKey: KeyInput,\n keyId = 'default',\n): string {\n if (keyId.includes(':')) throw new Error('keyId must not contain \":\"');\n const sig = cryptoSign(null, toBytes(payload), toPrivateKey(privateKey));\n return `${SIG_PREFIX}${keyId}:${sig.toString('base64url')}`;\n}\n\nexport interface ParsedSignature {\n alg: 'ed25519';\n keyId: string;\n signature: Uint8Array;\n}\n\n/** Parse an `ed25519:<keyId>:<base64url>` signature string. Returns null if malformed. */\nexport function parseSignature(s: string | undefined | null): ParsedSignature | null {\n if (typeof s !== 'string' || !s.startsWith(SIG_PREFIX)) return null;\n const rest = s.slice(SIG_PREFIX.length);\n const idx = rest.indexOf(':');\n if (idx <= 0) return null;\n const keyId = rest.slice(0, idx);\n const b64 = rest.slice(idx + 1);\n if (!keyId || !b64) return null;\n try {\n return { alg: 'ed25519', keyId, signature: new Uint8Array(Buffer.from(b64, 'base64url')) };\n } catch {\n return null;\n }\n}\n\n/** Verify a formatted signature string over `payload` with the given public key. */\nexport function verifyPayload(\n payload: string | Uint8Array,\n signature: string,\n publicKey: KeyInput,\n): boolean {\n const parsed = parseSignature(signature);\n if (!parsed) return false;\n try {\n return cryptoVerify(null, toBytes(payload), toPublicKey(publicKey), parsed.signature);\n } catch {\n return false;\n }\n}\n\n/**\n * Canonical payload the platform counter-signs at approval. Binds the\n * attestation to the version identity + artifact location + the publisher\n * signature (which itself binds the artifact bytes). MUST match the cloud\n * control plane's `counterSignPayload` exactly.\n */\nexport function counterSignPayload(version: {\n package_id: string;\n version: string;\n blob_key?: string | null;\n signature?: string | null;\n}): string {\n return [\n version.package_id,\n version.version,\n version.blob_key ?? '',\n version.signature ?? '',\n ].join('\\n');\n}\n\nexport interface PublisherVerifyResult {\n /** Whether loading may proceed on signature grounds. */\n ok: boolean;\n /** True when a signature was present AND cryptographically verified. */\n verified: boolean;\n reason?: string;\n}\n\n/**\n * Verify a publisher signature over the raw artifact bytes. `getPublicKey`\n * resolves the verifying key from the signature's embedded keyId.\n *\n * Mirrors cloud's publish-time policy:\n * - no signature → ok, verified=false (caller decides via trust tier).\n * - malformed / fails verification → NOT ok.\n * - unknown keyId → NOT ok (never silently trust).\n */\nexport async function verifyPublisherSignature(\n args: { artifact: Uint8Array; signature?: string | null },\n getPublicKey?: (keyId: string) => Promise<KeyInput | null> | KeyInput | null,\n): Promise<PublisherVerifyResult> {\n const sig = args.signature;\n if (!sig) return { ok: true, verified: false, reason: 'no signature supplied' };\n\n const parsed = parseSignature(sig);\n if (!parsed) return { ok: false, verified: false, reason: 'signature is malformed' };\n\n if (!getPublicKey) {\n return { ok: true, verified: false, reason: 'no publisher key registry configured' };\n }\n\n const pub = await getPublicKey(parsed.keyId);\n if (!pub) return { ok: false, verified: false, reason: `unknown publisher key '${parsed.keyId}'` };\n\n return verifyPayload(args.artifact, sig, pub)\n ? { ok: true, verified: true }\n : { ok: false, verified: false, reason: 'publisher signature does not match artifact' };\n}\n\n/** Verify a platform counter-signature against the version identity + platform public key. */\nexport function verifyPlatformSignature(\n version: {\n package_id: string;\n version: string;\n blob_key?: string | null;\n signature?: string | null;\n platform_signature?: string | null;\n },\n platformPublicKey: KeyInput,\n): boolean {\n if (!version.platform_signature) return false;\n return verifyPayload(counterSignPayload(version), version.platform_signature, platformPublicKey);\n}\n\nexport interface PluginArtifactVerifyResult {\n /** Overall verdict: both required chains satisfied under the given policy. */\n ok: boolean;\n publisherVerified: boolean;\n platformVerified: boolean;\n reason?: string;\n}\n\n/**\n * Verify both trust chains for a downloaded plugin artifact at load time\n * (ADR-0025 §3.7). The platform counter-signature is the authoritative\n * marketplace attestation; the publisher signature additionally binds the\n * exact bytes. `requirePlatform` (default true) rejects artifacts that lack\n * a valid platform counter-sign — set false for first-party / local builds.\n */\nexport async function verifyPluginArtifact(\n input: {\n artifact: Uint8Array;\n version: {\n package_id: string;\n version: string;\n blob_key?: string | null;\n signature?: string | null;\n platform_signature?: string | null;\n };\n },\n keys: {\n platformPublicKey?: KeyInput;\n getPublisherPublicKey?: (keyId: string) => Promise<KeyInput | null> | KeyInput | null;\n requirePlatform?: boolean;\n },\n): Promise<PluginArtifactVerifyResult> {\n const requirePlatform = keys.requirePlatform ?? true;\n\n const publisher = await verifyPublisherSignature(\n { artifact: input.artifact, signature: input.version.signature },\n keys.getPublisherPublicKey,\n );\n if (!publisher.ok) {\n return { ok: false, publisherVerified: false, platformVerified: false, reason: publisher.reason };\n }\n\n let platformVerified = false;\n if (keys.platformPublicKey) {\n platformVerified = verifyPlatformSignature(input.version, keys.platformPublicKey);\n }\n if (requirePlatform && !platformVerified) {\n return {\n ok: false,\n publisherVerified: publisher.verified,\n platformVerified,\n reason: keys.platformPublicKey\n ? 'platform counter-signature missing or invalid'\n : 'no platform public key configured',\n };\n }\n\n return { ok: true, publisherVerified: publisher.verified, platformVerified };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext } from './types.js';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport { z } from 'zod';\nimport { PluginConfigValidator } from './security/plugin-config-validator.js';\nimport { parseSignature } from './security/plugin-artifact-signature.js';\n\n/**\n * Service Lifecycle Types\n * Defines how services are instantiated and managed\n */\nexport enum ServiceLifecycle {\n /** Single instance shared across all requests */\n SINGLETON = 'singleton',\n /** New instance created for each request */\n TRANSIENT = 'transient',\n /** New instance per scope (e.g., per HTTP request) */\n SCOPED = 'scoped',\n}\n\n/**\n * Service Factory\n * Function that creates a service instance\n */\nexport type ServiceFactory<T = any> = (ctx: PluginContext, scopeId?: string) => T | Promise<T>;\n\n/**\n * Service Registration Options\n */\nexport interface ServiceRegistration {\n name: string;\n factory: ServiceFactory;\n lifecycle: ServiceLifecycle;\n dependencies?: string[];\n}\n\n/**\n * Plugin Metadata with Enhanced Features\n */\nexport interface PluginMetadata extends Plugin {\n /** Semantic version (e.g., \"1.0.0\") */\n version: string;\n \n /** Configuration schema for validation */\n configSchema?: z.ZodSchema;\n \n /** Plugin signature for security verification */\n signature?: string;\n \n /** Plugin health check function */\n healthCheck?(): Promise<PluginHealthStatus>;\n \n /** Startup timeout in milliseconds (default: 30000) */\n startupTimeout?: number;\n \n /** Whether plugin supports hot reload */\n hotReloadable?: boolean;\n}\n\n/**\n * Plugin Health Status\n */\nexport interface PluginHealthStatus {\n healthy: boolean;\n message?: string;\n details?: Record<string, any>;\n lastCheck?: Date;\n}\n\n/**\n * Plugin Load Result\n */\nexport interface PluginLoadResult {\n success: boolean;\n plugin?: PluginMetadata;\n error?: Error;\n loadTime?: number;\n}\n\n/**\n * Plugin Startup Result\n */\nexport interface PluginStartupResult {\n success: boolean;\n pluginName: string;\n startTime?: number;\n error?: Error;\n timedOut?: boolean;\n}\n\n/**\n * Version Compatibility Result\n */\nexport interface VersionCompatibility {\n compatible: boolean;\n pluginVersion: string;\n requiredVersion?: string;\n message?: string;\n}\n\n/**\n * Enhanced Plugin Loader\n * Provides advanced plugin loading capabilities with validation, security, and lifecycle management\n */\nexport class PluginLoader {\n private logger: Logger;\n private context?: PluginContext;\n private configValidator: PluginConfigValidator;\n private loadedPlugins: Map<string, PluginMetadata> = new Map();\n private serviceFactories: Map<string, ServiceRegistration> = new Map();\n private serviceInstances: Map<string, any> = new Map();\n private scopedServices: Map<string, Map<string, any>> = new Map();\n private creating: Set<string> = new Set();\n\n constructor(logger: Logger) {\n this.logger = logger;\n this.configValidator = new PluginConfigValidator(logger);\n }\n\n /**\n * Set the plugin context for service factories\n */\n setContext(context: PluginContext): void {\n this.context = context;\n }\n\n /**\n * Get a synchronous service instance if it exists (Sync Helper)\n */\n getServiceInstance<T>(name: string): T | undefined {\n return this.serviceInstances.get(name) as T;\n }\n\n /**\n * Load a plugin asynchronously with validation\n */\n async loadPlugin(plugin: Plugin): Promise<PluginLoadResult> {\n const startTime = Date.now();\n \n try {\n this.logger.info(`Loading plugin: ${plugin.name}`);\n \n // Convert to PluginMetadata\n const metadata = this.toPluginMetadata(plugin);\n \n // Validate plugin structure\n this.validatePluginStructure(metadata);\n \n // Check version compatibility\n const versionCheck = this.checkVersionCompatibility(metadata);\n if (!versionCheck.compatible) {\n throw new Error(`Version incompatible: ${versionCheck.message}`);\n }\n \n // Validate configuration if schema is provided\n if (metadata.configSchema) {\n this.validatePluginConfig(metadata);\n }\n \n // Verify signature if provided\n if (metadata.signature) {\n await this.verifyPluginSignature(metadata);\n }\n \n // Store loaded plugin\n this.loadedPlugins.set(metadata.name, metadata);\n \n const loadTime = Date.now() - startTime;\n this.logger.info(`Plugin loaded: ${plugin.name} (${loadTime}ms)`);\n \n return {\n success: true,\n plugin: metadata,\n loadTime,\n };\n } catch (error) {\n this.logger.error(`Failed to load plugin: ${plugin.name}`, error as Error);\n return {\n success: false,\n error: error as Error,\n loadTime: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Register a service with factory function\n */\n registerServiceFactory(registration: ServiceRegistration): void {\n if (this.serviceFactories.has(registration.name)) {\n throw new Error(`Service factory '${registration.name}' already registered`);\n }\n \n this.serviceFactories.set(registration.name, registration);\n this.logger.debug(`Service factory registered: ${registration.name} (${registration.lifecycle})`);\n }\n\n /**\n * Get or create a service instance based on lifecycle type\n */\n async getService<T>(name: string, scopeId?: string): Promise<T> {\n const registration = this.serviceFactories.get(name);\n \n if (!registration) {\n // Fall back to static service instances\n const instance = this.serviceInstances.get(name);\n if (!instance) {\n throw new Error(`Service '${name}' not found`);\n }\n return instance as T;\n }\n \n switch (registration.lifecycle) {\n case ServiceLifecycle.SINGLETON:\n return await this.getSingletonService<T>(registration);\n \n case ServiceLifecycle.TRANSIENT:\n return await this.createTransientService<T>(registration);\n \n case ServiceLifecycle.SCOPED:\n if (!scopeId) {\n throw new Error(`Scope ID required for scoped service '${name}'`);\n }\n return await this.getScopedService<T>(registration, scopeId);\n \n default:\n throw new Error(`Unknown service lifecycle: ${registration.lifecycle}`);\n }\n }\n\n /**\n * Register a static service instance (legacy support)\n */\n registerService(name: string, service: any): void {\n if (this.serviceInstances.has(name)) {\n throw new Error(`Service '${name}' already registered`);\n }\n this.serviceInstances.set(name, service);\n }\n\n /**\n * Replace an existing service instance.\n * Used by optimization plugins to swap kernel internals.\n * @throws Error if service does not exist\n */\n replaceService(name: string, service: any): void {\n if (!this.hasService(name)) {\n throw new Error(`Service '${name}' not found`);\n }\n this.serviceInstances.set(name, service);\n }\n\n /**\n * Check if a service is registered (either as instance or factory)\n */\n hasService(name: string): boolean {\n return this.serviceInstances.has(name) || this.serviceFactories.has(name);\n }\n\n /**\n * Detect circular dependencies in service factories\n * Note: This only detects cycles in service dependencies, not plugin dependencies.\n * Plugin dependency cycles are detected in the kernel's resolveDependencies method.\n */\n detectCircularDependencies(): string[] {\n const cycles: string[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n \n const visit = (serviceName: string, path: string[] = []) => {\n if (visiting.has(serviceName)) {\n const cycle = [...path, serviceName].join(' -> ');\n cycles.push(cycle);\n return;\n }\n \n if (visited.has(serviceName)) {\n return;\n }\n \n visiting.add(serviceName);\n \n const registration = this.serviceFactories.get(serviceName);\n if (registration?.dependencies) {\n for (const dep of registration.dependencies) {\n visit(dep, [...path, serviceName]);\n }\n }\n \n visiting.delete(serviceName);\n visited.add(serviceName);\n };\n \n for (const serviceName of this.serviceFactories.keys()) {\n visit(serviceName);\n }\n \n return cycles;\n }\n\n /**\n * Check plugin health\n */\n async checkPluginHealth(pluginName: string): Promise<PluginHealthStatus> {\n const plugin = this.loadedPlugins.get(pluginName);\n \n if (!plugin) {\n return {\n healthy: false,\n message: 'Plugin not found',\n lastCheck: new Date(),\n };\n }\n \n if (!plugin.healthCheck) {\n return {\n healthy: true,\n message: 'No health check defined',\n lastCheck: new Date(),\n };\n }\n \n try {\n const status = await plugin.healthCheck();\n return {\n ...status,\n lastCheck: new Date(),\n };\n } catch (error) {\n return {\n healthy: false,\n message: `Health check failed: ${(error as Error).message}`,\n lastCheck: new Date(),\n };\n }\n }\n\n /**\n * Clear scoped services for a scope\n */\n clearScope(scopeId: string): void {\n this.scopedServices.delete(scopeId);\n this.logger.debug(`Cleared scope: ${scopeId}`);\n }\n\n /**\n * Get all loaded plugins\n */\n getLoadedPlugins(): Map<string, PluginMetadata> {\n return new Map(this.loadedPlugins);\n }\n\n // Private helper methods\n\n private toPluginMetadata(plugin: Plugin): PluginMetadata {\n // Fix: Do not use object spread {...plugin} as it destroys the prototype chain for Class-based plugins.\n // Instead, cast the original object and inject default values if missing.\n const metadata = plugin as PluginMetadata;\n \n if (!metadata.version) {\n metadata.version = '0.0.0';\n }\n \n return metadata;\n }\n\n private validatePluginStructure(plugin: PluginMetadata): void {\n if (!plugin.name) {\n throw new Error('Plugin name is required');\n }\n \n if (!plugin.init) {\n throw new Error('Plugin init function is required');\n }\n \n if (!this.isValidSemanticVersion(plugin.version)) {\n throw new Error(`Invalid semantic version: ${plugin.version}`);\n }\n }\n\n private checkVersionCompatibility(plugin: PluginMetadata): VersionCompatibility {\n // Basic semantic version compatibility check\n // In a real implementation, this would check against kernel version\n const version = plugin.version;\n \n if (!this.isValidSemanticVersion(version)) {\n return {\n compatible: false,\n pluginVersion: version,\n message: 'Invalid semantic version format',\n };\n }\n \n return {\n compatible: true,\n pluginVersion: version,\n };\n }\n\n private isValidSemanticVersion(version: string): boolean {\n const semverRegex = /^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$/;\n return semverRegex.test(version);\n }\n\n private validatePluginConfig(plugin: PluginMetadata, config?: any): void {\n if (!plugin.configSchema) {\n return;\n }\n\n if (config === undefined) {\n // In loadPlugin, we often don't have the config yet.\n // We skip validation here or valid against empty object if schema allows?\n // For now, let's keep the logging behavior but note it's delegating\n this.logger.debug(`Plugin ${plugin.name} has configuration schema (config validation postponed)`);\n return;\n }\n\n this.configValidator.validatePluginConfig(plugin, config);\n }\n\n private async verifyPluginSignature(plugin: PluginMetadata): Promise<void> {\n if (!plugin.signature) {\n return;\n }\n \n // Cryptographic verification of a third-party plugin's PUBLISHER and\n // PLATFORM signatures is performed against the `.osplugin` artifact\n // bytes + version identity at materialize/install time, by\n // `verifyPluginArtifact` (security/plugin-artifact-signature.ts —\n // ADR-0025 §3.7). By the time a plugin reaches loadPlugin() it is an\n // in-memory module with no artifact bytes, so we cannot re-run the\n // artifact chains here; we only validate that any signature carried\n // on the metadata is well-formed (`ed25519:<keyId>:<base64url>`) and\n // surface its keyId, failing fast on a malformed value.\n const parsed = parseSignature(plugin.signature);\n if (!parsed) {\n throw new Error(\n `Plugin ${plugin.name} carries a malformed signature (expected ed25519:<keyId>:<base64url>)`,\n );\n }\n this.logger.debug(\n `Plugin ${plugin.name} signature well-formed (alg=${parsed.alg}, keyId=${parsed.keyId}); ` +\n `artifact verification occurs at materialize time`,\n );\n }\n\n private async getSingletonService<T>(registration: ServiceRegistration): Promise<T> {\n let instance = this.serviceInstances.get(registration.name);\n \n if (!instance) {\n // Create instance (would need context)\n instance = await this.createServiceInstance(registration);\n this.serviceInstances.set(registration.name, instance);\n this.logger.debug(`Singleton service created: ${registration.name}`);\n }\n \n return instance as T;\n }\n\n private async createTransientService<T>(registration: ServiceRegistration): Promise<T> {\n const instance = await this.createServiceInstance(registration);\n this.logger.debug(`Transient service created: ${registration.name}`);\n return instance as T;\n }\n\n private async getScopedService<T>(registration: ServiceRegistration, scopeId: string): Promise<T> {\n if (!this.scopedServices.has(scopeId)) {\n this.scopedServices.set(scopeId, new Map());\n }\n\n const scope = this.scopedServices.get(scopeId)!;\n let instance = scope.get(registration.name);\n\n if (!instance) {\n instance = await this.createServiceInstance(registration, scopeId);\n scope.set(registration.name, instance);\n this.logger.debug(`Scoped service created: ${registration.name} (scope: ${scopeId})`);\n }\n\n return instance as T;\n }\n\n private async createServiceInstance(registration: ServiceRegistration, scopeId?: string): Promise<any> {\n if (!this.context) {\n throw new Error(`[PluginLoader] Context not set - cannot create service '${registration.name}'`);\n }\n\n if (this.creating.has(registration.name)) {\n throw new Error(`Circular dependency detected: ${Array.from(this.creating).join(' -> ')} -> ${registration.name}`);\n }\n\n this.creating.add(registration.name);\n try {\n return await registration.factory(this.context, scopeId);\n } finally {\n this.creating.delete(registration.name);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Environment utilities for universal (Node/Browser) compatibility.\n */\n\n// Check if running in a Node.js environment\nexport const isNode = typeof process !== 'undefined' && \n process.versions != null && \n process.versions.node != null;\n\n/**\n * Safely access environment variables\n */\nexport function getEnv(key: string, defaultValue?: string): string | undefined {\n // Node.js\n if (typeof process !== 'undefined' && process.env) {\n return process.env[key] || defaultValue;\n }\n \n // Browser (Vite/Webpack replacement usually handles process.env, \n // but if not, we check safe global access)\n try {\n // @ts-ignore\n if (typeof globalThis !== 'undefined' && globalThis.process?.env) {\n // @ts-ignore\n return globalThis.process.env[key] || defaultValue;\n }\n } catch (e) {\n // Ignore access errors\n }\n \n return defaultValue;\n}\n\n/**\n * Safely exit the process if in Node.js\n */\nexport function safeExit(code: number = 0): void {\n if (isNode) {\n process.exit(code);\n }\n}\n\n/**\n * Safely get memory usage\n */\nexport function getMemoryUsage(): { heapUsed: number; heapTotal: number } {\n if (isNode) {\n return process.memoryUsage();\n }\n return { heapUsed: 0, heapTotal: 0 };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory Map-backed cache fallback.\n *\n * Implements the ICacheService contract with basic get/set/delete/has/clear\n * and TTL expiry. Used by ObjectKernel as an automatic fallback when no\n * real cache plugin (e.g. Redis) is registered.\n */\nexport function createMemoryCache() {\n const store = new Map<string, { value: unknown; expires?: number }>();\n let hits = 0;\n let misses = 0;\n return {\n _fallback: true, _serviceName: 'cache',\n async get<T = unknown>(key: string): Promise<T | undefined> {\n const entry = store.get(key);\n if (!entry || (entry.expires && Date.now() > entry.expires)) {\n store.delete(key);\n misses++;\n return undefined;\n }\n hits++;\n return entry.value as T;\n },\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n store.set(key, { value, expires: ttl ? Date.now() + ttl * 1000 : undefined });\n },\n async delete(key: string): Promise<boolean> { return store.delete(key); },\n async has(key: string): Promise<boolean> { return store.has(key); },\n async clear(): Promise<void> { store.clear(); },\n async stats() { return { hits, misses, keyCount: store.size }; },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory publish/subscribe queue fallback.\n *\n * Implements the IQueueService contract with synchronous in-process delivery.\n * Used by ObjectKernel as an automatic fallback when no real queue plugin\n * (e.g. BullMQ / RabbitMQ) is registered.\n */\nexport function createMemoryQueue() {\n const handlers = new Map<string, Function[]>();\n let msgId = 0;\n return {\n _fallback: true, _serviceName: 'queue',\n async publish<T = unknown>(queue: string, data: T): Promise<string> {\n const id = `fallback-msg-${++msgId}`;\n const fns = handlers.get(queue) ?? [];\n for (const fn of fns) fn({ id, data, attempts: 1, timestamp: Date.now() });\n return id;\n },\n async subscribe(queue: string, handler: (msg: any) => Promise<void>): Promise<void> {\n handlers.set(queue, [...(handlers.get(queue) ?? []), handler]);\n },\n async unsubscribe(queue: string): Promise<void> { handlers.delete(queue); },\n async getQueueSize(): Promise<number> { return 0; },\n async purge(queue: string): Promise<void> { handlers.delete(queue); },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory job scheduler fallback.\n *\n * Implements the IJobService contract with basic schedule/cancel/trigger\n * operations. Used by ObjectKernel as an automatic fallback when no real\n * job plugin (e.g. Agenda / BullMQ) is registered.\n */\nexport function createMemoryJob() {\n const jobs = new Map<string, any>();\n return {\n _fallback: true, _serviceName: 'job',\n async schedule(name: string, schedule: any, handler: any): Promise<void> { jobs.set(name, { schedule, handler }); },\n async cancel(name: string): Promise<void> { jobs.delete(name); },\n async trigger(name: string, data?: unknown): Promise<void> {\n const job = jobs.get(name);\n if (job?.handler) await job.handler({ jobId: name, data });\n },\n async getExecutions(): Promise<any[]> { return []; },\n async listJobs(): Promise<string[]> { return [...jobs.keys()]; },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Recursively merge `source` into `target`. Nested plain objects are merged\n * rather than replaced, so multiple plugins can each contribute their own\n * slice of a locale's translations (e.g. `{objects: {account: ...}}` and\n * `{objects: {task: ...}}`) without clobbering one another.\n * Exported for the authored-translation sync (#2591).\n */\nexport function deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const tVal = target[key];\n const sVal = source[key];\n if (\n tVal && sVal\n && typeof tVal === 'object' && !Array.isArray(tVal)\n && typeof sVal === 'object' && !Array.isArray(sVal)\n ) {\n result[key] = deepMerge(\n tVal as Record<string, unknown>,\n sVal as Record<string, unknown>,\n );\n } else {\n result[key] = sVal;\n }\n }\n return result;\n}\n\n/**\n * Resolve a locale code against available locales with fallback.\n *\n * Fallback chain:\n * 1. Exact match (e.g. `zh-CN` → `zh-CN`)\n * 2. Case-insensitive match (e.g. `zh-cn` → `zh-CN`)\n * 3. Base language match (e.g. `zh-CN` → `zh`)\n * 4. Variant expansion (e.g. `zh` → `zh-CN`)\n *\n * Returns the matched locale code, or `undefined` when no match is found.\n */\nexport function resolveLocale(requestedLocale: string, availableLocales: string[]): string | undefined {\n if (availableLocales.length === 0) return undefined;\n\n // 1. Exact match\n if (availableLocales.includes(requestedLocale)) return requestedLocale;\n\n // 2. Case-insensitive match\n const lower = requestedLocale.toLowerCase();\n const caseMatch = availableLocales.find(l => l.toLowerCase() === lower);\n if (caseMatch) return caseMatch;\n\n // 3. Base language match (zh-CN → zh)\n const baseLang = requestedLocale.split('-')[0].toLowerCase();\n const baseMatch = availableLocales.find(l => l.toLowerCase() === baseLang);\n if (baseMatch) return baseMatch;\n\n // 4. Variant expansion (zh → zh-CN, zh-TW, etc. — first match wins)\n const variantMatch = availableLocales.find(l => l.split('-')[0].toLowerCase() === baseLang);\n if (variantMatch) return variantMatch;\n\n return undefined;\n}\n\n/**\n * In-memory i18n service fallback.\n *\n * Implements the II18nService contract with basic translate/load/getLocales\n * operations. Used by ObjectKernel as an automatic fallback when no real\n * i18n plugin (e.g. I18nServicePlugin) is registered.\n *\n * Supports runtime translation loading, locale management, and\n * locale code fallback (e.g. `zh` → `zh-CN`).\n * Does not load files from disk — operates purely in-memory.\n */\nexport function createMemoryI18n() {\n const translations = new Map<string, Record<string, unknown>>();\n // Runtime-AUTHORED overlay (#2591): translations published as `translation`\n // metadata. Kept separate from the static map so a re-sync can REPLACE the\n // whole authored layer (clear-then-reload — deleted keys must not linger),\n // while authored values win over static bundle values on read.\n const authored = new Map<string, Record<string, unknown>>();\n let defaultLocale = 'en';\n\n /**\n * Resolve a dot-notation key from a nested object.\n */\n function resolveKey(data: Record<string, unknown>, key: string): string | undefined {\n const parts = key.split('.');\n let current: unknown = data;\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return typeof current === 'string' ? current : undefined;\n }\n\n /** Merged (static ⊕ authored) view of a single, exact locale key. */\n function mergedLocale(locale: string): Record<string, unknown> | undefined {\n const stat = translations.get(locale);\n const auth = authored.get(locale);\n if (stat && auth) return deepMerge(stat, auth);\n return auth ?? stat;\n }\n\n /**\n * Find translation data for a locale, with fallback resolution.\n */\n function resolveTranslations(locale: string): Record<string, unknown> | undefined {\n // Exact match\n const exact = mergedLocale(locale);\n if (exact) return exact;\n\n // Locale fallback (zh → zh-CN, en-us → en-US, etc.)\n const allLocales = [...new Set([...translations.keys(), ...authored.keys()])];\n const resolved = resolveLocale(locale, allLocales);\n if (resolved) return mergedLocale(resolved);\n\n return undefined;\n }\n\n return {\n _fallback: true, _serviceName: 'i18n',\n\n t(key: string, locale: string, params?: Record<string, unknown>): string {\n const data = resolveTranslations(locale) ?? mergedLocale(defaultLocale);\n const value = data ? resolveKey(data, key) : undefined;\n if (value == null) return key;\n if (!params) return value;\n // Interpolation format: {{paramName}} — matches FileI18nAdapter convention\n return value.replace(/\\{\\{(\\w+)\\}\\}/g, (_, name) => String(params[name] ?? `{{${name}}}`));\n },\n\n getTranslations(locale: string): Record<string, unknown> {\n return resolveTranslations(locale) ?? {};\n },\n\n loadTranslations(locale: string, data: Record<string, unknown>): void {\n const existing = translations.get(locale);\n if (existing) {\n translations.set(locale, deepMerge(existing, data));\n } else {\n translations.set(locale, { ...data });\n }\n },\n\n /**\n * Replace the ENTIRE runtime-authored translation layer (#2591). Called\n * by the authored-translation sync with the full current set of active\n * `translation` metadata items keyed by locale. Wholesale replacement —\n * not a merge — so deleted items/keys stop resolving on the next sync.\n */\n replaceAuthoredTranslations(byLocale: Record<string, Record<string, unknown>>): void {\n authored.clear();\n for (const [locale, data] of Object.entries(byLocale ?? {})) {\n if (!data || typeof data !== 'object') continue;\n authored.set(locale, { ...data });\n }\n },\n\n getLocales(): string[] {\n return [...new Set([...translations.keys(), ...authored.keys()])];\n },\n\n getDefaultLocale(): string {\n return defaultLocale;\n },\n\n setDefaultLocale(locale: string): void {\n defaultLocale = locale;\n },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory metadata service fallback.\n *\n * Implements the IMetadataService contract with a simple Map-of-Maps store.\n * Used by ObjectKernel as an automatic fallback when no real metadata plugin\n * (e.g. MetadataPlugin with file-system persistence) is registered.\n */\nexport function createMemoryMetadata() {\n // type -> name -> data\n const store = new Map<string, Map<string, any>>();\n\n function getTypeMap(type: string): Map<string, any> {\n let map = store.get(type);\n if (!map) {\n map = new Map();\n store.set(type, map);\n }\n return map;\n }\n\n return {\n _fallback: true, _serviceName: 'metadata',\n async register(type: string, name: string, data: any): Promise<void> {\n getTypeMap(type).set(name, data);\n },\n // Mirror MetadataManager.registerInMemory (synchronous, no persistence).\n // AppPlugin gates code-defined-datasource / stack-RBAC registration on\n // `typeof metadata.registerInMemory === 'function'` (it must register\n // GitOps-managed artefacts *listably* but never persist them). Without this\n // method the guard was false on the host-config / standalone boot path —\n // where this fallback (not MetadataPlugin) provides the `metadata` service —\n // so `defineStack({ datasources })` entries silently never reached the\n // registry and were absent from GET /api/v1/datasources and\n // GET /api/v1/meta/datasource (ADR-0015 §18). This store is already\n // in-memory only, so registerInMemory and register share an implementation.\n registerInMemory(type: string, name: string, data: any): void {\n getTypeMap(type).set(name, data);\n },\n async get(type: string, name: string): Promise<any> {\n return getTypeMap(type).get(name);\n },\n async list(type: string): Promise<any[]> {\n return Array.from(getTypeMap(type).values());\n },\n async unregister(type: string, name: string): Promise<void> {\n getTypeMap(type).delete(name);\n },\n async exists(type: string, name: string): Promise<boolean> {\n return getTypeMap(type).has(name);\n },\n async listNames(type: string): Promise<string[]> {\n return Array.from(getTypeMap(type).keys());\n },\n async getObject(name: string): Promise<any> {\n return getTypeMap('object').get(name);\n },\n async listObjects(): Promise<any[]> {\n return Array.from(getTypeMap('object').values());\n },\n };\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Runtime-authored translation sync (#2591).\n *\n * Translations authored in the Studio persist as `translation` sys_metadata\n * rows (`allowRuntimeCreate: true`), but historically only STATIC bundles\n * (app `bundle.translations`, plugin `translations/`) were ever loaded into\n * the i18n runtime — a published translation was a dead-end on publish AND\n * after a restart.\n *\n * This module is the single shared implementation of the fix, wired by both\n * hosts an `i18n` service can come from:\n * - the runtime's AppPlugin (covers the kernel's in-memory fallback — the\n * dev/standalone reality) and\n * - @objectstack/service-i18n's I18nServicePlugin (the file-based adapter).\n * Both adapters expose `replaceAuthoredTranslations(byLocale)`; the sync\n * computes the full authored layer from the rows and REPLACES it wholesale\n * (clear-then-reload), so deleted items/keys stop resolving.\n *\n * Item payload is a single-locale `AppTranslationBundle` (the `translation`\n * type's canonical schema). Locale resolution, in order: `_meta.locale`, a\n * top-level `locale` string, then the item name when it looks like a BCP-47\n * tag (an item named `zh-CN` translates that locale). Items with no\n * resolvable locale are skipped with a warning. Multiple items on one locale\n * deep-merge in name order (deterministic).\n *\n * Trigger points (wired by {@link wireAuthoredTranslationSync}):\n * • `kernel:ready` — cold-boot coverage;\n * • `metadata:reloaded` — publish-while-running coverage (#2576);\n * • protocol `onMetadataMutation` — direct-active saves / deletes of\n * `translation` rows that don't go through a package publish (#2588's\n * mutation stream).\n *\n * Rows are read straight from `sys_metadata` through the engine — the same\n * discipline as the authored-hook re-sync (#2588): env-scoped kernels\n * surface authored rows nowhere else, and the i18n map is process-wide so\n * rows are taken across all organizations. Best-effort: a failed read keeps\n * the currently applied authored layer.\n */\n\nimport { deepMerge } from './memory-i18n.js';\n\ntype AnyRecord = Record<string, any>;\n\ninterface MinimalCtx {\n logger: { debug?: (...a: any[]) => void; info?: (...a: any[]) => void; warn?: (...a: any[]) => void };\n getService(name: string): any;\n hook?(name: string, fn: () => Promise<void> | void): void;\n}\n\n/**\n * Ownership marker: several plugins may wire the sync against the same\n * kernel (AppPlugin AND I18nServicePlugin on a production server). The first\n * wirer to touch a given i18n service instance claims it; later wirers\n * no-op, so the layer is computed once per change instead of N times.\n */\nconst OWNER_PROP = '__authoredTranslationSyncOwner';\n\n// Deliberately narrow (language + optional script/region only): item names\n// are snake_case, so a permissive multi-segment pattern would classify names\n// like `my_custom_strings` as locales.\nconst LOCALE_LIKE = /^[a-z]{2,3}([_-]([A-Za-z]{4}|[A-Za-z]{2}|[0-9]{3}))?$/;\n\n/**\n * Read ACTIVE `translation` metadata rows and compute the authored layer,\n * keyed by locale. Returns `null` when the read failed (callers must keep\n * the current layer, never tear it down on an error).\n */\nexport async function readAuthoredTranslationLayer(\n engine: { find(object: string, opts?: AnyRecord): Promise<any[]> },\n logger?: MinimalCtx['logger'],\n): Promise<Record<string, Record<string, unknown>> | null> {\n let rows: any[];\n try {\n rows = (await engine.find('sys_metadata', {\n where: { type: 'translation', state: 'active' },\n })) ?? [];\n if (rows.length === 0) {\n // Legacy plural rows — mirrors the protocol's singular/plural fallback.\n rows = (await engine.find('sys_metadata', {\n where: { type: 'translations', state: 'active' },\n })) ?? [];\n }\n } catch (err: any) {\n logger?.debug?.('[i18n] authored-translation read failed — keeping current layer', {\n error: err?.message,\n });\n return null;\n }\n\n const byLocale: Record<string, Record<string, unknown>> = {};\n const sorted = [...rows].sort((a, b) => String(a?.name ?? '').localeCompare(String(b?.name ?? '')));\n for (const row of sorted) {\n let data: any;\n try {\n data = typeof row.metadata === 'string' ? JSON.parse(row.metadata) : row.metadata;\n } catch {\n continue; // malformed row — skip it, keep the rest\n }\n if (!data || typeof data !== 'object') continue;\n const locale: string | undefined =\n (typeof data?._meta?.locale === 'string' && data._meta.locale)\n || (typeof data?.locale === 'string' && data.locale)\n || (typeof row?.name === 'string' && LOCALE_LIKE.test(row.name) ? row.name : undefined)\n || undefined;\n if (!locale) {\n logger?.warn?.(\n `[i18n] authored translation '${row?.name}' has no resolvable locale `\n + '(set _meta.locale, or name the item after its BCP-47 locale) — skipped',\n );\n continue;\n }\n // Strip authoring bookkeeping; everything else is translation data.\n const { name: _n, locale: _l, _packageId: _p, _provenance: _pr, _lock: _lk, ...payload } = data;\n byLocale[locale] = deepMerge(byLocale[locale] ?? {}, payload as Record<string, unknown>);\n }\n return byLocale;\n}\n\n/**\n * Wire the authored-translation sync into a plugin context: registers the\n * `kernel:ready` / `metadata:reloaded` hooks and (at kernel:ready) the\n * protocol mutation subscription. Idempotent per i18n service instance via\n * the ownership marker. Safe to call on kernels with no engine, no protocol,\n * or an i18n service without `replaceAuthoredTranslations` — every path\n * degrades to a no-op.\n */\nexport function wireAuthoredTranslationSync(ctx: MinimalCtx): void {\n if (typeof ctx.hook !== 'function') return;\n\n const token = Symbol('authored-translation-sync');\n const resolveOwnedI18n = (): any | null => {\n let i18n: any;\n try { i18n = ctx.getService('i18n'); } catch { return null; }\n if (!i18n || typeof i18n.replaceAuthoredTranslations !== 'function') return null;\n const current = i18n[OWNER_PROP];\n if (current === undefined) {\n i18n[OWNER_PROP] = token;\n return i18n;\n }\n return current === token ? i18n : null; // another wirer owns this instance\n };\n\n // Serialized: overlapping publishes must not finish out of order and leave\n // the older authored snapshot applied.\n let chain: Promise<void> = Promise.resolve();\n const sync = (): Promise<void> => {\n const run = chain.then(async () => {\n const i18n = resolveOwnedI18n();\n if (!i18n) return;\n let engine: any;\n try { engine = ctx.getService('objectql'); } catch { return; }\n if (!engine || typeof engine.find !== 'function') return;\n const layer = await readAuthoredTranslationLayer(engine, ctx.logger);\n if (layer === null) return; // failed read — keep current layer\n i18n.replaceAuthoredTranslations(layer);\n ctx.logger.info?.('[i18n] synced runtime-authored translations', {\n locales: Object.keys(layer),\n });\n });\n chain = run.catch(() => undefined);\n return run;\n };\n\n ctx.hook('kernel:ready', async () => {\n // Subscribe to translation mutations through the protocol choke point\n // (#2588). Only the owning wirer subscribes.\n if (resolveOwnedI18n()) {\n let protocol: any = null;\n try { protocol = ctx.getService('protocol'); } catch { /* no protocol on this kernel */ }\n if (protocol && typeof protocol.onMetadataMutation === 'function') {\n protocol.onMetadataMutation((evt: { type: string; name: string; state: string }) => {\n if (evt?.type !== 'translation' || evt.state === 'draft') return;\n void sync().catch((err: any) => {\n ctx.logger.warn?.('[i18n] authored-translation re-sync after mutation failed', {\n item: evt.name,\n error: err?.message,\n });\n });\n });\n }\n }\n await sync();\n });\n ctx.hook('metadata:reloaded', async () => {\n await sync();\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { createMemoryCache } from './memory-cache.js';\nimport { createMemoryQueue } from './memory-queue.js';\nimport { createMemoryJob } from './memory-job.js';\nimport { createMemoryI18n } from './memory-i18n.js';\nimport { createMemoryMetadata } from './memory-metadata.js';\n\nexport { createMemoryCache } from './memory-cache.js';\nexport { createMemoryQueue } from './memory-queue.js';\nexport { createMemoryJob } from './memory-job.js';\nexport { createMemoryI18n, resolveLocale, deepMerge } from './memory-i18n.js';\nexport { createMemoryMetadata } from './memory-metadata.js';\nexport {\n wireAuthoredTranslationSync,\n readAuthoredTranslationLayer,\n} from './authored-translation-sync.js';\n\n/**\n * Map of core-criticality service names to their in-memory fallback factories.\n * Used by ObjectKernel.validateSystemRequirements() to auto-inject fallbacks\n * when no real plugin provides the service.\n */\nexport const CORE_FALLBACK_FACTORIES: Record<string, () => Record<string, any>> = {\n metadata: createMemoryMetadata,\n cache: createMemoryCache,\n queue: createMemoryQueue,\n job: createMemoryJob,\n i18n: createMemoryI18n,\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin } from './types.js';\nimport { createLogger, ObjectLogger } from './logger.js';\nimport type { LoggerConfig } from '@objectstack/spec/system';\nimport { ObjectKernelBase } from './kernel-base.js';\n\n/**\n * ObjectKernel - MiniKernel Architecture\n * \n * A highly modular, plugin-based microkernel that:\n * - Manages plugin lifecycle (init, start, destroy)\n * - Provides dependency injection via service registry\n * - Implements event/hook system for inter-plugin communication\n * - Handles dependency resolution (topological sort)\n * - Provides configurable logging for server and browser\n * \n * Core philosophy:\n * - Business logic is completely separated into plugins\n * - Kernel only manages lifecycle, DI, and hooks\n * - Plugins are loaded as equal building blocks\n */\nexport class LiteKernel extends ObjectKernelBase {\n constructor(config?: { logger?: Partial<LoggerConfig> }) {\n const logger = createLogger(config?.logger);\n super(logger);\n \n // Initialize context after logger is created\n this.context = this.createContext();\n }\n\n /**\n * Register a plugin\n * @param plugin - Plugin instance\n */\n use(plugin: Plugin): this {\n this.validateIdle();\n\n const pluginName = plugin.name;\n if (this.plugins.has(pluginName)) {\n throw new Error(`[Kernel] Plugin '${pluginName}' already registered`);\n }\n\n this.plugins.set(pluginName, plugin);\n return this;\n }\n\n /**\n * Bootstrap the kernel\n * 1. Resolve dependencies (topological sort)\n * 2. Init phase - plugins register services\n * 3. Start phase - plugins execute business logic\n * 4. Trigger 'kernel:ready' hook\n */\n async bootstrap(): Promise<void> {\n this.validateState('idle');\n\n this.state = 'initializing';\n this.logger.info('Bootstrap started');\n\n // Resolve dependencies\n const orderedPlugins = this.resolveDependencies();\n\n // Phase 1: Init - Plugins register services\n this.logger.info('Phase 1: Init plugins');\n for (const plugin of orderedPlugins) {\n await this.runPluginInit(plugin);\n }\n\n // Phase 2: Start - Plugins execute business logic\n this.logger.info('Phase 2: Start plugins');\n this.state = 'running';\n \n for (const plugin of orderedPlugins) {\n await this.runPluginStart(plugin);\n }\n\n // Trigger ready hook (route/middleware registration phase)\n await this.triggerHook('kernel:ready');\n // Trigger bootstrapped hook — \"all synchronous bootstrap has settled\"\n // anchor, strictly after every kernel:ready handler has settled and\n // before any HTTP socket opens. NOTE: does not guarantee background app\n // seed data has settled — subscribe `app:seeded` for that\n // (see plugin-lifecycle-events.ts).\n await this.triggerHook('kernel:bootstrapped');\n // Trigger listening hook (HTTP servers open their socket here —\n // strictly after every kernel:ready handler has completed).\n await this.triggerHook('kernel:listening');\n this.logger.info('✅ Bootstrap complete', { \n pluginCount: this.plugins.size \n });\n }\n\n /**\n * Shutdown the kernel\n * Calls destroy on all plugins in reverse order\n */\n async shutdown(): Promise<void> {\n await this.destroy();\n }\n\n /**\n * Graceful shutdown - destroy all plugins in reverse order\n */\n async destroy(): Promise<void> {\n if (this.state === 'stopped') {\n this.logger.warn('Kernel already stopped');\n return;\n }\n\n this.state = 'stopping';\n this.logger.info('Shutdown started');\n\n // Trigger shutdown hook\n await this.triggerHook('kernel:shutdown');\n\n // Destroy plugins in reverse order\n const orderedPlugins = this.resolveDependencies();\n for (const plugin of orderedPlugins.reverse()) {\n await this.runPluginDestroy(plugin);\n }\n\n this.state = 'stopped';\n this.logger.info('✅ Shutdown complete');\n \n // Cleanup logger resources\n if (this.logger && typeof (this.logger as ObjectLogger).destroy === 'function') {\n await (this.logger as ObjectLogger).destroy();\n }\n }\n\n /**\n * Get a service from the registry\n * Convenience method for external access\n */\n getService<T>(name: string): T {\n return this.context.getService<T>(name);\n }\n\n /**\n * Check if kernel is running\n */\n isRunning(): boolean {\n return this.state === 'running';\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n ApiRegistry as ApiRegistryType,\n ApiRegistryEntry,\n ApiRegistryEntryInput,\n ApiEndpointRegistration,\n ConflictResolutionStrategy,\n ApiDiscoveryQuery,\n ApiDiscoveryResponse,\n} from '@objectstack/spec/api';\nimport { ApiRegistryEntrySchema } from '@objectstack/spec/api';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport { getEnv } from './utils/env.js';\n\n/**\n * API Registry Service\n * \n * Central registry for managing API endpoints across different protocols.\n * Provides endpoint registration, discovery, and conflict resolution.\n * \n * **Features:**\n * - Multi-protocol support (REST, GraphQL, OData, WebSocket, etc.)\n * - Route conflict detection with configurable resolution strategies\n * - RBAC permission integration\n * - Dynamic schema linking with ObjectQL references\n * - Plugin API registration\n * \n * **Architecture Alignment:**\n * - Kubernetes: Service Discovery & API Server\n * - AWS API Gateway: Unified API Management\n * - Kong Gateway: Plugin-based API Management\n * \n * @example\n * ```typescript\n * const registry = new ApiRegistry(logger, 'priority');\n * \n * // Register an API\n * registry.registerApi({\n * id: 'customer_api',\n * name: 'Customer API',\n * type: 'rest',\n * version: 'v1',\n * basePath: '/api/v1/customers',\n * endpoints: [...]\n * });\n * \n * // Discover APIs\n * const apis = registry.findApis({ type: 'rest', status: 'active' });\n * \n * // Get registry snapshot\n * const snapshot = registry.getRegistry();\n * ```\n */\nexport class ApiRegistry {\n private apis: Map<string, ApiRegistryEntry> = new Map();\n private endpoints: Map<string, { api: string; endpoint: ApiEndpointRegistration }> = new Map();\n private routes: Map<string, { api: string; endpointId: string; priority: number }> = new Map();\n \n // Performance optimization: Auxiliary indices for O(1) lookups\n private apisByType: Map<string, Set<string>> = new Map();\n private apisByTag: Map<string, Set<string>> = new Map();\n private apisByStatus: Map<string, Set<string>> = new Map();\n \n private conflictResolution: ConflictResolutionStrategy;\n private logger: Logger;\n private version: string;\n private updatedAt: string;\n\n constructor(\n logger: Logger,\n conflictResolution: ConflictResolutionStrategy = 'error',\n version: string = '1.0.0'\n ) {\n this.logger = logger;\n this.conflictResolution = conflictResolution;\n this.version = version;\n this.updatedAt = new Date().toISOString();\n }\n\n /**\n * Register an API with its endpoints\n * \n * @param api - API registry entry\n * @throws Error if API already registered or route conflicts detected\n */\n registerApi(api: ApiRegistryEntryInput): void {\n // Check if API already exists\n if (this.apis.has(api.id)) {\n throw new Error(`[ApiRegistry] API '${api.id}' already registered`);\n }\n\n // Parse and validate the input using Zod schema\n const fullApi = ApiRegistryEntrySchema.parse(api);\n\n // Validate and register endpoints\n for (const endpoint of fullApi.endpoints) {\n this.validateEndpoint(endpoint, fullApi.id);\n }\n\n // Register the API\n this.apis.set(fullApi.id, fullApi);\n \n // Register endpoints\n for (const endpoint of fullApi.endpoints) {\n this.registerEndpoint(fullApi.id, endpoint);\n }\n\n // Update auxiliary indices for performance optimization\n this.updateIndices(fullApi);\n\n this.updatedAt = new Date().toISOString();\n this.logger.info(`API registered: ${fullApi.id}`, {\n api: fullApi.id,\n type: fullApi.type,\n endpointCount: fullApi.endpoints.length,\n });\n }\n\n /**\n * Unregister an API and all its endpoints\n * \n * @param apiId - API identifier\n */\n unregisterApi(apiId: string): void {\n const api = this.apis.get(apiId);\n if (!api) {\n throw new Error(`[ApiRegistry] API '${apiId}' not found`);\n }\n\n // Remove all endpoints\n for (const endpoint of api.endpoints) {\n this.unregisterEndpoint(apiId, endpoint.id);\n }\n\n // Remove from auxiliary indices\n this.removeFromIndices(api);\n\n // Remove the API\n this.apis.delete(apiId);\n this.updatedAt = new Date().toISOString();\n \n this.logger.info(`API unregistered: ${apiId}`);\n }\n\n /**\n * Register a single endpoint\n * \n * @param apiId - API identifier\n * @param endpoint - Endpoint registration\n * @throws Error if route conflict detected\n */\n private registerEndpoint(apiId: string, endpoint: ApiEndpointRegistration): void {\n const endpointKey = `${apiId}:${endpoint.id}`;\n \n // Check if endpoint already registered\n if (this.endpoints.has(endpointKey)) {\n throw new Error(`[ApiRegistry] Endpoint '${endpoint.id}' already registered for API '${apiId}'`);\n }\n\n // Register endpoint\n this.endpoints.set(endpointKey, { api: apiId, endpoint });\n\n // Register route if path is defined\n if (endpoint.path) {\n this.registerRoute(apiId, endpoint);\n }\n }\n\n /**\n * Unregister a single endpoint\n * \n * @param apiId - API identifier\n * @param endpointId - Endpoint identifier\n */\n private unregisterEndpoint(apiId: string, endpointId: string): void {\n const endpointKey = `${apiId}:${endpointId}`;\n const entry = this.endpoints.get(endpointKey);\n \n if (!entry) {\n return; // Already unregistered\n }\n\n // Unregister route\n if (entry.endpoint.path) {\n const routeKey = this.getRouteKey(entry.endpoint);\n this.routes.delete(routeKey);\n }\n\n // Unregister endpoint\n this.endpoints.delete(endpointKey);\n }\n\n /**\n * Register a route with conflict detection\n * \n * @param apiId - API identifier\n * @param endpoint - Endpoint registration\n * @throws Error if route conflict detected (based on strategy)\n */\n private registerRoute(apiId: string, endpoint: ApiEndpointRegistration): void {\n const routeKey = this.getRouteKey(endpoint);\n const priority = endpoint.priority ?? 100;\n const existingRoute = this.routes.get(routeKey);\n\n if (existingRoute) {\n // Route conflict detected\n this.handleRouteConflict(routeKey, apiId, endpoint, existingRoute, priority);\n return;\n }\n\n // Register route\n this.routes.set(routeKey, {\n api: apiId,\n endpointId: endpoint.id,\n priority,\n });\n }\n\n /**\n * Handle route conflict based on resolution strategy\n * \n * @param routeKey - Route key\n * @param apiId - New API identifier\n * @param endpoint - New endpoint\n * @param existingRoute - Existing route registration\n * @param newPriority - New endpoint priority\n * @throws Error if strategy is 'error'\n */\n private handleRouteConflict(\n routeKey: string,\n apiId: string,\n endpoint: ApiEndpointRegistration,\n existingRoute: { api: string; endpointId: string; priority: number },\n newPriority: number\n ): void {\n const strategy = this.conflictResolution;\n\n switch (strategy) {\n case 'error':\n throw new Error(\n `[ApiRegistry] Route conflict detected: '${routeKey}' is already registered by API '${existingRoute.api}' endpoint '${existingRoute.endpointId}'`\n );\n\n case 'priority':\n if (newPriority > existingRoute.priority) {\n // New endpoint has higher priority, replace\n this.logger.warn(\n `Route conflict: replacing '${routeKey}' (priority ${existingRoute.priority} -> ${newPriority})`,\n {\n oldApi: existingRoute.api,\n oldEndpoint: existingRoute.endpointId,\n newApi: apiId,\n newEndpoint: endpoint.id,\n }\n );\n this.routes.set(routeKey, {\n api: apiId,\n endpointId: endpoint.id,\n priority: newPriority,\n });\n } else {\n // Existing endpoint has higher priority, keep it\n this.logger.warn(\n `Route conflict: keeping existing '${routeKey}' (priority ${existingRoute.priority} >= ${newPriority})`,\n {\n existingApi: existingRoute.api,\n existingEndpoint: existingRoute.endpointId,\n newApi: apiId,\n newEndpoint: endpoint.id,\n }\n );\n }\n break;\n\n case 'first-wins':\n // Keep existing route\n this.logger.warn(\n `Route conflict: keeping first registered '${routeKey}'`,\n {\n existingApi: existingRoute.api,\n newApi: apiId,\n }\n );\n break;\n\n case 'last-wins':\n // Replace with new route\n this.logger.warn(\n `Route conflict: replacing with last registered '${routeKey}'`,\n {\n oldApi: existingRoute.api,\n newApi: apiId,\n }\n );\n this.routes.set(routeKey, {\n api: apiId,\n endpointId: endpoint.id,\n priority: newPriority,\n });\n break;\n\n default:\n throw new Error(`[ApiRegistry] Unknown conflict resolution strategy: ${strategy}`);\n }\n }\n\n /**\n * Generate a unique route key for conflict detection\n * \n * NOTE: This implementation uses exact string matching for route conflict detection.\n * It works well for static paths but has limitations with parameterized routes.\n * For example, `/api/users/:id` and `/api/users/:userId` will NOT be detected as conflicts\n * even though they are semantically identical parameterized patterns. Similarly,\n * `/api/:resource/list` and `/api/:entity/list` would also not be detected as conflicting.\n * \n * For more advanced conflict detection (e.g., path-to-regexp pattern matching),\n * consider integrating with your routing library's conflict detection mechanism.\n * \n * @param endpoint - Endpoint registration\n * @returns Route key (e.g., \"GET:/api/v1/customers/:id\")\n */\n private getRouteKey(endpoint: ApiEndpointRegistration): string {\n const method = endpoint.method || 'ANY';\n return `${method}:${endpoint.path}`;\n }\n\n /**\n * Validate endpoint registration\n * \n * @param endpoint - Endpoint to validate\n * @param apiId - API identifier (for error messages)\n * @throws Error if endpoint is invalid\n */\n private validateEndpoint(endpoint: ApiEndpointRegistration, apiId: string): void {\n if (!endpoint.id) {\n throw new Error(`[ApiRegistry] Endpoint in API '${apiId}' missing 'id' field`);\n }\n\n if (!endpoint.path) {\n throw new Error(`[ApiRegistry] Endpoint '${endpoint.id}' in API '${apiId}' missing 'path' field`);\n }\n }\n\n /**\n * Get an API by ID\n * \n * @param apiId - API identifier\n * @returns API registry entry or undefined\n */\n getApi(apiId: string): ApiRegistryEntry | undefined {\n return this.apis.get(apiId);\n }\n\n /**\n * Get all registered APIs\n * \n * @returns Array of all APIs\n */\n getAllApis(): ApiRegistryEntry[] {\n return Array.from(this.apis.values());\n }\n\n /**\n * Find APIs matching query criteria\n * \n * Performance optimized with auxiliary indices for O(1) lookups on type, tags, and status.\n * \n * @param query - Discovery query parameters\n * @returns Matching APIs\n */\n findApis(query: ApiDiscoveryQuery): ApiDiscoveryResponse {\n let resultIds: Set<string> | undefined;\n\n // Use indices for performance-optimized filtering\n // Start with the most restrictive filter to minimize subsequent filtering\n \n // Filter by type (using index for O(1) lookup)\n if (query.type) {\n const typeIds = this.apisByType.get(query.type);\n if (!typeIds || typeIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n resultIds = new Set(typeIds);\n }\n\n // Filter by status (using index for O(1) lookup)\n if (query.status) {\n const statusIds = this.apisByStatus.get(query.status);\n if (!statusIds || statusIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n \n if (resultIds) {\n // Intersect with previous results\n resultIds = new Set([...resultIds].filter(id => statusIds.has(id)));\n } else {\n resultIds = new Set(statusIds);\n }\n \n if (resultIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n }\n\n // Filter by tags (using index for O(M) lookup where M is number of tags)\n if (query.tags && query.tags.length > 0) {\n const tagMatches = new Set<string>();\n \n for (const tag of query.tags) {\n const tagIds = this.apisByTag.get(tag);\n if (tagIds) {\n tagIds.forEach(id => tagMatches.add(id));\n }\n }\n \n if (tagMatches.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n \n if (resultIds) {\n // Intersect with previous results\n resultIds = new Set([...resultIds].filter(id => tagMatches.has(id)));\n } else {\n resultIds = tagMatches;\n }\n \n if (resultIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n }\n\n // Get the actual API objects\n let results: ApiRegistryEntry[];\n if (resultIds) {\n results = Array.from(resultIds)\n .map(id => this.apis.get(id))\n .filter((api): api is ApiRegistryEntry => api !== undefined);\n } else {\n results = Array.from(this.apis.values());\n }\n\n // Apply remaining filters that don't have indices (less common filters)\n \n // Filter by plugin source\n if (query.pluginSource) {\n results = results.filter(\n (api) => api.metadata?.pluginSource === query.pluginSource\n );\n }\n\n // Filter by version\n if (query.version) {\n results = results.filter((api) => api.version === query.version);\n }\n\n // Search in name/description\n if (query.search) {\n const searchLower = query.search.toLowerCase();\n results = results.filter(\n (api) =>\n api.name.toLowerCase().includes(searchLower) ||\n (api.description && api.description.toLowerCase().includes(searchLower))\n );\n }\n\n return {\n apis: results,\n total: results.length,\n filters: query,\n };\n }\n\n /**\n * Get endpoint by API ID and endpoint ID\n * \n * @param apiId - API identifier\n * @param endpointId - Endpoint identifier\n * @returns Endpoint registration or undefined\n */\n getEndpoint(apiId: string, endpointId: string): ApiEndpointRegistration | undefined {\n const key = `${apiId}:${endpointId}`;\n return this.endpoints.get(key)?.endpoint;\n }\n\n /**\n * Find endpoint by route (method + path)\n * \n * @param method - HTTP method\n * @param path - URL path\n * @returns Endpoint registration or undefined\n */\n findEndpointByRoute(method: string, path: string): {\n api: ApiRegistryEntry;\n endpoint: ApiEndpointRegistration;\n } | undefined {\n const routeKey = `${method}:${path}`;\n const route = this.routes.get(routeKey);\n \n if (!route) {\n return undefined;\n }\n\n const api = this.apis.get(route.api);\n const endpoint = this.getEndpoint(route.api, route.endpointId);\n\n if (!api || !endpoint) {\n return undefined;\n }\n\n return { api, endpoint };\n }\n\n /**\n * Get complete registry snapshot\n * \n * @returns Current registry state\n */\n getRegistry(): ApiRegistryType {\n const apis = Array.from(this.apis.values());\n \n // Group by type\n const byType: Record<string, ApiRegistryEntry[]> = {};\n for (const api of apis) {\n if (!byType[api.type]) {\n byType[api.type] = [];\n }\n byType[api.type].push(api);\n }\n\n // Group by status\n const byStatus: Record<string, ApiRegistryEntry[]> = {};\n for (const api of apis) {\n const status = api.metadata?.status || 'active';\n if (!byStatus[status]) {\n byStatus[status] = [];\n }\n byStatus[status].push(api);\n }\n\n // Count total endpoints\n const totalEndpoints = apis.reduce(\n (sum, api) => sum + api.endpoints.length,\n 0\n );\n\n return {\n version: this.version,\n conflictResolution: this.conflictResolution,\n apis,\n totalApis: apis.length,\n totalEndpoints,\n byType,\n byStatus,\n updatedAt: this.updatedAt,\n };\n }\n\n /**\n * Clear all registered APIs\n * \n * **⚠️ SAFETY WARNING:**\n * This method clears all registered APIs and should be used with caution.\n * \n * **Usage Restrictions:**\n * - In production environments (NODE_ENV=production), a `force: true` parameter is required\n * - Primarily intended for testing and development hot-reload scenarios\n * \n * @param options - Clear options\n * @param options.force - Force clear in production environment (default: false)\n * @throws Error if called in production without force flag\n * \n * @example Safe usage in tests\n * ```typescript\n * beforeEach(() => {\n * registry.clear(); // OK in test environment\n * });\n * ```\n * \n * @example Usage in production (requires explicit force)\n * ```typescript\n * // In production, explicit force is required\n * registry.clear({ force: true });\n * ```\n */\n clear(options: { force?: boolean } = {}): void {\n const isProduction = this.isProductionEnvironment();\n \n if (isProduction && !options.force) {\n throw new Error(\n '[ApiRegistry] Cannot clear registry in production environment without force flag. ' +\n 'Use clear({ force: true }) if you really want to clear the registry.'\n );\n }\n\n this.apis.clear();\n this.endpoints.clear();\n this.routes.clear();\n \n // Clear auxiliary indices\n this.apisByType.clear();\n this.apisByTag.clear();\n this.apisByStatus.clear();\n \n this.updatedAt = new Date().toISOString();\n \n if (isProduction) {\n this.logger.warn('API registry forcefully cleared in production', { force: options.force });\n } else {\n this.logger.info('API registry cleared');\n }\n }\n\n /**\n * Get registry statistics\n * \n * @returns Registry statistics\n */\n getStats(): {\n totalApis: number;\n totalEndpoints: number;\n totalRoutes: number;\n apisByType: Record<string, number>;\n endpointsByApi: Record<string, number>;\n } {\n const apis = Array.from(this.apis.values());\n \n const apisByType: Record<string, number> = {};\n for (const api of apis) {\n apisByType[api.type] = (apisByType[api.type] || 0) + 1;\n }\n\n const endpointsByApi: Record<string, number> = {};\n for (const api of apis) {\n endpointsByApi[api.id] = api.endpoints.length;\n }\n\n return {\n totalApis: this.apis.size,\n totalEndpoints: this.endpoints.size,\n totalRoutes: this.routes.size,\n apisByType,\n endpointsByApi,\n };\n }\n\n /**\n * Update auxiliary indices when an API is registered\n * \n * @param api - API entry to index\n * @private\n * @internal\n */\n private updateIndices(api: ApiRegistryEntry): void {\n // Index by type\n this.ensureIndexSet(this.apisByType, api.type).add(api.id);\n\n // Index by status\n const status = api.metadata?.status || 'active';\n this.ensureIndexSet(this.apisByStatus, status).add(api.id);\n\n // Index by tags\n const tags = api.metadata?.tags || [];\n for (const tag of tags) {\n this.ensureIndexSet(this.apisByTag, tag).add(api.id);\n }\n }\n\n /**\n * Remove API from auxiliary indices when unregistered\n * \n * @param api - API entry to remove from indices\n * @private\n * @internal\n */\n private removeFromIndices(api: ApiRegistryEntry): void {\n // Remove from type index\n this.removeFromIndexSet(this.apisByType, api.type, api.id);\n\n // Remove from status index\n const status = api.metadata?.status || 'active';\n this.removeFromIndexSet(this.apisByStatus, status, api.id);\n\n // Remove from tag indices\n const tags = api.metadata?.tags || [];\n for (const tag of tags) {\n this.removeFromIndexSet(this.apisByTag, tag, api.id);\n }\n }\n\n /**\n * Helper to ensure an index set exists and return it\n * \n * @param map - Index map\n * @param key - Index key\n * @returns The Set for this key (created if needed)\n * @private\n * @internal\n */\n private ensureIndexSet(map: Map<string, Set<string>>, key: string): Set<string> {\n let set = map.get(key);\n if (!set) {\n set = new Set();\n map.set(key, set);\n }\n return set;\n }\n\n /**\n * Helper to remove an ID from an index set and clean up empty sets\n * \n * @param map - Index map\n * @param key - Index key\n * @param id - API ID to remove\n * @private\n * @internal\n */\n private removeFromIndexSet(map: Map<string, Set<string>>, key: string, id: string): void {\n const set = map.get(key);\n if (set) {\n set.delete(id);\n // Clean up empty sets to avoid memory leaks\n if (set.size === 0) {\n map.delete(key);\n }\n }\n }\n\n /**\n * Check if running in production environment\n * \n * @returns true if NODE_ENV is 'production'\n * @private\n * @internal\n */\n private isProductionEnvironment(): boolean {\n return getEnv('NODE_ENV') === 'production';\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from './types.js';\nimport { ApiRegistry } from './api-registry.js';\nimport type { ConflictResolutionStrategy } from '@objectstack/spec/api';\n\n/**\n * API Registry Plugin Configuration\n */\nexport interface ApiRegistryPluginConfig {\n /**\n * Conflict resolution strategy for route conflicts\n * @default 'error'\n */\n conflictResolution?: ConflictResolutionStrategy;\n \n /**\n * Registry version\n * @default '1.0.0'\n */\n version?: string;\n}\n\n/**\n * API Registry Plugin\n * \n * Registers the API Registry service in the kernel, making it available\n * to all plugins for endpoint registration and discovery.\n * \n * **Usage:**\n * ```typescript\n * const kernel = new ObjectKernel();\n * \n * // Register API Registry Plugin\n * kernel.use(createApiRegistryPlugin({ conflictResolution: 'priority' }));\n * \n * // In other plugins, access the API Registry\n * const plugin: Plugin = {\n * name: 'my-plugin',\n * init: async (ctx) => {\n * const registry = ctx.getService<ApiRegistry>('api-registry');\n * \n * // Register plugin APIs\n * registry.registerApi({\n * id: 'my_plugin_api',\n * name: 'My Plugin API',\n * type: 'rest',\n * version: 'v1',\n * basePath: '/api/v1/my-plugin',\n * endpoints: [...]\n * });\n * }\n * };\n * ```\n * \n * @param config - Plugin configuration\n * @returns Plugin instance\n */\nexport function createApiRegistryPlugin(\n config: ApiRegistryPluginConfig = {}\n): Plugin {\n const {\n conflictResolution = 'error',\n version = '1.0.0',\n } = config;\n\n return {\n name: 'com.objectstack.core.api-registry',\n type: 'standard',\n version: '1.0.0',\n\n init: async (ctx: PluginContext) => {\n // Create API Registry instance\n const registry = new ApiRegistry(\n ctx.logger,\n conflictResolution,\n version\n );\n\n // Register as a service\n ctx.registerService('api-registry', registry);\n\n ctx.logger.info('API Registry plugin initialized', {\n conflictResolution,\n version,\n });\n },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport * from './adapter.js';\nexport * from './runner.js';\nexport * from './http-adapter.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport * as QA from '@objectstack/spec/qa';\nimport { TestExecutionAdapter } from './adapter.js';\n\nexport interface TestResult {\n scenarioId: string;\n passed: boolean;\n steps: StepResult[];\n error?: unknown;\n duration: number;\n}\n\nexport interface StepResult {\n stepName: string;\n passed: boolean;\n error?: unknown;\n output?: unknown;\n duration: number;\n}\n\nexport class TestRunner {\n constructor(private adapter: TestExecutionAdapter) {}\n\n async runSuite(suite: QA.TestSuite): Promise<TestResult[]> {\n const results: TestResult[] = [];\n for (const scenario of suite.scenarios) {\n results.push(await this.runScenario(scenario));\n }\n return results;\n }\n\n async runScenario(scenario: QA.TestScenario): Promise<TestResult> {\n const startTime = Date.now();\n const context: Record<string, unknown> = {}; // Variable context\n \n // Initialize context from initial payload if needed? Currently schema doesn't have initial context prop on Scenario\n // But we defined TestContextSchema separately.\n \n // Setup\n if (scenario.setup) {\n for (const step of scenario.setup) {\n try {\n await this.runStep(step, context);\n } catch (e) {\n return {\n scenarioId: scenario.id,\n passed: false,\n steps: [],\n error: `Setup failed: ${e instanceof Error ? e.message : String(e)}`,\n duration: Date.now() - startTime\n };\n }\n }\n }\n\n const stepResults: StepResult[] = [];\n let scenarioPassed = true;\n let scenarioError: unknown = undefined;\n\n // Main Steps\n for (const step of scenario.steps) {\n const stepStartTime = Date.now();\n try {\n const output = await this.runStep(step, context);\n stepResults.push({\n stepName: step.name,\n passed: true,\n output,\n duration: Date.now() - stepStartTime\n });\n } catch (e) {\n scenarioPassed = false;\n scenarioError = e;\n stepResults.push({\n stepName: step.name,\n passed: false,\n error: e,\n duration: Date.now() - stepStartTime\n });\n break; // Stop on first failure\n }\n }\n\n // Teardown (run even if failed)\n if (scenario.teardown) {\n for (const step of scenario.teardown) {\n try {\n await this.runStep(step, context);\n } catch (e) {\n // Log teardown failure but don't override main failure if it exists\n if (scenarioPassed) {\n scenarioPassed = false;\n scenarioError = `Teardown failed: ${e instanceof Error ? e.message : String(e)}`;\n }\n }\n }\n }\n\n return {\n scenarioId: scenario.id,\n passed: scenarioPassed,\n steps: stepResults,\n error: scenarioError,\n duration: Date.now() - startTime\n };\n }\n\n private async runStep(step: QA.TestStep, context: Record<string, unknown>): Promise<unknown> {\n // 1. Resolve Variables with Context (Simple interpolation or just pass context?)\n // For now, assume adpater handles context resolution or we do basic replacement\n const resolvedAction = this.resolveVariables(step.action, context);\n\n // 2. Execute Action\n const result = await this.adapter.execute(resolvedAction, context);\n\n // 3. Capture Outputs\n if (step.capture) {\n for (const [varName, path] of Object.entries(step.capture)) {\n context[varName] = this.getValueByPath(result, path);\n }\n }\n\n // 4. Run Assertions\n if (step.assertions) {\n for (const assertion of step.assertions) {\n this.assert(result, assertion, context);\n }\n }\n\n return result;\n }\n\n private resolveVariables(action: QA.TestAction, context: Record<string, unknown>): QA.TestAction {\n const actionStr = JSON.stringify(action);\n const resolved = actionStr.replace(/\\{\\{([^}]+)\\}\\}/g, (_match, varPath: string) => {\n const value = this.getValueByPath(context, varPath.trim());\n if (value === undefined) return _match; // Keep unresolved\n return typeof value === 'string' ? value : JSON.stringify(value);\n });\n try {\n return JSON.parse(resolved) as QA.TestAction;\n } catch {\n return action; // Fallback to original if parse fails\n }\n }\n\n private getValueByPath(obj: unknown, path: string): unknown {\n if (!path) return obj;\n const parts = path.split('.');\n let current: any = obj;\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n current = current[part];\n }\n return current;\n }\n\n private assert(result: unknown, assertion: QA.TestAssertion, _context: Record<string, unknown>) {\n const actual = this.getValueByPath(result, assertion.field);\n // Resolve expected value if it's a variable ref? \n const expected = assertion.expectedValue; // Simplify for now\n\n switch (assertion.operator) {\n case 'equals':\n if (actual !== expected) throw new Error(`Assertion failed: ${assertion.field} expected ${expected}, got ${actual}`);\n break;\n case 'not_equals':\n if (actual === expected) throw new Error(`Assertion failed: ${assertion.field} expected not ${expected}, got ${actual}`);\n break;\n case 'contains':\n if (Array.isArray(actual)) {\n if (!actual.includes(expected)) throw new Error(`Assertion failed: ${assertion.field} array does not contain ${expected}`);\n } else if (typeof actual === 'string') {\n if (!actual.includes(String(expected))) throw new Error(`Assertion failed: ${assertion.field} string does not contain ${expected}`);\n }\n break;\n case 'not_null':\n if (actual === null || actual === undefined) throw new Error(`Assertion failed: ${assertion.field} is null`);\n break;\n case 'is_null':\n if (actual !== null && actual !== undefined) throw new Error(`Assertion failed: ${assertion.field} is not null`);\n break;\n // ... Add other operators\n default:\n throw new Error(`Unknown assertion operator: ${assertion.operator}`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport * as QA from '@objectstack/spec/qa';\nimport { TestExecutionAdapter } from './adapter.js';\n\nexport class HttpTestAdapter implements TestExecutionAdapter {\n constructor(private baseUrl: string, private authToken?: string) {}\n\n async execute(action: QA.TestAction, _context: Record<string, unknown>): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n // If action.user is specified, maybe add a specific header for impersonation if supported?\n if (action.user) {\n headers['X-Run-As'] = action.user;\n }\n\n switch (action.type) {\n case 'create_record':\n return this.createRecord(action.target, action.payload || {}, headers);\n case 'update_record':\n return this.updateRecord(action.target, action.payload || {}, headers);\n case 'delete_record':\n return this.deleteRecord(action.target, action.payload || {}, headers);\n case 'read_record':\n return this.readRecord(action.target, action.payload || {}, headers);\n case 'query_records':\n return this.queryRecords(action.target, action.payload || {}, headers);\n case 'api_call':\n return this.rawApiCall(action.target, action.payload || {}, headers);\n case 'wait':\n const ms = Number(action.payload?.duration || 1000);\n return new Promise(resolve => setTimeout(() => resolve({ waited: ms }), ms));\n default:\n throw new Error(`Unsupported action type in HttpAdapter: ${action.type}`);\n }\n }\n\n private async createRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(data)\n });\n return this.handleResponse(response);\n }\n\n private async updateRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const id = data.id;\n if (!id) throw new Error('Update record requires id in payload');\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {\n method: 'PUT',\n headers,\n body: JSON.stringify(data)\n });\n return this.handleResponse(response);\n }\n\n private async deleteRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const id = data.id;\n if (!id) throw new Error('Delete record requires id in payload');\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {\n method: 'DELETE',\n headers\n });\n return this.handleResponse(response);\n }\n\n private async readRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const id = data.id;\n if (!id) throw new Error('Read record requires id in payload');\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {\n method: 'GET',\n headers\n });\n return this.handleResponse(response);\n }\n\n private async queryRecords(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n // Assuming query via POST or GraphQL-like endpoint\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/query`, {\n method: 'POST',\n headers,\n body: JSON.stringify(data)\n });\n return this.handleResponse(response);\n }\n\n private async rawApiCall(endpoint: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const method = (data.method as string) || 'GET';\n const body = data.body ? JSON.stringify(data.body) : undefined;\n const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;\n \n const response = await fetch(url, {\n method,\n headers,\n body\n });\n return this.handleResponse(response);\n }\n\n private async handleResponse(response: Response) {\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`HTTP Error ${response.status}: ${text}`);\n }\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('application/json')) {\n return response.json();\n }\n return response.text();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { PluginMetadata } from '../plugin-loader.js';\n\n// Conditionally import crypto for Node.js environments\nlet cryptoModule: typeof import('crypto') | null = null;\n\n\n/**\n * Plugin Signature Configuration\n * Controls how plugin signatures are verified\n */\nexport interface PluginSignatureConfig {\n /**\n * Map of publisher IDs to their trusted public keys\n * Format: { 'com.objectstack': '-----BEGIN PUBLIC KEY-----...' }\n */\n trustedPublicKeys: Map<string, string>;\n \n /**\n * Signature algorithm to use\n * - RS256: RSA with SHA-256\n * - ES256: ECDSA with SHA-256\n */\n algorithm: 'RS256' | 'ES256';\n \n /**\n * Strict mode: reject plugins without signatures\n * - true: All plugins must be signed\n * - false: Unsigned plugins are allowed with warning\n */\n strictMode: boolean;\n \n /**\n * Allow self-signed plugins in development\n */\n allowSelfSigned?: boolean;\n}\n\n/**\n * Plugin Signature Verification Result\n */\nexport interface SignatureVerificationResult {\n verified: boolean;\n error?: string;\n publisherId?: string;\n algorithm?: string;\n signedAt?: Date;\n}\n\n/**\n * Plugin Signature Verifier\n * \n * Implements cryptographic verification of plugin signatures to ensure:\n * 1. Plugin integrity - code hasn't been tampered with\n * 2. Publisher authenticity - plugin comes from trusted source\n * 3. Non-repudiation - publisher cannot deny signing\n * \n * Architecture:\n * - Uses Node.js crypto module for signature verification\n * - Supports RSA (RS256) and ECDSA (ES256) algorithms\n * - Verifies against trusted public key registry\n * - Computes hash of plugin code for integrity check\n * \n * Security Model:\n * - Public keys are pre-registered and trusted\n * - Plugin signature is verified before loading\n * - Strict mode rejects unsigned plugins\n * - Development mode allows self-signed plugins\n */\nexport class PluginSignatureVerifier {\n private config: PluginSignatureConfig;\n private logger: Logger;\n \n constructor(config: PluginSignatureConfig, logger: Logger) {\n this.config = config;\n this.logger = logger;\n \n this.validateConfig();\n }\n \n /**\n * Verify plugin signature\n * \n * @param plugin - Plugin metadata with signature\n * @returns Verification result\n * @throws Error if verification fails in strict mode\n */\n async verifyPluginSignature(plugin: PluginMetadata): Promise<SignatureVerificationResult> {\n // Handle unsigned plugins\n if (!plugin.signature) {\n return this.handleUnsignedPlugin(plugin);\n }\n \n try {\n // 1. Extract publisher ID from plugin name (reverse domain notation)\n const publisherId = this.extractPublisherId(plugin.name);\n \n // 2. Get trusted public key for publisher\n const publicKey = this.config.trustedPublicKeys.get(publisherId);\n if (!publicKey) {\n const error = `No trusted public key for publisher: ${publisherId}`;\n this.logger.warn(error, { plugin: plugin.name, publisherId });\n \n if (this.config.strictMode && !this.config.allowSelfSigned) {\n throw new Error(error);\n }\n \n return {\n verified: false,\n error,\n publisherId,\n };\n }\n \n // 3. Compute plugin code hash\n const pluginHash = this.computePluginHash(plugin);\n \n // 4. Verify signature using crypto module\n const isValid = await this.verifyCryptoSignature(\n pluginHash,\n plugin.signature,\n publicKey\n );\n \n if (!isValid) {\n const error = `Signature verification failed for plugin: ${plugin.name}`;\n this.logger.error(error, undefined, { plugin: plugin.name, publisherId });\n throw new Error(error);\n }\n \n this.logger.info(`✅ Plugin signature verified: ${plugin.name}`, {\n plugin: plugin.name,\n publisherId,\n algorithm: this.config.algorithm,\n });\n \n return {\n verified: true,\n publisherId,\n algorithm: this.config.algorithm,\n };\n \n } catch (error) {\n this.logger.error(`Signature verification error: ${plugin.name}`, error as Error);\n \n if (this.config.strictMode) {\n throw error;\n }\n \n return {\n verified: false,\n error: (error as Error).message,\n };\n }\n }\n \n /**\n * Register a trusted public key for a publisher\n */\n registerPublicKey(publisherId: string, publicKey: string): void {\n this.config.trustedPublicKeys.set(publisherId, publicKey);\n this.logger.info(`Trusted public key registered for: ${publisherId}`);\n }\n \n /**\n * Remove a trusted public key\n */\n revokePublicKey(publisherId: string): void {\n this.config.trustedPublicKeys.delete(publisherId);\n this.logger.warn(`Public key revoked for: ${publisherId}`);\n }\n \n /**\n * Get list of trusted publishers\n */\n getTrustedPublishers(): string[] {\n return Array.from(this.config.trustedPublicKeys.keys());\n }\n \n // Private methods\n \n private handleUnsignedPlugin(plugin: PluginMetadata): SignatureVerificationResult {\n if (this.config.strictMode) {\n const error = `Plugin missing signature (strict mode): ${plugin.name}`;\n this.logger.error(error, undefined, { plugin: plugin.name });\n throw new Error(error);\n }\n \n this.logger.warn(`⚠️ Plugin not signed: ${plugin.name}`, {\n plugin: plugin.name,\n recommendation: 'Consider signing plugins for production environments',\n });\n \n return {\n verified: false,\n error: 'Plugin not signed',\n };\n }\n \n private extractPublisherId(pluginName: string): string {\n // Extract publisher from reverse domain notation\n // Example: \"com.objectstack.engine.objectql\" -> \"com.objectstack\"\n const parts = pluginName.split('.');\n \n if (parts.length < 2) {\n throw new Error(`Invalid plugin name format: ${pluginName} (expected reverse domain notation)`);\n }\n \n // Return first two parts (domain reversed)\n return `${parts[0]}.${parts[1]}`;\n }\n \n private computePluginHash(plugin: PluginMetadata): string {\n // In browser environment, use SubtleCrypto\n if (typeof (globalThis as any).window !== 'undefined') {\n return this.computePluginHashBrowser(plugin);\n }\n \n // In Node.js environment, use crypto module\n return this.computePluginHashNode(plugin);\n }\n \n private computePluginHashNode(plugin: PluginMetadata): string {\n // Use pre-loaded crypto module\n if (!cryptoModule) {\n this.logger.warn('crypto module not available, using fallback hash');\n return this.computePluginHashFallback(plugin);\n }\n \n // Compute hash of plugin code\n const pluginCode = this.serializePluginCode(plugin);\n return cryptoModule.createHash('sha256').update(pluginCode).digest('hex');\n }\n \n private computePluginHashBrowser(plugin: PluginMetadata): string {\n // Browser environment - use simple hash for now\n // In production, should use SubtleCrypto for proper cryptographic hash\n this.logger.debug('Using browser hash (SubtleCrypto integration pending)');\n return this.computePluginHashFallback(plugin);\n }\n \n private computePluginHashFallback(plugin: PluginMetadata): string {\n // Simple hash fallback (not cryptographically secure)\n const pluginCode = this.serializePluginCode(plugin);\n let hash = 0;\n \n for (let i = 0; i < pluginCode.length; i++) {\n const char = pluginCode.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n \n return hash.toString(16);\n }\n \n private serializePluginCode(plugin: PluginMetadata): string {\n // Serialize plugin code for hashing\n // Include init, start, destroy functions\n const parts: string[] = [\n plugin.name,\n plugin.version,\n plugin.init.toString(),\n ];\n \n if (plugin.start) {\n parts.push(plugin.start.toString());\n }\n \n if (plugin.destroy) {\n parts.push(plugin.destroy.toString());\n }\n \n return parts.join('|');\n }\n \n private async verifyCryptoSignature(\n data: string,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n // In browser environment, use SubtleCrypto\n if (typeof (globalThis as any).window !== 'undefined') {\n return this.verifyCryptoSignatureBrowser(data, signature, publicKey);\n }\n \n // In Node.js environment, use crypto module\n return this.verifyCryptoSignatureNode(data, signature, publicKey);\n }\n \n private async verifyCryptoSignatureNode(\n data: string,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n if (!cryptoModule) {\n try {\n // @ts-ignore\n cryptoModule = await import('crypto');\n } catch (e) {\n // ignore\n }\n }\n\n if (!cryptoModule) {\n this.logger.error('Crypto module not available for signature verification');\n return false;\n }\n \n try {\n // Create verify object based on algorithm\n if (this.config.algorithm === 'ES256') {\n // ECDSA verification - requires lowercase 'sha256'\n const verify = cryptoModule.createVerify('sha256');\n verify.update(data);\n return verify.verify(\n {\n key: publicKey,\n format: 'pem',\n type: 'spki',\n },\n signature,\n 'base64'\n );\n } else {\n // RSA verification (RS256)\n const verify = cryptoModule.createVerify('RSA-SHA256');\n verify.update(data);\n return verify.verify(publicKey, signature, 'base64');\n }\n } catch (error) {\n this.logger.error('Signature verification failed', error as Error);\n return false;\n }\n }\n \n private async verifyCryptoSignatureBrowser(\n data: string,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n try {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n this.logger.error('SubtleCrypto not available in this environment');\n return false;\n }\n\n // Decode PEM public key to raw DER bytes\n const pemBody = publicKey\n .replace(/-----BEGIN PUBLIC KEY-----/, '')\n .replace(/-----END PUBLIC KEY-----/, '')\n .replace(/\\s/g, '');\n const keyBytes = Uint8Array.from(atob(pemBody), c => c.charCodeAt(0));\n\n // Configure algorithms based on RS256 or ES256\n let importAlgorithm: { name: string; hash?: string; namedCurve?: string };\n let verifyAlgorithm: { name: string; hash?: string };\n\n if (this.config.algorithm === 'ES256') {\n importAlgorithm = { name: 'ECDSA', namedCurve: 'P-256' };\n verifyAlgorithm = { name: 'ECDSA', hash: 'SHA-256' };\n } else {\n importAlgorithm = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };\n verifyAlgorithm = { name: 'RSASSA-PKCS1-v1_5' };\n }\n\n const cryptoKey = await subtle.importKey(\n 'spki',\n keyBytes,\n importAlgorithm,\n false,\n ['verify']\n );\n\n // Decode base64 signature to ArrayBuffer\n const signatureBytes = Uint8Array.from(atob(signature), c => c.charCodeAt(0));\n\n // Encode data to ArrayBuffer\n const dataBytes = new TextEncoder().encode(data);\n\n return await subtle.verify(verifyAlgorithm, cryptoKey, signatureBytes, dataBytes);\n } catch (error) {\n this.logger.error('Browser signature verification failed', error as Error);\n return false;\n }\n }\n \n private validateConfig(): void {\n if (!this.config.trustedPublicKeys || this.config.trustedPublicKeys.size === 0) {\n this.logger.warn('No trusted public keys configured - all signatures will fail');\n }\n \n if (!this.config.algorithm) {\n throw new Error('Signature algorithm must be specified');\n }\n \n if (!['RS256', 'ES256'].includes(this.config.algorithm)) {\n throw new Error(`Unsupported algorithm: ${this.config.algorithm}`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { PluginCapability, PluginPermissions as GrantedPermissions } from '@objectstack/spec/kernel';\nimport type { PluginContext } from '../types.js';\n\n/**\n * Plugin Permissions\n * Defines what actions a plugin is allowed to perform\n */\nexport interface PluginPermissions {\n canAccessService(serviceName: string): boolean;\n canTriggerHook(hookName: string): boolean;\n canReadFile(path: string): boolean;\n canWriteFile(path: string): boolean;\n canNetworkRequest(url: string): boolean;\n}\n\n/**\n * Permission Check Result\n */\nexport interface PermissionCheckResult {\n allowed: boolean;\n reason?: string;\n capability?: string;\n}\n\n/**\n * Plugin Permission Enforcer\n * \n * Implements capability-based security model to enforce:\n * 1. Service access control - which services a plugin can use\n * 2. Hook restrictions - which hooks a plugin can trigger\n * 3. File system permissions - what files a plugin can read/write\n * 4. Network permissions - what URLs a plugin can access\n * \n * Architecture:\n * - Uses capability declarations from plugin manifest\n * - Checks permissions before allowing operations\n * - Logs all permission denials for security audit\n * - Supports allowlist and denylist patterns\n * \n * Security Model:\n * - Principle of least privilege - plugins get minimal permissions\n * - Explicit declaration - all capabilities must be declared\n * - Runtime enforcement - checks happen at operation time\n * - Audit trail - all denials are logged\n * \n * Usage:\n * ```typescript\n * const enforcer = new PluginPermissionEnforcer(logger);\n * enforcer.registerPluginPermissions(pluginName, capabilities);\n * enforcer.enforceServiceAccess(pluginName, 'database');\n * ```\n */\nexport class PluginPermissionEnforcer {\n private logger: Logger;\n private permissionRegistry: Map<string, PluginPermissions> = new Map();\n private capabilityRegistry: Map<string, PluginCapability[]> = new Map();\n \n constructor(logger: Logger) {\n this.logger = logger;\n }\n \n /**\n * Register plugin capabilities and build permission set\n * \n * @param pluginName - Plugin identifier\n * @param capabilities - Array of capability declarations\n */\n registerPluginPermissions(pluginName: string, capabilities: PluginCapability[]): void {\n this.capabilityRegistry.set(pluginName, capabilities);\n \n const permissions: PluginPermissions = {\n canAccessService: (service) => this.checkServiceAccess(capabilities, service),\n canTriggerHook: (hook) => this.checkHookAccess(capabilities, hook),\n canReadFile: (path) => this.checkFileRead(capabilities, path),\n canWriteFile: (path) => this.checkFileWrite(capabilities, path),\n canNetworkRequest: (url) => this.checkNetworkAccess(capabilities, url),\n };\n \n this.permissionRegistry.set(pluginName, permissions);\n \n this.logger.info(`Permissions registered for plugin: ${pluginName}`, {\n plugin: pluginName,\n capabilityCount: capabilities.length,\n });\n }\n \n /**\n * Register the install-time GRANTED permission set for a plugin\n * (ADR-0025 F4). This is the structured `{ services, hooks, network, fs }`\n * grant that the cloud control plane persists to\n * `sys_package_installation.granted_permissions` after the user consents\n * at install (ADR §3.5 step 2). The runtime calls this when materializing\n * a third-party plugin so {@link SecurePluginContext} enforces exactly the\n * consented surface — independent of whatever the manifest *requested*.\n *\n * Prefer this over {@link registerPluginPermissions} for distributed\n * plugins: it enforces what was granted, not what was declared.\n */\n registerGrantedPermissions(pluginName: string, granted: GrantedPermissions | null | undefined): void {\n this.permissionRegistry.set(pluginName, buildPermissionsFromGrants(granted));\n this.logger.info(`Granted permissions registered for plugin: ${pluginName}`, {\n plugin: pluginName,\n services: granted?.services?.length ?? 0,\n hooks: granted?.hooks?.length ?? 0,\n network: granted?.network?.length ?? 0,\n fs: granted?.fs?.length ?? 0,\n });\n }\n\n /**\n * Enforce service access permission\n *\n * @param pluginName - Plugin requesting access\n * @param serviceName - Service to access\n * @throws Error if permission denied\n */\n enforceServiceAccess(pluginName: string, serviceName: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canAccessService(serviceName));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot access service ${serviceName}`;\n this.logger.warn(error, {\n plugin: pluginName,\n service: serviceName,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`Service access granted: ${pluginName} -> ${serviceName}`);\n }\n \n /**\n * Enforce hook trigger permission\n * \n * @param pluginName - Plugin requesting access\n * @param hookName - Hook to trigger\n * @throws Error if permission denied\n */\n enforceHookTrigger(pluginName: string, hookName: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canTriggerHook(hookName));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot trigger hook ${hookName}`;\n this.logger.warn(error, {\n plugin: pluginName,\n hook: hookName,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`Hook trigger granted: ${pluginName} -> ${hookName}`);\n }\n \n /**\n * Enforce file read permission\n * \n * @param pluginName - Plugin requesting access\n * @param path - File path to read\n * @throws Error if permission denied\n */\n enforceFileRead(pluginName: string, path: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canReadFile(path));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot read file ${path}`;\n this.logger.warn(error, {\n plugin: pluginName,\n path,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`File read granted: ${pluginName} -> ${path}`);\n }\n \n /**\n * Enforce file write permission\n * \n * @param pluginName - Plugin requesting access\n * @param path - File path to write\n * @throws Error if permission denied\n */\n enforceFileWrite(pluginName: string, path: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canWriteFile(path));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot write file ${path}`;\n this.logger.warn(error, {\n plugin: pluginName,\n path,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`File write granted: ${pluginName} -> ${path}`);\n }\n \n /**\n * Enforce network request permission\n * \n * @param pluginName - Plugin requesting access\n * @param url - URL to access\n * @throws Error if permission denied\n */\n enforceNetworkRequest(pluginName: string, url: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canNetworkRequest(url));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot access URL ${url}`;\n this.logger.warn(error, {\n plugin: pluginName,\n url,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`Network request granted: ${pluginName} -> ${url}`);\n }\n \n /**\n * Get plugin capabilities\n * \n * @param pluginName - Plugin identifier\n * @returns Array of capabilities or undefined\n */\n getPluginCapabilities(pluginName: string): PluginCapability[] | undefined {\n return this.capabilityRegistry.get(pluginName);\n }\n \n /**\n * Get plugin permissions\n * \n * @param pluginName - Plugin identifier\n * @returns Permissions object or undefined\n */\n getPluginPermissions(pluginName: string): PluginPermissions | undefined {\n return this.permissionRegistry.get(pluginName);\n }\n \n /**\n * Revoke all permissions for a plugin\n * \n * @param pluginName - Plugin identifier\n */\n revokePermissions(pluginName: string): void {\n this.permissionRegistry.delete(pluginName);\n this.capabilityRegistry.delete(pluginName);\n this.logger.warn(`Permissions revoked for plugin: ${pluginName}`);\n }\n \n // Private methods\n \n private checkPermission(\n pluginName: string,\n check: (perms: PluginPermissions) => boolean\n ): PermissionCheckResult {\n const permissions = this.permissionRegistry.get(pluginName);\n \n if (!permissions) {\n return {\n allowed: false,\n reason: 'Plugin permissions not registered',\n };\n }\n \n const allowed = check(permissions);\n \n return {\n allowed,\n reason: allowed ? undefined : 'No matching capability found',\n };\n }\n \n private checkServiceAccess(capabilities: PluginCapability[], serviceName: string): boolean {\n // Check if plugin has capability to access this service\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for wildcard service access\n if (protocolId.includes('protocol.service.all')) {\n return true;\n }\n \n // Check for specific service protocol\n if (protocolId.includes(`protocol.service.${serviceName}`)) {\n return true;\n }\n \n // Check for service category match\n const serviceCategory = serviceName.split('.')[0];\n if (protocolId.includes(`protocol.service.${serviceCategory}`)) {\n return true;\n }\n \n return false;\n });\n }\n \n private checkHookAccess(capabilities: PluginCapability[], hookName: string): boolean {\n // Check if plugin has capability to trigger this hook\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for wildcard hook access\n if (protocolId.includes('protocol.hook.all')) {\n return true;\n }\n \n // Check for specific hook protocol\n if (protocolId.includes(`protocol.hook.${hookName}`)) {\n return true;\n }\n \n // Check for hook category match\n const hookCategory = hookName.split(':')[0];\n if (protocolId.includes(`protocol.hook.${hookCategory}`)) {\n return true;\n }\n \n return false;\n });\n }\n \n private matchGlob(pattern: string, str: string): boolean {\n const regexStr = pattern\n .split('**')\n .map(segment => {\n const escaped = segment.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return escaped.replace(/\\*/g, '[^/]*');\n })\n .join('.*');\n return new RegExp(`^${regexStr}$`).test(str);\n }\n \n private checkFileRead(capabilities: PluginCapability[], path: string): boolean {\n // Check if plugin has capability to read this file\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for file read capability\n if (protocolId.includes('protocol.filesystem.read')) {\n const paths = cap.metadata?.paths;\n if (!Array.isArray(paths) || paths.length === 0) {\n return true;\n }\n return paths.some(p => typeof p === 'string' && this.matchGlob(p, path));\n }\n \n return false;\n });\n }\n \n private checkFileWrite(capabilities: PluginCapability[], path: string): boolean {\n // Check if plugin has capability to write this file\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for file write capability\n if (protocolId.includes('protocol.filesystem.write')) {\n const paths = cap.metadata?.paths;\n if (!Array.isArray(paths) || paths.length === 0) {\n return true;\n }\n return paths.some(p => typeof p === 'string' && this.matchGlob(p, path));\n }\n \n return false;\n });\n }\n \n private checkNetworkAccess(capabilities: PluginCapability[], url: string): boolean {\n // Check if plugin has capability to access this URL\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for network capability\n if (protocolId.includes('protocol.network')) {\n const hosts = cap.metadata?.hosts;\n if (!Array.isArray(hosts) || hosts.length === 0) {\n return true;\n }\n return hosts.some(h => typeof h === 'string' && this.matchGlob(h, url));\n }\n \n return false;\n });\n }\n}\n\n/**\n * Secure Plugin Context\n * Wraps PluginContext with permission checks\n */\nexport class SecurePluginContext implements PluginContext {\n constructor(\n private pluginName: string,\n private permissionEnforcer: PluginPermissionEnforcer,\n private baseContext: PluginContext\n ) {}\n \n registerService(name: string, service: any): void {\n // No permission check for service registration (handled during init)\n this.baseContext.registerService(name, service);\n }\n \n getService<T>(name: string): T {\n // Check permission before accessing service\n this.permissionEnforcer.enforceServiceAccess(this.pluginName, name);\n return this.baseContext.getService<T>(name);\n }\n \n replaceService<T>(name: string, implementation: T): void {\n // Check permission before replacing service\n this.permissionEnforcer.enforceServiceAccess(this.pluginName, name);\n this.baseContext.replaceService(name, implementation);\n }\n \n getServices(): Map<string, any> {\n // Return all services (no permission check for listing)\n return this.baseContext.getServices();\n }\n \n hook(name: string, handler: (...args: any[]) => void | Promise<void>): void {\n // No permission check for registering hooks (handled during init)\n this.baseContext.hook(name, handler);\n }\n \n async trigger(name: string, ...args: any[]): Promise<void> {\n // Check permission before triggering hook\n this.permissionEnforcer.enforceHookTrigger(this.pluginName, name);\n await this.baseContext.trigger(name, ...args);\n }\n \n get logger() {\n return this.baseContext.logger;\n }\n \n getKernel() {\n return this.baseContext.getKernel();\n }\n\n registerServiceFactory(name: string, factory: (ctx: PluginContext, scopeId?: string) => any, lifecycle?: import('../plugin-loader.js').ServiceLifecycle, dependencies?: string[]): void {\n this.baseContext.registerServiceFactory(name, factory, lifecycle, dependencies);\n }\n\n getServiceScoped<T>(name: string, scopeId: string): Promise<T> {\n return this.baseContext.getServiceScoped<T>(name, scopeId);\n }\n}\n\n/**\n * Create a plugin permission enforcer\n *\n * @param logger - Logger instance\n * @returns Plugin permission enforcer\n */\nexport function createPluginPermissionEnforcer(logger: Logger): PluginPermissionEnforcer {\n return new PluginPermissionEnforcer(logger);\n}\n\n/**\n * Glob match supporting `*` (within a path segment) and `**` (across\n * segments). A bare `*` entry matches everything.\n */\nfunction grantGlobMatch(pattern: string, value: string): boolean {\n if (pattern === '*' || pattern === '**') return true;\n const regexStr = pattern\n .split('**')\n .map((segment) => segment.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^/]*'))\n .join('.*');\n return new RegExp(`^${regexStr}$`).test(value);\n}\n\n/** Extract the host from a URL for network-grant matching; falls back to the raw value. */\nfunction hostOf(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return url;\n }\n}\n\nconst inList = (list: string[] | undefined, value: string): boolean =>\n Array.isArray(list) && list.some((p) => p === value || grantGlobMatch(p, value));\n\n/**\n * Build the runtime {@link PluginPermissions} bag from a structured\n * install-time grant set (ADR-0025 §3.2 `{ services, hooks, network, fs }`).\n *\n * Matching: an entry allows when it equals the requested value, is a glob\n * that matches it, or is the wildcard `*`. Network grants match against the\n * request URL's host (or the raw URL). `fs` governs both read and write —\n * the structured grant set does not split the two. A null/empty grant set\n * denies everything (principle of least privilege).\n */\nexport function buildPermissionsFromGrants(\n granted: GrantedPermissions | null | undefined,\n): PluginPermissions {\n const services = granted?.services;\n const hooks = granted?.hooks;\n const network = granted?.network;\n const fs = granted?.fs;\n return {\n canAccessService: (name) => inList(services, name),\n canTriggerHook: (name) => inList(hooks, name),\n canReadFile: (path) => inList(fs, path),\n canWriteFile: (path) => inList(fs, path),\n canNetworkRequest: (url) =>\n inList(network, hostOf(url)) || inList(network, url),\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n PluginPermission,\n PluginPermissionSet,\n PermissionAction,\n ResourceType\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from '../logger.js';\n\n/**\n * Permission Grant\n * Represents a granted permission at runtime\n */\nexport interface PermissionGrant {\n permissionId: string;\n pluginId: string;\n grantedAt: Date;\n grantedBy?: string;\n expiresAt?: Date;\n conditions?: Record<string, any>;\n}\n\n/**\n * Permission Check Result\n */\nexport interface PermissionCheckResult {\n allowed: boolean;\n reason?: string;\n requiredPermission?: string;\n grantedPermissions?: string[];\n}\n\n/**\n * Plugin Permission Manager\n * \n * Manages fine-grained permissions for plugin security and access control\n */\nexport class PluginPermissionManager {\n private logger: ObjectLogger;\n \n // Plugin permission definitions\n private permissionSets = new Map<string, PluginPermissionSet>();\n \n // Granted permissions (pluginId -> Set of permission IDs)\n private grants = new Map<string, Set<string>>();\n \n // Permission grant details\n private grantDetails = new Map<string, PermissionGrant>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'PermissionManager' });\n }\n\n /**\n * Register permission requirements for a plugin\n */\n registerPermissions(pluginId: string, permissionSet: PluginPermissionSet): void {\n this.permissionSets.set(pluginId, permissionSet);\n \n this.logger.info('Permissions registered for plugin', { \n pluginId,\n permissionCount: permissionSet.permissions.length\n });\n }\n\n /**\n * Grant a permission to a plugin\n */\n grantPermission(\n pluginId: string,\n permissionId: string,\n grantedBy?: string,\n expiresAt?: Date\n ): void {\n // Verify permission exists in plugin's declared permissions\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n throw new Error(`No permissions registered for plugin: ${pluginId}`);\n }\n\n const permission = permissionSet.permissions.find(p => p.id === permissionId);\n if (!permission) {\n throw new Error(`Permission ${permissionId} not declared by plugin ${pluginId}`);\n }\n\n // Create grant\n if (!this.grants.has(pluginId)) {\n this.grants.set(pluginId, new Set());\n }\n this.grants.get(pluginId)!.add(permissionId);\n\n // Store grant details\n const grantKey = `${pluginId}:${permissionId}`;\n this.grantDetails.set(grantKey, {\n permissionId,\n pluginId,\n grantedAt: new Date(),\n grantedBy,\n expiresAt,\n });\n\n this.logger.info('Permission granted', { \n pluginId, \n permissionId,\n grantedBy \n });\n }\n\n /**\n * Revoke a permission from a plugin\n */\n revokePermission(pluginId: string, permissionId: string): void {\n const grants = this.grants.get(pluginId);\n if (grants) {\n grants.delete(permissionId);\n \n const grantKey = `${pluginId}:${permissionId}`;\n this.grantDetails.delete(grantKey);\n\n this.logger.info('Permission revoked', { pluginId, permissionId });\n }\n }\n\n /**\n * Grant all permissions for a plugin\n */\n grantAllPermissions(pluginId: string, grantedBy?: string): void {\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n throw new Error(`No permissions registered for plugin: ${pluginId}`);\n }\n\n for (const permission of permissionSet.permissions) {\n this.grantPermission(pluginId, permission.id, grantedBy);\n }\n\n this.logger.info('All permissions granted', { pluginId, grantedBy });\n }\n\n /**\n * Check if a plugin has a specific permission\n */\n hasPermission(pluginId: string, permissionId: string): boolean {\n const grants = this.grants.get(pluginId);\n if (!grants) {\n return false;\n }\n\n // Check if granted\n if (!grants.has(permissionId)) {\n return false;\n }\n\n // Check expiration\n const grantKey = `${pluginId}:${permissionId}`;\n const grantDetails = this.grantDetails.get(grantKey);\n if (grantDetails?.expiresAt && grantDetails.expiresAt < new Date()) {\n this.revokePermission(pluginId, permissionId);\n return false;\n }\n\n return true;\n }\n\n /**\n * Check if plugin can perform an action on a resource\n */\n checkAccess(\n pluginId: string,\n resource: ResourceType,\n action: PermissionAction,\n resourceId?: string\n ): PermissionCheckResult {\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n return {\n allowed: false,\n reason: 'No permissions registered for plugin',\n };\n }\n\n // Find matching permissions\n const matchingPermissions = permissionSet.permissions.filter(p => {\n // Check resource type\n if (p.resource !== resource) {\n return false;\n }\n\n // Check action\n if (!p.actions.includes(action)) {\n return false;\n }\n\n // Check resource filter if specified\n if (resourceId && p.filter?.resourceIds) {\n if (!p.filter.resourceIds.includes(resourceId)) {\n return false;\n }\n }\n\n return true;\n });\n\n if (matchingPermissions.length === 0) {\n return {\n allowed: false,\n reason: `No permission found for ${action} on ${resource}`,\n };\n }\n\n // Check if any matching permission is granted\n const grantedPermissions = matchingPermissions.filter(p => \n this.hasPermission(pluginId, p.id)\n );\n\n if (grantedPermissions.length === 0) {\n return {\n allowed: false,\n reason: 'Required permissions not granted',\n requiredPermission: matchingPermissions[0].id,\n };\n }\n\n return {\n allowed: true,\n grantedPermissions: grantedPermissions.map(p => p.id),\n };\n }\n\n /**\n * Get all permissions for a plugin\n */\n getPluginPermissions(pluginId: string): PluginPermission[] {\n const permissionSet = this.permissionSets.get(pluginId);\n return permissionSet?.permissions || [];\n }\n\n /**\n * Get granted permissions for a plugin\n */\n getGrantedPermissions(pluginId: string): string[] {\n const grants = this.grants.get(pluginId);\n return grants ? Array.from(grants) : [];\n }\n\n /**\n * Get required but not granted permissions\n */\n getMissingPermissions(pluginId: string): PluginPermission[] {\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n return [];\n }\n\n const granted = this.grants.get(pluginId) || new Set();\n \n return permissionSet.permissions.filter(p => \n p.required && !granted.has(p.id)\n );\n }\n\n /**\n * Check if all required permissions are granted\n */\n hasAllRequiredPermissions(pluginId: string): boolean {\n return this.getMissingPermissions(pluginId).length === 0;\n }\n\n /**\n * Get permission grant details\n */\n getGrantDetails(pluginId: string, permissionId: string): PermissionGrant | undefined {\n const grantKey = `${pluginId}:${permissionId}`;\n return this.grantDetails.get(grantKey);\n }\n\n /**\n * Validate permission against scope constraints\n */\n validatePermissionScope(\n permission: PluginPermission,\n context: {\n tenantId?: string;\n userId?: string;\n resourceId?: string;\n }\n ): boolean {\n switch (permission.scope) {\n case 'global':\n return true;\n\n case 'tenant':\n return !!context.tenantId;\n\n case 'user':\n return !!context.userId;\n\n case 'resource':\n return !!context.resourceId;\n\n case 'plugin':\n return true;\n\n default:\n return false;\n }\n }\n\n /**\n * Clear all permissions for a plugin\n */\n clearPluginPermissions(pluginId: string): void {\n this.permissionSets.delete(pluginId);\n \n const grants = this.grants.get(pluginId);\n if (grants) {\n for (const permissionId of grants) {\n const grantKey = `${pluginId}:${permissionId}`;\n this.grantDetails.delete(grantKey);\n }\n this.grants.delete(pluginId);\n }\n\n this.logger.info('All permissions cleared', { pluginId });\n }\n\n /**\n * Shutdown permission manager\n */\n shutdown(): void {\n this.permissionSets.clear();\n this.grants.clear();\n this.grantDetails.clear();\n \n this.logger.info('Permission manager shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport nodePath from 'node:path';\n\nimport type { \n SandboxConfig\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from '../logger.js';\nimport { getMemoryUsage } from '../utils/env.js';\n\n/**\n * Resource Usage Statistics\n */\nexport interface ResourceUsage {\n memory: {\n current: number;\n peak: number;\n limit?: number;\n };\n cpu: {\n current: number;\n average: number;\n limit?: number;\n };\n connections: {\n current: number;\n limit?: number;\n };\n}\n\n/**\n * Sandbox Execution Context\n * Represents an isolated execution environment for a plugin\n */\nexport interface SandboxContext {\n pluginId: string;\n config: SandboxConfig;\n startTime: Date;\n resourceUsage: ResourceUsage;\n}\n\n/**\n * Plugin Sandbox Runtime\n * \n * Provides isolated execution environments for plugins with resource limits\n * and access controls\n */\nexport class PluginSandboxRuntime {\n private static readonly MONITORING_INTERVAL_MS = 5000;\n\n private logger: ObjectLogger;\n \n // Active sandboxes (pluginId -> context)\n private sandboxes = new Map<string, SandboxContext>();\n \n // Resource monitoring intervals\n private monitoringIntervals = new Map<string, NodeJS.Timeout>();\n\n // Per-plugin resource baselines for delta tracking\n private memoryBaselines = new Map<string, number>();\n private cpuBaselines = new Map<string, { user: number; system: number }>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'SandboxRuntime' });\n }\n\n /**\n * Create a sandbox for a plugin\n */\n createSandbox(pluginId: string, config: SandboxConfig): SandboxContext {\n if (this.sandboxes.has(pluginId)) {\n throw new Error(`Sandbox already exists for plugin: ${pluginId}`);\n }\n\n const context: SandboxContext = {\n pluginId,\n config,\n startTime: new Date(),\n resourceUsage: {\n memory: { current: 0, peak: 0, limit: config.memory?.maxHeap },\n cpu: { current: 0, average: 0, limit: config.cpu?.maxCpuPercent },\n connections: { current: 0, limit: config.network?.maxConnections },\n },\n };\n\n this.sandboxes.set(pluginId, context);\n\n // Capture resource baselines for per-plugin delta tracking\n const baselineMemory = getMemoryUsage();\n this.memoryBaselines.set(pluginId, baselineMemory.heapUsed);\n this.cpuBaselines.set(pluginId, process.cpuUsage());\n\n // Start resource monitoring\n this.startResourceMonitoring(pluginId);\n\n this.logger.info('Sandbox created', { \n pluginId,\n level: config.level,\n memoryLimit: config.memory?.maxHeap,\n cpuLimit: config.cpu?.maxCpuPercent\n });\n\n return context;\n }\n\n /**\n * Destroy a sandbox\n */\n destroySandbox(pluginId: string): void {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return;\n }\n\n // Stop monitoring\n this.stopResourceMonitoring(pluginId);\n\n this.memoryBaselines.delete(pluginId);\n this.cpuBaselines.delete(pluginId);\n this.sandboxes.delete(pluginId);\n\n this.logger.info('Sandbox destroyed', { pluginId });\n }\n\n /**\n * Check if resource access is allowed\n */\n checkResourceAccess(\n pluginId: string,\n resourceType: 'file' | 'network' | 'process' | 'env',\n resourcePath?: string\n ): { allowed: boolean; reason?: string } {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return { allowed: false, reason: 'Sandbox not found' };\n }\n\n const { config } = context;\n\n switch (resourceType) {\n case 'file':\n return this.checkFileAccess(config, resourcePath);\n \n case 'network':\n return this.checkNetworkAccess(config, resourcePath);\n \n case 'process':\n return this.checkProcessAccess(config);\n \n case 'env':\n return this.checkEnvAccess(config, resourcePath);\n \n default:\n return { allowed: false, reason: 'Unknown resource type' };\n }\n }\n\n /**\n * Check file system access\n * Uses path.resolve() and path.normalize() to prevent directory traversal.\n */\n private checkFileAccess(\n config: SandboxConfig,\n filePath?: string\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.filesystem) {\n return { allowed: false, reason: 'File system access not configured' };\n }\n\n // If no path specified, check general access\n if (!filePath) {\n return { allowed: config.filesystem.mode !== 'none' };\n }\n\n // Check allowed paths using proper path resolution to prevent directory traversal\n const allowedPaths = config.filesystem.allowedPaths || [];\n const resolvedPath = nodePath.normalize(nodePath.resolve(filePath));\n const isAllowed = allowedPaths.some(allowed => {\n const resolvedAllowed = nodePath.normalize(nodePath.resolve(allowed));\n return resolvedPath.startsWith(resolvedAllowed);\n });\n\n if (allowedPaths.length > 0 && !isAllowed) {\n return { \n allowed: false, \n reason: `Path not in allowed list: ${filePath}` \n };\n }\n\n // Check denied paths using proper path resolution\n const deniedPaths = config.filesystem.deniedPaths || [];\n const isDenied = deniedPaths.some(denied => {\n const resolvedDenied = nodePath.normalize(nodePath.resolve(denied));\n return resolvedPath.startsWith(resolvedDenied);\n });\n\n if (isDenied) {\n return { \n allowed: false, \n reason: `Path is explicitly denied: ${filePath}` \n };\n }\n\n return { allowed: true };\n }\n\n /**\n * Check network access\n * Uses URL parsing to properly validate hostnames.\n */\n private checkNetworkAccess(\n config: SandboxConfig,\n url?: string\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.network) {\n return { allowed: false, reason: 'Network access not configured' };\n }\n\n // Check if network access is enabled\n if (config.network.mode === 'none') {\n return { allowed: false, reason: 'Network access disabled' };\n }\n\n // If no URL specified, check general access\n if (!url) {\n return { allowed: (config.network.mode as string) !== 'none' };\n }\n\n // Parse URL and check hostname against allowed/denied hosts\n let parsedHostname: string;\n try {\n parsedHostname = new URL(url).hostname;\n } catch {\n return { allowed: false, reason: `Invalid URL: ${url}` };\n }\n\n // Check allowed hosts\n const allowedHosts = config.network.allowedHosts || [];\n if (allowedHosts.length > 0) {\n const isAllowed = allowedHosts.some(host => {\n return parsedHostname === host;\n });\n\n if (!isAllowed) {\n return { \n allowed: false, \n reason: `Host not in allowed list: ${url}` \n };\n }\n }\n\n // Check denied hosts\n const deniedHosts = config.network.deniedHosts || [];\n const isDenied = deniedHosts.some(host => {\n return parsedHostname === host;\n });\n\n if (isDenied) {\n return { \n allowed: false, \n reason: `Host is blocked: ${url}` \n };\n }\n\n return { allowed: true };\n }\n\n /**\n * Check process spawning access\n */\n private checkProcessAccess(\n config: SandboxConfig\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.process) {\n return { allowed: false, reason: 'Process access not configured' };\n }\n\n if (!config.process.allowSpawn) {\n return { allowed: false, reason: 'Process spawning not allowed' };\n }\n\n return { allowed: true };\n }\n\n /**\n * Check environment variable access\n */\n private checkEnvAccess(\n config: SandboxConfig,\n varName?: string\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.process) {\n return { allowed: false, reason: 'Environment access not configured' };\n }\n\n // If no variable specified, check general access\n if (!varName) {\n return { allowed: true };\n }\n\n // For now, allow all env access if process is configured\n // In a real implementation, would check specific allowed vars\n return { allowed: true };\n }\n\n /**\n * Check resource limits\n */\n checkResourceLimits(pluginId: string): { \n withinLimits: boolean; \n violations: string[] \n } {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return { withinLimits: true, violations: [] };\n }\n\n const violations: string[] = [];\n const { resourceUsage, config } = context;\n\n // Check memory limit\n if (config.memory?.maxHeap && \n resourceUsage.memory.current > config.memory.maxHeap) {\n violations.push(`Memory limit exceeded: ${resourceUsage.memory.current} > ${config.memory.maxHeap}`);\n }\n\n // Check CPU limit (would need runtime config)\n if (config.runtime?.resourceLimits?.maxCpu && \n resourceUsage.cpu.current > config.runtime.resourceLimits.maxCpu) {\n violations.push(`CPU limit exceeded: ${resourceUsage.cpu.current}% > ${config.runtime.resourceLimits.maxCpu}%`);\n }\n\n // Check connection limit\n if (config.network?.maxConnections && \n resourceUsage.connections.current > config.network.maxConnections) {\n violations.push(`Connection limit exceeded: ${resourceUsage.connections.current} > ${config.network.maxConnections}`);\n }\n\n return {\n withinLimits: violations.length === 0,\n violations,\n };\n }\n\n /**\n * Get resource usage for a plugin\n */\n getResourceUsage(pluginId: string): ResourceUsage | undefined {\n const context = this.sandboxes.get(pluginId);\n return context?.resourceUsage;\n }\n\n /**\n * Start monitoring resource usage\n */\n private startResourceMonitoring(pluginId: string): void {\n // Monitor at the configured interval\n const interval = setInterval(() => {\n this.updateResourceUsage(pluginId);\n }, PluginSandboxRuntime.MONITORING_INTERVAL_MS);\n\n this.monitoringIntervals.set(pluginId, interval);\n }\n\n /**\n * Stop monitoring resource usage\n */\n private stopResourceMonitoring(pluginId: string): void {\n const interval = this.monitoringIntervals.get(pluginId);\n if (interval) {\n clearInterval(interval);\n this.monitoringIntervals.delete(pluginId);\n }\n }\n\n /**\n * Update resource usage statistics\n * \n * Tracks per-plugin memory and CPU usage using delta from baseline\n * captured at sandbox creation time. This is an approximation since\n * true per-plugin isolation isn't possible in a single Node.js process.\n */\n private updateResourceUsage(pluginId: string): void {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return;\n }\n\n // In a real implementation, this would collect actual metrics\n // For now, this is a placeholder structure\n \n // Update memory usage using delta from baseline for per-plugin approximation\n const memoryUsage = getMemoryUsage();\n const memoryBaseline = this.memoryBaselines.get(pluginId) ?? 0;\n const memoryDelta = Math.max(0, memoryUsage.heapUsed - memoryBaseline);\n context.resourceUsage.memory.current = memoryDelta;\n context.resourceUsage.memory.peak = Math.max(\n context.resourceUsage.memory.peak,\n memoryDelta\n );\n\n // Update CPU usage using delta from baseline for per-plugin approximation\n const cpuBaseline = this.cpuBaselines.get(pluginId) ?? { user: 0, system: 0 };\n const cpuCurrent = process.cpuUsage();\n const cpuDeltaUser = cpuCurrent.user - cpuBaseline.user;\n const cpuDeltaSystem = cpuCurrent.system - cpuBaseline.system;\n // Convert microseconds to a percentage approximation over the monitoring interval\n const totalCpuMicros = cpuDeltaUser + cpuDeltaSystem;\n const intervalMicros = PluginSandboxRuntime.MONITORING_INTERVAL_MS * 1000;\n context.resourceUsage.cpu.current = (totalCpuMicros / intervalMicros) * 100;\n // Update baseline for next interval\n this.cpuBaselines.set(pluginId, cpuCurrent);\n\n // Check for violations\n const { withinLimits, violations } = this.checkResourceLimits(pluginId);\n if (!withinLimits) {\n this.logger.warn('Resource limit violations detected', { \n pluginId, \n violations \n });\n }\n }\n\n /**\n * Get all active sandboxes\n */\n getAllSandboxes(): Map<string, SandboxContext> {\n return new Map(this.sandboxes);\n }\n\n /**\n * Shutdown sandbox runtime\n */\n shutdown(): void {\n // Stop all monitoring\n for (const pluginId of this.monitoringIntervals.keys()) {\n this.stopResourceMonitoring(pluginId);\n }\n\n this.sandboxes.clear();\n this.memoryBaselines.clear();\n this.cpuBaselines.clear();\n \n this.logger.info('Sandbox runtime shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n KernelSecurityVulnerability,\n KernelSecurityScanResult\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from '../logger.js';\n\n/**\n * Scan Target\n */\nexport interface ScanTarget {\n pluginId: string;\n version: string;\n files?: string[];\n dependencies?: Record<string, string>;\n}\n\n/**\n * Security Issue\n */\nexport interface SecurityIssue {\n id: string;\n severity: 'critical' | 'high' | 'medium' | 'low' | 'info';\n category: 'vulnerability' | 'malware' | 'license' | 'code-quality' | 'configuration';\n title: string;\n description: string;\n location?: {\n file?: string;\n line?: number;\n column?: number;\n };\n remediation?: string;\n cve?: string;\n cvss?: number;\n}\n\n/**\n * Plugin Security Scanner\n * \n * Scans plugins for security vulnerabilities, malware, and license issues\n */\nexport class PluginSecurityScanner {\n private logger: ObjectLogger;\n \n // Known vulnerabilities database (CVE cache)\n private vulnerabilityDb = new Map<string, KernelSecurityVulnerability>();\n \n // Scan results cache\n private scanResults = new Map<string, KernelSecurityScanResult>();\n\n private passThreshold: number = 70;\n\n constructor(logger: ObjectLogger, config?: { passThreshold?: number }) {\n this.logger = logger.child({ component: 'SecurityScanner' });\n if (config?.passThreshold !== undefined) {\n this.passThreshold = config.passThreshold;\n }\n }\n\n /**\n * Perform a comprehensive security scan on a plugin\n */\n async scan(target: ScanTarget): Promise<KernelSecurityScanResult> {\n this.logger.info('Starting security scan', { \n pluginId: target.pluginId,\n version: target.version \n });\n\n const issues: SecurityIssue[] = [];\n\n try {\n // 1. Scan for code vulnerabilities\n const codeIssues = await this.scanCode(target);\n issues.push(...codeIssues);\n\n // 2. Scan dependencies for known vulnerabilities\n const depIssues = await this.scanDependencies(target);\n issues.push(...depIssues);\n\n // 3. Scan for malware patterns\n const malwareIssues = await this.scanMalware(target);\n issues.push(...malwareIssues);\n\n // 4. Check license compliance\n const licenseIssues = await this.scanLicenses(target);\n issues.push(...licenseIssues);\n\n // 5. Check configuration security\n const configIssues = await this.scanConfiguration(target);\n issues.push(...configIssues);\n\n // Calculate security score (0-100, higher is better)\n const score = this.calculateSecurityScore(issues);\n\n const result: KernelSecurityScanResult = {\n timestamp: new Date().toISOString(),\n scanner: { name: 'ObjectStack Security Scanner', version: '1.0.0' },\n status: score >= this.passThreshold ? 'passed' : 'failed',\n vulnerabilities: issues.map(issue => ({\n id: issue.id,\n severity: issue.severity,\n category: issue.category,\n title: issue.title,\n description: issue.description,\n location: issue.location ? `${issue.location.file}:${issue.location.line}` : undefined,\n remediation: issue.remediation,\n affectedVersions: [],\n exploitAvailable: false,\n patchAvailable: false,\n })),\n summary: {\n totalVulnerabilities: issues.length,\n criticalCount: issues.filter(i => i.severity === 'critical').length,\n highCount: issues.filter(i => i.severity === 'high').length,\n mediumCount: issues.filter(i => i.severity === 'medium').length,\n lowCount: issues.filter(i => i.severity === 'low').length,\n infoCount: issues.filter(i => i.severity === 'info').length,\n },\n };\n\n this.scanResults.set(`${target.pluginId}:${target.version}`, result);\n\n this.logger.info('Security scan complete', { \n pluginId: target.pluginId,\n score,\n status: result.status,\n summary: result.summary\n });\n\n return result;\n } catch (error) {\n this.logger.error('Security scan failed', { \n pluginId: target.pluginId, \n error \n });\n\n throw error;\n }\n }\n\n /**\n * Scan code for vulnerabilities\n */\n private async scanCode(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n // In a real implementation, this would:\n // - Parse code with AST (e.g., using @typescript-eslint/parser)\n // - Check for dangerous patterns (eval, Function constructor, etc.)\n // - Check for XSS vulnerabilities\n // - Check for SQL injection patterns\n // - Check for insecure crypto usage\n // - Check for path traversal vulnerabilities\n\n this.logger.debug('Code scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Scan dependencies for known vulnerabilities\n */\n private async scanDependencies(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n if (!target.dependencies) {\n return issues;\n }\n\n // In a real implementation, this would:\n // - Query npm audit API\n // - Check GitHub Advisory Database\n // - Check Snyk vulnerability database\n // - Check OSV (Open Source Vulnerabilities)\n\n for (const [depName, version] of Object.entries(target.dependencies)) {\n const vulnKey = `${depName}@${version}`;\n const vulnerability = this.vulnerabilityDb.get(vulnKey);\n\n if (vulnerability) {\n issues.push({\n id: `vuln-${vulnerability.cve || depName}`,\n severity: vulnerability.severity,\n category: 'vulnerability',\n title: `Vulnerable dependency: ${depName}`,\n description: `${depName}@${version} has known security vulnerabilities`,\n remediation: vulnerability.fixedIn \n ? `Upgrade to ${vulnerability.fixedIn.join(' or ')}`\n : 'No fix available',\n cve: vulnerability.cve,\n });\n }\n }\n\n this.logger.debug('Dependency scan complete', { \n pluginId: target.pluginId,\n dependencies: Object.keys(target.dependencies).length,\n vulnerabilities: issues.length \n });\n\n return issues;\n }\n\n /**\n * Scan for malware patterns\n */\n private async scanMalware(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n // In a real implementation, this would:\n // - Check for obfuscated code\n // - Check for suspicious network activity patterns\n // - Check for crypto mining patterns\n // - Check for data exfiltration patterns\n // - Use ML-based malware detection\n // - Check file hashes against known malware databases\n\n this.logger.debug('Malware scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Check license compliance\n */\n private async scanLicenses(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n if (!target.dependencies) {\n return issues;\n }\n\n // In a real implementation, this would:\n // - Check license compatibility\n // - Detect GPL contamination\n // - Flag proprietary dependencies\n // - Check for missing licenses\n // - Verify SPDX identifiers\n\n this.logger.debug('License scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Check configuration security\n */\n private async scanConfiguration(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n // In a real implementation, this would:\n // - Check for hardcoded secrets\n // - Check for weak permissions\n // - Check for insecure defaults\n // - Check for missing security headers\n // - Check CSP policies\n\n this.logger.debug('Configuration scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Calculate security score based on issues\n */\n private calculateSecurityScore(issues: SecurityIssue[]): number {\n // Start with perfect score\n let score = 100;\n\n // Deduct points based on severity\n for (const issue of issues) {\n switch (issue.severity) {\n case 'critical':\n score -= 20;\n break;\n case 'high':\n score -= 10;\n break;\n case 'medium':\n score -= 5;\n break;\n case 'low':\n score -= 2;\n break;\n case 'info':\n score -= 0;\n break;\n }\n }\n\n // Ensure score doesn't go below 0\n return Math.max(0, score);\n }\n\n /**\n * Add a vulnerability to the database\n */\n addVulnerability(\n packageName: string,\n version: string,\n vulnerability: KernelSecurityVulnerability\n ): void {\n const key = `${packageName}@${version}`;\n this.vulnerabilityDb.set(key, vulnerability);\n \n this.logger.debug('Vulnerability added to database', { \n package: packageName, \n version,\n cve: vulnerability.cve \n });\n }\n\n /**\n * Get scan result from cache\n */\n getScanResult(pluginId: string, version: string): KernelSecurityScanResult | undefined {\n return this.scanResults.get(`${pluginId}:${version}`);\n }\n\n /**\n * Clear scan results cache\n */\n clearCache(): void {\n this.scanResults.clear();\n this.logger.debug('Scan results cache cleared');\n }\n\n /**\n * Update vulnerability database from external source\n */\n async updateVulnerabilityDatabase(): Promise<void> {\n this.logger.info('Updating vulnerability database');\n\n // In a real implementation, this would:\n // - Fetch from GitHub Advisory Database\n // - Fetch from npm audit\n // - Fetch from NVD (National Vulnerability Database)\n // - Parse and cache vulnerability data\n\n this.logger.info('Vulnerability database updated', { \n entries: this.vulnerabilityDb.size \n });\n }\n\n /**\n * Shutdown security scanner\n */\n shutdown(): void {\n this.vulnerabilityDb.clear();\n this.scanResults.clear();\n \n this.logger.info('Security scanner shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * api-key — hand-rolled API-key primitives + verifier for `sys_api_key`.\n *\n * better-auth 1.6.x ships no apiKey plugin, so ObjectStack owns the full\n * lifecycle: generation, at-rest hashing, header extraction, validation, and\n * the verify-time principal lookup. This is the SINGLE shared source of truth\n * used by BOTH inbound surfaces — the runtime dispatcher / MCP path\n * (`resolveExecutionContext`) and the REST data API (`@objectstack/rest`) — so\n * the two can never drift on how a key authenticates. It lives in\n * `@objectstack/core` (server-side; both `runtime` and `rest` depend on it,\n * and `core` depends on neither, so there is no cycle).\n *\n * SECURITY (zero-tolerance):\n * - The raw key is returned EXACTLY ONCE, by {@link generateApiKey}. It is\n * never persisted; only `sha256(raw)` (hex) is stored in `sys_api_key.key`.\n * - The raw key and its hash must never enter logs, HTTP responses, error\n * messages, commit messages or comments.\n * - Validation is fail-closed: anything ambiguous (missing, revoked, expired,\n * malformed) resolves to \"no principal\", never to an elevated one.\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\n\n/** Default visible prefix for generated keys (helps users identify a key). */\nexport const API_KEY_PREFIX = 'osk_';\n\n/** Bytes of entropy in the secret portion of a generated key (256 bits). */\nconst API_KEY_ENTROPY_BYTES = 32;\n\n/** Length of the human-visible prefix stored in `sys_api_key.prefix`. */\nconst VISIBLE_PREFIX_LEN = 12;\n\n/**\n * Derive the at-rest hash for an API key. Inbound keys are hashed the same way\n * before the DB lookup. Because the lookup matches an indexed, high-entropy\n * hash exactly, this doubles as a constant-effort comparison: an attacker\n * cannot recover the raw key by probing for partial matches.\n */\nexport function hashApiKey(raw: string): string {\n return createHash('sha256').update(raw, 'utf8').digest('hex');\n}\n\n/** Result of {@link generateApiKey}. `raw` is shown to the user only once. */\nexport interface GeneratedApiKey {\n /** The full secret to hand to the client. NEVER persist this. */\n raw: string;\n /** `sha256(raw)` hex — store this in `sys_api_key.key`. */\n hash: string;\n /** Short non-secret prefix for display/identification (`sys_api_key.prefix`). */\n prefix: string;\n}\n\n/**\n * Generate a fresh API key. Returns the raw secret (caller must surface it to\n * the user exactly once and then discard it), its at-rest hash, and a short\n * non-secret prefix for display.\n */\nexport function generateApiKey(prefix: string = API_KEY_PREFIX): GeneratedApiKey {\n // base64url so the token is URL/header-safe with no padding.\n const secret = randomBytes(API_KEY_ENTROPY_BYTES).toString('base64url');\n const raw = `${prefix}${secret}`;\n return {\n raw,\n hash: hashApiKey(raw),\n prefix: raw.slice(0, VISIBLE_PREFIX_LEN),\n };\n}\n\n/**\n * Extract an API key from request headers. Accepts, in order:\n * - `X-API-Key: <token>`\n * - `Authorization: ApiKey <token>` (case-insensitive scheme)\n * - `Authorization: Bearer <token>` ONLY when `<token>` carries the ObjectStack\n * api-key prefix (`osk_`). Remote MCP clients (Claude Desktop / Cursor /\n * Claude Code) authenticate to `/api/v1/mcp` with the key as a Bearer per the\n * MCP spec, so rejecting Bearer outright made every standard MCP client fail.\n * A better-auth *session* token never starts with `osk_`, so a session Bearer\n * still falls through to the session path — this can't shadow it.\n */\nexport function extractApiKey(headers: any): string | undefined {\n const x = readHeader(headers, 'x-api-key');\n if (x && x.trim()) return x.trim();\n const auth = readHeader(headers, 'authorization');\n if (!auth) return undefined;\n const apiKeyScheme = auth.match(/^ApiKey\\s+(\\S.*)$/i);\n if (apiKeyScheme?.[1]?.trim()) return apiKeyScheme[1].trim();\n // Bearer is accepted only for prefixed api-keys (never for session tokens).\n const bearer = auth.match(/^Bearer\\s+(\\S.*)$/i)?.[1]?.trim();\n if (bearer && bearer.startsWith(API_KEY_PREFIX)) return bearer;\n return undefined;\n}\n\n/** Parse a `scopes` value that may be a JSON-string textarea or a real array. */\nexport function parseScopes(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.filter((s): s is string => typeof s === 'string' && s.length > 0);\n }\n if (typeof value === 'string' && value.trim()) {\n const parsed = safeJsonParse<unknown>(value, []);\n if (Array.isArray(parsed)) {\n return parsed.filter((s): s is string => typeof s === 'string' && s.length > 0);\n }\n }\n return [];\n}\n\n/** Return true when an expiry timestamp is in the past (i.e. the key is dead). */\nexport function isExpired(value: unknown, nowMs: number): boolean {\n if (value == null) return false;\n let ms: number;\n if (typeof value === 'number') {\n // Heuristic: seconds vs milliseconds epoch.\n ms = value < 1e12 ? value * 1000 : value;\n } else if (value instanceof Date) {\n ms = value.getTime();\n } else if (typeof value === 'string') {\n ms = Date.parse(value);\n } else {\n return false;\n }\n if (Number.isNaN(ms)) return false;\n return ms <= nowMs;\n}\n\n/** The principal resolved from a valid `sys_api_key`. */\nexport interface ApiKeyPrincipal {\n userId: string;\n tenantId?: string;\n scopes: string[];\n}\n\n/**\n * Verify an inbound API key against `sys_api_key` and resolve its principal.\n * This is the ONE verify path shared by the dispatcher/MCP and REST surfaces.\n *\n * Fail-closed: returns `undefined` for a missing key, an unusable data engine,\n * a lookup error, or a key that is unknown / revoked / expired / owner-less.\n *\n * @param ql A data engine with `find(object, { where, limit, context })`.\n * @param headers Request headers (Web `Headers` or a plain object).\n * @param nowMs Clock for expiry checks (injectable for tests).\n */\nexport async function resolveApiKeyPrincipal(\n ql: any,\n headers: any,\n nowMs: number = Date.now(),\n): Promise<ApiKeyPrincipal | undefined> {\n const apiKey = extractApiKey(headers);\n if (!apiKey) return undefined;\n if (!ql || typeof ql.find !== 'function') return undefined;\n\n // Match by the indexed at-rest hash only — never query by the raw key.\n let rows: any;\n try {\n rows = await ql.find('sys_api_key', {\n where: { key: hashApiKey(apiKey), revoked: false },\n limit: 1,\n context: { isSystem: true },\n });\n } catch {\n return undefined;\n }\n if (rows && (rows as any).value) rows = (rows as any).value;\n const row = Array.isArray(rows) ? rows[0] : undefined;\n if (!row || row.revoked === true) return undefined;\n\n const expiresAt = row.expires_at ?? row.expiresAt;\n if (isExpired(expiresAt, nowMs)) return undefined;\n\n const userId = row.user_id ?? row.userId;\n if (!userId || typeof userId !== 'string') return undefined;\n\n return {\n userId,\n tenantId: row.organization_id ?? row.organizationId ?? undefined,\n scopes: parseScopes(row.scopes),\n };\n}\n\nfunction readHeader(headers: any, name: string): string | undefined {\n if (!headers) return undefined;\n const lower = name.toLowerCase();\n if (typeof headers.get === 'function') {\n const v = headers.get(name) ?? headers.get(lower);\n return v == null ? undefined : String(v);\n }\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === lower) {\n const v = headers[key];\n return Array.isArray(v) ? v[0] : v == null ? undefined : String(v);\n }\n }\n return undefined;\n}\n\nfunction safeJsonParse<T>(s: string, fallback: T): T {\n try {\n return JSON.parse(s) as T;\n } catch {\n return fallback;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * resolveAuthzContext — the SINGLE source of truth for resolving an inbound\n * request's identity + authorization context (positions, permissions, RLS scoping).\n *\n * Every HTTP entry point (REST server, runtime dispatcher, MCP, any future\n * transport) MUST resolve authorization through this function — never by\n * re-reading `sys_member` / `sys_user_position` / `sys_*_permission_set` itself.\n *\n * Why this exists: authorization resolution used to be DUPLICATED across the\n * REST server (`@objectstack/rest`) and the runtime dispatcher\n * (`@objectstack/runtime`). On a security path, duplicated logic drifts and the\n * drift is silent: the REST copy had quietly omitted `sys_user_position` (so custom\n * roles granted via the ADR-0057 D4 platform-RBAC path didn't apply over REST),\n * `sys_position_permission_set`, `mapMembershipRole` normalization, the\n * platform-admin derivation, and the `ai_seat` synthesis. The API-key half was\n * already shared here (`resolveApiKeyPrincipal`); this completes the extraction\n * by bringing session + role/permission aggregation home too. There is now ONE\n * implementation; both entry points are thin adapters that supply `ql` /\n * `getSession` their own way and delegate here.\n *\n * Fail-closed: every read is defensive. Missing services / tables yield a\n * partial context (even `{ positions: [], permissions: [] }`) — enforcement is the\n * SecurityPlugin's job, never this resolver's.\n */\n\nimport {\n mapMembershipRole,\n BUILTIN_IDENTITY_PLATFORM_ADMIN,\n ADMIN_FULL_ACCESS,\n ORGANIZATION_ADMIN,\n} from '@objectstack/spec';\nimport type { AuthzPosture } from '@objectstack/spec/security';\n\nimport { resolveApiKeyPrincipal } from './api-key.js';\nimport { isGrantActive } from './grant-validity.js';\nimport { derivePosture } from './posture-ladder.js';\n\n/** The transport-agnostic authorization envelope produced from a request. */\nexport interface ResolvedAuthzContext {\n userId?: string;\n tenantId?: string;\n email?: string;\n accessToken?: string;\n positions: string[];\n permissions: string[];\n systemPermissions: string[];\n tabPermissions?: Record<string, 'visible' | 'hidden' | 'default_on' | 'default_off'>;\n /** Fellow-org user IDs for RLS scoping of identity tables (`id IN (...)`). */\n org_user_ids: string[];\n /**\n * [ADR-0095 D2/D3] The monotonic posture rung this principal resolves to,\n * DERIVED once here from held capability grants (never a better-auth role):\n * `PLATFORM_ADMIN` (unscoped `admin_full_access`) > `TENANT_ADMIN`\n * (`organization_admin`) > `MEMBER` (the authenticated floor). `EXTERNAL` is\n * defined/test-locked but never resolved yet (no external principal type —\n * see `posture-ladder.ts`). Present only for an authenticated principal;\n * anonymous requests carry no rung.\n */\n posture?: AuthzPosture;\n}\n\nexport interface ResolveAuthzInput {\n /** Data engine (ObjectQL) exposing `find(object, { where, limit, context })`. */\n ql: any;\n /** Inbound request headers (Web `Headers` or a plain record). */\n headers: any;\n /**\n * Resolve a better-auth session from `headers`, returning `{ user?, session? }`\n * (or undefined). Optional — when omitted or throwing, only the API-key path\n * runs and anonymous requests resolve to an empty context.\n */\n getSession?: (headers: any) => Promise<any> | any;\n /** Clock injection for API-key expiry (tests). */\n nowMs?: number;\n}\n\nfunction safeJsonParse<T>(s: string, fallback: T): T {\n try { return JSON.parse(s) as T; } catch { return fallback; }\n}\n\nasync function tryFind(ql: any, object: string, where: any, limit = 100): Promise<any[]> {\n if (!ql || typeof ql.find !== 'function') return [];\n try {\n let rows = await ql.find(object, { where, limit, context: { isSystem: true } } as any);\n if (rows && (rows as any).value) rows = (rows as any).value;\n return Array.isArray(rows) ? rows : [];\n } catch {\n return [];\n }\n}\n\n/**\n * Resolve the authorization context for an inbound request. Always resolves —\n * never throws. Anonymous requests yield `{ positions: [], permissions: [], ... }`.\n */\nexport async function resolveAuthzContext(input: ResolveAuthzInput): Promise<ResolvedAuthzContext> {\n const { ql, headers } = input;\n const ctx: ResolvedAuthzContext = {\n positions: [],\n permissions: [],\n systemPermissions: [],\n org_user_ids: [],\n };\n\n let userId: string | undefined;\n let tenantId: string | undefined;\n\n // 1. API key (explicit opt-in via header) takes precedence over session.\n const keyPrincipal = await resolveApiKeyPrincipal(ql, headers, input.nowMs);\n if (keyPrincipal) {\n userId = keyPrincipal.userId;\n tenantId = keyPrincipal.tenantId;\n for (const scope of keyPrincipal.scopes) {\n if (!ctx.permissions.includes(scope)) ctx.permissions.push(scope);\n }\n }\n\n // 2. Session / Bearer path — fall back when no API key resolved a user.\n if (!userId && typeof input.getSession === 'function') {\n try {\n const sessionData = await input.getSession(headers);\n userId = sessionData?.user?.id ?? sessionData?.session?.userId;\n tenantId = tenantId ?? sessionData?.session?.activeOrganizationId;\n ctx.accessToken = sessionData?.session?.token ?? ctx.accessToken;\n if (sessionData?.user?.email) ctx.email = String(sessionData.user.email);\n } catch {\n // no auth configured / bad session → anonymous\n }\n }\n\n if (!userId) return ctx;\n ctx.userId = userId;\n if (tenantId) ctx.tenantId = tenantId;\n if (!ql || typeof ql.find !== 'function') return ctx;\n\n // sys_user is needed for both the `current_user.email` fallback (API-key auth,\n // where the session didn't supply an email) and the ai_seat synthesis below.\n // Read the row at most once per resolution — the two reads were a duplicate\n // query on the API-key path.\n let userRowLoaded = false;\n let userRow: any;\n const getUserRow = async (): Promise<any> => {\n if (!userRowLoaded) {\n userRowLoaded = true;\n const rows = await tryFind(ql, 'sys_user', { id: userId }, 1);\n userRow = rows[0];\n }\n return userRow;\n };\n\n // Resolve the caller's unique email for `current_user.email` RLS owner\n // policies when the session path didn't supply it (e.g. API-key auth).\n if (!ctx.email) {\n const u = await getUserRow();\n if (u?.email) ctx.email = String(u.email);\n }\n\n // 3. Organization-administration roles via sys_member (better-auth), normalized\n // to the canonical built-in names (owner→org_owner, admin→org_admin, …).\n // [ADR-0095 D3] This is the ONE PROVISIONING boundary where a better-auth\n // role is read: it is projected into `positions` here, and separately drives\n // the `organization_admin` capability grant (auto-org-admin-grant.ts). No\n // enforcement code path reads the raw role — posture/adjudication run off\n // the resulting capability grants, so the #2836 dual-track cannot recur.\n const memberWhere: any = tenantId\n ? { user_id: userId, organization_id: tenantId }\n : { user_id: userId };\n const members = await tryFind(ql, 'sys_member', memberWhere, 50);\n for (const m of members) {\n if (m.role && typeof m.role === 'string') {\n for (const raw of m.role.split(',').map((s: string) => s.trim()).filter(Boolean)) {\n const r = mapMembershipRole(raw);\n if (!ctx.positions.includes(r)) ctx.positions.push(r);\n }\n }\n }\n\n // Single clock for every validity-window check in this resolution\n // (ADR-0091 D2 — a grant row outside [valid_from, valid_until) does not\n // resolve, fail-closed, with no background job involved).\n const nowMs = input.nowMs ?? Date.now();\n\n // 4. [ADR-0057 D4] Platform-owned RBAC role assignments (sys_user_position) — the\n // source of truth for custom roles, decoupled from sys_member.role.\n // `organization_id = null` = global (cross-tenant); else match active org.\n const userPositionRows = await tryFind(ql, 'sys_user_position', { user_id: userId }, 200);\n for (const ur of userPositionRows) {\n const org = ur.organization_id ?? null;\n if (org && tenantId && org !== tenantId) continue;\n if (!isGrantActive(ur, nowMs)) continue;\n const r = ur.position;\n if (typeof r === 'string' && r && !ctx.positions.includes(r)) ctx.positions.push(r);\n }\n\n // 5. Fellow-org user IDs so RLS can scope identity tables to collaborators.\n if (tenantId) {\n const orgMembers = await tryFind(ql, 'sys_member', { organization_id: tenantId }, 1000);\n const ids = new Set<string>(\n orgMembers\n .map((m) => m.user_id ?? m.userId)\n .filter((v): v is string => typeof v === 'string' && v.length > 0),\n );\n ids.add(userId);\n ctx.org_user_ids = Array.from(ids);\n } else {\n ctx.org_user_ids = [userId];\n }\n\n // 6. Permission sets — user-scoped grants (null org = global, else active org).\n // Rows outside their validity window are dropped BEFORE any derivation, so\n // an expired admin_full_access grant cannot yield platform_admin either.\n const upsRowsAll = await tryFind(ql, 'sys_user_permission_set', { user_id: userId }, 100);\n const upsRows = upsRowsAll.filter((r) => isGrantActive(r, nowMs));\n const psIds = new Set<string>(\n upsRows\n .filter((r) => {\n const org = (r.organization_id ?? r.organizationId) ?? null;\n return !(org && tenantId && org !== tenantId);\n })\n .map((r) => r.permission_set_id ?? r.permissionSetId)\n .filter(Boolean),\n );\n // platform_admin (ADR-0068 D2) is DERIVED from an UNSCOPED admin_full_access\n // USER grant — the single source of truth (no trusted stored boolean).\n const unscopedUserPsIds = new Set<string>(\n upsRows\n .filter((r) => ((r.organization_id ?? r.organizationId) ?? null) === null)\n .map((r) => r.permission_set_id ?? r.permissionSetId)\n .filter(Boolean),\n );\n let hasPlatformAdminGrant = false;\n\n // 5b. [ADR-0090 D5] Audience anchor: every AUTHENTICATED member implicitly\n // holds the built-in `everyone` position, so sets bound to it resolve\n // below exactly like any other position-bound grant — ADDITIVE, with no\n // \"only when the user has nothing else\" cliff.\n if (!ctx.positions.includes('everyone')) ctx.positions.push('everyone');\n\n // 6a. Position-bound permission sets (sys_position_permission_set): a position\n // carries its permission sets.\n if (ctx.positions.length > 0) {\n const positionRows = await tryFind(ql, 'sys_position', { name: { $in: ctx.positions } }, 100);\n const positionIds = positionRows.map((r) => r.id).filter(Boolean);\n if (positionIds.length > 0) {\n const rpsRows = await tryFind(ql, 'sys_position_permission_set', { position_id: { $in: positionIds } }, 500);\n for (const r of rpsRows) {\n const id = r.permission_set_id ?? r.permissionSetId;\n if (id) psIds.add(id);\n }\n }\n }\n\n // 6b. Resolve permission-set details (names → ctx.permissions; system_permissions;\n // tab_permissions merged by highest visibility).\n if (psIds.size > 0) {\n const psRows = await tryFind(ql, 'sys_permission_set', { id: { $in: Array.from(psIds) } }, 500);\n const tabRank: Record<string, number> = { hidden: 0, default_off: 1, default_on: 2, visible: 3 };\n const mergedTabs: Record<string, 'visible' | 'hidden' | 'default_on' | 'default_off'> = {};\n for (const ps of psRows) {\n if (ps.name && !ctx.permissions.includes(ps.name)) ctx.permissions.push(ps.name);\n if (ps.name === ADMIN_FULL_ACCESS && unscopedUserPsIds.has(ps.id)) hasPlatformAdminGrant = true;\n const sysPerms = typeof ps.system_permissions === 'string'\n ? safeJsonParse(ps.system_permissions, [])\n : (ps.system_permissions ?? ps.systemPermissions);\n if (Array.isArray(sysPerms)) {\n for (const p of sysPerms) {\n if (typeof p === 'string' && !ctx.systemPermissions.includes(p)) ctx.systemPermissions.push(p);\n }\n }\n const tabs = typeof ps.tab_permissions === 'string'\n ? safeJsonParse(ps.tab_permissions, {})\n : (ps.tab_permissions ?? ps.tabPermissions);\n if (tabs && typeof tabs === 'object') {\n for (const [app, val] of Object.entries(tabs as Record<string, unknown>)) {\n if (typeof val !== 'string' || !(val in tabRank)) continue;\n const cur = mergedTabs[app];\n if (!cur || tabRank[val] > tabRank[cur]) {\n mergedTabs[app] = val as 'visible' | 'hidden' | 'default_on' | 'default_off';\n }\n }\n }\n }\n if (Object.keys(mergedTabs).length > 0) ctx.tabPermissions = mergedTabs;\n }\n\n // 6c. Project the derived platform_admin built-in role (leads the list).\n if (hasPlatformAdminGrant && !ctx.positions.includes(BUILTIN_IDENTITY_PLATFORM_ADMIN)) {\n ctx.positions.unshift(BUILTIN_IDENTITY_PLATFORM_ADMIN);\n }\n\n // 6d. [ADR-0095 D2/D3] Resolve the posture rung ONCE, from held CAPABILITY\n // grants — never from a better-auth role. `PLATFORM_ADMIN` from the\n // unscoped `admin_full_access` grant (the same `viewAllRecords`/\n // `modifyAllRecords` evidence the superuser bypass trusts); `TENANT_ADMIN`\n // from the `organization_admin` grant (auto-provisioned from the better-\n // auth owner/admin role at §3 above — a provisioning source, not an\n // enforcement input, closing the #2836 dual-track class). Enforcement\n // behavior is unchanged: the per-object Layer 0 exemption + per-side\n // superuser bypass still gate access; posture is the carried, explainable\n // tier. `EXTERNAL` is never derived (no external principal type yet).\n ctx.posture = derivePosture({\n isPlatformAdmin: hasPlatformAdminGrant,\n isTenantAdmin: ctx.permissions.includes(ORGANIZATION_ADMIN),\n });\n\n // 7. [ADR-0024] Env-side AI seat: synthesize the `ai_seat` capability from the\n // boolean sys_user.ai_access (sqlite returns 1/0; memory returns boolean).\n if (!ctx.permissions.includes('ai_seat')) {\n const aiAccess = ((await getUserRow()) as { ai_access?: unknown } | undefined)?.ai_access;\n if (aiAccess === true || aiAccess === 1 || aiAccess === '1') ctx.permissions.push('ai_seat');\n }\n\n return ctx;\n}\n\n// ── Localization (ADR-0053 Phase 2) ─────────────────────────────────────────\n\nfunction isValidTimeZone(tz: string): boolean {\n try { new Intl.DateTimeFormat('en-US', { timeZone: tz }); return true; } catch { return false; }\n}\nfunction coerceTimeZone(value: unknown): string | undefined {\n const s = typeof value === 'string' ? value.trim() : value != null ? String(value).trim() : '';\n return s && isValidTimeZone(s) ? s : undefined;\n}\nfunction coerceLocale(value: unknown): string | undefined {\n const s = typeof value === 'string' ? value.trim() : value != null ? String(value).trim() : '';\n return s || undefined;\n}\nfunction coerceCurrency(value: unknown): string | undefined {\n const s = typeof value === 'string' ? value.trim().toUpperCase() : '';\n return /^[A-Z]{3}$/.test(s) ? s : undefined;\n}\n\nexport interface ResolveLocalizationInput {\n ql: any;\n /** Settings service exposing `get(namespace, key, { tenantId, userId })`. */\n settings?: any;\n tenantId?: string;\n userId?: string;\n}\n\n/**\n * Resolve workspace localization defaults (reference `timezone` / `locale` /\n * `currency`). Canonical path is the `localization` SettingsManifest (cascade:\n * platform default → global → tenant); falls back to direct tenant-scoped\n * `sys_setting` rows, then the built-ins `UTC` / `en-US`. Never throws.\n */\nexport async function resolveLocalizationContext(\n input: ResolveLocalizationInput,\n): Promise<{ timezone: string; locale: string; currency?: string }> {\n const { ql, settings, tenantId, userId } = input;\n try {\n if (settings && typeof settings.get === 'function') {\n const sctx = { tenantId, userId } as any;\n const [tzRes, localeRes, currencyRes] = await Promise.all([\n settings.get('localization', 'timezone', sctx).catch(() => undefined),\n settings.get('localization', 'locale', sctx).catch(() => undefined),\n settings.get('localization', 'currency', sctx).catch(() => undefined),\n ]);\n const tz = coerceTimeZone(tzRes?.value);\n const locale = coerceLocale(localeRes?.value);\n const currency = coerceCurrency(currencyRes?.value);\n if (tz || locale || currency) return { timezone: tz ?? 'UTC', locale: locale ?? 'en-US', currency };\n }\n } catch {\n // settings service unavailable → direct read\n }\n // One read for all three keys instead of a query per key (`$in` on `key`).\n const rows = await tryFind(\n ql,\n 'sys_setting',\n { namespace: 'localization', key: { $in: ['timezone', 'locale', 'currency'] }, scope: 'tenant' },\n 10,\n );\n const valueOf = (k: string) => rows.find((r) => r.key === k)?.value;\n return {\n timezone: coerceTimeZone(valueOf('timezone')) ?? 'UTC',\n locale: coerceLocale(valueOf('locale')) ?? 'en-US',\n currency: coerceCurrency(valueOf('currency')),\n };\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Grant validity windows (ADR-0091 D1/D2).\n *\n * `sys_user_position` and `sys_user_permission_set` rows carry optional\n * `valid_from` / `valid_until` columns. A row outside its window MUST NOT\n * resolve — anywhere, symmetrically: `resolveAuthzContext`, the explain\n * engine's `buildContextForUser`, plugin-sharing's `expandPositionUsers`,\n * and (transitively) the delegated-admin gate's held-scope resolution.\n *\n * Correctness lives HERE, at resolution time — never in a cleanup job\n * (ADR-0049: no unenforced security properties). The window is half-open\n * `[from, until)` in UTC: a grant is inactive before `valid_from` and\n * inactive AT and AFTER `valid_until`. Null/absent bounds mean unbounded,\n * so pre-ADR-0091 rows behave exactly as before.\n *\n * Fail-closed: a bound that is PRESENT but unparseable disables the grant\n * (unlike API-key `isExpired`, which tolerates garbage — an API key is a\n * single credential, a grant row is standing authority).\n */\n\n/**\n * Coerce a stored timestamp to epoch milliseconds.\n * Returns `undefined` for absent (null/undefined/'') values — \"no bound\" —\n * and `NaN` for present-but-unparseable values, which callers treat as\n * out-of-window (fail closed).\n */\nfunction toEpochMs(value: unknown): number | undefined {\n if (value == null || value === '') return undefined;\n if (typeof value === 'number') {\n // Heuristic: seconds vs milliseconds epoch (same rule as api-key.ts).\n return value < 1e12 ? value * 1000 : value;\n }\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string') return Date.parse(value);\n return Number.NaN;\n}\n\n/** The validity-window shape shared by both user-grant tables (ADR-0091 D1). */\nexport interface GrantValidityWindow {\n valid_from?: unknown;\n valid_until?: unknown;\n}\n\n/**\n * True when a grant row is inside its validity window at `nowMs`.\n * The single predicate every resolver uses (ADR-0091 D2):\n * `(valid_from is null or valid_from <= now) and (valid_until is null or valid_until > now)`.\n */\nexport function isGrantActive(row: GrantValidityWindow | null | undefined, nowMs: number): boolean {\n if (!row) return false;\n const from = toEpochMs((row as any).valid_from ?? (row as any).validFrom);\n // NaN comparisons are always false, so an unparseable bound fails closed.\n if (from !== undefined && !(nowMs >= from)) return false;\n const until = toEpochMs((row as any).valid_until ?? (row as any).validUntil);\n if (until !== undefined && !(nowMs < until)) return false;\n return true;\n}\n\n/**\n * True when a grant row carries a `valid_until` that has already passed —\n * i.e. it WAS active and expired (not merely not-yet-active). The explain\n * engine uses this to report the dedicated \"held until … — expired\"\n * contributor state (ADR-0091 D2).\n */\nexport function isGrantExpired(row: GrantValidityWindow | null | undefined, nowMs: number): boolean {\n if (!row) return false;\n const until = toEpochMs((row as any).valid_until ?? (row as any).validUntil);\n if (until === undefined) return false;\n return !(nowMs < until);\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ── The monotonic posture ladder (ADR-0095 D2/D3) ───────────────────────────\n *\n * The principal-tiering enum resolved ONCE in `resolveAuthzContext`\n * (`PLATFORM_ADMIN > TENANT_ADMIN > MEMBER > EXTERNAL`). This module owns two\n * things and deliberately nothing more:\n *\n * 1. **Derivation (D3).** {@link derivePosture} maps held *capability grants*\n * — never a better-auth role — to a rung. `PLATFORM_ADMIN` derives from the\n * unscoped `admin_full_access` grant (the `viewAllRecords`/`modifyAllRecords`\n * evidence the superuser bypass already trusts); `TENANT_ADMIN` from the\n * `organization_admin` grant. The better-auth `role='admin'` is upstream a\n * *provisioning source* of those grants (`auto-org-admin-grant.ts`), so it\n * never re-enters adjudication here — the #2836 dual-track class is closed\n * by construction.\n *\n * 2. **The rung → injection-rule mapping + its tested invariants (D2).** Each\n * rung maps to EXACTLY ONE row-visibility injection rule\n * ({@link POSTURE_INJECTION_RULE}). {@link postureVisibleRows} is the\n * REFERENCE MODEL of those rules over a synthetic row-set — it locks the two\n * properties the ADR requires as invariants: strict nesting (rung n's\n * visible set ⊇ rung n−1's) and the EXTERNAL deny-by-default semantics\n * (explicit shares only, OWD never widens it).\n *\n * This module is NOT the enforcement path. The effective read/write filter is\n * `Layer0(tenant) AND Layer1(business RLS)`, computed in `@objectstack/plugin-\n * security` (`tenant-layer.ts` + `security-plugin.ts`), and the real behavior\n * guard is the `authz-matrix-gate` unit snapshot + the dogfood conformance\n * matrix. The reference model here exists so the ladder's *mathematical*\n * properties can be asserted at the unit layer without an enforcement boot, and\n * so the EXTERNAL rung — which has no enforcement path yet — cannot be\n * reinvented differently when portal/external membership arrives.\n */\n\nimport type { AuthzPosture } from '@objectstack/spec/security';\n\n/**\n * The rung ordering, high privilege → low, matching the spec enum's numeric\n * values (`PLATFORM_ADMIN=3 … EXTERNAL=0`). Visibility grows monotonically UP\n * this ladder (see {@link postureVisibleRows}).\n */\nexport const POSTURE_LADDER = [\n 'PLATFORM_ADMIN',\n 'TENANT_ADMIN',\n 'MEMBER',\n 'EXTERNAL',\n] as const satisfies readonly AuthzPosture[];\n\n/** Numeric rank per rung (mirrors the spec `AuthzPosture` enum values). */\nexport const POSTURE_RANK: Record<AuthzPosture, number> = {\n PLATFORM_ADMIN: 3,\n TENANT_ADMIN: 2,\n MEMBER: 1,\n EXTERNAL: 0,\n};\n\n/**\n * The ONE row-visibility injection rule each rung maps to (ADR-0095 D2). Prose,\n * because the machine artifacts live in enforcement (Layer 0 + the per-rung\n * Layer 1 rule); this is the enumerable contract the explain track reports and\n * {@link postureVisibleRows} models.\n */\nexport const POSTURE_INJECTION_RULE: Record<AuthzPosture, string> = {\n PLATFORM_ADMIN:\n 'Layer 0 exemption where the object posture permits (private / platform-global / better-auth-managed) — crosses the tenant wall; org-scoped like TENANT_ADMIN on ordinary tenant business objects.',\n TENANT_ADMIN:\n 'All rows within the active organization (organization_id == ctx.tenantId); no ownership / depth / sharing narrowing.',\n MEMBER:\n 'Business RLS within the organization — ownership (owner / unit depth), the OWD baseline, and explicit sharing.',\n EXTERNAL:\n 'Explicitly shared rows ONLY — OWD baselines and sharing rules never apply; a misconfiguration can only shrink visibility, never widen it.',\n};\n\n/** Capability-grant evidence the posture derivation consumes (ADR-0095 D3). */\nexport interface PostureEvidence {\n /**\n * Holds the UNSCOPED platform-admin capability grant (`admin_full_access` →\n * `viewAllRecords`/`modifyAllRecords`) — the same evidence the superuser\n * bypass trusts. NOT a better-auth role.\n */\n isPlatformAdmin: boolean;\n /**\n * Holds the org-admin capability grant (`organization_admin`, tenant-scoped\n * `viewAllRecords`/`modifyAllRecords`). Provisioned from the better-auth\n * owner/admin role upstream, consumed here only as a held capability.\n */\n isTenantAdmin: boolean;\n}\n\n/**\n * Resolve the principal's posture rung from held capability grants (ADR-0095 D3).\n *\n * Returns `PLATFORM_ADMIN` | `TENANT_ADMIN` | `MEMBER`. It NEVER returns\n * `EXTERNAL`: no external principal type exists yet (the sharing chain has no\n * portal/guest-share concept — ADR-0095 W4). The `EXTERNAL` rung, its injection\n * rule, and its semantics are defined and test-locked ({@link postureVisibleRows},\n * {@link POSTURE_INJECTION_RULE}) so that when portal/external membership lands\n * (ADR-0093) the derivation gains an EXTERNAL branch HERE without the rung being\n * reinvented. `MEMBER` is the authenticated-principal floor.\n */\nexport function derivePosture(evidence: PostureEvidence): AuthzPosture {\n if (evidence.isPlatformAdmin) return 'PLATFORM_ADMIN';\n if (evidence.isTenantAdmin) return 'TENANT_ADMIN';\n return 'MEMBER';\n}\n\n// ── Reference visibility model (invariant lock, NOT enforcement) ─────────────\n\n/** A synthetic record for the ladder reference model. */\nexport interface LadderRow {\n id: string;\n /** The row's tenant. `undefined` = a non-tenant (platform-global) row. */\n organization_id?: string;\n /** The row's owner (drives the MEMBER ownership disjunct). */\n owner_id?: string;\n /**\n * Whether an OWD-derived source would admit this row for a member (public\n * baseline / criteria sharing). EXTERNAL deliberately ignores this field.\n */\n owdVisible?: boolean;\n /** User ids this row is EXPLICITLY shared to (the only EXTERNAL source). */\n sharedTo?: readonly string[];\n}\n\n/** The principal the reference model evaluates a rung for. */\nexport interface LadderPrincipal {\n userId: string;\n /** The principal's active organization (undefined for an unscoped principal). */\n organizationId?: string;\n}\n\nfunction isSharedTo(row: LadderRow, userId: string): boolean {\n return (row.sharedTo ?? []).includes(userId);\n}\n\n/** EXTERNAL rung: explicitly shared rows ONLY — never OWD, never org-wide. */\nfunction externalVisible(rows: readonly LadderRow[], p: LadderPrincipal): LadderRow[] {\n return rows.filter((r) => isSharedTo(r, p.userId));\n}\n\n/**\n * MEMBER rung: business RLS within the org — ownership OR OWD baseline OR\n * explicit sharing. Composed as `EXTERNAL ∪ (in-org ownership/OWD)` so the\n * EXTERNAL ⊆ MEMBER leg of the nesting invariant holds by construction.\n */\nfunction memberVisible(rows: readonly LadderRow[], p: LadderPrincipal): LadderRow[] {\n const shared = new Set(externalVisible(rows, p));\n return rows.filter(\n (r) =>\n shared.has(r) ||\n (r.organization_id === p.organizationId && (r.owner_id === p.userId || r.owdVisible === true)),\n );\n}\n\n/**\n * TENANT_ADMIN rung: all rows in the active organization. Composed as\n * `MEMBER ∪ (all in-org)` so MEMBER ⊆ TENANT_ADMIN holds by construction.\n */\nfunction tenantAdminVisible(rows: readonly LadderRow[], p: LadderPrincipal): LadderRow[] {\n const member = new Set(memberVisible(rows, p));\n return rows.filter((r) => member.has(r) || r.organization_id === p.organizationId);\n}\n\n/** PLATFORM_ADMIN rung: crosses the tenant wall — every row (⊇ TENANT_ADMIN trivially). */\nfunction platformAdminVisible(rows: readonly LadderRow[]): LadderRow[] {\n return [...rows];\n}\n\n/**\n * Reference model of the per-rung injection rule: the visible-row set a rung\n * would resolve to over `rows` for `principal`. Used to lock the ADR-0095 D2\n * invariants (strict nesting + EXTERNAL deny-by-default). NOT an enforcement\n * path — see the module header.\n */\nexport function postureVisibleRows(\n posture: AuthzPosture,\n rows: readonly LadderRow[],\n principal: LadderPrincipal,\n): LadderRow[] {\n switch (posture) {\n case 'PLATFORM_ADMIN':\n return platformAdminVisible(rows);\n case 'TENANT_ADMIN':\n return tenantAdminVisible(rows, principal);\n case 'MEMBER':\n return memberVisible(rows, principal);\n case 'EXTERNAL':\n return externalVisible(rows, principal);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ADR-0069 — authentication-policy session gate.\n *\n * Some auth policies (password expiry, enforced MFA) must block an\n * authenticated user from PROTECTED RESOURCES until they remediate, while\n * still letting them reach the auth endpoints (change-password, two-factor\n * enrollment, sign-out) and a few UI-bootstrap reads.\n *\n * The posture is computed ONCE, in the auth `customSession` enrichment, and\n * attached to the session user as `user.authGate = { code, message }`. The\n * transport seams (REST middleware, dispatcher) then call\n * {@link evaluateAuthGate} to decide whether THIS request is blocked. Keeping\n * the allow-list + decision in one pure function means the seams can never\n * drift on what is blocked.\n */\n\nexport interface AuthGate {\n /** Stable machine code, e.g. `PASSWORD_EXPIRED` / `MFA_REQUIRED`. */\n code: string;\n /** Human-facing message. */\n message: string;\n}\n\n// Endpoints a gated user MUST still reach to remediate or bootstrap the\n// remediation UI. Matched against the request path (query stripped). Covers\n// both REST (`/api/v1/auth/…`) and dispatcher (`/auth/…`) path shapes.\nconst ALLOW_PREFIXES = ['/api/v1/auth/', '/api/auth/', '/auth/'];\nconst ALLOW_SUFFIXES = ['/health', '/ready', '/discovery', '/me/apps', '/me/localization'];\n\n/** True when `path` is exempt from the auth gate (auth + remediation + health). */\nexport function isAuthGateAllowlisted(rawPath: string | undefined | null): boolean {\n if (!rawPath) return true;\n // Strip query + trailing slashes WITHOUT a regex (avoids ReDoS on a\n // path of many '/'). char 47 = '/'.\n let path = rawPath.split('?')[0] || '/';\n let end = path.length;\n while (end > 1 && path.charCodeAt(end - 1) === 47) end--;\n path = path.slice(0, end) || '/';\n // Any path with an `/auth/` segment is an auth endpoint (covers project-\n // scoped mounts like `/api/v1/environments/:env/auth/...`).\n if (path.includes('/auth/')) return true;\n for (const p of ALLOW_PREFIXES) {\n if (path.startsWith(p) || path === p.replace(/\\/$/, '')) return true;\n }\n for (const s of ALLOW_SUFFIXES) {\n if (path.endsWith(s)) return true;\n }\n return false;\n}\n\n/**\n * Returns the active gate when `sessionUser` carries an `authGate` AND `path`\n * is not allow-listed; otherwise null. Anonymous users (no `authGate`) and\n * allow-listed paths always pass.\n */\nexport function evaluateAuthGate(sessionUser: any, path: string): AuthGate | null {\n const gate = sessionUser?.authGate;\n if (!gate || typeof gate.code !== 'string') return null;\n if (isAuthGateAllowlisted(path)) return null;\n return {\n code: gate.code,\n message:\n typeof gate.message === 'string' && gate.message\n ? gate.message\n : 'Access is blocked by an authentication policy.',\n };\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * #2567 — the single anonymous-deny decision, shared by every HTTP seam.\n *\n * ADR-0056 D2 made the platform deny anonymous callers by default\n * (`requireAuth`). Phase 1 gated each surface (REST `/data`, dispatcher\n * `/graphql` + `/meta`, raw-hono `/data`) but every seam hand-rolled the same\n * `!userId && !isSystem → 401` check. This centralises that DECISION into one\n * pure, tested function — the exact pattern {@link ./auth-gate.ts} established\n * for the ADR-0069 auth-policy gate: keeping the decision in one function means\n * the seams can never drift on who is denied.\n *\n * It deliberately does NOT own identity resolution or the dynamic exemptions\n * (public-form submission, share-link tokens): those run UPSTREAM and set the\n * execution context (a `userId`, or `isSystem`) before a seam calls this, so\n * this function only ever inspects the already-resolved context.\n */\n\nimport { isAuthGateAllowlisted } from './auth-gate.js';\n\n/** HTTP status every seam returns for an anonymous-denied request. */\nexport const ANONYMOUS_DENY_STATUS = 401 as const;\n/** Stable machine code (mirrors the REST `enforceAuth` seam). */\nexport const ANONYMOUS_DENY_CODE = 'unauthenticated' as const;\n/** Human-facing message. */\nexport const ANONYMOUS_DENY_MESSAGE = 'Authentication is required to access this endpoint.';\n/** The single 401 body shape every seam returns: `{ error, message }`. */\nexport const ANONYMOUS_DENY_BODY = {\n error: ANONYMOUS_DENY_CODE,\n message: ANONYMOUS_DENY_MESSAGE,\n} as const;\n\nexport interface AnonymousDenyInput {\n /** The `requireAuth` posture. Falsy ⇒ no-op (demo / single-tenant). */\n requireAuth: boolean | undefined;\n /** Resolved caller id, if any. */\n userId?: string | null;\n /** Internal system context (never set on inbound HTTP; cannot be forged). */\n isSystem?: boolean;\n /** HTTP method — `OPTIONS` (CORS preflight) always passes. */\n method?: string | null;\n /**\n * OPTIONAL request path. When a NON-EMPTY string, a control-plane path\n * (auth / health / ready / discovery — see {@link isAuthGateAllowlisted}) is\n * exempt. Body-routed seams (GraphQL) have no meaningful path and pass\n * `undefined`; see the guard below for why that is load-bearing.\n */\n path?: string | null;\n}\n\n/**\n * True when the request MUST be rejected with 401. The one decision every HTTP\n * seam shares.\n */\nexport function shouldDenyAnonymous(input: AnonymousDenyInput): boolean {\n if (!input.requireAuth) return false; // posture off\n if (typeof input.method === 'string' && input.method.toUpperCase() === 'OPTIONS') {\n return false; // CORS preflight\n }\n if (input.userId || input.isSystem) return false; // authenticated / system\n // Control-plane exemption — ONLY for a real, non-empty path.\n //\n // ⚠️ `isAuthGateAllowlisted(undefined)` returns `true` (it treats \"no path\"\n // as allow-listed for the auth-gate's purposes). A body-routed seam such as\n // GraphQL has no meaningful request path; if it passed `undefined` straight\n // through, the allowlist would exempt EVERY anonymous query and silently\n // reopen exactly the hole #2567 closes. The non-empty guard is mandatory.\n if (typeof input.path === 'string' && input.path.length > 0 && isAuthGateAllowlisted(input.path)) {\n return false;\n }\n return true;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Timezone-aware calendar utilities (ADR-0053 Phase 2).\n *\n * The one primitive everything else builds on is {@link calendarPartsInTz}:\n * the year/month/day an instant falls on *as seen in a reference timezone*.\n * It uses `Intl.DateTimeFormat().formatToParts()` so DST transitions are\n * handled by the platform's tz database — never hand-rolled offset math, which\n * is the classic source of off-by-one-hour bucket errors.\n *\n * This lives in `@objectstack/core` (not `@objectstack/formula`) because both\n * the ObjectQL aggregation engine and the analytics service need it and both\n * already depend on core, whereas neither depends on formula's public surface.\n * (`@objectstack/formula` keeps its own private copy for `today()`/`daysFromNow`\n * to avoid a layering dependency on core.)\n */\n\n/** Calendar-day parts in a reference timezone. `month` is 1-12. */\nexport interface CalendarParts {\n year: number;\n month: number;\n day: number;\n}\n\n/**\n * The year/month/day an instant falls on in `tz`. Throws if `tz` is not a\n * valid IANA zone (callers treat that as a fall-through to UTC).\n */\nexport function calendarPartsInTz(d: Date, tz: string): CalendarParts {\n const parts = new Intl.DateTimeFormat('en-US', {\n timeZone: tz,\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n }).formatToParts(d);\n const get = (t: string) => Number(parts.find((p) => p.type === t)?.value);\n return { year: get('year'), month: get('month'), day: get('day') };\n}\n\n/**\n * The calendar-day parts of an instant, in `tz` when it's a real non-UTC zone,\n * otherwise in UTC. Never throws: an unset, `'UTC'`, or invalid zone falls back\n * to the UTC calendar day. This is the safe entry point for bucketing code that\n * must degrade to the historical UTC behavior rather than error.\n */\nexport function calendarPartsInTzOrUtc(d: Date, tz?: string): CalendarParts {\n if (tz && tz !== 'UTC') {\n try {\n return calendarPartsInTz(d, tz);\n } catch {\n // unknown zone → fall through to UTC\n }\n }\n return {\n year: d.getUTCFullYear(),\n month: d.getUTCMonth() + 1,\n day: d.getUTCDate(),\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * `bulkWrite` — the shared batched-write helper used by BOTH the seed loader\n * (`@objectstack/metadata-protocol`) and the data-import runner\n * (`@objectstack/rest`), so neither reimplements batching, transient-error\n * retry, or per-row degradation. See framework#2678.\n *\n * ObjectQL's engine already does the efficient thing when handed an ARRAY —\n * one `driver.bulkCreate` round-trip plus parent-deduplicated summary\n * recompute (`engine.insert(object, rows[])`) — but seed/import fed it one\n * record at a time, so neither got the benefit. This module re-chunks rows\n * into batches and drives them through a caller-supplied batch-write\n * function, adding:\n *\n * - transient-error retry (network blip / timeout) with exponential\n * backoff, so a dropped connection doesn't silently drop the row (the\n * 2026-07-06 HotCRM incident: a turso `fetch failed` mid-seed dropped rows\n * silently because nothing retried);\n * - per-row degradation when a batch fails for a non-transient (logical /\n * validation) reason, so one bad row can't fail the other N-1 — needed\n * because `driver.bulkCreate` is a single multi-row statement/`Promise.all`\n * on every driver in this repo (sql, memory, mongodb): one bad row fails\n * the whole call;\n * - a stable per-row result keyed by the row's original index, so callers\n * can reassemble output in input order even though rows are processed in\n * batches (and a batch's flush may be interleaved with other, immediate,\n * per-row work such as updates).\n */\n\nexport interface BulkWriteRowResult<TRecord = any> {\n /** Index into the original `rows` array passed to {@link bulkWrite}. */\n index: number;\n ok: boolean;\n record?: TRecord;\n error?: unknown;\n}\n\nexport interface RetryOptions {\n /** Max attempts for one write (batch or single-row), including the first. Default 3. */\n maxRetries?: number;\n /** Base backoff in ms; doubled each retry, plus jitter. Default 200. */\n backoffBaseMs?: number;\n /** Classifies an error as transient (worth retrying) vs logical (the row/batch is just bad). */\n isTransientError?: (err: unknown) => boolean;\n /** Injectable sleep, for deterministic tests. */\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface BulkWriteOptions<TRow, TRecord = any> extends RetryOptions {\n /** Rows per batch. Default 200 (framework#2678 suggests 100-500). */\n batchSize?: number;\n /**\n * Write one batch. MUST resolve to one record per input row, in the SAME\n * order as `batch` — {@link bulkWrite} correlates `records[i]` back to\n * `batch[i]` positionally (this is how every `bulkCreate` implementation in\n * this repo already behaves: sql's single `INSERT ... VALUES (...), (...)\n * RETURNING *`, memory's `Promise.all`, mongodb's ordered `insertMany`).\n */\n writeBatch: (batch: TRow[]) => Promise<TRecord[]>;\n /** Write a single row — used only to degrade a failed batch. */\n writeOne: (row: TRow) => Promise<TRecord>;\n}\n\nconst DEFAULT_BATCH_SIZE = 200;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_BACKOFF_BASE_MS = 200;\n\n/**\n * Transient-error signatures shared by common HTTP/TCP-backed drivers\n * (turso/libsql's fetch-based transport included). Deliberately excludes\n * anything that looks like a validation/constraint error — those must NOT be\n * retried, only degraded to per-row.\n */\nconst TRANSIENT_PATTERNS: RegExp[] = [\n /fetch failed/i,\n /network/i,\n /timed?\\s*out/i,\n /timeout/i,\n /socket hang ?up/i,\n /connection.*(closed|reset|refused|terminated|aborted)/i,\n /\\b(502|503|504)\\b/,\n /server.*unavailable/i,\n /too many connections/i,\n];\n\nconst TRANSIENT_CODES = /^(ECONNRESET|ECONNREFUSED|ECONNABORTED|EPIPE|EAI_AGAIN|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|ENOTFOUND)$/i;\n\nexport function defaultIsTransientError(err: unknown): boolean {\n const code = (err as { code?: unknown } | null)?.code;\n if (typeof code === 'string' && TRANSIENT_CODES.test(code)) return true;\n const message = (err as { message?: unknown } | null)?.message;\n const text = typeof message === 'string' ? message : String(err ?? '');\n return TRANSIENT_PATTERNS.some((re) => re.test(text));\n}\n\nconst defaultSleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\ninterface ResolvedRetryOptions {\n maxRetries: number;\n backoffBaseMs: number;\n isTransientError: (err: unknown) => boolean;\n sleep: (ms: number) => Promise<void>;\n}\n\nasync function withRetry<T>(fn: () => Promise<T>, opts: ResolvedRetryOptions): Promise<T> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= opts.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (attempt >= opts.maxRetries || !opts.isTransientError(err)) throw err;\n const jitter = Math.floor(Math.random() * 50);\n await opts.sleep(opts.backoffBaseMs * 2 ** (attempt - 1) + jitter);\n }\n }\n // Unreachable — the loop above always returns or throws — but keeps TS's\n // control-flow analysis happy about a guaranteed return type.\n throw lastError;\n}\n\n/**\n * Retry a single write (e.g. an `engine.update()` call the seed loader or\n * import runner makes outside the batched-insert path) with the same\n * transient-error backoff {@link bulkWrite} applies to batches — so a\n * network blip doesn't drop an update the way it used to drop an insert.\n */\nexport async function withTransientRetry<T>(fn: () => Promise<T>, opts: RetryOptions = {}): Promise<T> {\n return withRetry(fn, {\n maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),\n backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,\n isTransientError: opts.isTransientError ?? defaultIsTransientError,\n sleep: opts.sleep ?? defaultSleep,\n });\n}\n\n/**\n * Write `rows` through `opts.writeBatch` in chunks of `opts.batchSize`,\n * retrying a whole-batch transient failure with backoff, and degrading to\n * per-row `opts.writeOne` calls (each itself retried) when a batch fails for\n * a non-transient reason — so one bad row can't drop the rest of the batch.\n *\n * Returns one {@link BulkWriteRowResult} per input row, indexed to match\n * `rows`' original order.\n */\nexport async function bulkWrite<TRow, TRecord = any>(\n rows: TRow[],\n opts: BulkWriteOptions<TRow, TRecord>,\n): Promise<BulkWriteRowResult<TRecord>[]> {\n const batchSize = Math.max(1, opts.batchSize ?? DEFAULT_BATCH_SIZE);\n const retryOpts: ResolvedRetryOptions = {\n maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),\n backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,\n isTransientError: opts.isTransientError ?? defaultIsTransientError,\n sleep: opts.sleep ?? defaultSleep,\n };\n\n const results: BulkWriteRowResult<TRecord>[] = new Array(rows.length);\n\n for (let start = 0; start < rows.length; start += batchSize) {\n const batch = rows.slice(start, start + batchSize);\n try {\n const records = await withRetry(() => opts.writeBatch(batch), retryOpts);\n for (let i = 0; i < batch.length; i++) {\n results[start + i] = { index: start + i, ok: true, record: records[i] };\n }\n } catch (batchErr) {\n // A single-row \"batch\" already IS the per-row attempt — its failure\n // (after transient retry) is the row's final outcome; calling\n // `writeOne` again would just repeat the identical work.\n if (batch.length === 1) {\n results[start] = { index: start, ok: false, error: batchErr };\n continue;\n }\n // The batch failed even after transient retry, or failed for a logical\n // reason retry wouldn't fix. Degrade to per-row so one bad row can't\n // fail the other rows in this batch. Each row still gets its own\n // transient retry — the batch-level failure doesn't tell us which row\n // (if any) was actually the transient one.\n for (let i = 0; i < batch.length; i++) {\n const idx = start + i;\n try {\n const record = await withRetry(() => opts.writeOne(batch[i]), retryOpts);\n results[idx] = { index: idx, ok: true, record };\n } catch (err) {\n results[idx] = { index: idx, ok: false, error: err };\n }\n }\n }\n }\n\n return results;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n PluginHealthStatus, \n PluginHealthCheck, \n PluginHealthReport \n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from './logger.js';\nimport type { Plugin } from './types.js';\n\n/**\n * Plugin Health Monitor\n * \n * Monitors plugin health status and performs automatic recovery actions.\n * Implements the advanced lifecycle health monitoring protocol.\n */\nexport class PluginHealthMonitor {\n private logger: ObjectLogger;\n private healthChecks = new Map<string, PluginHealthCheck>();\n private healthStatus = new Map<string, PluginHealthStatus>();\n private healthReports = new Map<string, PluginHealthReport>();\n private checkIntervals = new Map<string, NodeJS.Timeout>();\n private failureCounters = new Map<string, number>();\n private successCounters = new Map<string, number>();\n private restartAttempts = new Map<string, number>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'HealthMonitor' });\n }\n\n /**\n * Register a plugin for health monitoring\n */\n registerPlugin(pluginName: string, config: PluginHealthCheck): void {\n this.healthChecks.set(pluginName, config);\n this.healthStatus.set(pluginName, 'unknown');\n this.failureCounters.set(pluginName, 0);\n this.successCounters.set(pluginName, 0);\n this.restartAttempts.set(pluginName, 0);\n\n this.logger.info('Plugin registered for health monitoring', { \n plugin: pluginName,\n interval: config.interval \n });\n }\n\n /**\n * Start monitoring a plugin\n */\n startMonitoring(pluginName: string, plugin: Plugin): void {\n const config = this.healthChecks.get(pluginName);\n if (!config) {\n this.logger.warn('Cannot start monitoring - plugin not registered', { plugin: pluginName });\n return;\n }\n\n // Clear any existing interval\n this.stopMonitoring(pluginName);\n\n // Set up periodic health checks\n const interval = setInterval(() => {\n this.performHealthCheck(pluginName, plugin, config).catch(error => {\n this.logger.error('Health check failed with error', { \n plugin: pluginName, \n error \n });\n });\n }, config.interval);\n\n this.checkIntervals.set(pluginName, interval);\n this.logger.info('Health monitoring started', { plugin: pluginName });\n\n // Perform initial health check\n this.performHealthCheck(pluginName, plugin, config).catch(error => {\n this.logger.error('Initial health check failed', { \n plugin: pluginName, \n error \n });\n });\n }\n\n /**\n * Stop monitoring a plugin\n */\n stopMonitoring(pluginName: string): void {\n const interval = this.checkIntervals.get(pluginName);\n if (interval) {\n clearInterval(interval);\n this.checkIntervals.delete(pluginName);\n this.logger.info('Health monitoring stopped', { plugin: pluginName });\n }\n }\n\n /**\n * Perform a health check on a plugin\n */\n private async performHealthCheck(\n pluginName: string,\n plugin: Plugin,\n config: PluginHealthCheck\n ): Promise<void> {\n const startTime = Date.now();\n let status: PluginHealthStatus = 'healthy';\n let message: string | undefined;\n const checks: Array<{ name: string; status: 'passed' | 'failed' | 'warning'; message?: string }> = [];\n\n try {\n // Check if plugin has a custom health check method\n if (config.checkMethod && typeof (plugin as any)[config.checkMethod] === 'function') {\n const checkResult = await Promise.race([\n (plugin as any)[config.checkMethod](),\n this.timeout(config.timeout, `Health check timeout after ${config.timeout}ms`)\n ]);\n\n if (checkResult === false || (checkResult && checkResult.status === 'unhealthy')) {\n status = 'unhealthy';\n message = checkResult?.message || 'Custom health check failed';\n checks.push({ name: config.checkMethod, status: 'failed', message });\n } else {\n checks.push({ name: config.checkMethod, status: 'passed' });\n }\n } else {\n // Default health check - just verify plugin is loaded\n checks.push({ name: 'plugin-loaded', status: 'passed' });\n }\n\n // Update counters based on result\n if (status === 'healthy') {\n this.successCounters.set(pluginName, (this.successCounters.get(pluginName) || 0) + 1);\n this.failureCounters.set(pluginName, 0);\n\n // Recover from unhealthy state if we have enough successes\n const currentStatus = this.healthStatus.get(pluginName);\n if (currentStatus === 'unhealthy' || currentStatus === 'degraded') {\n const successCount = this.successCounters.get(pluginName) || 0;\n if (successCount >= config.successThreshold) {\n this.healthStatus.set(pluginName, 'healthy');\n this.logger.info('Plugin recovered to healthy state', { plugin: pluginName });\n } else {\n this.healthStatus.set(pluginName, 'recovering');\n }\n } else {\n this.healthStatus.set(pluginName, 'healthy');\n }\n } else {\n this.failureCounters.set(pluginName, (this.failureCounters.get(pluginName) || 0) + 1);\n this.successCounters.set(pluginName, 0);\n\n const failureCount = this.failureCounters.get(pluginName) || 0;\n if (failureCount >= config.failureThreshold) {\n this.healthStatus.set(pluginName, 'unhealthy');\n this.logger.warn('Plugin marked as unhealthy', { \n plugin: pluginName, \n failures: failureCount \n });\n\n // Attempt auto-restart if configured\n if (config.autoRestart) {\n await this.attemptRestart(pluginName, plugin, config);\n }\n } else {\n this.healthStatus.set(pluginName, 'degraded');\n }\n }\n } catch (error) {\n status = 'failed';\n message = error instanceof Error ? error.message : 'Unknown error';\n this.failureCounters.set(pluginName, (this.failureCounters.get(pluginName) || 0) + 1);\n this.healthStatus.set(pluginName, 'failed');\n \n checks.push({ \n name: 'health-check', \n status: 'failed', \n message: message \n });\n\n this.logger.error('Health check exception', { \n plugin: pluginName, \n error \n });\n }\n\n // Create health report\n const report: PluginHealthReport = {\n status: this.healthStatus.get(pluginName) || 'unknown',\n timestamp: new Date().toISOString(),\n message,\n metrics: {\n uptime: Date.now() - startTime,\n },\n checks: checks.length > 0 ? checks : undefined,\n };\n\n this.healthReports.set(pluginName, report);\n }\n\n /**\n * Attempt to restart a plugin\n */\n private async attemptRestart(\n pluginName: string,\n plugin: Plugin,\n config: PluginHealthCheck\n ): Promise<void> {\n const attempts = this.restartAttempts.get(pluginName) || 0;\n \n if (attempts >= config.maxRestartAttempts) {\n this.logger.error('Max restart attempts reached, giving up', { \n plugin: pluginName, \n attempts \n });\n this.healthStatus.set(pluginName, 'failed');\n return;\n }\n\n this.restartAttempts.set(pluginName, attempts + 1);\n \n // Calculate backoff delay\n const delay = this.calculateBackoff(attempts, config.restartBackoff);\n \n this.logger.info('Scheduling plugin restart', { \n plugin: pluginName, \n attempt: attempts + 1, \n delay \n });\n\n await new Promise(resolve => setTimeout(resolve, delay));\n\n try {\n // Call destroy and init to restart\n if (plugin.destroy) {\n await plugin.destroy();\n }\n \n // Note: Full restart would require kernel context\n // This is a simplified version - actual implementation would need kernel integration\n this.logger.info('Plugin restarted', { plugin: pluginName });\n \n // Reset counters on successful restart\n this.failureCounters.set(pluginName, 0);\n this.successCounters.set(pluginName, 0);\n this.healthStatus.set(pluginName, 'recovering');\n } catch (error) {\n this.logger.error('Plugin restart failed', { \n plugin: pluginName, \n error \n });\n this.healthStatus.set(pluginName, 'failed');\n }\n }\n\n /**\n * Calculate backoff delay for restarts\n */\n private calculateBackoff(attempt: number, strategy: 'fixed' | 'linear' | 'exponential'): number {\n const baseDelay = 1000; // 1 second base\n\n switch (strategy) {\n case 'fixed':\n return baseDelay;\n case 'linear':\n return baseDelay * (attempt + 1);\n case 'exponential':\n return baseDelay * Math.pow(2, attempt);\n default:\n return baseDelay;\n }\n }\n\n /**\n * Get current health status of a plugin\n */\n getHealthStatus(pluginName: string): PluginHealthStatus | undefined {\n return this.healthStatus.get(pluginName);\n }\n\n /**\n * Get latest health report for a plugin\n */\n getHealthReport(pluginName: string): PluginHealthReport | undefined {\n return this.healthReports.get(pluginName);\n }\n\n /**\n * Get all health statuses\n */\n getAllHealthStatuses(): Map<string, PluginHealthStatus> {\n return new Map(this.healthStatus);\n }\n\n /**\n * Shutdown health monitor\n */\n shutdown(): void {\n // Stop all monitoring intervals\n for (const pluginName of this.checkIntervals.keys()) {\n this.stopMonitoring(pluginName);\n }\n \n this.healthChecks.clear();\n this.healthStatus.clear();\n this.healthReports.clear();\n this.failureCounters.clear();\n this.successCounters.clear();\n this.restartAttempts.clear();\n \n this.logger.info('Health monitor shutdown complete');\n }\n\n /**\n * Timeout helper\n */\n private timeout<T>(ms: number, message: string): Promise<T> {\n return new Promise((_, reject) => {\n setTimeout(() => reject(new Error(message)), ms);\n });\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { createHash } from 'node:crypto';\n\nimport type { \n HotReloadConfig, \n PluginStateSnapshot \n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from './logger.js';\nimport type { Plugin } from './types.js';\n\n// Polyfill for UUID generation to support both Node.js and Browser\nconst generateUUID = () => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Basic UUID v4 fallback\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n};\n\n/**\n * Plugin State Manager\n * \n * Handles state persistence and restoration during hot reloads\n */\nclass PluginStateManager {\n private logger: ObjectLogger;\n private stateSnapshots = new Map<string, PluginStateSnapshot>();\n private memoryStore = new Map<string, any>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'StateManager' });\n }\n\n /**\n * Save plugin state before reload\n */\n async saveState(\n pluginId: string,\n version: string,\n state: Record<string, any>,\n config: HotReloadConfig\n ): Promise<string> {\n const snapshot: PluginStateSnapshot = {\n pluginId,\n version,\n timestamp: new Date().toISOString(),\n state,\n metadata: {\n checksum: this.calculateChecksum(state),\n compressed: false,\n },\n };\n\n const snapshotId = generateUUID();\n\n switch (config.stateStrategy) {\n case 'memory':\n this.memoryStore.set(snapshotId, snapshot);\n this.logger.debug('State saved to memory', { pluginId, snapshotId });\n break;\n\n case 'disk':\n // For disk storage, we would write to file system\n // For now, store in memory as fallback\n this.memoryStore.set(snapshotId, snapshot);\n this.logger.debug('State saved to disk (memory fallback)', { pluginId, snapshotId });\n break;\n\n case 'distributed':\n // For distributed storage, would use Redis/etcd\n // For now, store in memory as fallback\n this.memoryStore.set(snapshotId, snapshot);\n this.logger.debug('State saved to distributed store (memory fallback)', { \n pluginId, \n snapshotId \n });\n break;\n\n case 'none':\n this.logger.debug('State persistence disabled', { pluginId });\n break;\n }\n\n this.stateSnapshots.set(pluginId, snapshot);\n return snapshotId;\n }\n\n /**\n * Restore plugin state after reload\n */\n async restoreState(\n pluginId: string,\n snapshotId?: string\n ): Promise<Record<string, any> | undefined> {\n // Try to get from snapshot ID first, otherwise use latest for plugin\n let snapshot: PluginStateSnapshot | undefined;\n\n if (snapshotId) {\n snapshot = this.memoryStore.get(snapshotId);\n } else {\n snapshot = this.stateSnapshots.get(pluginId);\n }\n\n if (!snapshot) {\n this.logger.warn('No state snapshot found', { pluginId, snapshotId });\n return undefined;\n }\n\n // Verify checksum if available\n if (snapshot.metadata?.checksum) {\n const currentChecksum = this.calculateChecksum(snapshot.state);\n if (currentChecksum !== snapshot.metadata.checksum) {\n this.logger.error('State checksum mismatch - data may be corrupted', { \n pluginId,\n expected: snapshot.metadata.checksum,\n actual: currentChecksum\n });\n return undefined;\n }\n }\n\n this.logger.debug('State restored', { pluginId, version: snapshot.version });\n return snapshot.state;\n }\n\n /**\n * Clear state for a plugin\n */\n clearState(pluginId: string): void {\n this.stateSnapshots.delete(pluginId);\n // Note: We don't clear memory store as it might have multiple snapshots\n this.logger.debug('State cleared', { pluginId });\n }\n\n /**\n * Calculate checksum for state verification using SHA-256.\n */\n private calculateChecksum(state: Record<string, any>): string {\n const stateStr = JSON.stringify(state);\n return createHash('sha256').update(stateStr).digest('hex');\n }\n\n /**\n * Shutdown state manager\n */\n shutdown(): void {\n this.stateSnapshots.clear();\n this.memoryStore.clear();\n this.logger.info('State manager shutdown complete');\n }\n}\n\n/**\n * Hot Reload Manager\n * \n * Manages hot reloading of plugins with state preservation\n */\nexport class HotReloadManager {\n private logger: ObjectLogger;\n private stateManager: PluginStateManager;\n private reloadConfigs = new Map<string, HotReloadConfig>();\n private watchHandles = new Map<string, any>();\n private reloadTimers = new Map<string, NodeJS.Timeout>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'HotReload' });\n this.stateManager = new PluginStateManager(logger);\n }\n\n /**\n * Register a plugin for hot reload\n */\n registerPlugin(pluginName: string, config: HotReloadConfig): void {\n if (!config.enabled) {\n this.logger.debug('Hot reload disabled for plugin', { plugin: pluginName });\n return;\n }\n\n this.reloadConfigs.set(pluginName, config);\n this.logger.info('Plugin registered for hot reload', { \n plugin: pluginName,\n watchPatterns: config.watchPatterns,\n stateStrategy: config.stateStrategy\n });\n }\n\n /**\n * Start watching for changes (requires file system integration)\n */\n startWatching(pluginName: string): void {\n const config = this.reloadConfigs.get(pluginName);\n if (!config || !config.enabled) {\n return;\n }\n\n // Note: Actual file watching would require chokidar or similar\n // This is a placeholder for the integration point\n this.logger.info('File watching started', { \n plugin: pluginName,\n patterns: config.watchPatterns \n });\n }\n\n /**\n * Stop watching for changes\n */\n stopWatching(pluginName: string): void {\n const handle = this.watchHandles.get(pluginName);\n if (handle) {\n // Stop watching (would call chokidar close())\n this.watchHandles.delete(pluginName);\n this.logger.info('File watching stopped', { plugin: pluginName });\n }\n\n // Clear any pending reload timers\n const timer = this.reloadTimers.get(pluginName);\n if (timer) {\n clearTimeout(timer);\n this.reloadTimers.delete(pluginName);\n }\n }\n\n /**\n * Trigger hot reload for a plugin\n */\n async reloadPlugin(\n pluginName: string,\n plugin: Plugin,\n version: string,\n getPluginState: () => Record<string, any>,\n restorePluginState: (state: Record<string, any>) => void\n ): Promise<boolean> {\n const config = this.reloadConfigs.get(pluginName);\n if (!config) {\n this.logger.warn('Cannot reload - plugin not registered', { plugin: pluginName });\n return false;\n }\n\n this.logger.info('Starting hot reload', { plugin: pluginName });\n\n try {\n // Call before reload hooks\n if (config.beforeReload) {\n this.logger.debug('Executing before reload hooks', { \n plugin: pluginName,\n hooks: config.beforeReload \n });\n // Hook execution would be done through kernel's hook system\n }\n\n // Save state if configured\n let snapshotId: string | undefined;\n if (config.preserveState && config.stateStrategy !== 'none') {\n const state = getPluginState();\n snapshotId = await this.stateManager.saveState(\n pluginName,\n version,\n state,\n config\n );\n this.logger.debug('Plugin state saved', { plugin: pluginName, snapshotId });\n }\n\n // Gracefully shutdown the plugin\n if (plugin.destroy) {\n this.logger.debug('Destroying plugin', { plugin: pluginName });\n \n const shutdownPromise = plugin.destroy();\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error('Shutdown timeout')), config.shutdownTimeout);\n });\n\n await Promise.race([shutdownPromise, timeoutPromise]);\n this.logger.debug('Plugin destroyed successfully', { plugin: pluginName });\n }\n\n // At this point, the kernel would reload the plugin module\n // This would be handled by the plugin loader\n this.logger.debug('Plugin module would be reloaded here', { plugin: pluginName });\n\n // Restore state if we saved it\n if (snapshotId && config.preserveState) {\n const restoredState = await this.stateManager.restoreState(pluginName, snapshotId);\n if (restoredState) {\n restorePluginState(restoredState);\n this.logger.debug('Plugin state restored', { plugin: pluginName });\n }\n }\n\n // Call after reload hooks\n if (config.afterReload) {\n this.logger.debug('Executing after reload hooks', { \n plugin: pluginName,\n hooks: config.afterReload \n });\n // Hook execution would be done through kernel's hook system\n }\n\n this.logger.info('Hot reload completed successfully', { plugin: pluginName });\n return true;\n } catch (error) {\n this.logger.error('Hot reload failed', { \n plugin: pluginName, \n error \n });\n return false;\n }\n }\n\n /**\n * Schedule a reload with debouncing\n */\n scheduleReload(\n pluginName: string,\n reloadFn: () => Promise<void>\n ): void {\n const config = this.reloadConfigs.get(pluginName);\n if (!config) {\n return;\n }\n\n // Clear existing timer\n const existingTimer = this.reloadTimers.get(pluginName);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Schedule new reload with debounce\n const timer = setTimeout(() => {\n this.logger.debug('Debounce period elapsed, executing reload', { \n plugin: pluginName \n });\n reloadFn().catch(error => {\n this.logger.error('Scheduled reload failed', { \n plugin: pluginName, \n error \n });\n });\n this.reloadTimers.delete(pluginName);\n }, config.debounceDelay);\n\n this.reloadTimers.set(pluginName, timer);\n this.logger.debug('Reload scheduled with debounce', { \n plugin: pluginName,\n delay: config.debounceDelay \n });\n }\n\n /**\n * Get state manager for direct access\n */\n getStateManager(): PluginStateManager {\n return this.stateManager;\n }\n\n /**\n * Shutdown hot reload manager\n */\n shutdown(): void {\n // Stop all watching\n for (const pluginName of this.watchHandles.keys()) {\n this.stopWatching(pluginName);\n }\n\n // Clear all timers\n for (const timer of this.reloadTimers.values()) {\n clearTimeout(timer);\n }\n\n this.reloadConfigs.clear();\n this.watchHandles.clear();\n this.reloadTimers.clear();\n this.stateManager.shutdown();\n \n this.logger.info('Hot reload manager shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n SemanticVersion,\n VersionConstraint,\n CompatibilityLevel,\n DependencyConflict\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from './logger.js';\n\n/**\n * Semantic Version Parser and Comparator\n * \n * Implements semantic versioning comparison and constraint matching\n */\nexport class SemanticVersionManager {\n /**\n * Parse a version string into semantic version components\n */\n static parse(versionStr: string): SemanticVersion {\n // Remove 'v' prefix if present\n const cleanVersion = versionStr.replace(/^v/, '');\n \n // Match semver pattern: major.minor.patch[-prerelease][+build]\n const match = cleanVersion.match(\n /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([a-zA-Z0-9.-]+))?(?:\\+([a-zA-Z0-9.-]+))?$/\n );\n\n if (!match) {\n throw new Error(`Invalid semantic version: ${versionStr}`);\n }\n\n return {\n major: parseInt(match[1], 10),\n minor: parseInt(match[2], 10),\n patch: parseInt(match[3], 10),\n preRelease: match[4],\n build: match[5],\n };\n }\n\n /**\n * Convert semantic version back to string\n */\n static toString(version: SemanticVersion): string {\n let str = `${version.major}.${version.minor}.${version.patch}`;\n if (version.preRelease) {\n str += `-${version.preRelease}`;\n }\n if (version.build) {\n str += `+${version.build}`;\n }\n return str;\n }\n\n /**\n * Compare two semantic versions\n * Returns: -1 if a < b, 0 if a === b, 1 if a > b\n */\n static compare(a: SemanticVersion, b: SemanticVersion): number {\n // Compare major, minor, patch\n if (a.major !== b.major) return a.major - b.major;\n if (a.minor !== b.minor) return a.minor - b.minor;\n if (a.patch !== b.patch) return a.patch - b.patch;\n\n // Pre-release versions have lower precedence\n if (a.preRelease && !b.preRelease) return -1;\n if (!a.preRelease && b.preRelease) return 1;\n \n // Compare pre-release versions\n if (a.preRelease && b.preRelease) {\n return a.preRelease.localeCompare(b.preRelease);\n }\n\n return 0;\n }\n\n /**\n * Check if version satisfies constraint\n */\n static satisfies(version: SemanticVersion, constraint: VersionConstraint): boolean {\n const constraintStr = constraint as string;\n\n // Any version\n if (constraintStr === '*' || constraintStr === 'latest') {\n return true;\n }\n\n // Exact version\n if (/^[\\d.]+$/.test(constraintStr)) {\n const exact = this.parse(constraintStr);\n return this.compare(version, exact) === 0;\n }\n\n // Caret range (^): Compatible with version\n if (constraintStr.startsWith('^')) {\n const base = this.parse(constraintStr.slice(1));\n return (\n version.major === base.major &&\n this.compare(version, base) >= 0\n );\n }\n\n // Tilde range (~): Approximately equivalent\n if (constraintStr.startsWith('~')) {\n const base = this.parse(constraintStr.slice(1));\n return (\n version.major === base.major &&\n version.minor === base.minor &&\n this.compare(version, base) >= 0\n );\n }\n\n // Greater than or equal\n if (constraintStr.startsWith('>=')) {\n const base = this.parse(constraintStr.slice(2));\n return this.compare(version, base) >= 0;\n }\n\n // Greater than\n if (constraintStr.startsWith('>')) {\n const base = this.parse(constraintStr.slice(1));\n return this.compare(version, base) > 0;\n }\n\n // Less than or equal\n if (constraintStr.startsWith('<=')) {\n const base = this.parse(constraintStr.slice(2));\n return this.compare(version, base) <= 0;\n }\n\n // Less than\n if (constraintStr.startsWith('<')) {\n const base = this.parse(constraintStr.slice(1));\n return this.compare(version, base) < 0;\n }\n\n // Range (1.2.3 - 2.3.4)\n const rangeMatch = constraintStr.match(/^([\\d.]+)\\s*-\\s*([\\d.]+)$/);\n if (rangeMatch) {\n const min = this.parse(rangeMatch[1]);\n const max = this.parse(rangeMatch[2]);\n return this.compare(version, min) >= 0 && this.compare(version, max) <= 0;\n }\n\n return false;\n }\n\n /**\n * Determine compatibility level between two versions\n */\n static getCompatibilityLevel(from: SemanticVersion, to: SemanticVersion): CompatibilityLevel {\n const cmp = this.compare(from, to);\n\n // Same version\n if (cmp === 0) {\n return 'fully-compatible';\n }\n\n // Major version changed - breaking changes\n if (from.major !== to.major) {\n return 'breaking-changes';\n }\n\n // Minor version increased - backward compatible\n if (from.minor < to.minor) {\n return 'backward-compatible';\n }\n\n // Patch version increased - fully compatible\n if (from.patch < to.patch) {\n return 'fully-compatible';\n }\n\n // Downgrade - incompatible\n return 'incompatible';\n }\n}\n\n/**\n * Plugin Dependency Resolver\n * \n * Resolves plugin dependencies using topological sorting and conflict detection\n */\nexport class DependencyResolver {\n private logger: ObjectLogger;\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'DependencyResolver' });\n }\n\n /**\n * Resolve dependencies using topological sort\n */\n resolve(\n plugins: Map<string, { version?: string; dependencies?: string[] }>\n ): string[] {\n const graph = new Map<string, string[]>();\n const inDegree = new Map<string, number>();\n\n // Build dependency graph\n for (const [pluginName, pluginInfo] of plugins) {\n if (!graph.has(pluginName)) {\n graph.set(pluginName, []);\n inDegree.set(pluginName, 0);\n }\n\n const deps = pluginInfo.dependencies || [];\n for (const dep of deps) {\n // Check if dependency exists\n if (!plugins.has(dep)) {\n throw new Error(`Missing dependency: ${pluginName} requires ${dep}`);\n }\n\n // Add edge\n if (!graph.has(dep)) {\n graph.set(dep, []);\n inDegree.set(dep, 0);\n }\n graph.get(dep)!.push(pluginName);\n inDegree.set(pluginName, (inDegree.get(pluginName) || 0) + 1);\n }\n }\n\n // Topological sort using Kahn's algorithm\n const queue: string[] = [];\n const result: string[] = [];\n\n // Add all nodes with no incoming edges\n for (const [node, degree] of inDegree) {\n if (degree === 0) {\n queue.push(node);\n }\n }\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n result.push(node);\n\n // Reduce in-degree for dependent nodes\n const dependents = graph.get(node) || [];\n for (const dependent of dependents) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n \n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n // Check for circular dependencies\n if (result.length !== plugins.size) {\n const remaining = Array.from(plugins.keys()).filter(p => !result.includes(p));\n this.logger.error('Circular dependency detected', { remaining });\n throw new Error(`Circular dependency detected among: ${remaining.join(', ')}`);\n }\n\n this.logger.debug('Dependencies resolved', { order: result });\n return result;\n }\n\n /**\n * Detect dependency conflicts\n */\n detectConflicts(\n plugins: Map<string, { version: string; dependencies?: Record<string, VersionConstraint> }>\n ): DependencyConflict[] {\n const conflicts: DependencyConflict[] = [];\n const versionRequirements = new Map<string, Map<string, VersionConstraint>>();\n\n // Collect all version requirements\n for (const [pluginName, pluginInfo] of plugins) {\n if (!pluginInfo.dependencies) continue;\n\n for (const [depName, constraint] of Object.entries(pluginInfo.dependencies)) {\n if (!versionRequirements.has(depName)) {\n versionRequirements.set(depName, new Map());\n }\n versionRequirements.get(depName)!.set(pluginName, constraint);\n }\n }\n\n // Check for version mismatches\n for (const [depName, requirements] of versionRequirements) {\n const depInfo = plugins.get(depName);\n if (!depInfo) continue;\n\n const depVersion = SemanticVersionManager.parse(depInfo.version);\n const unsatisfied: Array<{ pluginId: string; version: string }> = [];\n\n for (const [requiringPlugin, constraint] of requirements) {\n if (!SemanticVersionManager.satisfies(depVersion, constraint)) {\n unsatisfied.push({\n pluginId: requiringPlugin,\n version: constraint as string,\n });\n }\n }\n\n if (unsatisfied.length > 0) {\n conflicts.push({\n type: 'version-mismatch',\n severity: 'error',\n description: `Version mismatch for ${depName}: detected ${unsatisfied.length} unsatisfied requirements`,\n plugins: [\n { pluginId: depName, version: depInfo.version },\n ...unsatisfied,\n ],\n resolutions: [{\n strategy: 'upgrade',\n description: `Upgrade ${depName} to satisfy all constraints`,\n targetPlugins: [depName],\n automatic: false,\n } as any],\n });\n }\n }\n\n // Check for circular dependencies (will be caught by resolve())\n try {\n this.resolve(new Map(\n Array.from(plugins.entries()).map(([name, info]) => [\n name,\n { version: info.version, dependencies: info.dependencies ? Object.keys(info.dependencies) : [] }\n ])\n ));\n } catch (error) {\n if (error instanceof Error && error.message.includes('Circular dependency')) {\n conflicts.push({\n type: 'circular-dependency',\n severity: 'critical',\n description: error.message,\n plugins: [], // Would need to extract from error\n resolutions: [{\n strategy: 'manual',\n description: 'Remove circular dependency by restructuring plugins',\n automatic: false,\n } as any],\n });\n }\n }\n\n return conflicts;\n }\n\n /**\n * Find best version that satisfies all constraints\n */\n findBestVersion(\n availableVersions: string[],\n constraints: VersionConstraint[]\n ): string | undefined {\n // Parse and sort versions (highest first)\n const versions = availableVersions\n .map(v => ({ str: v, parsed: SemanticVersionManager.parse(v) }))\n .sort((a, b) => -SemanticVersionManager.compare(a.parsed, b.parsed));\n\n // Find highest version that satisfies all constraints\n for (const version of versions) {\n const satisfiesAll = constraints.every(constraint =>\n SemanticVersionManager.satisfies(version.parsed, constraint)\n );\n\n if (satisfiesAll) {\n return version.str;\n }\n }\n\n return undefined;\n }\n\n /**\n * Check if dependencies form a valid DAG (no cycles)\n */\n isAcyclic(dependencies: Map<string, string[]>): boolean {\n try {\n const plugins = new Map(\n Array.from(dependencies.entries()).map(([name, deps]) => [\n name,\n { dependencies: deps }\n ])\n );\n this.resolve(plugins);\n return true;\n } catch {\n return false;\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ObjectLogger } from './logger.js';\n\n/**\n * Namespace entry representing an object/view/flow etc. registered by a package.\n */\nexport interface NamespaceEntry {\n /** The namespace path (e.g. \"objects.project_task\", \"views.task_list\") */\n namespace: string;\n /** The package that owns this namespace */\n packageId: string;\n /** When this entry was registered */\n registeredAt: string;\n}\n\n/**\n * Result of a namespace conflict check.\n */\nexport interface NamespaceConflict {\n /** The conflicting namespace path */\n namespace: string;\n /** The package that currently owns this namespace */\n existingPackageId: string;\n /** The package attempting to register the same namespace */\n incomingPackageId: string;\n /** A suggested alternative name to avoid the conflict */\n suggestion?: string;\n}\n\n/**\n * Result of namespace availability check.\n */\nexport interface NamespaceCheckResult {\n /** Whether all requested namespaces are available */\n available: boolean;\n /** List of conflicts detected */\n conflicts: NamespaceConflict[];\n /** Suggested alternatives for each conflict */\n suggestions: Record<string, string>;\n}\n\n/**\n * Namespace Resolver\n *\n * Manages namespace registration for installed packages and detects collisions\n * during install-time. Each metadata item (object, view, flow, page, etc.)\n * produces a namespace like `objects.<name>` or `views.<name>`.\n *\n * When a new package declares objects, views, or other metadata that would\n * collide with an existing package's metadata, this resolver reports the\n * conflicts and suggests prefixed alternatives.\n */\nexport class NamespaceResolver {\n private logger: ObjectLogger;\n private registry: Map<string, NamespaceEntry> = new Map();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'NamespaceResolver' });\n }\n\n /**\n * Register namespaces owned by a package.\n */\n register(packageId: string, namespaces: string[]): void {\n const now = new Date().toISOString();\n for (const ns of namespaces) {\n if (this.registry.has(ns)) {\n const existing = this.registry.get(ns)!;\n if (existing.packageId !== packageId) {\n this.logger.warn('Overwriting namespace entry', { namespace: ns, existing: existing.packageId, incoming: packageId });\n }\n }\n this.registry.set(ns, { namespace: ns, packageId, registeredAt: now });\n this.logger.debug('Namespace registered', { namespace: ns, packageId });\n }\n }\n\n /**\n * Unregister all namespaces belonging to a package.\n */\n unregister(packageId: string): string[] {\n const removed: string[] = [];\n for (const [ns, entry] of this.registry) {\n if (entry.packageId === packageId) {\n this.registry.delete(ns);\n removed.push(ns);\n }\n }\n this.logger.debug('Namespaces unregistered', { packageId, count: removed.length });\n return removed;\n }\n\n /**\n * Check whether a set of namespaces is available for a given package.\n */\n checkAvailability(packageId: string, namespaces: string[]): NamespaceCheckResult {\n const conflicts: NamespaceConflict[] = [];\n const suggestions: Record<string, string> = {};\n\n for (const ns of namespaces) {\n const existing = this.registry.get(ns);\n if (existing && existing.packageId !== packageId) {\n const suggestion = this.suggestAlternative(ns, packageId);\n conflicts.push({\n namespace: ns,\n existingPackageId: existing.packageId,\n incomingPackageId: packageId,\n suggestion,\n });\n suggestions[ns] = suggestion;\n }\n }\n\n return {\n available: conflicts.length === 0,\n conflicts,\n suggestions,\n };\n }\n\n /**\n * Extract namespace strings from a package's metadata definition.\n */\n extractNamespaces(config: Record<string, unknown>): string[] {\n const namespaces: string[] = [];\n const categories = [\n 'objects', 'views', 'pages', 'flows', 'workflows',\n 'apps', 'dashboards', 'reports', 'actions', 'agents',\n ];\n\n for (const category of categories) {\n const items = config[category];\n if (Array.isArray(items)) {\n for (const item of items) {\n const name = (item as Record<string, unknown>)?.name;\n if (typeof name === 'string') {\n namespaces.push(`${category}.${name}`);\n }\n }\n } else if (items && typeof items === 'object') {\n for (const key of Object.keys(items as object)) {\n namespaces.push(`${category}.${key}`);\n }\n }\n }\n\n return namespaces;\n }\n\n /**\n * Get all registered entries.\n */\n getRegistry(): ReadonlyMap<string, NamespaceEntry> {\n return this.registry;\n }\n\n /**\n * Get all namespaces belonging to a specific package.\n */\n getPackageNamespaces(packageId: string): string[] {\n const namespaces: string[] = [];\n for (const [ns, entry] of this.registry) {\n if (entry.packageId === packageId) {\n namespaces.push(ns);\n }\n }\n return namespaces;\n }\n\n /**\n * Generate a prefixed alternative namespace to avoid conflicts.\n */\n private suggestAlternative(ns: string, packageId: string): string {\n // Extract the short package name for prefixing\n const shortName = packageId\n .replace(/^@[^/]+\\//, '')\n .replace(/^plugin-/, '')\n .replace(/-/g, '_');\n\n const parts = ns.split('.');\n if (parts.length >= 2) {\n // e.g. \"objects.task\" → \"objects.crm_task\"\n return `${parts[0]}.${shortName}_${parts.slice(1).join('.')}`;\n }\n return `${shortName}_${ns}`;\n }\n}\n"],"mappings":"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","names":["cryptoSign","cryptoVerify","ServiceLifecycle","service","nodePath","import_node_crypto","safeJsonParse","import_node_crypto"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/kernel-base.ts","../src/logger.ts","../src/kernel.ts","../src/security/plugin-config-validator.ts","../src/security/plugin-artifact-signature.ts","../src/plugin-loader.ts","../src/utils/env.ts","../src/fallbacks/memory-cache.ts","../src/fallbacks/memory-queue.ts","../src/fallbacks/memory-job.ts","../src/fallbacks/memory-i18n.ts","../src/fallbacks/memory-metadata.ts","../src/fallbacks/authored-translation-sync.ts","../src/fallbacks/index.ts","../src/lite-kernel.ts","../src/api-registry.ts","../src/api-registry-plugin.ts","../src/qa/index.ts","../src/qa/runner.ts","../src/qa/http-adapter.ts","../src/security/plugin-signature-verifier.ts","../src/security/plugin-permission-enforcer.ts","../src/security/permission-manager.ts","../src/security/sandbox-runtime.ts","../src/security/security-scanner.ts","../src/security/api-key.ts","../src/security/resolve-authz-context.ts","../src/security/grant-validity.ts","../src/security/posture-ladder.ts","../src/security/auth-gate.ts","../src/security/anonymous-deny.ts","../src/utils/datetime.ts","../src/utils/bulk-write.ts","../src/health-monitor.ts","../src/hot-reload.ts","../src/dependency-resolver.ts","../src/namespace-resolver.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/core\n * \n * Core runtime for ObjectStack microkernel architecture.\n * Provides plugin system, dependency injection, and lifecycle management.\n */\n\nexport * from './kernel-base.js';\nexport * from './kernel.js';\nexport * from './lite-kernel.js';\nexport * from './types.js';\nexport * from './logger.js';\nexport * from './plugin-loader.js';\nexport * from './api-registry.js';\nexport * from './api-registry-plugin.js';\nexport * as QA from './qa/index.js';\n\n// Export security utilities\nexport * from './security/index.js';\n\n// Export environment utilities\nexport * from './utils/env.js';\n\n// Export timezone-aware calendar utilities (ADR-0053 Phase 2)\nexport * from './utils/datetime.js';\n\n// Export the shared batched-write helper (framework#2678)\nexport * from './utils/bulk-write.js';\n\n// Export in-memory fallbacks for core-criticality services\nexport * from './fallbacks/index.js';\n\n// Export Phase 2 components - Advanced lifecycle management\nexport * from './health-monitor.js';\nexport * from './hot-reload.js';\nexport * from './dependency-resolver.js';\n\n// Export Phase 3 components - Package lifecycle management\nexport * from './namespace-resolver.js';\n\n// Re-export contracts from @objectstack/spec for backward compatibility\nexport type { \n Logger,\n IHttpServer,\n IHttpRequest,\n IHttpResponse,\n RouteHandler,\n Middleware,\n IDataEngine,\n IDataDriver,\n} from '@objectstack/spec/contracts';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from './types.js';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { IServiceRegistry } from '@objectstack/spec/contracts';\n\n/**\n * Kernel state machine\n */\nexport type KernelState = 'idle' | 'initializing' | 'running' | 'stopping' | 'stopped';\n\n/**\n * ObjectKernelBase - Abstract Base Class for Microkernel\n * \n * Provides common functionality for ObjectKernel and LiteKernel:\n * - Plugin management (Map storage)\n * - Dependency resolution (topological sort)\n * - Hook/Event system\n * - Context creation\n * - State validation\n * \n * This eliminates code duplication between the implementations.\n */\nexport abstract class ObjectKernelBase {\n protected plugins: Map<string, Plugin> = new Map();\n protected services: IServiceRegistry | Map<string, any> = new Map();\n protected hooks: Map<string, Array<(...args: any[]) => void | Promise<void>>> = new Map();\n protected state: KernelState = 'idle';\n protected logger: Logger;\n protected context!: PluginContext;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n /**\n * Validate kernel state\n * @param requiredState - Required state for the operation\n * @throws Error if current state doesn't match\n */\n protected validateState(requiredState: KernelState): void {\n if (this.state !== requiredState) {\n throw new Error(\n `[Kernel] Invalid state: expected '${requiredState}', got '${this.state}'`\n );\n }\n }\n\n /**\n * Validate kernel is in idle state (for plugin registration)\n */\n protected validateIdle(): void {\n if (this.state !== 'idle') {\n throw new Error('[Kernel] Cannot register plugins after bootstrap has started');\n }\n }\n\n /**\n * Create the plugin context\n * Subclasses can override to customize context creation\n */\n protected createContext(): PluginContext {\n return {\n registerService: (name, service) => {\n if (this.services instanceof Map) {\n if (this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' already registered`);\n }\n this.services.set(name, service);\n } else {\n // IServiceRegistry implementation\n this.services.register(name, service);\n }\n this.logger.info(`Service '${name}' registered`, { service: name });\n },\n getService: <T>(name: string): T => {\n if (this.services instanceof Map) {\n const service = this.services.get(name);\n if (!service) {\n throw new Error(`[Kernel] Service '${name}' not found`);\n }\n return service as T;\n } else {\n // IServiceRegistry implementation\n return this.services.get<T>(name);\n }\n },\n replaceService: <T>(name: string, implementation: T): void => {\n if (this.services instanceof Map) {\n if (!this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' not found. Use registerService() to add new services.`);\n }\n this.services.set(name, implementation);\n } else {\n // IServiceRegistry implementation\n if (!this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' not found. Use registerService() to add new services.`);\n }\n this.services.register(name, implementation);\n }\n this.logger.info(`Service '${name}' replaced`, { service: name });\n },\n hook: (name, handler) => {\n if (!this.hooks.has(name)) {\n this.hooks.set(name, []);\n }\n this.hooks.get(name)!.push(handler);\n },\n trigger: async (name, ...args) => {\n const handlers = this.hooks.get(name) || [];\n for (const handler of handlers) {\n await handler(...args);\n }\n },\n getServices: () => {\n if (this.services instanceof Map) {\n return new Map(this.services);\n } else {\n // For IServiceRegistry, we need to return the underlying Map\n // This is a compatibility method\n return new Map();\n }\n },\n logger: this.logger,\n getKernel: () => this as any,\n registerServiceFactory: (_name, _factory, _lifecycle, _dependencies) => {\n throw new Error('[KernelBase] registerServiceFactory not supported — use ObjectKernel');\n },\n getServiceScoped: async <T>(_name: string, _scopeId: string): Promise<T> => {\n throw new Error('[KernelBase] getServiceScoped not supported — use ObjectKernel');\n },\n };\n }\n\n /**\n * Resolve plugin dependencies using topological sort\n * @returns Ordered list of plugins (dependencies first)\n */\n protected resolveDependencies(): Plugin[] {\n const resolved: Plugin[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (pluginName: string) => {\n if (visited.has(pluginName)) return;\n \n if (visiting.has(pluginName)) {\n throw new Error(`[Kernel] Circular dependency detected: ${pluginName}`);\n }\n\n const plugin = this.plugins.get(pluginName);\n if (!plugin) {\n throw new Error(`[Kernel] Plugin '${pluginName}' not found`);\n }\n\n visiting.add(pluginName);\n\n // Visit dependencies first\n const deps = plugin.dependencies || [];\n for (const dep of deps) {\n if (!this.plugins.has(dep)) {\n throw new Error(\n `[Kernel] Dependency '${dep}' not found for plugin '${pluginName}'`\n );\n }\n visit(dep);\n }\n\n visiting.delete(pluginName);\n visited.add(pluginName);\n resolved.push(plugin);\n };\n\n // Visit all plugins\n for (const pluginName of this.plugins.keys()) {\n visit(pluginName);\n }\n\n return resolved;\n }\n\n /**\n * Run plugin init phase\n * @param plugin - Plugin to initialize\n */\n protected async runPluginInit(plugin: Plugin): Promise<void> {\n const pluginName = plugin.name;\n this.logger.info(`Initializing plugin: ${pluginName}`);\n \n try {\n await plugin.init(this.context);\n this.logger.info(`Plugin initialized: ${pluginName}`);\n } catch (error) {\n this.logger.error(`Plugin init failed: ${pluginName}`, error as Error);\n throw error;\n }\n }\n\n /**\n * Run plugin start phase\n * @param plugin - Plugin to start\n */\n protected async runPluginStart(plugin: Plugin): Promise<void> {\n if (!plugin.start) return;\n \n const pluginName = plugin.name;\n this.logger.info(`Starting plugin: ${pluginName}`);\n \n try {\n await plugin.start(this.context);\n this.logger.info(`Plugin started: ${pluginName}`);\n } catch (error) {\n this.logger.error(`Plugin start failed: ${pluginName}`, error as Error);\n throw error;\n }\n }\n\n /**\n * Run plugin destroy phase\n * @param plugin - Plugin to destroy\n */\n protected async runPluginDestroy(plugin: Plugin): Promise<void> {\n if (!plugin.destroy) return;\n \n const pluginName = plugin.name;\n this.logger.info(`Destroying plugin: ${pluginName}`);\n \n try {\n await plugin.destroy();\n this.logger.info(`Plugin destroyed: ${pluginName}`);\n } catch (error) {\n this.logger.error(`Plugin destroy failed: ${pluginName}`, error as Error);\n throw error;\n }\n }\n\n /**\n * Trigger a hook with all registered handlers\n * @param name - Hook name\n * @param args - Arguments to pass to handlers\n */\n protected async triggerHook(name: string, ...args: any[]): Promise<void> {\n const handlers = this.hooks.get(name) || [];\n this.logger.debug(`Triggering hook: ${name}`, { \n hook: name, \n handlerCount: handlers.length \n });\n \n for (const handler of handlers) {\n try {\n await handler(...args);\n } catch (error) {\n this.logger.error(`Hook handler failed: ${name}`, error as Error);\n // Continue with other handlers even if one fails\n }\n }\n }\n\n /**\n * Get current kernel state\n */\n getState(): KernelState {\n return this.state;\n }\n\n /**\n * Get all registered plugins\n */\n getPlugins(): Map<string, Plugin> {\n return new Map(this.plugins);\n }\n\n /**\n * Abstract methods to be implemented by subclasses\n */\n abstract use(plugin: Plugin): this | Promise<this>;\n abstract bootstrap(): Promise<void>;\n abstract destroy(): Promise<void>;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { LoggerConfig, LogLevel } from '@objectstack/spec/system';\nimport type { Logger } from '@objectstack/spec/contracts';\n\n// Re-export the contract type so consumers can do\n// `import type { Logger } from '@objectstack/core/logger'` without also\n// pulling `@objectstack/spec` into their bundle graph manually.\nexport type { Logger };\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 4,\n silent: 5,\n};\n\nconst LEVEL_COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m',\n info: '\\x1b[32m',\n warn: '\\x1b[33m',\n error: '\\x1b[31m',\n fatal: '\\x1b[35m',\n silent: '',\n};\n\nconst RESET = '\\x1b[0m';\n\n/**\n * Whether ANSI color may be written to the given stream.\n *\n * Follows the https://no-color.org convention: a non-empty `NO_COLOR` env var\n * disables color regardless of TTY, and non-TTY destinations (pipes, CI logs,\n * redirected output) always get plain text so plain-text log scanners see\n * uncolored level tags. Browser bundles have no `process`/TTY → plain text.\n */\nfunction colorEnabled(stream: { isTTY?: boolean } | undefined): boolean {\n if (typeof process !== 'undefined') {\n const noColor = (process as any).env?.NO_COLOR;\n if (noColor !== undefined && noColor !== '') return false;\n }\n return Boolean(stream?.isTTY);\n}\n\n/**\n * Resolve a Node builtin without putting it in this module's import graph.\n *\n * This entry is deliberately browser-safe — `@objectstack/client` bundles it —\n * so `fs`/`path` must never be imported statically. A lazy `require()` used to\n * meet that bar, but esbuild rewrites it to the `__require` shim in the ESM\n * output, which throws `Dynamic require of \"fs\" is not supported`. Every Node\n * ESM consumer (`os serve`, `os dev`) therefore lost file logging (#3110).\n * `process.getBuiltinModule` is a plain method call — opaque to bundlers — and\n * works in both module systems.\n */\nfunction loadNodeBuiltin<T>(id: string): T | undefined {\n if (typeof process === 'undefined') return undefined;\n\n const getBuiltinModule = (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule;\n if (typeof getBuiltinModule === 'function') {\n try {\n return getBuiltinModule.call(process, `node:${id}`) as T;\n } catch {\n return undefined;\n }\n }\n\n // Node < 20.16 / < 22.3 predates `getBuiltinModule`. Real `require` still\n // resolves in the CJS build; in the ESM build this is the shim that throws,\n // which the caller now reports rather than swallows.\n try {\n return require(id) as T;\n } catch {\n return undefined;\n }\n}\n\nexport class ObjectLogger implements Logger {\n private config: Required<Omit<LoggerConfig, 'file' | 'rotation' | 'name'>> & {\n file?: string;\n rotation?: { maxSize: string; maxFiles: number };\n name?: string;\n };\n private bindings: Record<string, any>;\n private fileStream?: any;\n /** Only the logger that opened the stream may close it — children share it. */\n private ownsFileStream = false;\n private fileLoggingDisabled = false;\n\n constructor(config: Partial<LoggerConfig> = {}, bindings: Record<string, any> = {}) {\n this.config = {\n name: config.name,\n level: config.level ?? 'info',\n format: config.format ?? 'pretty',\n redact: config.redact ?? ['password', 'token', 'secret', 'key'],\n sourceLocation: config.sourceLocation ?? false,\n file: config.file,\n rotation: config.rotation ?? { maxSize: '10m', maxFiles: 5 },\n };\n this.bindings = bindings;\n\n if (this.config.file && typeof process !== 'undefined') {\n this.openFileStream(this.config.file);\n }\n }\n\n private openFileStream(path: string) {\n const fs = loadNodeBuiltin<typeof import('node:fs')>('fs');\n const nodePath = loadNodeBuiltin<typeof import('node:path')>('path');\n if (!fs || !nodePath) {\n this.disableFileLogging(path, 'no filesystem access in this runtime');\n return;\n }\n\n try {\n fs.mkdirSync(nodePath.dirname(path), { recursive: true });\n const stream = fs.createWriteStream(path, { flags: 'a' });\n // `createWriteStream` reports open failures (EACCES, EISDIR, …)\n // asynchronously. An 'error' event with no listener is fatal to the\n // process, so file logging must degrade here rather than take the\n // host down.\n stream.on('error', (err: Error) => this.disableFileLogging(path, err.message));\n this.fileStream = stream;\n this.ownsFileStream = true;\n } catch (err) {\n this.disableFileLogging(path, (err as Error).message);\n }\n }\n\n /**\n * Report — once — that an explicitly configured `file` destination is not\n * being written, and stop trying.\n *\n * Deliberately not routed through `write()`: this says the logger cannot\n * honour its own config, so `level` must not filter it. The bare `catch {}`\n * this replaces is exactly how #3110 stayed hidden.\n */\n private disableFileLogging(path: string, reason: string) {\n this.fileStream = undefined;\n this.ownsFileStream = false;\n if (this.fileLoggingDisabled) return;\n this.fileLoggingDisabled = true;\n\n const label = this.config.name ? `[${this.config.name}] ` : '';\n const notice = `${label}logger: file logging disabled — cannot write to ${path}: ${reason}`;\n if (typeof process !== 'undefined' && (process as any).stderr) {\n (process as any).stderr.write(notice + '\\n');\n } else if (typeof console !== 'undefined') {\n console.warn(notice);\n }\n }\n\n private isEnabled(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[this.config.level];\n }\n\n private redactSensitive(obj: any): any {\n if (!obj || typeof obj !== 'object') return obj;\n const redacted = Array.isArray(obj) ? [...obj] : { ...obj };\n for (const key in redacted) {\n const lower = key.toLowerCase();\n if (this.config.redact.some((p: string) => lower.includes(p.toLowerCase()))) {\n redacted[key] = '***REDACTED***';\n } else if (typeof redacted[key] === 'object' && redacted[key] !== null) {\n redacted[key] = this.redactSensitive(redacted[key]);\n }\n }\n return redacted;\n }\n\n private write(level: LogLevel, message: string, meta?: Record<string, any>, error?: Error) {\n if (!this.isEnabled(level)) return;\n\n const context = this.redactSensitive({\n ...this.bindings,\n ...meta,\n ...(error ? { error: { message: error.message, stack: error.stack } } : {}),\n });\n\n const hasContext = Object.keys(context).length > 0;\n const ts = new Date().toISOString();\n\n const isErrorLevel = level === 'error' || level === 'fatal';\n const proc = typeof process !== 'undefined' ? (process as any) : undefined;\n const stream = proc ? (isErrorLevel ? proc.stderr : proc.stdout) : undefined;\n\n let line: string; // console output — may carry ANSI color\n let plainLine: string; // file output — never colored\n\n if (this.config.format === 'json') {\n line = plainLine = JSON.stringify({\n time: ts,\n level,\n ...(this.config.name ? { name: this.config.name } : {}),\n msg: message,\n ...context,\n });\n } else if (this.config.format === 'text') {\n const parts = [ts, level.toUpperCase(), message];\n if (hasContext) parts.push(JSON.stringify(context));\n line = plainLine = parts.join(' | ');\n } else {\n // pretty\n const label = this.config.name ? `[${this.config.name}] ` : '';\n const head = `${ts} ${level.toUpperCase()}`;\n let tail = ` ${label}${message}`;\n if (hasContext) tail += ` ${JSON.stringify(context)}`;\n plainLine = head + tail;\n const color = LEVEL_COLORS[level] || '';\n line = color && colorEnabled(stream) ? `${color}${head}${RESET}${tail}` : plainLine;\n }\n\n // Browser-safe output: prefer process streams when available, otherwise\n // fall back to console. `process` may be missing entirely (browsers) or\n // present without stdio streams (bundler shims) — both fall through to\n // console. The previous unguarded `process.stderr?.write` threw\n // `ReferenceError: process is not defined` in browsers because\n // `process` itself is the missing global, not just its `stderr` field.\n if (stream) {\n stream.write(line + '\\n');\n } else if (typeof console !== 'undefined') {\n const fn =\n level === 'error' || level === 'fatal' ? console.error\n : level === 'warn' ? console.warn\n : level === 'debug' ? console.debug\n : console.log;\n fn(line);\n }\n\n if (this.fileStream) {\n this.fileStream.write(plainLine + '\\n');\n }\n }\n\n debug(message: string, meta?: Record<string, any>): void {\n this.write('debug', message, meta);\n }\n\n info(message: string, meta?: Record<string, any>): void {\n this.write('info', message, meta);\n }\n\n warn(message: string, meta?: Record<string, any>): void {\n this.write('warn', message, meta);\n }\n\n error(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void {\n if (errorOrMeta instanceof Error) {\n this.write('error', message, meta, errorOrMeta);\n } else {\n this.write('error', message, errorOrMeta);\n }\n }\n\n fatal(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void {\n if (errorOrMeta instanceof Error) {\n this.write('fatal', message, meta, errorOrMeta);\n } else {\n this.write('fatal', message, errorOrMeta);\n }\n }\n\n log(message: string, ...args: any[]): void {\n this.info(message, args.length > 0 ? { args } : undefined);\n }\n\n child(context: Record<string, any>): ObjectLogger {\n // Construct without `file`, then share the parent's stream: the\n // constructor opens eagerly, so passing `file` through would open a\n // second stream per child and immediately orphan it. That leak was\n // unreachable while #3110 kept the ESM open path dead.\n const child = new ObjectLogger({ ...this.config, file: undefined }, { ...this.bindings, ...context });\n child.config.file = this.config.file;\n child.fileStream = this.fileStream;\n return child;\n }\n\n withTrace(traceId: string, spanId?: string): ObjectLogger {\n return this.child({ traceId, spanId });\n }\n\n async destroy(): Promise<void> {\n const stream = this.fileStream;\n this.fileStream = undefined;\n // Children share the opener's stream; if they closed it too, one child's\n // teardown would end file logging for the parent and every sibling,\n // whose writes then land on a closed stream and only trip the 'error'\n // handler above.\n if (!stream || !this.ownsFileStream) return;\n this.ownsFileStream = false;\n await new Promise<void>((resolve) => stream.end(resolve));\n }\n}\n\nexport function createLogger(config?: Partial<LoggerConfig>): ObjectLogger {\n return new ObjectLogger(config);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext } from './types.js';\nimport { createLogger, ObjectLogger } from './logger.js';\nimport type { LoggerConfig } from '@objectstack/spec/system';\nimport { ServiceRequirementDef } from '@objectstack/spec/system';\nimport { PluginLoader, PluginMetadata, ServiceLifecycle, ServiceFactory, PluginStartupResult } from './plugin-loader.js';\nimport { isNode, safeExit } from './utils/env.js';\nimport { CORE_FALLBACK_FACTORIES } from './fallbacks/index.js';\n\n/**\n * Enhanced Kernel Configuration\n */\nexport interface ObjectKernelConfig {\n logger?: Partial<LoggerConfig>;\n \n /** Default plugin startup timeout in milliseconds */\n defaultStartupTimeout?: number;\n \n /** Whether to enable graceful shutdown */\n gracefulShutdown?: boolean;\n \n /** Graceful shutdown timeout in milliseconds */\n shutdownTimeout?: number;\n \n /** Whether to rollback on startup failure */\n rollbackOnFailure?: boolean;\n \n /** Whether to skip strict system requirement validation (Critical for testing) */\n skipSystemValidation?: boolean;\n}\n\n/**\n * Enhanced ObjectKernel with Advanced Plugin Management\n * \n * Extends the basic ObjectKernel with:\n * - Async plugin loading with validation\n * - Version compatibility checking\n * - Plugin signature verification\n * - Configuration validation (Zod)\n * - Factory-based dependency injection\n * - Service lifecycle management (singleton/transient/scoped)\n * - Circular dependency detection\n * - Lazy loading services\n * - Graceful shutdown\n * - Plugin startup timeout control\n * - Startup failure rollback\n * - Plugin health checks\n */\nexport class ObjectKernel {\n private plugins: Map<string, PluginMetadata> = new Map();\n private services: Map<string, any> = new Map();\n private hooks: Map<string, Array<(...args: any[]) => void | Promise<void>>> = new Map();\n private state: 'idle' | 'initializing' | 'running' | 'stopping' | 'stopped' = 'idle';\n private logger: ObjectLogger;\n private context: PluginContext;\n private pluginLoader: PluginLoader;\n private config: ObjectKernelConfig;\n private startedPlugins: Set<string> = new Set();\n private pluginStartTimes: Map<string, number> = new Map();\n private shutdownHandlers: Array<() => Promise<void>> = [];\n\n constructor(config: ObjectKernelConfig = {}) {\n this.config = {\n defaultStartupTimeout: 30000, // 30 seconds\n gracefulShutdown: true,\n shutdownTimeout: 60000, // 60 seconds\n rollbackOnFailure: true,\n ...config,\n };\n\n this.logger = createLogger(config.logger);\n this.pluginLoader = new PluginLoader(this.logger);\n \n // Initialize context\n this.context = {\n registerService: (name, service) => {\n this.registerService(name, service);\n },\n registerServiceFactory: (name, factory, lifecycle, dependencies) => {\n this.registerServiceFactory(name, factory, lifecycle, dependencies);\n },\n getService: <T>(name: string) => {\n // 1. Try direct service map first (synchronous cache)\n const service = this.services.get(name);\n if (service) {\n return service as T;\n }\n\n // 2. Try to get from plugin loader cache (Sync access to factories)\n const loaderService = this.pluginLoader.getServiceInstance<T>(name);\n if (loaderService) {\n // Cache it locally for faster next access\n this.services.set(name, loaderService);\n return loaderService;\n }\n\n // 3. Try to get from plugin loader (support async factories)\n try {\n const service = this.pluginLoader.getService(name);\n if (service instanceof Promise) {\n // If we found it in the loader but not in the sync map, it's likely a factory-based service or still loading\n // We must silence any potential rejection from this promise since we are about to throw our own error\n // and abandon the promise. Without this, Node.js will crash with \"Unhandled Promise Rejection\".\n service.catch(() => {});\n throw new Error(`Service '${name}' is async - use await`);\n }\n return service as T;\n } catch (error: any) {\n if (error.message?.includes('is async')) {\n throw error;\n }\n \n // Re-throw critical factory errors instead of masking them as \"not found\"\n // If the error came from the factory execution (e.g. database connection failed), we must see it.\n // \"Service '${name}' not found\" comes from PluginLoader.getService fallback.\n const isNotFoundError = error.message === `Service '${name}' not found`;\n \n if (!isNotFoundError) {\n throw error;\n }\n\n throw new Error(`[Kernel] Service '${name}' not found`);\n }\n },\n replaceService: <T>(name: string, implementation: T): void => {\n const hasService = this.services.has(name) || this.pluginLoader.hasService(name);\n if (!hasService) {\n throw new Error(`[Kernel] Service '${name}' not found. Use registerService() to add new services.`);\n }\n this.services.set(name, implementation);\n this.pluginLoader.replaceService(name, implementation);\n this.logger.info(`Service '${name}' replaced`, { service: name });\n },\n hook: (name, handler) => {\n if (!this.hooks.has(name)) {\n this.hooks.set(name, []);\n }\n this.hooks.get(name)!.push(handler);\n },\n trigger: async (name, ...args) => {\n const handlers = this.hooks.get(name) || [];\n for (const handler of handlers) {\n await handler(...args);\n }\n },\n getServices: () => {\n return new Map(this.services);\n },\n getServiceScoped: <T>(name: string, scopeId: string): Promise<T> => {\n return this.pluginLoader.getService<T>(name, scopeId);\n },\n logger: this.logger,\n getKernel: () => this as any, // Type compatibility\n };\n\n this.pluginLoader.setContext(this.context);\n\n // Register shutdown handler\n if (this.config.gracefulShutdown) {\n this.registerShutdownSignals();\n }\n }\n\n /**\n * Register a plugin with enhanced validation\n */\n async use(plugin: Plugin): Promise<this> {\n if (this.state !== 'idle') {\n throw new Error('[Kernel] Cannot register plugins after bootstrap has started');\n }\n\n // Load plugin through enhanced loader\n const result = await this.pluginLoader.loadPlugin(plugin);\n \n if (!result.success || !result.plugin) {\n throw new Error(`Failed to load plugin: ${plugin.name} - ${result.error?.message}`);\n }\n\n const pluginMeta = result.plugin;\n this.plugins.set(pluginMeta.name, pluginMeta);\n \n this.logger.info(`Plugin registered: ${pluginMeta.name}@${pluginMeta.version}`, {\n plugin: pluginMeta.name,\n version: pluginMeta.version,\n });\n\n return this;\n }\n\n /**\n * Register a service instance directly\n */\n registerService<T>(name: string, service: T): this {\n if (this.services.has(name)) {\n throw new Error(`[Kernel] Service '${name}' already registered`);\n }\n this.services.set(name, service);\n this.pluginLoader.registerService(name, service);\n this.logger.info(`Service '${name}' registered`, { service: name });\n return this;\n }\n\n /**\n * Register a service factory with lifecycle management\n */\n registerServiceFactory<T>(\n name: string,\n factory: ServiceFactory<T>,\n lifecycle: ServiceLifecycle = ServiceLifecycle.SINGLETON,\n dependencies?: string[]\n ): this {\n this.pluginLoader.registerServiceFactory({\n name,\n factory,\n lifecycle,\n dependencies,\n });\n return this;\n }\n\n /**\n * Pre-inject in-memory fallbacks for 'core' services that were not registered\n * by plugins during Phase 1. Called before Phase 2 so that all core services\n * (e.g. 'metadata', 'cache', 'queue') are resolvable via ctx.getService()\n * when plugin start() methods execute.\n */\n private preInjectCoreFallbacks() {\n if (this.config.skipSystemValidation) return;\n for (const [serviceName, criticality] of Object.entries(ServiceRequirementDef)) {\n if (criticality !== 'core') continue;\n const hasService = this.services.has(serviceName) || this.pluginLoader.hasService(serviceName);\n if (!hasService) {\n const factory = CORE_FALLBACK_FACTORIES[serviceName];\n if (factory) {\n const fallback = factory();\n this.registerService(serviceName, fallback);\n this.logger.debug(`[Kernel] Pre-injected in-memory fallback for '${serviceName}' before Phase 2`);\n }\n }\n }\n }\n\n /**\n * Validate Critical System Requirements\n */\n private validateSystemRequirements() {\n if (this.config.skipSystemValidation) {\n this.logger.debug('System requirement validation skipped');\n return;\n }\n\n this.logger.debug('Validating system service requirements...');\n const missingServices: string[] = [];\n const missingCoreServices: string[] = [];\n \n // Iterate through all defined requirements\n for (const [serviceName, criticality] of Object.entries(ServiceRequirementDef)) {\n const hasService = this.services.has(serviceName) || this.pluginLoader.hasService(serviceName);\n \n if (!hasService) {\n if (criticality === 'required') {\n this.logger.error(`CRITICAL: Required service missing: ${serviceName}`);\n missingServices.push(serviceName);\n } else if (criticality === 'core') {\n // Auto-inject in-memory fallback if available\n const factory = CORE_FALLBACK_FACTORIES[serviceName];\n if (factory) {\n const fallback = factory();\n this.registerService(serviceName, fallback);\n this.logger.warn(`Service '${serviceName}' not provided — using in-memory fallback`);\n } else {\n this.logger.warn(`CORE: Core service missing, functionality may be degraded: ${serviceName}`);\n missingCoreServices.push(serviceName);\n }\n } else {\n this.logger.info(`Info: Optional service not present: ${serviceName}`);\n }\n }\n }\n\n if (missingServices.length > 0) {\n const errorMsg = `System failed to start. Missing critical services: ${missingServices.join(', ')}`;\n this.logger.error(errorMsg);\n throw new Error(errorMsg);\n }\n\n if (missingCoreServices.length > 0) {\n this.logger.warn(`System started with degraded capabilities. Missing core services: ${missingCoreServices.join(', ')}`);\n }\n \n this.logger.info('System requirement check passed');\n }\n\n /**\n * Bootstrap the kernel with enhanced features\n */\n async bootstrap(): Promise<void> {\n if (this.state !== 'idle') {\n throw new Error('[Kernel] Kernel already bootstrapped');\n }\n\n this.state = 'initializing';\n this.logger.info('Bootstrap started');\n\n try {\n // Check for circular dependencies\n const cycles = this.pluginLoader.detectCircularDependencies();\n if (cycles.length > 0) {\n this.logger.warn('Circular service dependencies detected:', { cycles });\n }\n\n // Resolve plugin dependencies\n const orderedPlugins = this.resolveDependencies();\n\n // Phase 1: Init - Plugins register services\n this.logger.info('Phase 1: Init plugins');\n for (const plugin of orderedPlugins) {\n await this.initPluginWithTimeout(plugin);\n }\n\n // Pre-inject in-memory fallbacks for 'core' services that were not\n // registered by any plugin during Phase 1. This ensures services like\n // 'metadata', 'cache', 'queue', etc. are always available when plugins\n // call ctx.getService() during their start() methods.\n this.preInjectCoreFallbacks();\n\n // Phase 2: Start - Plugins execute business logic\n this.logger.info('Phase 2: Start plugins');\n this.state = 'running';\n \n for (const plugin of orderedPlugins) {\n const result = await this.startPluginWithTimeout(plugin);\n \n if (!result.success) {\n this.logger.error(`Plugin startup failed: ${plugin.name}`, result.error);\n const origMsg = result.error instanceof Error ? result.error.message : String(result.error);\n const origStack = result.error instanceof Error ? result.error.stack : '';\n console.error(`[Kernel] Plugin startup failed: ${plugin.name}`, origMsg, origStack);\n\n if (this.config.rollbackOnFailure) {\n this.logger.warn('Rolling back started plugins...');\n await this.rollbackStartedPlugins();\n // Propagate the original cause through the thrown error\n // so callers (e.g. cloud auth-proxy) can surface the\n // real failure instead of an opaque \"rollback complete\"\n // string. Without this, every kernel-boot failure looks\n // identical from the outside.\n const err: any = new Error(\n `Plugin ${plugin.name} failed to start - rollback complete: ${origMsg}`,\n );\n if (result.error instanceof Error) {\n err.cause = result.error;\n err.originalStack = origStack;\n }\n throw err;\n }\n }\n }\n\n // Phase 3: Trigger kernel:ready hook\n this.validateSystemRequirements(); // Final check before ready\n this.logger.debug('Triggering kernel:ready hook');\n await this.context.trigger('kernel:ready');\n\n // Phase 3.5: Trigger kernel:bootstrapped AFTER every kernel:ready\n // handler has settled — the \"all synchronous bootstrap has settled\"\n // anchor. Reconcile/backfill work that consumes data produced by a\n // later-starting plugin's kernel:ready handler belongs here, not in\n // kernel:ready (where handler order would race the data). NOTE: this\n // does NOT guarantee background app seed data has settled (an inline\n // seed that overruns OS_INLINE_SEED_BUDGET_MS finishes later) —\n // subscribe `app:seeded` for that. See\n // packages/spec/src/contracts/plugin-lifecycle-events.ts.\n this.logger.debug('Triggering kernel:bootstrapped hook');\n await this.context.trigger('kernel:bootstrapped');\n\n // Phase 4: Trigger kernel:listening hook AFTER all kernel:ready\n // handlers have completed. This is the cue for HTTP server\n // plugins to actually open the listening socket — by now every\n // other plugin has finished registering routes/middleware.\n // See `kernel:listening` docs in\n // packages/spec/src/contracts/plugin-lifecycle-events.ts\n // for the race-condition rationale.\n this.logger.debug('Triggering kernel:listening hook');\n await this.context.trigger('kernel:listening');\n\n this.logger.info('✅ Bootstrap complete');\n } catch (error) {\n this.state = 'stopped';\n throw error;\n }\n }\n\n /**\n * Graceful shutdown with timeout\n */\n async shutdown(): Promise<void> {\n if (this.state === 'stopped' || this.state === 'stopping') {\n this.logger.warn('Kernel already stopped or stopping');\n return;\n }\n\n if (this.state !== 'running') {\n throw new Error('[Kernel] Kernel not running');\n }\n\n this.state = 'stopping';\n this.logger.info('Graceful shutdown started');\n\n try {\n const shutdownPromise = this.performShutdown();\n const timeoutPromise = new Promise<void>((_, reject) => {\n const t = setTimeout(() => {\n reject(new Error('Shutdown timeout exceeded'));\n }, this.config.shutdownTimeout);\n // Don't let this timer keep the event loop alive\n if (t.unref) t.unref();\n });\n\n await Promise.race([shutdownPromise, timeoutPromise]);\n\n this.state = 'stopped';\n this.logger.info('✅ Graceful shutdown complete');\n } catch (error) {\n this.logger.error('Shutdown timed out — forcing exit', error as Error);\n this.state = 'stopped';\n // Flush logger then hard-exit; the process would otherwise hang\n await this.logger.destroy();\n process.exit(1);\n } finally {\n await this.logger.destroy();\n }\n }\n\n /**\n * Check health of a specific plugin\n */\n async checkPluginHealth(pluginName: string): Promise<any> {\n return await this.pluginLoader.checkPluginHealth(pluginName);\n }\n\n /**\n * Check health of all plugins\n */\n async checkAllPluginsHealth(): Promise<Map<string, any>> {\n const results = new Map();\n \n for (const pluginName of this.plugins.keys()) {\n const health = await this.checkPluginHealth(pluginName);\n results.set(pluginName, health);\n }\n \n return results;\n }\n\n /**\n * Get plugin startup metrics\n */\n getPluginMetrics(): Map<string, number> {\n return new Map(this.pluginStartTimes);\n }\n\n /**\n * Whether a plugin with the given name has been registered on this kernel.\n *\n * Registration happens synchronously in `use()` before any plugin's\n * `start()` runs, so a plugin may use this during its own start() to make\n * composition-dependent decisions deterministically — e.g. the dispatcher\n * bridge cedes `${prefix}/discovery` to `com.objectstack.rest.api` when\n * both are mounted (ADR-0076 D11: single owner per route, not\n * first-registration-wins).\n */\n hasPlugin(name: string): boolean {\n return this.plugins.has(name);\n }\n\n /**\n * Get a service (sync helper)\n */\n getService<T>(name: string): T {\n return this.context.getService<T>(name);\n }\n\n /**\n * Get a service asynchronously (supports factories)\n */\n async getServiceAsync<T>(name: string, scopeId?: string): Promise<T> {\n return await this.pluginLoader.getService<T>(name, scopeId);\n }\n\n /**\n * Clear all scoped service instances for a given scope (e.g., environmentId).\n * Releases driver connections and metadata caches for idle projects.\n */\n clearScope(scopeId: string): void {\n this.pluginLoader.clearScope(scopeId);\n }\n\n /**\n * Check if kernel is running\n */\n isRunning(): boolean {\n return this.state === 'running';\n }\n\n /**\n * Get kernel state\n */\n getState(): string {\n return this.state;\n }\n\n // Private methods\n\n private async initPluginWithTimeout(plugin: PluginMetadata): Promise<void> {\n const timeout = plugin.startupTimeout || this.config.defaultStartupTimeout!;\n \n this.logger.debug(`Init: ${plugin.name}`, { plugin: plugin.name });\n \n const initPromise = plugin.init(this.context);\n const timeoutPromise = new Promise<void>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Plugin ${plugin.name} init timeout after ${timeout}ms`));\n }, timeout);\n });\n\n await Promise.race([initPromise, timeoutPromise]);\n }\n\n private async startPluginWithTimeout(plugin: PluginMetadata): Promise<PluginStartupResult> {\n if (!plugin.start) {\n return { success: true, pluginName: plugin.name };\n }\n\n const timeout = plugin.startupTimeout || this.config.defaultStartupTimeout!;\n const startTime = Date.now();\n \n this.logger.debug(`Start: ${plugin.name}`, { plugin: plugin.name });\n \n try {\n const startPromise = plugin.start(this.context);\n const timeoutPromise = new Promise<void>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Plugin ${plugin.name} start timeout after ${timeout}ms`));\n }, timeout);\n });\n\n await Promise.race([startPromise, timeoutPromise]);\n \n const duration = Date.now() - startTime;\n this.startedPlugins.add(plugin.name);\n this.pluginStartTimes.set(plugin.name, duration);\n \n this.logger.debug(`Plugin started: ${plugin.name} (${duration}ms)`);\n \n return {\n success: true,\n pluginName: plugin.name,\n startTime: duration,\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n const isTimeout = (error as Error).message.includes('timeout');\n \n return {\n success: false,\n pluginName: plugin.name,\n error: error as Error,\n startTime: duration,\n timedOut: isTimeout,\n };\n }\n }\n\n private async rollbackStartedPlugins(): Promise<void> {\n const pluginsToRollback = Array.from(this.startedPlugins).reverse();\n \n for (const pluginName of pluginsToRollback) {\n const plugin = this.plugins.get(pluginName);\n if (plugin?.destroy) {\n try {\n this.logger.debug(`Rollback: ${pluginName}`);\n await plugin.destroy();\n } catch (error) {\n this.logger.error(`Rollback failed for ${pluginName}`, error as Error);\n }\n }\n }\n \n this.startedPlugins.clear();\n }\n\n private async performShutdown(): Promise<void> {\n // Trigger shutdown hook\n await this.context.trigger('kernel:shutdown');\n\n // Destroy plugins in reverse order\n const orderedPlugins = Array.from(this.plugins.values()).reverse();\n for (const plugin of orderedPlugins) {\n if (plugin.destroy) {\n this.logger.debug(`Destroy: ${plugin.name}`, { plugin: plugin.name });\n try {\n await plugin.destroy();\n } catch (error) {\n this.logger.error(`Error destroying plugin ${plugin.name}`, error as Error);\n }\n }\n }\n\n // Execute custom shutdown handlers\n for (const handler of this.shutdownHandlers) {\n try {\n await handler();\n } catch (error) {\n this.logger.error('Shutdown handler error', error as Error);\n }\n }\n }\n\n private resolveDependencies(): PluginMetadata[] {\n const resolved: PluginMetadata[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (pluginName: string) => {\n if (visited.has(pluginName)) return;\n \n if (visiting.has(pluginName)) {\n throw new Error(`[Kernel] Circular dependency detected: ${pluginName}`);\n }\n\n const plugin = this.plugins.get(pluginName);\n if (!plugin) {\n throw new Error(`[Kernel] Plugin '${pluginName}' not found`);\n }\n\n visiting.add(pluginName);\n\n // Visit dependencies first\n const deps = plugin.dependencies || [];\n for (const dep of deps) {\n if (!this.plugins.has(dep)) {\n throw new Error(`[Kernel] Dependency '${dep}' not found for plugin '${pluginName}'`);\n }\n visit(dep);\n }\n\n visiting.delete(pluginName);\n visited.add(pluginName);\n resolved.push(plugin);\n };\n\n // Visit all plugins\n for (const pluginName of this.plugins.keys()) {\n visit(pluginName);\n }\n\n return resolved;\n }\n\n private registerShutdownSignals(): void {\n const signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGQUIT'];\n let shutdownInProgress = false;\n \n const handleShutdown = async (signal: string) => {\n if (shutdownInProgress) {\n this.logger.warn(`Shutdown already in progress, ignoring ${signal}`);\n return;\n }\n \n shutdownInProgress = true;\n this.logger.info(`Received ${signal} - initiating graceful shutdown`);\n \n try {\n await this.shutdown();\n safeExit(0);\n } catch (error) {\n this.logger.error('Shutdown failed', error as Error);\n safeExit(1);\n }\n };\n \n if (isNode) {\n for (const signal of signals) {\n process.on(signal, () => handleShutdown(signal));\n }\n }\n }\n\n /**\n * Register a custom shutdown handler\n */\n onShutdown(handler: () => Promise<void>): void {\n this.shutdownHandlers.push(handler);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { z } from 'zod';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { PluginMetadata } from '../plugin-loader.js';\n\n/**\n * Plugin Configuration Validator\n * \n * Validates plugin configurations against Zod schemas to ensure:\n * 1. Type safety - all config values have correct types\n * 2. Business rules - values meet constraints (min/max, regex, etc.)\n * 3. Required fields - all mandatory configuration is provided\n * 4. Default values - missing optional fields get defaults\n * \n * Architecture:\n * - Uses Zod for runtime validation\n * - Provides detailed error messages with field paths\n * - Supports nested configuration objects\n * - Allows partial validation for incremental updates\n * \n * Usage:\n * ```typescript\n * const validator = new PluginConfigValidator(logger);\n * const validConfig = validator.validatePluginConfig(plugin, userConfig);\n * ```\n */\nexport class PluginConfigValidator {\n private logger: Logger;\n \n constructor(logger: Logger) {\n this.logger = logger;\n }\n \n /**\n * Validate plugin configuration against its Zod schema\n * \n * @param plugin - Plugin metadata with configSchema\n * @param config - User-provided configuration\n * @returns Validated and typed configuration\n * @throws Error with detailed validation errors\n */\n validatePluginConfig<T = any>(plugin: PluginMetadata, config: any): T {\n if (!plugin.configSchema) {\n this.logger.debug(`Plugin ${plugin.name} has no config schema - skipping validation`);\n return config as T;\n }\n \n try {\n // Use Zod to parse and validate\n const validatedConfig = plugin.configSchema.parse(config);\n \n this.logger.debug(`✅ Plugin config validated: ${plugin.name}`, {\n plugin: plugin.name,\n configKeys: Object.keys(config || {}).length,\n });\n \n return validatedConfig as T;\n } catch (error) {\n if (error instanceof z.ZodError) {\n const formattedErrors = this.formatZodErrors(error);\n const errorMessage = [\n `Plugin ${plugin.name} configuration validation failed:`,\n ...formattedErrors.map(e => ` - ${e.path}: ${e.message}`),\n ].join('\\n');\n \n this.logger.error(errorMessage, undefined, {\n plugin: plugin.name,\n errors: formattedErrors,\n });\n \n throw new Error(errorMessage);\n }\n \n // Re-throw other errors\n throw error;\n }\n }\n \n /**\n * Validate partial configuration (for incremental updates)\n * \n * @param plugin - Plugin metadata\n * @param partialConfig - Partial configuration to validate\n * @returns Validated partial configuration\n */\n validatePartialConfig<T = any>(plugin: PluginMetadata, partialConfig: any): Partial<T> {\n if (!plugin.configSchema) {\n return partialConfig as Partial<T>;\n }\n \n try {\n // Use Zod's partial() method for partial validation\n // Cast to ZodObject to access partial() method\n const partialSchema = (plugin.configSchema as any).partial();\n const validatedConfig = partialSchema.parse(partialConfig);\n \n this.logger.debug(`✅ Partial config validated: ${plugin.name}`);\n return validatedConfig as Partial<T>;\n } catch (error) {\n if (error instanceof z.ZodError) {\n const formattedErrors = this.formatZodErrors(error);\n const errorMessage = [\n `Plugin ${plugin.name} partial configuration validation failed:`,\n ...formattedErrors.map(e => ` - ${e.path}: ${e.message}`),\n ].join('\\n');\n \n throw new Error(errorMessage);\n }\n \n throw error;\n }\n }\n \n /**\n * Get default configuration from schema\n * \n * @param plugin - Plugin metadata\n * @returns Default configuration object\n */\n getDefaultConfig<T = any>(plugin: PluginMetadata): T | undefined {\n if (!plugin.configSchema) {\n return undefined;\n }\n \n try {\n // Parse empty object to get defaults\n const defaults = plugin.configSchema.parse({});\n this.logger.debug(`Default config extracted: ${plugin.name}`);\n return defaults as T;\n } catch (error) {\n // Schema may require some fields - return undefined\n this.logger.debug(`No default config available: ${plugin.name}`);\n return undefined;\n }\n }\n \n /**\n * Check if configuration is valid without throwing\n * \n * @param plugin - Plugin metadata\n * @param config - Configuration to check\n * @returns True if valid, false otherwise\n */\n isConfigValid(plugin: PluginMetadata, config: any): boolean {\n if (!plugin.configSchema) {\n return true;\n }\n \n const result = plugin.configSchema.safeParse(config);\n return result.success;\n }\n \n /**\n * Get configuration errors without throwing\n * \n * @param plugin - Plugin metadata\n * @param config - Configuration to check\n * @returns Array of validation errors, or empty array if valid\n */\n getConfigErrors(plugin: PluginMetadata, config: any): Array<{path: string; message: string}> {\n if (!plugin.configSchema) {\n return [];\n }\n \n const result = plugin.configSchema.safeParse(config);\n \n if (result.success) {\n return [];\n }\n \n return this.formatZodErrors(result.error);\n }\n \n // Private methods\n \n private formatZodErrors(error: z.ZodError<any>): Array<{path: string; message: string}> {\n return error.issues.map((e: z.ZodIssue) => ({\n path: e.path.join('.') || 'root',\n message: e.message,\n }));\n }\n}\n\n/**\n * Create a plugin config validator\n * \n * @param logger - Logger instance\n * @returns Plugin config validator\n */\nexport function createPluginConfigValidator(logger: Logger): PluginConfigValidator {\n return new PluginConfigValidator(logger);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Plugin artifact signing & verification (ADR-0025 §3.4–§3.7, framework F3).\n *\n * This is the CANONICAL Ed25519 detached-signature contract shared by the\n * whole plugin distribution pipeline. It is intentionally byte-for-byte\n * compatible with the cloud control plane's `package-signing.ts` so the\n * two never drift:\n *\n * - signature string format: `ed25519:<keyId>:<base64url(signature)>`\n * - publisher signature: Ed25519 over the raw `.osplugin` artifact bytes,\n * produced by `os plugin sign`, verified by cloud at publish time and by\n * the runtime when it materializes the artifact.\n * - platform counter-signature: Ed25519 over {@link counterSignPayload}\n * (the version identity), produced by cloud at approval, verified by the\n * runtime at load time as the marketplace's \"reviewed + approved\" attest.\n *\n * Algorithm: Ed25519 via node:crypto (`sign(null, …)` / `verify(null, …)`):\n * short, deterministic, no padding ambiguity. The `keyId` is an opaque\n * rotation handle used to resolve the verifying public key.\n *\n * The two trust chains the runtime checks before loading a third-party\n * plugin are combined in {@link verifyPluginArtifact}.\n */\n\nimport {\n sign as cryptoSign,\n verify as cryptoVerify,\n createPublicKey,\n createPrivateKey,\n generateKeyPairSync,\n type KeyObject,\n} from 'node:crypto';\n\nexport const SIGNATURE_ALG = 'ed25519';\nconst SIG_PREFIX = 'ed25519:';\n\nexport type KeyInput = string | KeyObject;\n\nfunction toPrivateKey(key: KeyInput): KeyObject {\n return typeof key === 'string' ? createPrivateKey(key) : key;\n}\nfunction toPublicKey(key: KeyInput): KeyObject {\n return typeof key === 'string' ? createPublicKey(key) : key;\n}\nfunction toBytes(payload: string | Uint8Array): Uint8Array {\n return typeof payload === 'string' ? new TextEncoder().encode(payload) : payload;\n}\n\n/** Generate an Ed25519 keypair as PEM strings (publisher bootstrap / tests). */\nexport function generateEd25519KeyPair(): { publicKeyPem: string; privateKeyPem: string } {\n const { publicKey, privateKey } = generateKeyPairSync('ed25519');\n return {\n publicKeyPem: publicKey.export({ type: 'spki', format: 'pem' }).toString(),\n privateKeyPem: privateKey.export({ type: 'pkcs8', format: 'pem' }).toString(),\n };\n}\n\n/**\n * Sign `payload` with an Ed25519 private key, returning the formatted\n * signature string `ed25519:<keyId>:<base64url(sig)>`.\n */\nexport function signPayload(\n payload: string | Uint8Array,\n privateKey: KeyInput,\n keyId = 'default',\n): string {\n if (keyId.includes(':')) throw new Error('keyId must not contain \":\"');\n const sig = cryptoSign(null, toBytes(payload), toPrivateKey(privateKey));\n return `${SIG_PREFIX}${keyId}:${sig.toString('base64url')}`;\n}\n\nexport interface ParsedSignature {\n alg: 'ed25519';\n keyId: string;\n signature: Uint8Array;\n}\n\n/** Parse an `ed25519:<keyId>:<base64url>` signature string. Returns null if malformed. */\nexport function parseSignature(s: string | undefined | null): ParsedSignature | null {\n if (typeof s !== 'string' || !s.startsWith(SIG_PREFIX)) return null;\n const rest = s.slice(SIG_PREFIX.length);\n const idx = rest.indexOf(':');\n if (idx <= 0) return null;\n const keyId = rest.slice(0, idx);\n const b64 = rest.slice(idx + 1);\n if (!keyId || !b64) return null;\n try {\n return { alg: 'ed25519', keyId, signature: new Uint8Array(Buffer.from(b64, 'base64url')) };\n } catch {\n return null;\n }\n}\n\n/** Verify a formatted signature string over `payload` with the given public key. */\nexport function verifyPayload(\n payload: string | Uint8Array,\n signature: string,\n publicKey: KeyInput,\n): boolean {\n const parsed = parseSignature(signature);\n if (!parsed) return false;\n try {\n return cryptoVerify(null, toBytes(payload), toPublicKey(publicKey), parsed.signature);\n } catch {\n return false;\n }\n}\n\n/**\n * Canonical payload the platform counter-signs at approval. Binds the\n * attestation to the version identity + artifact location + the publisher\n * signature (which itself binds the artifact bytes). MUST match the cloud\n * control plane's `counterSignPayload` exactly.\n */\nexport function counterSignPayload(version: {\n package_id: string;\n version: string;\n blob_key?: string | null;\n signature?: string | null;\n}): string {\n return [\n version.package_id,\n version.version,\n version.blob_key ?? '',\n version.signature ?? '',\n ].join('\\n');\n}\n\nexport interface PublisherVerifyResult {\n /** Whether loading may proceed on signature grounds. */\n ok: boolean;\n /** True when a signature was present AND cryptographically verified. */\n verified: boolean;\n reason?: string;\n}\n\n/**\n * Verify a publisher signature over the raw artifact bytes. `getPublicKey`\n * resolves the verifying key from the signature's embedded keyId.\n *\n * Mirrors cloud's publish-time policy:\n * - no signature → ok, verified=false (caller decides via trust tier).\n * - malformed / fails verification → NOT ok.\n * - unknown keyId → NOT ok (never silently trust).\n */\nexport async function verifyPublisherSignature(\n args: { artifact: Uint8Array; signature?: string | null },\n getPublicKey?: (keyId: string) => Promise<KeyInput | null> | KeyInput | null,\n): Promise<PublisherVerifyResult> {\n const sig = args.signature;\n if (!sig) return { ok: true, verified: false, reason: 'no signature supplied' };\n\n const parsed = parseSignature(sig);\n if (!parsed) return { ok: false, verified: false, reason: 'signature is malformed' };\n\n if (!getPublicKey) {\n return { ok: true, verified: false, reason: 'no publisher key registry configured' };\n }\n\n const pub = await getPublicKey(parsed.keyId);\n if (!pub) return { ok: false, verified: false, reason: `unknown publisher key '${parsed.keyId}'` };\n\n return verifyPayload(args.artifact, sig, pub)\n ? { ok: true, verified: true }\n : { ok: false, verified: false, reason: 'publisher signature does not match artifact' };\n}\n\n/** Verify a platform counter-signature against the version identity + platform public key. */\nexport function verifyPlatformSignature(\n version: {\n package_id: string;\n version: string;\n blob_key?: string | null;\n signature?: string | null;\n platform_signature?: string | null;\n },\n platformPublicKey: KeyInput,\n): boolean {\n if (!version.platform_signature) return false;\n return verifyPayload(counterSignPayload(version), version.platform_signature, platformPublicKey);\n}\n\nexport interface PluginArtifactVerifyResult {\n /** Overall verdict: both required chains satisfied under the given policy. */\n ok: boolean;\n publisherVerified: boolean;\n platformVerified: boolean;\n reason?: string;\n}\n\n/**\n * Verify both trust chains for a downloaded plugin artifact at load time\n * (ADR-0025 §3.7). The platform counter-signature is the authoritative\n * marketplace attestation; the publisher signature additionally binds the\n * exact bytes. `requirePlatform` (default true) rejects artifacts that lack\n * a valid platform counter-sign — set false for first-party / local builds.\n */\nexport async function verifyPluginArtifact(\n input: {\n artifact: Uint8Array;\n version: {\n package_id: string;\n version: string;\n blob_key?: string | null;\n signature?: string | null;\n platform_signature?: string | null;\n };\n },\n keys: {\n platformPublicKey?: KeyInput;\n getPublisherPublicKey?: (keyId: string) => Promise<KeyInput | null> | KeyInput | null;\n requirePlatform?: boolean;\n },\n): Promise<PluginArtifactVerifyResult> {\n const requirePlatform = keys.requirePlatform ?? true;\n\n const publisher = await verifyPublisherSignature(\n { artifact: input.artifact, signature: input.version.signature },\n keys.getPublisherPublicKey,\n );\n if (!publisher.ok) {\n return { ok: false, publisherVerified: false, platformVerified: false, reason: publisher.reason };\n }\n\n let platformVerified = false;\n if (keys.platformPublicKey) {\n platformVerified = verifyPlatformSignature(input.version, keys.platformPublicKey);\n }\n if (requirePlatform && !platformVerified) {\n return {\n ok: false,\n publisherVerified: publisher.verified,\n platformVerified,\n reason: keys.platformPublicKey\n ? 'platform counter-signature missing or invalid'\n : 'no platform public key configured',\n };\n }\n\n return { ok: true, publisherVerified: publisher.verified, platformVerified };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext } from './types.js';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport { z } from 'zod';\nimport { PluginConfigValidator } from './security/plugin-config-validator.js';\nimport { parseSignature } from './security/plugin-artifact-signature.js';\n\n/**\n * Service Lifecycle Types\n * Defines how services are instantiated and managed\n */\nexport enum ServiceLifecycle {\n /** Single instance shared across all requests */\n SINGLETON = 'singleton',\n /** New instance created for each request */\n TRANSIENT = 'transient',\n /** New instance per scope (e.g., per HTTP request) */\n SCOPED = 'scoped',\n}\n\n/**\n * Service Factory\n * Function that creates a service instance\n */\nexport type ServiceFactory<T = any> = (ctx: PluginContext, scopeId?: string) => T | Promise<T>;\n\n/**\n * Service Registration Options\n */\nexport interface ServiceRegistration {\n name: string;\n factory: ServiceFactory;\n lifecycle: ServiceLifecycle;\n dependencies?: string[];\n}\n\n/**\n * Plugin Metadata with Enhanced Features\n */\nexport interface PluginMetadata extends Plugin {\n /** Semantic version (e.g., \"1.0.0\") */\n version: string;\n \n /** Configuration schema for validation */\n configSchema?: z.ZodSchema;\n \n /** Plugin signature for security verification */\n signature?: string;\n \n /** Plugin health check function */\n healthCheck?(): Promise<PluginHealthStatus>;\n \n /** Startup timeout in milliseconds (default: 30000) */\n startupTimeout?: number;\n \n /** Whether plugin supports hot reload */\n hotReloadable?: boolean;\n}\n\n/**\n * Plugin Health Status\n */\nexport interface PluginHealthStatus {\n healthy: boolean;\n message?: string;\n details?: Record<string, any>;\n lastCheck?: Date;\n}\n\n/**\n * Plugin Load Result\n */\nexport interface PluginLoadResult {\n success: boolean;\n plugin?: PluginMetadata;\n error?: Error;\n loadTime?: number;\n}\n\n/**\n * Plugin Startup Result\n */\nexport interface PluginStartupResult {\n success: boolean;\n pluginName: string;\n startTime?: number;\n error?: Error;\n timedOut?: boolean;\n}\n\n/**\n * Version Compatibility Result\n */\nexport interface VersionCompatibility {\n compatible: boolean;\n pluginVersion: string;\n requiredVersion?: string;\n message?: string;\n}\n\n/**\n * Enhanced Plugin Loader\n * Provides advanced plugin loading capabilities with validation, security, and lifecycle management\n */\nexport class PluginLoader {\n private logger: Logger;\n private context?: PluginContext;\n private configValidator: PluginConfigValidator;\n private loadedPlugins: Map<string, PluginMetadata> = new Map();\n private serviceFactories: Map<string, ServiceRegistration> = new Map();\n private serviceInstances: Map<string, any> = new Map();\n private scopedServices: Map<string, Map<string, any>> = new Map();\n private creating: Set<string> = new Set();\n\n constructor(logger: Logger) {\n this.logger = logger;\n this.configValidator = new PluginConfigValidator(logger);\n }\n\n /**\n * Set the plugin context for service factories\n */\n setContext(context: PluginContext): void {\n this.context = context;\n }\n\n /**\n * Get a synchronous service instance if it exists (Sync Helper)\n */\n getServiceInstance<T>(name: string): T | undefined {\n return this.serviceInstances.get(name) as T;\n }\n\n /**\n * Load a plugin asynchronously with validation\n */\n async loadPlugin(plugin: Plugin): Promise<PluginLoadResult> {\n const startTime = Date.now();\n \n try {\n this.logger.info(`Loading plugin: ${plugin.name}`);\n \n // Convert to PluginMetadata\n const metadata = this.toPluginMetadata(plugin);\n \n // Validate plugin structure\n this.validatePluginStructure(metadata);\n \n // Check version compatibility\n const versionCheck = this.checkVersionCompatibility(metadata);\n if (!versionCheck.compatible) {\n throw new Error(`Version incompatible: ${versionCheck.message}`);\n }\n \n // Validate configuration if schema is provided\n if (metadata.configSchema) {\n this.validatePluginConfig(metadata);\n }\n \n // Verify signature if provided\n if (metadata.signature) {\n await this.verifyPluginSignature(metadata);\n }\n \n // Store loaded plugin\n this.loadedPlugins.set(metadata.name, metadata);\n \n const loadTime = Date.now() - startTime;\n this.logger.info(`Plugin loaded: ${plugin.name} (${loadTime}ms)`);\n \n return {\n success: true,\n plugin: metadata,\n loadTime,\n };\n } catch (error) {\n this.logger.error(`Failed to load plugin: ${plugin.name}`, error as Error);\n return {\n success: false,\n error: error as Error,\n loadTime: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Register a service with factory function\n */\n registerServiceFactory(registration: ServiceRegistration): void {\n if (this.serviceFactories.has(registration.name)) {\n throw new Error(`Service factory '${registration.name}' already registered`);\n }\n \n this.serviceFactories.set(registration.name, registration);\n this.logger.debug(`Service factory registered: ${registration.name} (${registration.lifecycle})`);\n }\n\n /**\n * Get or create a service instance based on lifecycle type\n */\n async getService<T>(name: string, scopeId?: string): Promise<T> {\n const registration = this.serviceFactories.get(name);\n \n if (!registration) {\n // Fall back to static service instances\n const instance = this.serviceInstances.get(name);\n if (!instance) {\n throw new Error(`Service '${name}' not found`);\n }\n return instance as T;\n }\n \n switch (registration.lifecycle) {\n case ServiceLifecycle.SINGLETON:\n return await this.getSingletonService<T>(registration);\n \n case ServiceLifecycle.TRANSIENT:\n return await this.createTransientService<T>(registration);\n \n case ServiceLifecycle.SCOPED:\n if (!scopeId) {\n throw new Error(`Scope ID required for scoped service '${name}'`);\n }\n return await this.getScopedService<T>(registration, scopeId);\n \n default:\n throw new Error(`Unknown service lifecycle: ${registration.lifecycle}`);\n }\n }\n\n /**\n * Register a static service instance (legacy support)\n */\n registerService(name: string, service: any): void {\n if (this.serviceInstances.has(name)) {\n throw new Error(`Service '${name}' already registered`);\n }\n this.serviceInstances.set(name, service);\n }\n\n /**\n * Replace an existing service instance.\n * Used by optimization plugins to swap kernel internals.\n * @throws Error if service does not exist\n */\n replaceService(name: string, service: any): void {\n if (!this.hasService(name)) {\n throw new Error(`Service '${name}' not found`);\n }\n this.serviceInstances.set(name, service);\n }\n\n /**\n * Check if a service is registered (either as instance or factory)\n */\n hasService(name: string): boolean {\n return this.serviceInstances.has(name) || this.serviceFactories.has(name);\n }\n\n /**\n * Detect circular dependencies in service factories\n * Note: This only detects cycles in service dependencies, not plugin dependencies.\n * Plugin dependency cycles are detected in the kernel's resolveDependencies method.\n */\n detectCircularDependencies(): string[] {\n const cycles: string[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n \n const visit = (serviceName: string, path: string[] = []) => {\n if (visiting.has(serviceName)) {\n const cycle = [...path, serviceName].join(' -> ');\n cycles.push(cycle);\n return;\n }\n \n if (visited.has(serviceName)) {\n return;\n }\n \n visiting.add(serviceName);\n \n const registration = this.serviceFactories.get(serviceName);\n if (registration?.dependencies) {\n for (const dep of registration.dependencies) {\n visit(dep, [...path, serviceName]);\n }\n }\n \n visiting.delete(serviceName);\n visited.add(serviceName);\n };\n \n for (const serviceName of this.serviceFactories.keys()) {\n visit(serviceName);\n }\n \n return cycles;\n }\n\n /**\n * Check plugin health\n */\n async checkPluginHealth(pluginName: string): Promise<PluginHealthStatus> {\n const plugin = this.loadedPlugins.get(pluginName);\n \n if (!plugin) {\n return {\n healthy: false,\n message: 'Plugin not found',\n lastCheck: new Date(),\n };\n }\n \n if (!plugin.healthCheck) {\n return {\n healthy: true,\n message: 'No health check defined',\n lastCheck: new Date(),\n };\n }\n \n try {\n const status = await plugin.healthCheck();\n return {\n ...status,\n lastCheck: new Date(),\n };\n } catch (error) {\n return {\n healthy: false,\n message: `Health check failed: ${(error as Error).message}`,\n lastCheck: new Date(),\n };\n }\n }\n\n /**\n * Clear scoped services for a scope\n */\n clearScope(scopeId: string): void {\n this.scopedServices.delete(scopeId);\n this.logger.debug(`Cleared scope: ${scopeId}`);\n }\n\n /**\n * Get all loaded plugins\n */\n getLoadedPlugins(): Map<string, PluginMetadata> {\n return new Map(this.loadedPlugins);\n }\n\n // Private helper methods\n\n private toPluginMetadata(plugin: Plugin): PluginMetadata {\n // Fix: Do not use object spread {...plugin} as it destroys the prototype chain for Class-based plugins.\n // Instead, cast the original object and inject default values if missing.\n const metadata = plugin as PluginMetadata;\n \n if (!metadata.version) {\n metadata.version = '0.0.0';\n }\n \n return metadata;\n }\n\n private validatePluginStructure(plugin: PluginMetadata): void {\n if (!plugin.name) {\n throw new Error('Plugin name is required');\n }\n \n if (!plugin.init) {\n throw new Error('Plugin init function is required');\n }\n \n if (!this.isValidSemanticVersion(plugin.version)) {\n throw new Error(`Invalid semantic version: ${plugin.version}`);\n }\n }\n\n private checkVersionCompatibility(plugin: PluginMetadata): VersionCompatibility {\n // Basic semantic version compatibility check\n // In a real implementation, this would check against kernel version\n const version = plugin.version;\n \n if (!this.isValidSemanticVersion(version)) {\n return {\n compatible: false,\n pluginVersion: version,\n message: 'Invalid semantic version format',\n };\n }\n \n return {\n compatible: true,\n pluginVersion: version,\n };\n }\n\n private isValidSemanticVersion(version: string): boolean {\n const semverRegex = /^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$/;\n return semverRegex.test(version);\n }\n\n private validatePluginConfig(plugin: PluginMetadata, config?: any): void {\n if (!plugin.configSchema) {\n return;\n }\n\n if (config === undefined) {\n // In loadPlugin, we often don't have the config yet.\n // We skip validation here or valid against empty object if schema allows?\n // For now, let's keep the logging behavior but note it's delegating\n this.logger.debug(`Plugin ${plugin.name} has configuration schema (config validation postponed)`);\n return;\n }\n\n this.configValidator.validatePluginConfig(plugin, config);\n }\n\n private async verifyPluginSignature(plugin: PluginMetadata): Promise<void> {\n if (!plugin.signature) {\n return;\n }\n \n // Cryptographic verification of a third-party plugin's PUBLISHER and\n // PLATFORM signatures is performed against the `.osplugin` artifact\n // bytes + version identity at materialize/install time, by\n // `verifyPluginArtifact` (security/plugin-artifact-signature.ts —\n // ADR-0025 §3.7). By the time a plugin reaches loadPlugin() it is an\n // in-memory module with no artifact bytes, so we cannot re-run the\n // artifact chains here; we only validate that any signature carried\n // on the metadata is well-formed (`ed25519:<keyId>:<base64url>`) and\n // surface its keyId, failing fast on a malformed value.\n const parsed = parseSignature(plugin.signature);\n if (!parsed) {\n throw new Error(\n `Plugin ${plugin.name} carries a malformed signature (expected ed25519:<keyId>:<base64url>)`,\n );\n }\n this.logger.debug(\n `Plugin ${plugin.name} signature well-formed (alg=${parsed.alg}, keyId=${parsed.keyId}); ` +\n `artifact verification occurs at materialize time`,\n );\n }\n\n private async getSingletonService<T>(registration: ServiceRegistration): Promise<T> {\n let instance = this.serviceInstances.get(registration.name);\n \n if (!instance) {\n // Create instance (would need context)\n instance = await this.createServiceInstance(registration);\n this.serviceInstances.set(registration.name, instance);\n this.logger.debug(`Singleton service created: ${registration.name}`);\n }\n \n return instance as T;\n }\n\n private async createTransientService<T>(registration: ServiceRegistration): Promise<T> {\n const instance = await this.createServiceInstance(registration);\n this.logger.debug(`Transient service created: ${registration.name}`);\n return instance as T;\n }\n\n private async getScopedService<T>(registration: ServiceRegistration, scopeId: string): Promise<T> {\n if (!this.scopedServices.has(scopeId)) {\n this.scopedServices.set(scopeId, new Map());\n }\n\n const scope = this.scopedServices.get(scopeId)!;\n let instance = scope.get(registration.name);\n\n if (!instance) {\n instance = await this.createServiceInstance(registration, scopeId);\n scope.set(registration.name, instance);\n this.logger.debug(`Scoped service created: ${registration.name} (scope: ${scopeId})`);\n }\n\n return instance as T;\n }\n\n private async createServiceInstance(registration: ServiceRegistration, scopeId?: string): Promise<any> {\n if (!this.context) {\n throw new Error(`[PluginLoader] Context not set - cannot create service '${registration.name}'`);\n }\n\n if (this.creating.has(registration.name)) {\n throw new Error(`Circular dependency detected: ${Array.from(this.creating).join(' -> ')} -> ${registration.name}`);\n }\n\n this.creating.add(registration.name);\n try {\n return await registration.factory(this.context, scopeId);\n } finally {\n this.creating.delete(registration.name);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Environment utilities for universal (Node/Browser) compatibility.\n */\n\n// Check if running in a Node.js environment\nexport const isNode = typeof process !== 'undefined' && \n process.versions != null && \n process.versions.node != null;\n\n/**\n * Safely access environment variables\n */\nexport function getEnv(key: string, defaultValue?: string): string | undefined {\n // Node.js\n if (typeof process !== 'undefined' && process.env) {\n return process.env[key] || defaultValue;\n }\n \n // Browser (Vite/Webpack replacement usually handles process.env, \n // but if not, we check safe global access)\n try {\n // @ts-ignore\n if (typeof globalThis !== 'undefined' && globalThis.process?.env) {\n // @ts-ignore\n return globalThis.process.env[key] || defaultValue;\n }\n } catch (e) {\n // Ignore access errors\n }\n \n return defaultValue;\n}\n\n/**\n * Safely exit the process if in Node.js\n */\nexport function safeExit(code: number = 0): void {\n if (isNode) {\n process.exit(code);\n }\n}\n\n/**\n * Safely get memory usage\n */\nexport function getMemoryUsage(): { heapUsed: number; heapTotal: number } {\n if (isNode) {\n return process.memoryUsage();\n }\n return { heapUsed: 0, heapTotal: 0 };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory Map-backed cache fallback.\n *\n * Implements the ICacheService contract with basic get/set/delete/has/clear\n * and TTL expiry. Used by ObjectKernel as an automatic fallback when no\n * real cache plugin (e.g. Redis) is registered.\n */\nexport function createMemoryCache() {\n const store = new Map<string, { value: unknown; expires?: number }>();\n let hits = 0;\n let misses = 0;\n return {\n _fallback: true, _serviceName: 'cache',\n async get<T = unknown>(key: string): Promise<T | undefined> {\n const entry = store.get(key);\n if (!entry || (entry.expires && Date.now() > entry.expires)) {\n store.delete(key);\n misses++;\n return undefined;\n }\n hits++;\n return entry.value as T;\n },\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n store.set(key, { value, expires: ttl ? Date.now() + ttl * 1000 : undefined });\n },\n async delete(key: string): Promise<boolean> { return store.delete(key); },\n async has(key: string): Promise<boolean> { return store.has(key); },\n async clear(): Promise<void> { store.clear(); },\n async stats() { return { hits, misses, keyCount: store.size }; },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory publish/subscribe queue fallback.\n *\n * Implements the IQueueService contract with synchronous in-process delivery.\n * Used by ObjectKernel as an automatic fallback when no real queue plugin\n * (e.g. BullMQ / RabbitMQ) is registered.\n */\nexport function createMemoryQueue() {\n const handlers = new Map<string, Function[]>();\n let msgId = 0;\n return {\n _fallback: true, _serviceName: 'queue',\n async publish<T = unknown>(queue: string, data: T): Promise<string> {\n const id = `fallback-msg-${++msgId}`;\n const fns = handlers.get(queue) ?? [];\n for (const fn of fns) fn({ id, data, attempts: 1, timestamp: Date.now() });\n return id;\n },\n async subscribe(queue: string, handler: (msg: any) => Promise<void>): Promise<void> {\n handlers.set(queue, [...(handlers.get(queue) ?? []), handler]);\n },\n async unsubscribe(queue: string): Promise<void> { handlers.delete(queue); },\n async getQueueSize(): Promise<number> { return 0; },\n async purge(queue: string): Promise<void> { handlers.delete(queue); },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory job scheduler fallback.\n *\n * Implements the IJobService contract with basic schedule/cancel/trigger\n * operations. Used by ObjectKernel as an automatic fallback when no real\n * job plugin (e.g. Agenda / BullMQ) is registered.\n */\nexport function createMemoryJob() {\n const jobs = new Map<string, any>();\n return {\n _fallback: true, _serviceName: 'job',\n async schedule(name: string, schedule: any, handler: any): Promise<void> { jobs.set(name, { schedule, handler }); },\n async cancel(name: string): Promise<void> { jobs.delete(name); },\n async trigger(name: string, data?: unknown): Promise<void> {\n const job = jobs.get(name);\n if (job?.handler) await job.handler({ jobId: name, data });\n },\n async getExecutions(): Promise<any[]> { return []; },\n async listJobs(): Promise<string[]> { return [...jobs.keys()]; },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Recursively merge `source` into `target`. Nested plain objects are merged\n * rather than replaced, so multiple plugins can each contribute their own\n * slice of a locale's translations (e.g. `{objects: {account: ...}}` and\n * `{objects: {task: ...}}`) without clobbering one another.\n * Exported for the authored-translation sync (#2591).\n */\nexport function deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const tVal = target[key];\n const sVal = source[key];\n if (\n tVal && sVal\n && typeof tVal === 'object' && !Array.isArray(tVal)\n && typeof sVal === 'object' && !Array.isArray(sVal)\n ) {\n result[key] = deepMerge(\n tVal as Record<string, unknown>,\n sVal as Record<string, unknown>,\n );\n } else {\n result[key] = sVal;\n }\n }\n return result;\n}\n\n/**\n * Resolve a locale code against available locales with fallback.\n *\n * Fallback chain:\n * 1. Exact match (e.g. `zh-CN` → `zh-CN`)\n * 2. Case-insensitive match (e.g. `zh-cn` → `zh-CN`)\n * 3. Base language match (e.g. `zh-CN` → `zh`)\n * 4. Variant expansion (e.g. `zh` → `zh-CN`)\n *\n * Returns the matched locale code, or `undefined` when no match is found.\n */\nexport function resolveLocale(requestedLocale: string, availableLocales: string[]): string | undefined {\n if (availableLocales.length === 0) return undefined;\n\n // 1. Exact match\n if (availableLocales.includes(requestedLocale)) return requestedLocale;\n\n // 2. Case-insensitive match\n const lower = requestedLocale.toLowerCase();\n const caseMatch = availableLocales.find(l => l.toLowerCase() === lower);\n if (caseMatch) return caseMatch;\n\n // 3. Base language match (zh-CN → zh)\n const baseLang = requestedLocale.split('-')[0].toLowerCase();\n const baseMatch = availableLocales.find(l => l.toLowerCase() === baseLang);\n if (baseMatch) return baseMatch;\n\n // 4. Variant expansion (zh → zh-CN, zh-TW, etc. — first match wins)\n const variantMatch = availableLocales.find(l => l.split('-')[0].toLowerCase() === baseLang);\n if (variantMatch) return variantMatch;\n\n return undefined;\n}\n\n/**\n * In-memory i18n service fallback.\n *\n * Implements the II18nService contract with basic translate/load/getLocales\n * operations. Used by ObjectKernel as an automatic fallback when no real\n * i18n plugin (e.g. I18nServicePlugin) is registered.\n *\n * Supports runtime translation loading, locale management, and\n * locale code fallback (e.g. `zh` → `zh-CN`).\n * Does not load files from disk — operates purely in-memory.\n */\nexport function createMemoryI18n() {\n const translations = new Map<string, Record<string, unknown>>();\n // Runtime-AUTHORED overlay (#2591): translations published as `translation`\n // metadata. Kept separate from the static map so a re-sync can REPLACE the\n // whole authored layer (clear-then-reload — deleted keys must not linger),\n // while authored values win over static bundle values on read.\n const authored = new Map<string, Record<string, unknown>>();\n let defaultLocale = 'en';\n\n /**\n * Resolve a dot-notation key from a nested object.\n */\n function resolveKey(data: Record<string, unknown>, key: string): string | undefined {\n const parts = key.split('.');\n let current: unknown = data;\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return typeof current === 'string' ? current : undefined;\n }\n\n /** Merged (static ⊕ authored) view of a single, exact locale key. */\n function mergedLocale(locale: string): Record<string, unknown> | undefined {\n const stat = translations.get(locale);\n const auth = authored.get(locale);\n if (stat && auth) return deepMerge(stat, auth);\n return auth ?? stat;\n }\n\n /**\n * Find translation data for a locale, with fallback resolution.\n */\n function resolveTranslations(locale: string): Record<string, unknown> | undefined {\n // Exact match\n const exact = mergedLocale(locale);\n if (exact) return exact;\n\n // Locale fallback (zh → zh-CN, en-us → en-US, etc.)\n const allLocales = [...new Set([...translations.keys(), ...authored.keys()])];\n const resolved = resolveLocale(locale, allLocales);\n if (resolved) return mergedLocale(resolved);\n\n return undefined;\n }\n\n return {\n _fallback: true, _serviceName: 'i18n',\n\n t(key: string, locale: string, params?: Record<string, unknown>): string {\n const data = resolveTranslations(locale) ?? mergedLocale(defaultLocale);\n const value = data ? resolveKey(data, key) : undefined;\n if (value == null) return key;\n if (!params) return value;\n // Interpolation format: {{paramName}} — matches FileI18nAdapter convention\n return value.replace(/\\{\\{(\\w+)\\}\\}/g, (_, name) => String(params[name] ?? `{{${name}}}`));\n },\n\n getTranslations(locale: string): Record<string, unknown> {\n return resolveTranslations(locale) ?? {};\n },\n\n loadTranslations(locale: string, data: Record<string, unknown>): void {\n const existing = translations.get(locale);\n if (existing) {\n translations.set(locale, deepMerge(existing, data));\n } else {\n translations.set(locale, { ...data });\n }\n },\n\n /**\n * Replace the ENTIRE runtime-authored translation layer (#2591). Called\n * by the authored-translation sync with the full current set of active\n * `translation` metadata items keyed by locale. Wholesale replacement —\n * not a merge — so deleted items/keys stop resolving on the next sync.\n */\n replaceAuthoredTranslations(byLocale: Record<string, Record<string, unknown>>): void {\n authored.clear();\n for (const [locale, data] of Object.entries(byLocale ?? {})) {\n if (!data || typeof data !== 'object') continue;\n authored.set(locale, { ...data });\n }\n },\n\n getLocales(): string[] {\n return [...new Set([...translations.keys(), ...authored.keys()])];\n },\n\n getDefaultLocale(): string {\n return defaultLocale;\n },\n\n setDefaultLocale(locale: string): void {\n defaultLocale = locale;\n },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * In-memory metadata service fallback.\n *\n * Implements the IMetadataService contract with a simple Map-of-Maps store.\n * Used by ObjectKernel as an automatic fallback when no real metadata plugin\n * (e.g. MetadataPlugin with file-system persistence) is registered.\n */\nexport function createMemoryMetadata() {\n // type -> name -> data\n const store = new Map<string, Map<string, any>>();\n\n function getTypeMap(type: string): Map<string, any> {\n let map = store.get(type);\n if (!map) {\n map = new Map();\n store.set(type, map);\n }\n return map;\n }\n\n return {\n _fallback: true, _serviceName: 'metadata',\n async register(type: string, name: string, data: any): Promise<void> {\n getTypeMap(type).set(name, data);\n },\n // Mirror MetadataManager.registerInMemory (synchronous, no persistence).\n // AppPlugin gates code-defined-datasource / stack-RBAC registration on\n // `typeof metadata.registerInMemory === 'function'` (it must register\n // GitOps-managed artefacts *listably* but never persist them). Without this\n // method the guard was false on the host-config / standalone boot path —\n // where this fallback (not MetadataPlugin) provides the `metadata` service —\n // so `defineStack({ datasources })` entries silently never reached the\n // registry and were absent from GET /api/v1/datasources and\n // GET /api/v1/meta/datasource (ADR-0015 §18). This store is already\n // in-memory only, so registerInMemory and register share an implementation.\n registerInMemory(type: string, name: string, data: any): void {\n getTypeMap(type).set(name, data);\n },\n async get(type: string, name: string): Promise<any> {\n return getTypeMap(type).get(name);\n },\n async list(type: string): Promise<any[]> {\n return Array.from(getTypeMap(type).values());\n },\n async unregister(type: string, name: string): Promise<void> {\n getTypeMap(type).delete(name);\n },\n async exists(type: string, name: string): Promise<boolean> {\n return getTypeMap(type).has(name);\n },\n async listNames(type: string): Promise<string[]> {\n return Array.from(getTypeMap(type).keys());\n },\n async getObject(name: string): Promise<any> {\n return getTypeMap('object').get(name);\n },\n async listObjects(): Promise<any[]> {\n return Array.from(getTypeMap('object').values());\n },\n };\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Runtime-authored translation sync (#2591).\n *\n * Translations authored in the Studio persist as `translation` sys_metadata\n * rows (`allowRuntimeCreate: true`), but historically only STATIC bundles\n * (app `bundle.translations`, plugin `translations/`) were ever loaded into\n * the i18n runtime — a published translation was a dead-end on publish AND\n * after a restart.\n *\n * This module is the single shared implementation of the fix, wired by both\n * hosts an `i18n` service can come from:\n * - the runtime's AppPlugin (covers the kernel's in-memory fallback — the\n * dev/standalone reality) and\n * - @objectstack/service-i18n's I18nServicePlugin (the file-based adapter).\n * Both adapters expose `replaceAuthoredTranslations(byLocale)`; the sync\n * computes the full authored layer from the rows and REPLACES it wholesale\n * (clear-then-reload), so deleted items/keys stop resolving.\n *\n * Item payload is a single-locale `AppTranslationBundle` (the `translation`\n * type's canonical schema). Locale resolution, in order: `_meta.locale`, a\n * top-level `locale` string, then the item name when it looks like a BCP-47\n * tag (an item named `zh-CN` translates that locale). Items with no\n * resolvable locale are skipped with a warning. Multiple items on one locale\n * deep-merge in name order (deterministic).\n *\n * Trigger points (wired by {@link wireAuthoredTranslationSync}):\n * • `kernel:ready` — cold-boot coverage;\n * • `metadata:reloaded` — publish-while-running coverage (#2576);\n * • protocol `onMetadataMutation` — direct-active saves / deletes of\n * `translation` rows that don't go through a package publish (#2588's\n * mutation stream).\n *\n * Rows are read straight from `sys_metadata` through the engine — the same\n * discipline as the authored-hook re-sync (#2588): env-scoped kernels\n * surface authored rows nowhere else, and the i18n map is process-wide so\n * rows are taken across all organizations. Best-effort: a failed read keeps\n * the currently applied authored layer.\n */\n\nimport { deepMerge } from './memory-i18n.js';\n\ntype AnyRecord = Record<string, any>;\n\ninterface MinimalCtx {\n logger: { debug?: (...a: any[]) => void; info?: (...a: any[]) => void; warn?: (...a: any[]) => void };\n getService(name: string): any;\n hook?(name: string, fn: () => Promise<void> | void): void;\n}\n\n/**\n * Ownership marker: several plugins may wire the sync against the same\n * kernel (AppPlugin AND I18nServicePlugin on a production server). The first\n * wirer to touch a given i18n service instance claims it; later wirers\n * no-op, so the layer is computed once per change instead of N times.\n */\nconst OWNER_PROP = '__authoredTranslationSyncOwner';\n\n// Deliberately narrow (language + optional script/region only): item names\n// are snake_case, so a permissive multi-segment pattern would classify names\n// like `my_custom_strings` as locales.\nconst LOCALE_LIKE = /^[a-z]{2,3}([_-]([A-Za-z]{4}|[A-Za-z]{2}|[0-9]{3}))?$/;\n\n/**\n * Read ACTIVE `translation` metadata rows and compute the authored layer,\n * keyed by locale. Returns `null` when the read failed (callers must keep\n * the current layer, never tear it down on an error).\n */\nexport async function readAuthoredTranslationLayer(\n engine: { find(object: string, opts?: AnyRecord): Promise<any[]> },\n logger?: MinimalCtx['logger'],\n): Promise<Record<string, Record<string, unknown>> | null> {\n let rows: any[];\n try {\n rows = (await engine.find('sys_metadata', {\n where: { type: 'translation', state: 'active' },\n })) ?? [];\n if (rows.length === 0) {\n // Legacy plural rows — mirrors the protocol's singular/plural fallback.\n rows = (await engine.find('sys_metadata', {\n where: { type: 'translations', state: 'active' },\n })) ?? [];\n }\n } catch (err: any) {\n logger?.debug?.('[i18n] authored-translation read failed — keeping current layer', {\n error: err?.message,\n });\n return null;\n }\n\n const byLocale: Record<string, Record<string, unknown>> = {};\n const sorted = [...rows].sort((a, b) => String(a?.name ?? '').localeCompare(String(b?.name ?? '')));\n for (const row of sorted) {\n let data: any;\n try {\n data = typeof row.metadata === 'string' ? JSON.parse(row.metadata) : row.metadata;\n } catch {\n continue; // malformed row — skip it, keep the rest\n }\n if (!data || typeof data !== 'object') continue;\n const locale: string | undefined =\n (typeof data?._meta?.locale === 'string' && data._meta.locale)\n || (typeof data?.locale === 'string' && data.locale)\n || (typeof row?.name === 'string' && LOCALE_LIKE.test(row.name) ? row.name : undefined)\n || undefined;\n if (!locale) {\n logger?.warn?.(\n `[i18n] authored translation '${row?.name}' has no resolvable locale `\n + '(set _meta.locale, or name the item after its BCP-47 locale) — skipped',\n );\n continue;\n }\n // Strip authoring bookkeeping; everything else is translation data.\n const { name: _n, locale: _l, _packageId: _p, _provenance: _pr, _lock: _lk, ...payload } = data;\n byLocale[locale] = deepMerge(byLocale[locale] ?? {}, payload as Record<string, unknown>);\n }\n return byLocale;\n}\n\n/**\n * Wire the authored-translation sync into a plugin context: registers the\n * `kernel:ready` / `metadata:reloaded` hooks and (at kernel:ready) the\n * protocol mutation subscription. Idempotent per i18n service instance via\n * the ownership marker. Safe to call on kernels with no engine, no protocol,\n * or an i18n service without `replaceAuthoredTranslations` — every path\n * degrades to a no-op.\n */\nexport function wireAuthoredTranslationSync(ctx: MinimalCtx): void {\n if (typeof ctx.hook !== 'function') return;\n\n const token = Symbol('authored-translation-sync');\n const resolveOwnedI18n = (): any | null => {\n let i18n: any;\n try { i18n = ctx.getService('i18n'); } catch { return null; }\n if (!i18n || typeof i18n.replaceAuthoredTranslations !== 'function') return null;\n const current = i18n[OWNER_PROP];\n if (current === undefined) {\n i18n[OWNER_PROP] = token;\n return i18n;\n }\n return current === token ? i18n : null; // another wirer owns this instance\n };\n\n // Serialized: overlapping publishes must not finish out of order and leave\n // the older authored snapshot applied.\n let chain: Promise<void> = Promise.resolve();\n const sync = (): Promise<void> => {\n const run = chain.then(async () => {\n const i18n = resolveOwnedI18n();\n if (!i18n) return;\n let engine: any;\n try { engine = ctx.getService('objectql'); } catch { return; }\n if (!engine || typeof engine.find !== 'function') return;\n const layer = await readAuthoredTranslationLayer(engine, ctx.logger);\n if (layer === null) return; // failed read — keep current layer\n i18n.replaceAuthoredTranslations(layer);\n ctx.logger.info?.('[i18n] synced runtime-authored translations', {\n locales: Object.keys(layer),\n });\n });\n chain = run.catch(() => undefined);\n return run;\n };\n\n ctx.hook('kernel:ready', async () => {\n // Subscribe to translation mutations through the protocol choke point\n // (#2588). Only the owning wirer subscribes.\n if (resolveOwnedI18n()) {\n let protocol: any = null;\n try { protocol = ctx.getService('protocol'); } catch { /* no protocol on this kernel */ }\n if (protocol && typeof protocol.onMetadataMutation === 'function') {\n protocol.onMetadataMutation((evt: { type: string; name: string; state: string }) => {\n if (evt?.type !== 'translation' || evt.state === 'draft') return;\n void sync().catch((err: any) => {\n ctx.logger.warn?.('[i18n] authored-translation re-sync after mutation failed', {\n item: evt.name,\n error: err?.message,\n });\n });\n });\n }\n }\n await sync();\n });\n ctx.hook('metadata:reloaded', async () => {\n await sync();\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { createMemoryCache } from './memory-cache.js';\nimport { createMemoryQueue } from './memory-queue.js';\nimport { createMemoryJob } from './memory-job.js';\nimport { createMemoryI18n } from './memory-i18n.js';\nimport { createMemoryMetadata } from './memory-metadata.js';\n\nexport { createMemoryCache } from './memory-cache.js';\nexport { createMemoryQueue } from './memory-queue.js';\nexport { createMemoryJob } from './memory-job.js';\nexport { createMemoryI18n, resolveLocale, deepMerge } from './memory-i18n.js';\nexport { createMemoryMetadata } from './memory-metadata.js';\nexport {\n wireAuthoredTranslationSync,\n readAuthoredTranslationLayer,\n} from './authored-translation-sync.js';\n\n/**\n * Map of core-criticality service names to their in-memory fallback factories.\n * Used by ObjectKernel.validateSystemRequirements() to auto-inject fallbacks\n * when no real plugin provides the service.\n */\nexport const CORE_FALLBACK_FACTORIES: Record<string, () => Record<string, any>> = {\n metadata: createMemoryMetadata,\n cache: createMemoryCache,\n queue: createMemoryQueue,\n job: createMemoryJob,\n i18n: createMemoryI18n,\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin } from './types.js';\nimport { createLogger, ObjectLogger } from './logger.js';\nimport type { LoggerConfig } from '@objectstack/spec/system';\nimport { ObjectKernelBase } from './kernel-base.js';\n\n/**\n * ObjectKernel - MiniKernel Architecture\n * \n * A highly modular, plugin-based microkernel that:\n * - Manages plugin lifecycle (init, start, destroy)\n * - Provides dependency injection via service registry\n * - Implements event/hook system for inter-plugin communication\n * - Handles dependency resolution (topological sort)\n * - Provides configurable logging for server and browser\n * \n * Core philosophy:\n * - Business logic is completely separated into plugins\n * - Kernel only manages lifecycle, DI, and hooks\n * - Plugins are loaded as equal building blocks\n */\nexport class LiteKernel extends ObjectKernelBase {\n constructor(config?: { logger?: Partial<LoggerConfig> }) {\n const logger = createLogger(config?.logger);\n super(logger);\n \n // Initialize context after logger is created\n this.context = this.createContext();\n }\n\n /**\n * Register a plugin\n * @param plugin - Plugin instance\n */\n use(plugin: Plugin): this {\n this.validateIdle();\n\n const pluginName = plugin.name;\n if (this.plugins.has(pluginName)) {\n throw new Error(`[Kernel] Plugin '${pluginName}' already registered`);\n }\n\n this.plugins.set(pluginName, plugin);\n return this;\n }\n\n /**\n * Bootstrap the kernel\n * 1. Resolve dependencies (topological sort)\n * 2. Init phase - plugins register services\n * 3. Start phase - plugins execute business logic\n * 4. Trigger 'kernel:ready' hook\n */\n async bootstrap(): Promise<void> {\n this.validateState('idle');\n\n this.state = 'initializing';\n this.logger.info('Bootstrap started');\n\n // Resolve dependencies\n const orderedPlugins = this.resolveDependencies();\n\n // Phase 1: Init - Plugins register services\n this.logger.info('Phase 1: Init plugins');\n for (const plugin of orderedPlugins) {\n await this.runPluginInit(plugin);\n }\n\n // Phase 2: Start - Plugins execute business logic\n this.logger.info('Phase 2: Start plugins');\n this.state = 'running';\n \n for (const plugin of orderedPlugins) {\n await this.runPluginStart(plugin);\n }\n\n // Trigger ready hook (route/middleware registration phase)\n await this.triggerHook('kernel:ready');\n // Trigger bootstrapped hook — \"all synchronous bootstrap has settled\"\n // anchor, strictly after every kernel:ready handler has settled and\n // before any HTTP socket opens. NOTE: does not guarantee background app\n // seed data has settled — subscribe `app:seeded` for that\n // (see plugin-lifecycle-events.ts).\n await this.triggerHook('kernel:bootstrapped');\n // Trigger listening hook (HTTP servers open their socket here —\n // strictly after every kernel:ready handler has completed).\n await this.triggerHook('kernel:listening');\n this.logger.info('✅ Bootstrap complete', { \n pluginCount: this.plugins.size \n });\n }\n\n /**\n * Shutdown the kernel\n * Calls destroy on all plugins in reverse order\n */\n async shutdown(): Promise<void> {\n await this.destroy();\n }\n\n /**\n * Graceful shutdown - destroy all plugins in reverse order\n */\n async destroy(): Promise<void> {\n if (this.state === 'stopped') {\n this.logger.warn('Kernel already stopped');\n return;\n }\n\n this.state = 'stopping';\n this.logger.info('Shutdown started');\n\n // Trigger shutdown hook\n await this.triggerHook('kernel:shutdown');\n\n // Destroy plugins in reverse order\n const orderedPlugins = this.resolveDependencies();\n for (const plugin of orderedPlugins.reverse()) {\n await this.runPluginDestroy(plugin);\n }\n\n this.state = 'stopped';\n this.logger.info('✅ Shutdown complete');\n \n // Cleanup logger resources\n if (this.logger && typeof (this.logger as ObjectLogger).destroy === 'function') {\n await (this.logger as ObjectLogger).destroy();\n }\n }\n\n /**\n * Get a service from the registry\n * Convenience method for external access\n */\n getService<T>(name: string): T {\n return this.context.getService<T>(name);\n }\n\n /**\n * Check if kernel is running\n */\n isRunning(): boolean {\n return this.state === 'running';\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n ApiRegistry as ApiRegistryType,\n ApiRegistryEntry,\n ApiRegistryEntryInput,\n ApiEndpointRegistration,\n ConflictResolutionStrategy,\n ApiDiscoveryQuery,\n ApiDiscoveryResponse,\n} from '@objectstack/spec/api';\nimport { ApiRegistryEntrySchema } from '@objectstack/spec/api';\nimport type { Logger } from '@objectstack/spec/contracts';\nimport { getEnv } from './utils/env.js';\n\n/**\n * API Registry Service\n * \n * Central registry for managing API endpoints across different protocols.\n * Provides endpoint registration, discovery, and conflict resolution.\n * \n * **Features:**\n * - Multi-protocol support (REST, GraphQL, OData, WebSocket, etc.)\n * - Route conflict detection with configurable resolution strategies\n * - RBAC permission integration\n * - Dynamic schema linking with ObjectQL references\n * - Plugin API registration\n * \n * **Architecture Alignment:**\n * - Kubernetes: Service Discovery & API Server\n * - AWS API Gateway: Unified API Management\n * - Kong Gateway: Plugin-based API Management\n * \n * @example\n * ```typescript\n * const registry = new ApiRegistry(logger, 'priority');\n * \n * // Register an API\n * registry.registerApi({\n * id: 'customer_api',\n * name: 'Customer API',\n * type: 'rest',\n * version: 'v1',\n * basePath: '/api/v1/customers',\n * endpoints: [...]\n * });\n * \n * // Discover APIs\n * const apis = registry.findApis({ type: 'rest', status: 'active' });\n * \n * // Get registry snapshot\n * const snapshot = registry.getRegistry();\n * ```\n */\nexport class ApiRegistry {\n private apis: Map<string, ApiRegistryEntry> = new Map();\n private endpoints: Map<string, { api: string; endpoint: ApiEndpointRegistration }> = new Map();\n private routes: Map<string, { api: string; endpointId: string; priority: number }> = new Map();\n \n // Performance optimization: Auxiliary indices for O(1) lookups\n private apisByType: Map<string, Set<string>> = new Map();\n private apisByTag: Map<string, Set<string>> = new Map();\n private apisByStatus: Map<string, Set<string>> = new Map();\n \n private conflictResolution: ConflictResolutionStrategy;\n private logger: Logger;\n private version: string;\n private updatedAt: string;\n\n constructor(\n logger: Logger,\n conflictResolution: ConflictResolutionStrategy = 'error',\n version: string = '1.0.0'\n ) {\n this.logger = logger;\n this.conflictResolution = conflictResolution;\n this.version = version;\n this.updatedAt = new Date().toISOString();\n }\n\n /**\n * Register an API with its endpoints\n * \n * @param api - API registry entry\n * @throws Error if API already registered or route conflicts detected\n */\n registerApi(api: ApiRegistryEntryInput): void {\n // Check if API already exists\n if (this.apis.has(api.id)) {\n throw new Error(`[ApiRegistry] API '${api.id}' already registered`);\n }\n\n // Parse and validate the input using Zod schema\n const fullApi = ApiRegistryEntrySchema.parse(api);\n\n // Validate and register endpoints\n for (const endpoint of fullApi.endpoints) {\n this.validateEndpoint(endpoint, fullApi.id);\n }\n\n // Register the API\n this.apis.set(fullApi.id, fullApi);\n \n // Register endpoints\n for (const endpoint of fullApi.endpoints) {\n this.registerEndpoint(fullApi.id, endpoint);\n }\n\n // Update auxiliary indices for performance optimization\n this.updateIndices(fullApi);\n\n this.updatedAt = new Date().toISOString();\n this.logger.info(`API registered: ${fullApi.id}`, {\n api: fullApi.id,\n type: fullApi.type,\n endpointCount: fullApi.endpoints.length,\n });\n }\n\n /**\n * Unregister an API and all its endpoints\n * \n * @param apiId - API identifier\n */\n unregisterApi(apiId: string): void {\n const api = this.apis.get(apiId);\n if (!api) {\n throw new Error(`[ApiRegistry] API '${apiId}' not found`);\n }\n\n // Remove all endpoints\n for (const endpoint of api.endpoints) {\n this.unregisterEndpoint(apiId, endpoint.id);\n }\n\n // Remove from auxiliary indices\n this.removeFromIndices(api);\n\n // Remove the API\n this.apis.delete(apiId);\n this.updatedAt = new Date().toISOString();\n \n this.logger.info(`API unregistered: ${apiId}`);\n }\n\n /**\n * Register a single endpoint\n * \n * @param apiId - API identifier\n * @param endpoint - Endpoint registration\n * @throws Error if route conflict detected\n */\n private registerEndpoint(apiId: string, endpoint: ApiEndpointRegistration): void {\n const endpointKey = `${apiId}:${endpoint.id}`;\n \n // Check if endpoint already registered\n if (this.endpoints.has(endpointKey)) {\n throw new Error(`[ApiRegistry] Endpoint '${endpoint.id}' already registered for API '${apiId}'`);\n }\n\n // Register endpoint\n this.endpoints.set(endpointKey, { api: apiId, endpoint });\n\n // Register route if path is defined\n if (endpoint.path) {\n this.registerRoute(apiId, endpoint);\n }\n }\n\n /**\n * Unregister a single endpoint\n * \n * @param apiId - API identifier\n * @param endpointId - Endpoint identifier\n */\n private unregisterEndpoint(apiId: string, endpointId: string): void {\n const endpointKey = `${apiId}:${endpointId}`;\n const entry = this.endpoints.get(endpointKey);\n \n if (!entry) {\n return; // Already unregistered\n }\n\n // Unregister route\n if (entry.endpoint.path) {\n const routeKey = this.getRouteKey(entry.endpoint);\n this.routes.delete(routeKey);\n }\n\n // Unregister endpoint\n this.endpoints.delete(endpointKey);\n }\n\n /**\n * Register a route with conflict detection\n * \n * @param apiId - API identifier\n * @param endpoint - Endpoint registration\n * @throws Error if route conflict detected (based on strategy)\n */\n private registerRoute(apiId: string, endpoint: ApiEndpointRegistration): void {\n const routeKey = this.getRouteKey(endpoint);\n const priority = endpoint.priority ?? 100;\n const existingRoute = this.routes.get(routeKey);\n\n if (existingRoute) {\n // Route conflict detected\n this.handleRouteConflict(routeKey, apiId, endpoint, existingRoute, priority);\n return;\n }\n\n // Register route\n this.routes.set(routeKey, {\n api: apiId,\n endpointId: endpoint.id,\n priority,\n });\n }\n\n /**\n * Handle route conflict based on resolution strategy\n * \n * @param routeKey - Route key\n * @param apiId - New API identifier\n * @param endpoint - New endpoint\n * @param existingRoute - Existing route registration\n * @param newPriority - New endpoint priority\n * @throws Error if strategy is 'error'\n */\n private handleRouteConflict(\n routeKey: string,\n apiId: string,\n endpoint: ApiEndpointRegistration,\n existingRoute: { api: string; endpointId: string; priority: number },\n newPriority: number\n ): void {\n const strategy = this.conflictResolution;\n\n switch (strategy) {\n case 'error':\n throw new Error(\n `[ApiRegistry] Route conflict detected: '${routeKey}' is already registered by API '${existingRoute.api}' endpoint '${existingRoute.endpointId}'`\n );\n\n case 'priority':\n if (newPriority > existingRoute.priority) {\n // New endpoint has higher priority, replace\n this.logger.warn(\n `Route conflict: replacing '${routeKey}' (priority ${existingRoute.priority} -> ${newPriority})`,\n {\n oldApi: existingRoute.api,\n oldEndpoint: existingRoute.endpointId,\n newApi: apiId,\n newEndpoint: endpoint.id,\n }\n );\n this.routes.set(routeKey, {\n api: apiId,\n endpointId: endpoint.id,\n priority: newPriority,\n });\n } else {\n // Existing endpoint has higher priority, keep it\n this.logger.warn(\n `Route conflict: keeping existing '${routeKey}' (priority ${existingRoute.priority} >= ${newPriority})`,\n {\n existingApi: existingRoute.api,\n existingEndpoint: existingRoute.endpointId,\n newApi: apiId,\n newEndpoint: endpoint.id,\n }\n );\n }\n break;\n\n case 'first-wins':\n // Keep existing route\n this.logger.warn(\n `Route conflict: keeping first registered '${routeKey}'`,\n {\n existingApi: existingRoute.api,\n newApi: apiId,\n }\n );\n break;\n\n case 'last-wins':\n // Replace with new route\n this.logger.warn(\n `Route conflict: replacing with last registered '${routeKey}'`,\n {\n oldApi: existingRoute.api,\n newApi: apiId,\n }\n );\n this.routes.set(routeKey, {\n api: apiId,\n endpointId: endpoint.id,\n priority: newPriority,\n });\n break;\n\n default:\n throw new Error(`[ApiRegistry] Unknown conflict resolution strategy: ${strategy}`);\n }\n }\n\n /**\n * Generate a unique route key for conflict detection\n * \n * NOTE: This implementation uses exact string matching for route conflict detection.\n * It works well for static paths but has limitations with parameterized routes.\n * For example, `/api/users/:id` and `/api/users/:userId` will NOT be detected as conflicts\n * even though they are semantically identical parameterized patterns. Similarly,\n * `/api/:resource/list` and `/api/:entity/list` would also not be detected as conflicting.\n * \n * For more advanced conflict detection (e.g., path-to-regexp pattern matching),\n * consider integrating with your routing library's conflict detection mechanism.\n * \n * @param endpoint - Endpoint registration\n * @returns Route key (e.g., \"GET:/api/v1/customers/:id\")\n */\n private getRouteKey(endpoint: ApiEndpointRegistration): string {\n const method = endpoint.method || 'ANY';\n return `${method}:${endpoint.path}`;\n }\n\n /**\n * Validate endpoint registration\n * \n * @param endpoint - Endpoint to validate\n * @param apiId - API identifier (for error messages)\n * @throws Error if endpoint is invalid\n */\n private validateEndpoint(endpoint: ApiEndpointRegistration, apiId: string): void {\n if (!endpoint.id) {\n throw new Error(`[ApiRegistry] Endpoint in API '${apiId}' missing 'id' field`);\n }\n\n if (!endpoint.path) {\n throw new Error(`[ApiRegistry] Endpoint '${endpoint.id}' in API '${apiId}' missing 'path' field`);\n }\n }\n\n /**\n * Get an API by ID\n * \n * @param apiId - API identifier\n * @returns API registry entry or undefined\n */\n getApi(apiId: string): ApiRegistryEntry | undefined {\n return this.apis.get(apiId);\n }\n\n /**\n * Get all registered APIs\n * \n * @returns Array of all APIs\n */\n getAllApis(): ApiRegistryEntry[] {\n return Array.from(this.apis.values());\n }\n\n /**\n * Find APIs matching query criteria\n * \n * Performance optimized with auxiliary indices for O(1) lookups on type, tags, and status.\n * \n * @param query - Discovery query parameters\n * @returns Matching APIs\n */\n findApis(query: ApiDiscoveryQuery): ApiDiscoveryResponse {\n let resultIds: Set<string> | undefined;\n\n // Use indices for performance-optimized filtering\n // Start with the most restrictive filter to minimize subsequent filtering\n \n // Filter by type (using index for O(1) lookup)\n if (query.type) {\n const typeIds = this.apisByType.get(query.type);\n if (!typeIds || typeIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n resultIds = new Set(typeIds);\n }\n\n // Filter by status (using index for O(1) lookup)\n if (query.status) {\n const statusIds = this.apisByStatus.get(query.status);\n if (!statusIds || statusIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n \n if (resultIds) {\n // Intersect with previous results\n resultIds = new Set([...resultIds].filter(id => statusIds.has(id)));\n } else {\n resultIds = new Set(statusIds);\n }\n \n if (resultIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n }\n\n // Filter by tags (using index for O(M) lookup where M is number of tags)\n if (query.tags && query.tags.length > 0) {\n const tagMatches = new Set<string>();\n \n for (const tag of query.tags) {\n const tagIds = this.apisByTag.get(tag);\n if (tagIds) {\n tagIds.forEach(id => tagMatches.add(id));\n }\n }\n \n if (tagMatches.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n \n if (resultIds) {\n // Intersect with previous results\n resultIds = new Set([...resultIds].filter(id => tagMatches.has(id)));\n } else {\n resultIds = tagMatches;\n }\n \n if (resultIds.size === 0) {\n return { apis: [], total: 0, filters: query };\n }\n }\n\n // Get the actual API objects\n let results: ApiRegistryEntry[];\n if (resultIds) {\n results = Array.from(resultIds)\n .map(id => this.apis.get(id))\n .filter((api): api is ApiRegistryEntry => api !== undefined);\n } else {\n results = Array.from(this.apis.values());\n }\n\n // Apply remaining filters that don't have indices (less common filters)\n \n // Filter by plugin source\n if (query.pluginSource) {\n results = results.filter(\n (api) => api.metadata?.pluginSource === query.pluginSource\n );\n }\n\n // Filter by version\n if (query.version) {\n results = results.filter((api) => api.version === query.version);\n }\n\n // Search in name/description\n if (query.search) {\n const searchLower = query.search.toLowerCase();\n results = results.filter(\n (api) =>\n api.name.toLowerCase().includes(searchLower) ||\n (api.description && api.description.toLowerCase().includes(searchLower))\n );\n }\n\n return {\n apis: results,\n total: results.length,\n filters: query,\n };\n }\n\n /**\n * Get endpoint by API ID and endpoint ID\n * \n * @param apiId - API identifier\n * @param endpointId - Endpoint identifier\n * @returns Endpoint registration or undefined\n */\n getEndpoint(apiId: string, endpointId: string): ApiEndpointRegistration | undefined {\n const key = `${apiId}:${endpointId}`;\n return this.endpoints.get(key)?.endpoint;\n }\n\n /**\n * Find endpoint by route (method + path)\n * \n * @param method - HTTP method\n * @param path - URL path\n * @returns Endpoint registration or undefined\n */\n findEndpointByRoute(method: string, path: string): {\n api: ApiRegistryEntry;\n endpoint: ApiEndpointRegistration;\n } | undefined {\n const routeKey = `${method}:${path}`;\n const route = this.routes.get(routeKey);\n \n if (!route) {\n return undefined;\n }\n\n const api = this.apis.get(route.api);\n const endpoint = this.getEndpoint(route.api, route.endpointId);\n\n if (!api || !endpoint) {\n return undefined;\n }\n\n return { api, endpoint };\n }\n\n /**\n * Get complete registry snapshot\n * \n * @returns Current registry state\n */\n getRegistry(): ApiRegistryType {\n const apis = Array.from(this.apis.values());\n \n // Group by type\n const byType: Record<string, ApiRegistryEntry[]> = {};\n for (const api of apis) {\n if (!byType[api.type]) {\n byType[api.type] = [];\n }\n byType[api.type].push(api);\n }\n\n // Group by status\n const byStatus: Record<string, ApiRegistryEntry[]> = {};\n for (const api of apis) {\n const status = api.metadata?.status || 'active';\n if (!byStatus[status]) {\n byStatus[status] = [];\n }\n byStatus[status].push(api);\n }\n\n // Count total endpoints\n const totalEndpoints = apis.reduce(\n (sum, api) => sum + api.endpoints.length,\n 0\n );\n\n return {\n version: this.version,\n conflictResolution: this.conflictResolution,\n apis,\n totalApis: apis.length,\n totalEndpoints,\n byType,\n byStatus,\n updatedAt: this.updatedAt,\n };\n }\n\n /**\n * Clear all registered APIs\n * \n * **⚠️ SAFETY WARNING:**\n * This method clears all registered APIs and should be used with caution.\n * \n * **Usage Restrictions:**\n * - In production environments (NODE_ENV=production), a `force: true` parameter is required\n * - Primarily intended for testing and development hot-reload scenarios\n * \n * @param options - Clear options\n * @param options.force - Force clear in production environment (default: false)\n * @throws Error if called in production without force flag\n * \n * @example Safe usage in tests\n * ```typescript\n * beforeEach(() => {\n * registry.clear(); // OK in test environment\n * });\n * ```\n * \n * @example Usage in production (requires explicit force)\n * ```typescript\n * // In production, explicit force is required\n * registry.clear({ force: true });\n * ```\n */\n clear(options: { force?: boolean } = {}): void {\n const isProduction = this.isProductionEnvironment();\n \n if (isProduction && !options.force) {\n throw new Error(\n '[ApiRegistry] Cannot clear registry in production environment without force flag. ' +\n 'Use clear({ force: true }) if you really want to clear the registry.'\n );\n }\n\n this.apis.clear();\n this.endpoints.clear();\n this.routes.clear();\n \n // Clear auxiliary indices\n this.apisByType.clear();\n this.apisByTag.clear();\n this.apisByStatus.clear();\n \n this.updatedAt = new Date().toISOString();\n \n if (isProduction) {\n this.logger.warn('API registry forcefully cleared in production', { force: options.force });\n } else {\n this.logger.info('API registry cleared');\n }\n }\n\n /**\n * Get registry statistics\n * \n * @returns Registry statistics\n */\n getStats(): {\n totalApis: number;\n totalEndpoints: number;\n totalRoutes: number;\n apisByType: Record<string, number>;\n endpointsByApi: Record<string, number>;\n } {\n const apis = Array.from(this.apis.values());\n \n const apisByType: Record<string, number> = {};\n for (const api of apis) {\n apisByType[api.type] = (apisByType[api.type] || 0) + 1;\n }\n\n const endpointsByApi: Record<string, number> = {};\n for (const api of apis) {\n endpointsByApi[api.id] = api.endpoints.length;\n }\n\n return {\n totalApis: this.apis.size,\n totalEndpoints: this.endpoints.size,\n totalRoutes: this.routes.size,\n apisByType,\n endpointsByApi,\n };\n }\n\n /**\n * Update auxiliary indices when an API is registered\n * \n * @param api - API entry to index\n * @private\n * @internal\n */\n private updateIndices(api: ApiRegistryEntry): void {\n // Index by type\n this.ensureIndexSet(this.apisByType, api.type).add(api.id);\n\n // Index by status\n const status = api.metadata?.status || 'active';\n this.ensureIndexSet(this.apisByStatus, status).add(api.id);\n\n // Index by tags\n const tags = api.metadata?.tags || [];\n for (const tag of tags) {\n this.ensureIndexSet(this.apisByTag, tag).add(api.id);\n }\n }\n\n /**\n * Remove API from auxiliary indices when unregistered\n * \n * @param api - API entry to remove from indices\n * @private\n * @internal\n */\n private removeFromIndices(api: ApiRegistryEntry): void {\n // Remove from type index\n this.removeFromIndexSet(this.apisByType, api.type, api.id);\n\n // Remove from status index\n const status = api.metadata?.status || 'active';\n this.removeFromIndexSet(this.apisByStatus, status, api.id);\n\n // Remove from tag indices\n const tags = api.metadata?.tags || [];\n for (const tag of tags) {\n this.removeFromIndexSet(this.apisByTag, tag, api.id);\n }\n }\n\n /**\n * Helper to ensure an index set exists and return it\n * \n * @param map - Index map\n * @param key - Index key\n * @returns The Set for this key (created if needed)\n * @private\n * @internal\n */\n private ensureIndexSet(map: Map<string, Set<string>>, key: string): Set<string> {\n let set = map.get(key);\n if (!set) {\n set = new Set();\n map.set(key, set);\n }\n return set;\n }\n\n /**\n * Helper to remove an ID from an index set and clean up empty sets\n * \n * @param map - Index map\n * @param key - Index key\n * @param id - API ID to remove\n * @private\n * @internal\n */\n private removeFromIndexSet(map: Map<string, Set<string>>, key: string, id: string): void {\n const set = map.get(key);\n if (set) {\n set.delete(id);\n // Clean up empty sets to avoid memory leaks\n if (set.size === 0) {\n map.delete(key);\n }\n }\n }\n\n /**\n * Check if running in production environment\n * \n * @returns true if NODE_ENV is 'production'\n * @private\n * @internal\n */\n private isProductionEnvironment(): boolean {\n return getEnv('NODE_ENV') === 'production';\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from './types.js';\nimport { ApiRegistry } from './api-registry.js';\nimport type { ConflictResolutionStrategy } from '@objectstack/spec/api';\n\n/**\n * API Registry Plugin Configuration\n */\nexport interface ApiRegistryPluginConfig {\n /**\n * Conflict resolution strategy for route conflicts\n * @default 'error'\n */\n conflictResolution?: ConflictResolutionStrategy;\n \n /**\n * Registry version\n * @default '1.0.0'\n */\n version?: string;\n}\n\n/**\n * API Registry Plugin\n * \n * Registers the API Registry service in the kernel, making it available\n * to all plugins for endpoint registration and discovery.\n * \n * **Usage:**\n * ```typescript\n * const kernel = new ObjectKernel();\n * \n * // Register API Registry Plugin\n * kernel.use(createApiRegistryPlugin({ conflictResolution: 'priority' }));\n * \n * // In other plugins, access the API Registry\n * const plugin: Plugin = {\n * name: 'my-plugin',\n * init: async (ctx) => {\n * const registry = ctx.getService<ApiRegistry>('api-registry');\n * \n * // Register plugin APIs\n * registry.registerApi({\n * id: 'my_plugin_api',\n * name: 'My Plugin API',\n * type: 'rest',\n * version: 'v1',\n * basePath: '/api/v1/my-plugin',\n * endpoints: [...]\n * });\n * }\n * };\n * ```\n * \n * @param config - Plugin configuration\n * @returns Plugin instance\n */\nexport function createApiRegistryPlugin(\n config: ApiRegistryPluginConfig = {}\n): Plugin {\n const {\n conflictResolution = 'error',\n version = '1.0.0',\n } = config;\n\n return {\n name: 'com.objectstack.core.api-registry',\n type: 'standard',\n version: '1.0.0',\n\n init: async (ctx: PluginContext) => {\n // Create API Registry instance\n const registry = new ApiRegistry(\n ctx.logger,\n conflictResolution,\n version\n );\n\n // Register as a service\n ctx.registerService('api-registry', registry);\n\n ctx.logger.info('API Registry plugin initialized', {\n conflictResolution,\n version,\n });\n },\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport * from './adapter.js';\nexport * from './runner.js';\nexport * from './http-adapter.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport * as QA from '@objectstack/spec/qa';\nimport { TestExecutionAdapter } from './adapter.js';\n\nexport interface TestResult {\n scenarioId: string;\n passed: boolean;\n steps: StepResult[];\n error?: unknown;\n duration: number;\n}\n\nexport interface StepResult {\n stepName: string;\n passed: boolean;\n error?: unknown;\n output?: unknown;\n duration: number;\n}\n\nexport class TestRunner {\n constructor(private adapter: TestExecutionAdapter) {}\n\n async runSuite(suite: QA.TestSuite): Promise<TestResult[]> {\n const results: TestResult[] = [];\n for (const scenario of suite.scenarios) {\n results.push(await this.runScenario(scenario));\n }\n return results;\n }\n\n async runScenario(scenario: QA.TestScenario): Promise<TestResult> {\n const startTime = Date.now();\n const context: Record<string, unknown> = {}; // Variable context\n \n // Initialize context from initial payload if needed? Currently schema doesn't have initial context prop on Scenario\n // But we defined TestContextSchema separately.\n \n // Setup\n if (scenario.setup) {\n for (const step of scenario.setup) {\n try {\n await this.runStep(step, context);\n } catch (e) {\n return {\n scenarioId: scenario.id,\n passed: false,\n steps: [],\n error: `Setup failed: ${e instanceof Error ? e.message : String(e)}`,\n duration: Date.now() - startTime\n };\n }\n }\n }\n\n const stepResults: StepResult[] = [];\n let scenarioPassed = true;\n let scenarioError: unknown = undefined;\n\n // Main Steps\n for (const step of scenario.steps) {\n const stepStartTime = Date.now();\n try {\n const output = await this.runStep(step, context);\n stepResults.push({\n stepName: step.name,\n passed: true,\n output,\n duration: Date.now() - stepStartTime\n });\n } catch (e) {\n scenarioPassed = false;\n scenarioError = e;\n stepResults.push({\n stepName: step.name,\n passed: false,\n error: e,\n duration: Date.now() - stepStartTime\n });\n break; // Stop on first failure\n }\n }\n\n // Teardown (run even if failed)\n if (scenario.teardown) {\n for (const step of scenario.teardown) {\n try {\n await this.runStep(step, context);\n } catch (e) {\n // Log teardown failure but don't override main failure if it exists\n if (scenarioPassed) {\n scenarioPassed = false;\n scenarioError = `Teardown failed: ${e instanceof Error ? e.message : String(e)}`;\n }\n }\n }\n }\n\n return {\n scenarioId: scenario.id,\n passed: scenarioPassed,\n steps: stepResults,\n error: scenarioError,\n duration: Date.now() - startTime\n };\n }\n\n private async runStep(step: QA.TestStep, context: Record<string, unknown>): Promise<unknown> {\n // 1. Resolve Variables with Context (Simple interpolation or just pass context?)\n // For now, assume adpater handles context resolution or we do basic replacement\n const resolvedAction = this.resolveVariables(step.action, context);\n\n // 2. Execute Action\n const result = await this.adapter.execute(resolvedAction, context);\n\n // 3. Capture Outputs\n if (step.capture) {\n for (const [varName, path] of Object.entries(step.capture)) {\n context[varName] = this.getValueByPath(result, path);\n }\n }\n\n // 4. Run Assertions\n if (step.assertions) {\n for (const assertion of step.assertions) {\n this.assert(result, assertion, context);\n }\n }\n\n return result;\n }\n\n private resolveVariables(action: QA.TestAction, context: Record<string, unknown>): QA.TestAction {\n const actionStr = JSON.stringify(action);\n const resolved = actionStr.replace(/\\{\\{([^}]+)\\}\\}/g, (_match, varPath: string) => {\n const value = this.getValueByPath(context, varPath.trim());\n if (value === undefined) return _match; // Keep unresolved\n return typeof value === 'string' ? value : JSON.stringify(value);\n });\n try {\n return JSON.parse(resolved) as QA.TestAction;\n } catch {\n return action; // Fallback to original if parse fails\n }\n }\n\n private getValueByPath(obj: unknown, path: string): unknown {\n if (!path) return obj;\n const parts = path.split('.');\n let current: any = obj;\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n current = current[part];\n }\n return current;\n }\n\n private assert(result: unknown, assertion: QA.TestAssertion, _context: Record<string, unknown>) {\n const actual = this.getValueByPath(result, assertion.field);\n // Resolve expected value if it's a variable ref? \n const expected = assertion.expectedValue; // Simplify for now\n\n switch (assertion.operator) {\n case 'equals':\n if (actual !== expected) throw new Error(`Assertion failed: ${assertion.field} expected ${expected}, got ${actual}`);\n break;\n case 'not_equals':\n if (actual === expected) throw new Error(`Assertion failed: ${assertion.field} expected not ${expected}, got ${actual}`);\n break;\n case 'contains':\n if (Array.isArray(actual)) {\n if (!actual.includes(expected)) throw new Error(`Assertion failed: ${assertion.field} array does not contain ${expected}`);\n } else if (typeof actual === 'string') {\n if (!actual.includes(String(expected))) throw new Error(`Assertion failed: ${assertion.field} string does not contain ${expected}`);\n }\n break;\n case 'not_null':\n if (actual === null || actual === undefined) throw new Error(`Assertion failed: ${assertion.field} is null`);\n break;\n case 'is_null':\n if (actual !== null && actual !== undefined) throw new Error(`Assertion failed: ${assertion.field} is not null`);\n break;\n // ... Add other operators\n default:\n throw new Error(`Unknown assertion operator: ${assertion.operator}`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport * as QA from '@objectstack/spec/qa';\nimport { TestExecutionAdapter } from './adapter.js';\n\nexport class HttpTestAdapter implements TestExecutionAdapter {\n constructor(private baseUrl: string, private authToken?: string) {}\n\n async execute(action: QA.TestAction, _context: Record<string, unknown>): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n // If action.user is specified, maybe add a specific header for impersonation if supported?\n if (action.user) {\n headers['X-Run-As'] = action.user;\n }\n\n switch (action.type) {\n case 'create_record':\n return this.createRecord(action.target, action.payload || {}, headers);\n case 'update_record':\n return this.updateRecord(action.target, action.payload || {}, headers);\n case 'delete_record':\n return this.deleteRecord(action.target, action.payload || {}, headers);\n case 'read_record':\n return this.readRecord(action.target, action.payload || {}, headers);\n case 'query_records':\n return this.queryRecords(action.target, action.payload || {}, headers);\n case 'api_call':\n return this.rawApiCall(action.target, action.payload || {}, headers);\n case 'wait':\n const ms = Number(action.payload?.duration || 1000);\n return new Promise(resolve => setTimeout(() => resolve({ waited: ms }), ms));\n default:\n throw new Error(`Unsupported action type in HttpAdapter: ${action.type}`);\n }\n }\n\n private async createRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(data)\n });\n return this.handleResponse(response);\n }\n\n private async updateRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const id = data.id;\n if (!id) throw new Error('Update record requires id in payload');\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {\n method: 'PUT',\n headers,\n body: JSON.stringify(data)\n });\n return this.handleResponse(response);\n }\n\n private async deleteRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const id = data.id;\n if (!id) throw new Error('Delete record requires id in payload');\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {\n method: 'DELETE',\n headers\n });\n return this.handleResponse(response);\n }\n\n private async readRecord(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const id = data.id;\n if (!id) throw new Error('Read record requires id in payload');\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {\n method: 'GET',\n headers\n });\n return this.handleResponse(response);\n }\n\n private async queryRecords(objectName: string, data: Record<string, unknown>, headers: Record<string, string>) {\n // Assuming query via POST or GraphQL-like endpoint\n const response = await fetch(`${this.baseUrl}/api/data/${objectName}/query`, {\n method: 'POST',\n headers,\n body: JSON.stringify(data)\n });\n return this.handleResponse(response);\n }\n\n private async rawApiCall(endpoint: string, data: Record<string, unknown>, headers: Record<string, string>) {\n const method = (data.method as string) || 'GET';\n const body = data.body ? JSON.stringify(data.body) : undefined;\n const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;\n \n const response = await fetch(url, {\n method,\n headers,\n body\n });\n return this.handleResponse(response);\n }\n\n private async handleResponse(response: Response) {\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`HTTP Error ${response.status}: ${text}`);\n }\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('application/json')) {\n return response.json();\n }\n return response.text();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { PluginMetadata } from '../plugin-loader.js';\n\n// Conditionally import crypto for Node.js environments\nlet cryptoModule: typeof import('crypto') | null = null;\n\n\n/**\n * Plugin Signature Configuration\n * Controls how plugin signatures are verified\n */\nexport interface PluginSignatureConfig {\n /**\n * Map of publisher IDs to their trusted public keys\n * Format: { 'com.objectstack': '-----BEGIN PUBLIC KEY-----...' }\n */\n trustedPublicKeys: Map<string, string>;\n \n /**\n * Signature algorithm to use\n * - RS256: RSA with SHA-256\n * - ES256: ECDSA with SHA-256\n */\n algorithm: 'RS256' | 'ES256';\n \n /**\n * Strict mode: reject plugins without signatures\n * - true: All plugins must be signed\n * - false: Unsigned plugins are allowed with warning\n */\n strictMode: boolean;\n \n /**\n * Allow self-signed plugins in development\n */\n allowSelfSigned?: boolean;\n}\n\n/**\n * Plugin Signature Verification Result\n */\nexport interface SignatureVerificationResult {\n verified: boolean;\n error?: string;\n publisherId?: string;\n algorithm?: string;\n signedAt?: Date;\n}\n\n/**\n * Plugin Signature Verifier\n * \n * Implements cryptographic verification of plugin signatures to ensure:\n * 1. Plugin integrity - code hasn't been tampered with\n * 2. Publisher authenticity - plugin comes from trusted source\n * 3. Non-repudiation - publisher cannot deny signing\n * \n * Architecture:\n * - Uses Node.js crypto module for signature verification\n * - Supports RSA (RS256) and ECDSA (ES256) algorithms\n * - Verifies against trusted public key registry\n * - Computes hash of plugin code for integrity check\n * \n * Security Model:\n * - Public keys are pre-registered and trusted\n * - Plugin signature is verified before loading\n * - Strict mode rejects unsigned plugins\n * - Development mode allows self-signed plugins\n */\nexport class PluginSignatureVerifier {\n private config: PluginSignatureConfig;\n private logger: Logger;\n \n constructor(config: PluginSignatureConfig, logger: Logger) {\n this.config = config;\n this.logger = logger;\n \n this.validateConfig();\n }\n \n /**\n * Verify plugin signature\n * \n * @param plugin - Plugin metadata with signature\n * @returns Verification result\n * @throws Error if verification fails in strict mode\n */\n async verifyPluginSignature(plugin: PluginMetadata): Promise<SignatureVerificationResult> {\n // Handle unsigned plugins\n if (!plugin.signature) {\n return this.handleUnsignedPlugin(plugin);\n }\n \n try {\n // 1. Extract publisher ID from plugin name (reverse domain notation)\n const publisherId = this.extractPublisherId(plugin.name);\n \n // 2. Get trusted public key for publisher\n const publicKey = this.config.trustedPublicKeys.get(publisherId);\n if (!publicKey) {\n const error = `No trusted public key for publisher: ${publisherId}`;\n this.logger.warn(error, { plugin: plugin.name, publisherId });\n \n if (this.config.strictMode && !this.config.allowSelfSigned) {\n throw new Error(error);\n }\n \n return {\n verified: false,\n error,\n publisherId,\n };\n }\n \n // 3. Compute plugin code hash\n const pluginHash = this.computePluginHash(plugin);\n \n // 4. Verify signature using crypto module\n const isValid = await this.verifyCryptoSignature(\n pluginHash,\n plugin.signature,\n publicKey\n );\n \n if (!isValid) {\n const error = `Signature verification failed for plugin: ${plugin.name}`;\n this.logger.error(error, undefined, { plugin: plugin.name, publisherId });\n throw new Error(error);\n }\n \n this.logger.info(`✅ Plugin signature verified: ${plugin.name}`, {\n plugin: plugin.name,\n publisherId,\n algorithm: this.config.algorithm,\n });\n \n return {\n verified: true,\n publisherId,\n algorithm: this.config.algorithm,\n };\n \n } catch (error) {\n this.logger.error(`Signature verification error: ${plugin.name}`, error as Error);\n \n if (this.config.strictMode) {\n throw error;\n }\n \n return {\n verified: false,\n error: (error as Error).message,\n };\n }\n }\n \n /**\n * Register a trusted public key for a publisher\n */\n registerPublicKey(publisherId: string, publicKey: string): void {\n this.config.trustedPublicKeys.set(publisherId, publicKey);\n this.logger.info(`Trusted public key registered for: ${publisherId}`);\n }\n \n /**\n * Remove a trusted public key\n */\n revokePublicKey(publisherId: string): void {\n this.config.trustedPublicKeys.delete(publisherId);\n this.logger.warn(`Public key revoked for: ${publisherId}`);\n }\n \n /**\n * Get list of trusted publishers\n */\n getTrustedPublishers(): string[] {\n return Array.from(this.config.trustedPublicKeys.keys());\n }\n \n // Private methods\n \n private handleUnsignedPlugin(plugin: PluginMetadata): SignatureVerificationResult {\n if (this.config.strictMode) {\n const error = `Plugin missing signature (strict mode): ${plugin.name}`;\n this.logger.error(error, undefined, { plugin: plugin.name });\n throw new Error(error);\n }\n \n this.logger.warn(`⚠️ Plugin not signed: ${plugin.name}`, {\n plugin: plugin.name,\n recommendation: 'Consider signing plugins for production environments',\n });\n \n return {\n verified: false,\n error: 'Plugin not signed',\n };\n }\n \n private extractPublisherId(pluginName: string): string {\n // Extract publisher from reverse domain notation\n // Example: \"com.objectstack.engine.objectql\" -> \"com.objectstack\"\n const parts = pluginName.split('.');\n \n if (parts.length < 2) {\n throw new Error(`Invalid plugin name format: ${pluginName} (expected reverse domain notation)`);\n }\n \n // Return first two parts (domain reversed)\n return `${parts[0]}.${parts[1]}`;\n }\n \n private computePluginHash(plugin: PluginMetadata): string {\n // In browser environment, use SubtleCrypto\n if (typeof (globalThis as any).window !== 'undefined') {\n return this.computePluginHashBrowser(plugin);\n }\n \n // In Node.js environment, use crypto module\n return this.computePluginHashNode(plugin);\n }\n \n private computePluginHashNode(plugin: PluginMetadata): string {\n // Use pre-loaded crypto module\n if (!cryptoModule) {\n this.logger.warn('crypto module not available, using fallback hash');\n return this.computePluginHashFallback(plugin);\n }\n \n // Compute hash of plugin code\n const pluginCode = this.serializePluginCode(plugin);\n return cryptoModule.createHash('sha256').update(pluginCode).digest('hex');\n }\n \n private computePluginHashBrowser(plugin: PluginMetadata): string {\n // Browser environment - use simple hash for now\n // In production, should use SubtleCrypto for proper cryptographic hash\n this.logger.debug('Using browser hash (SubtleCrypto integration pending)');\n return this.computePluginHashFallback(plugin);\n }\n \n private computePluginHashFallback(plugin: PluginMetadata): string {\n // Simple hash fallback (not cryptographically secure)\n const pluginCode = this.serializePluginCode(plugin);\n let hash = 0;\n \n for (let i = 0; i < pluginCode.length; i++) {\n const char = pluginCode.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n \n return hash.toString(16);\n }\n \n private serializePluginCode(plugin: PluginMetadata): string {\n // Serialize plugin code for hashing\n // Include init, start, destroy functions\n const parts: string[] = [\n plugin.name,\n plugin.version,\n plugin.init.toString(),\n ];\n \n if (plugin.start) {\n parts.push(plugin.start.toString());\n }\n \n if (plugin.destroy) {\n parts.push(plugin.destroy.toString());\n }\n \n return parts.join('|');\n }\n \n private async verifyCryptoSignature(\n data: string,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n // In browser environment, use SubtleCrypto\n if (typeof (globalThis as any).window !== 'undefined') {\n return this.verifyCryptoSignatureBrowser(data, signature, publicKey);\n }\n \n // In Node.js environment, use crypto module\n return this.verifyCryptoSignatureNode(data, signature, publicKey);\n }\n \n private async verifyCryptoSignatureNode(\n data: string,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n if (!cryptoModule) {\n try {\n // @ts-ignore\n cryptoModule = await import('crypto');\n } catch (e) {\n // ignore\n }\n }\n\n if (!cryptoModule) {\n this.logger.error('Crypto module not available for signature verification');\n return false;\n }\n \n try {\n // Create verify object based on algorithm\n if (this.config.algorithm === 'ES256') {\n // ECDSA verification - requires lowercase 'sha256'\n const verify = cryptoModule.createVerify('sha256');\n verify.update(data);\n return verify.verify(\n {\n key: publicKey,\n format: 'pem',\n type: 'spki',\n },\n signature,\n 'base64'\n );\n } else {\n // RSA verification (RS256)\n const verify = cryptoModule.createVerify('RSA-SHA256');\n verify.update(data);\n return verify.verify(publicKey, signature, 'base64');\n }\n } catch (error) {\n this.logger.error('Signature verification failed', error as Error);\n return false;\n }\n }\n \n private async verifyCryptoSignatureBrowser(\n data: string,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n try {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n this.logger.error('SubtleCrypto not available in this environment');\n return false;\n }\n\n // Decode PEM public key to raw DER bytes\n const pemBody = publicKey\n .replace(/-----BEGIN PUBLIC KEY-----/, '')\n .replace(/-----END PUBLIC KEY-----/, '')\n .replace(/\\s/g, '');\n const keyBytes = Uint8Array.from(atob(pemBody), c => c.charCodeAt(0));\n\n // Configure algorithms based on RS256 or ES256\n let importAlgorithm: { name: string; hash?: string; namedCurve?: string };\n let verifyAlgorithm: { name: string; hash?: string };\n\n if (this.config.algorithm === 'ES256') {\n importAlgorithm = { name: 'ECDSA', namedCurve: 'P-256' };\n verifyAlgorithm = { name: 'ECDSA', hash: 'SHA-256' };\n } else {\n importAlgorithm = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };\n verifyAlgorithm = { name: 'RSASSA-PKCS1-v1_5' };\n }\n\n const cryptoKey = await subtle.importKey(\n 'spki',\n keyBytes,\n importAlgorithm,\n false,\n ['verify']\n );\n\n // Decode base64 signature to ArrayBuffer\n const signatureBytes = Uint8Array.from(atob(signature), c => c.charCodeAt(0));\n\n // Encode data to ArrayBuffer\n const dataBytes = new TextEncoder().encode(data);\n\n return await subtle.verify(verifyAlgorithm, cryptoKey, signatureBytes, dataBytes);\n } catch (error) {\n this.logger.error('Browser signature verification failed', error as Error);\n return false;\n }\n }\n \n private validateConfig(): void {\n if (!this.config.trustedPublicKeys || this.config.trustedPublicKeys.size === 0) {\n this.logger.warn('No trusted public keys configured - all signatures will fail');\n }\n \n if (!this.config.algorithm) {\n throw new Error('Signature algorithm must be specified');\n }\n \n if (!['RS256', 'ES256'].includes(this.config.algorithm)) {\n throw new Error(`Unsupported algorithm: ${this.config.algorithm}`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Logger } from '@objectstack/spec/contracts';\nimport type { PluginCapability, PluginPermissions as GrantedPermissions } from '@objectstack/spec/kernel';\nimport type { PluginContext } from '../types.js';\n\n/**\n * Plugin Permissions\n * Defines what actions a plugin is allowed to perform\n */\nexport interface PluginPermissions {\n canAccessService(serviceName: string): boolean;\n canTriggerHook(hookName: string): boolean;\n canReadFile(path: string): boolean;\n canWriteFile(path: string): boolean;\n canNetworkRequest(url: string): boolean;\n}\n\n/**\n * Permission Check Result\n */\nexport interface PermissionCheckResult {\n allowed: boolean;\n reason?: string;\n capability?: string;\n}\n\n/**\n * Plugin Permission Enforcer\n * \n * Implements capability-based security model to enforce:\n * 1. Service access control - which services a plugin can use\n * 2. Hook restrictions - which hooks a plugin can trigger\n * 3. File system permissions - what files a plugin can read/write\n * 4. Network permissions - what URLs a plugin can access\n * \n * Architecture:\n * - Uses capability declarations from plugin manifest\n * - Checks permissions before allowing operations\n * - Logs all permission denials for security audit\n * - Supports allowlist and denylist patterns\n * \n * Security Model:\n * - Principle of least privilege - plugins get minimal permissions\n * - Explicit declaration - all capabilities must be declared\n * - Runtime enforcement - checks happen at operation time\n * - Audit trail - all denials are logged\n * \n * Usage:\n * ```typescript\n * const enforcer = new PluginPermissionEnforcer(logger);\n * enforcer.registerPluginPermissions(pluginName, capabilities);\n * enforcer.enforceServiceAccess(pluginName, 'database');\n * ```\n */\nexport class PluginPermissionEnforcer {\n private logger: Logger;\n private permissionRegistry: Map<string, PluginPermissions> = new Map();\n private capabilityRegistry: Map<string, PluginCapability[]> = new Map();\n \n constructor(logger: Logger) {\n this.logger = logger;\n }\n \n /**\n * Register plugin capabilities and build permission set\n * \n * @param pluginName - Plugin identifier\n * @param capabilities - Array of capability declarations\n */\n registerPluginPermissions(pluginName: string, capabilities: PluginCapability[]): void {\n this.capabilityRegistry.set(pluginName, capabilities);\n \n const permissions: PluginPermissions = {\n canAccessService: (service) => this.checkServiceAccess(capabilities, service),\n canTriggerHook: (hook) => this.checkHookAccess(capabilities, hook),\n canReadFile: (path) => this.checkFileRead(capabilities, path),\n canWriteFile: (path) => this.checkFileWrite(capabilities, path),\n canNetworkRequest: (url) => this.checkNetworkAccess(capabilities, url),\n };\n \n this.permissionRegistry.set(pluginName, permissions);\n \n this.logger.info(`Permissions registered for plugin: ${pluginName}`, {\n plugin: pluginName,\n capabilityCount: capabilities.length,\n });\n }\n \n /**\n * Register the install-time GRANTED permission set for a plugin\n * (ADR-0025 F4). This is the structured `{ services, hooks, network, fs }`\n * grant that the cloud control plane persists to\n * `sys_package_installation.granted_permissions` after the user consents\n * at install (ADR §3.5 step 2). The runtime calls this when materializing\n * a third-party plugin so {@link SecurePluginContext} enforces exactly the\n * consented surface — independent of whatever the manifest *requested*.\n *\n * Prefer this over {@link registerPluginPermissions} for distributed\n * plugins: it enforces what was granted, not what was declared.\n */\n registerGrantedPermissions(pluginName: string, granted: GrantedPermissions | null | undefined): void {\n this.permissionRegistry.set(pluginName, buildPermissionsFromGrants(granted));\n this.logger.info(`Granted permissions registered for plugin: ${pluginName}`, {\n plugin: pluginName,\n services: granted?.services?.length ?? 0,\n hooks: granted?.hooks?.length ?? 0,\n network: granted?.network?.length ?? 0,\n fs: granted?.fs?.length ?? 0,\n });\n }\n\n /**\n * Enforce service access permission\n *\n * @param pluginName - Plugin requesting access\n * @param serviceName - Service to access\n * @throws Error if permission denied\n */\n enforceServiceAccess(pluginName: string, serviceName: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canAccessService(serviceName));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot access service ${serviceName}`;\n this.logger.warn(error, {\n plugin: pluginName,\n service: serviceName,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`Service access granted: ${pluginName} -> ${serviceName}`);\n }\n \n /**\n * Enforce hook trigger permission\n * \n * @param pluginName - Plugin requesting access\n * @param hookName - Hook to trigger\n * @throws Error if permission denied\n */\n enforceHookTrigger(pluginName: string, hookName: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canTriggerHook(hookName));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot trigger hook ${hookName}`;\n this.logger.warn(error, {\n plugin: pluginName,\n hook: hookName,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`Hook trigger granted: ${pluginName} -> ${hookName}`);\n }\n \n /**\n * Enforce file read permission\n * \n * @param pluginName - Plugin requesting access\n * @param path - File path to read\n * @throws Error if permission denied\n */\n enforceFileRead(pluginName: string, path: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canReadFile(path));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot read file ${path}`;\n this.logger.warn(error, {\n plugin: pluginName,\n path,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`File read granted: ${pluginName} -> ${path}`);\n }\n \n /**\n * Enforce file write permission\n * \n * @param pluginName - Plugin requesting access\n * @param path - File path to write\n * @throws Error if permission denied\n */\n enforceFileWrite(pluginName: string, path: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canWriteFile(path));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot write file ${path}`;\n this.logger.warn(error, {\n plugin: pluginName,\n path,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`File write granted: ${pluginName} -> ${path}`);\n }\n \n /**\n * Enforce network request permission\n * \n * @param pluginName - Plugin requesting access\n * @param url - URL to access\n * @throws Error if permission denied\n */\n enforceNetworkRequest(pluginName: string, url: string): void {\n const result = this.checkPermission(pluginName, (perms) => perms.canNetworkRequest(url));\n \n if (!result.allowed) {\n const error = `Permission denied: Plugin ${pluginName} cannot access URL ${url}`;\n this.logger.warn(error, {\n plugin: pluginName,\n url,\n reason: result.reason,\n });\n throw new Error(error);\n }\n \n this.logger.debug(`Network request granted: ${pluginName} -> ${url}`);\n }\n \n /**\n * Get plugin capabilities\n * \n * @param pluginName - Plugin identifier\n * @returns Array of capabilities or undefined\n */\n getPluginCapabilities(pluginName: string): PluginCapability[] | undefined {\n return this.capabilityRegistry.get(pluginName);\n }\n \n /**\n * Get plugin permissions\n * \n * @param pluginName - Plugin identifier\n * @returns Permissions object or undefined\n */\n getPluginPermissions(pluginName: string): PluginPermissions | undefined {\n return this.permissionRegistry.get(pluginName);\n }\n \n /**\n * Revoke all permissions for a plugin\n * \n * @param pluginName - Plugin identifier\n */\n revokePermissions(pluginName: string): void {\n this.permissionRegistry.delete(pluginName);\n this.capabilityRegistry.delete(pluginName);\n this.logger.warn(`Permissions revoked for plugin: ${pluginName}`);\n }\n \n // Private methods\n \n private checkPermission(\n pluginName: string,\n check: (perms: PluginPermissions) => boolean\n ): PermissionCheckResult {\n const permissions = this.permissionRegistry.get(pluginName);\n \n if (!permissions) {\n return {\n allowed: false,\n reason: 'Plugin permissions not registered',\n };\n }\n \n const allowed = check(permissions);\n \n return {\n allowed,\n reason: allowed ? undefined : 'No matching capability found',\n };\n }\n \n private checkServiceAccess(capabilities: PluginCapability[], serviceName: string): boolean {\n // Check if plugin has capability to access this service\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for wildcard service access\n if (protocolId.includes('protocol.service.all')) {\n return true;\n }\n \n // Check for specific service protocol\n if (protocolId.includes(`protocol.service.${serviceName}`)) {\n return true;\n }\n \n // Check for service category match\n const serviceCategory = serviceName.split('.')[0];\n if (protocolId.includes(`protocol.service.${serviceCategory}`)) {\n return true;\n }\n \n return false;\n });\n }\n \n private checkHookAccess(capabilities: PluginCapability[], hookName: string): boolean {\n // Check if plugin has capability to trigger this hook\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for wildcard hook access\n if (protocolId.includes('protocol.hook.all')) {\n return true;\n }\n \n // Check for specific hook protocol\n if (protocolId.includes(`protocol.hook.${hookName}`)) {\n return true;\n }\n \n // Check for hook category match\n const hookCategory = hookName.split(':')[0];\n if (protocolId.includes(`protocol.hook.${hookCategory}`)) {\n return true;\n }\n \n return false;\n });\n }\n \n private matchGlob(pattern: string, str: string): boolean {\n const regexStr = pattern\n .split('**')\n .map(segment => {\n const escaped = segment.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return escaped.replace(/\\*/g, '[^/]*');\n })\n .join('.*');\n return new RegExp(`^${regexStr}$`).test(str);\n }\n \n private checkFileRead(capabilities: PluginCapability[], path: string): boolean {\n // Check if plugin has capability to read this file\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for file read capability\n if (protocolId.includes('protocol.filesystem.read')) {\n const paths = cap.metadata?.paths;\n if (!Array.isArray(paths) || paths.length === 0) {\n return true;\n }\n return paths.some(p => typeof p === 'string' && this.matchGlob(p, path));\n }\n \n return false;\n });\n }\n \n private checkFileWrite(capabilities: PluginCapability[], path: string): boolean {\n // Check if plugin has capability to write this file\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for file write capability\n if (protocolId.includes('protocol.filesystem.write')) {\n const paths = cap.metadata?.paths;\n if (!Array.isArray(paths) || paths.length === 0) {\n return true;\n }\n return paths.some(p => typeof p === 'string' && this.matchGlob(p, path));\n }\n \n return false;\n });\n }\n \n private checkNetworkAccess(capabilities: PluginCapability[], url: string): boolean {\n // Check if plugin has capability to access this URL\n return capabilities.some(cap => {\n const protocolId = cap.protocol.id;\n \n // Check for network capability\n if (protocolId.includes('protocol.network')) {\n const hosts = cap.metadata?.hosts;\n if (!Array.isArray(hosts) || hosts.length === 0) {\n return true;\n }\n return hosts.some(h => typeof h === 'string' && this.matchGlob(h, url));\n }\n \n return false;\n });\n }\n}\n\n/**\n * Secure Plugin Context\n * Wraps PluginContext with permission checks\n */\nexport class SecurePluginContext implements PluginContext {\n constructor(\n private pluginName: string,\n private permissionEnforcer: PluginPermissionEnforcer,\n private baseContext: PluginContext\n ) {}\n \n registerService(name: string, service: any): void {\n // No permission check for service registration (handled during init)\n this.baseContext.registerService(name, service);\n }\n \n getService<T>(name: string): T {\n // Check permission before accessing service\n this.permissionEnforcer.enforceServiceAccess(this.pluginName, name);\n return this.baseContext.getService<T>(name);\n }\n \n replaceService<T>(name: string, implementation: T): void {\n // Check permission before replacing service\n this.permissionEnforcer.enforceServiceAccess(this.pluginName, name);\n this.baseContext.replaceService(name, implementation);\n }\n \n getServices(): Map<string, any> {\n // Return all services (no permission check for listing)\n return this.baseContext.getServices();\n }\n \n hook(name: string, handler: (...args: any[]) => void | Promise<void>): void {\n // No permission check for registering hooks (handled during init)\n this.baseContext.hook(name, handler);\n }\n \n async trigger(name: string, ...args: any[]): Promise<void> {\n // Check permission before triggering hook\n this.permissionEnforcer.enforceHookTrigger(this.pluginName, name);\n await this.baseContext.trigger(name, ...args);\n }\n \n get logger() {\n return this.baseContext.logger;\n }\n \n getKernel() {\n return this.baseContext.getKernel();\n }\n\n registerServiceFactory(name: string, factory: (ctx: PluginContext, scopeId?: string) => any, lifecycle?: import('../plugin-loader.js').ServiceLifecycle, dependencies?: string[]): void {\n this.baseContext.registerServiceFactory(name, factory, lifecycle, dependencies);\n }\n\n getServiceScoped<T>(name: string, scopeId: string): Promise<T> {\n return this.baseContext.getServiceScoped<T>(name, scopeId);\n }\n}\n\n/**\n * Create a plugin permission enforcer\n *\n * @param logger - Logger instance\n * @returns Plugin permission enforcer\n */\nexport function createPluginPermissionEnforcer(logger: Logger): PluginPermissionEnforcer {\n return new PluginPermissionEnforcer(logger);\n}\n\n/**\n * Glob match supporting `*` (within a path segment) and `**` (across\n * segments). A bare `*` entry matches everything.\n */\nfunction grantGlobMatch(pattern: string, value: string): boolean {\n if (pattern === '*' || pattern === '**') return true;\n const regexStr = pattern\n .split('**')\n .map((segment) => segment.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^/]*'))\n .join('.*');\n return new RegExp(`^${regexStr}$`).test(value);\n}\n\n/** Extract the host from a URL for network-grant matching; falls back to the raw value. */\nfunction hostOf(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return url;\n }\n}\n\nconst inList = (list: string[] | undefined, value: string): boolean =>\n Array.isArray(list) && list.some((p) => p === value || grantGlobMatch(p, value));\n\n/**\n * Build the runtime {@link PluginPermissions} bag from a structured\n * install-time grant set (ADR-0025 §3.2 `{ services, hooks, network, fs }`).\n *\n * Matching: an entry allows when it equals the requested value, is a glob\n * that matches it, or is the wildcard `*`. Network grants match against the\n * request URL's host (or the raw URL). `fs` governs both read and write —\n * the structured grant set does not split the two. A null/empty grant set\n * denies everything (principle of least privilege).\n */\nexport function buildPermissionsFromGrants(\n granted: GrantedPermissions | null | undefined,\n): PluginPermissions {\n const services = granted?.services;\n const hooks = granted?.hooks;\n const network = granted?.network;\n const fs = granted?.fs;\n return {\n canAccessService: (name) => inList(services, name),\n canTriggerHook: (name) => inList(hooks, name),\n canReadFile: (path) => inList(fs, path),\n canWriteFile: (path) => inList(fs, path),\n canNetworkRequest: (url) =>\n inList(network, hostOf(url)) || inList(network, url),\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n PluginPermission,\n PluginPermissionSet,\n PermissionAction,\n ResourceType\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from '../logger.js';\n\n/**\n * Permission Grant\n * Represents a granted permission at runtime\n */\nexport interface PermissionGrant {\n permissionId: string;\n pluginId: string;\n grantedAt: Date;\n grantedBy?: string;\n expiresAt?: Date;\n conditions?: Record<string, any>;\n}\n\n/**\n * Permission Check Result\n */\nexport interface PermissionCheckResult {\n allowed: boolean;\n reason?: string;\n requiredPermission?: string;\n grantedPermissions?: string[];\n}\n\n/**\n * Plugin Permission Manager\n * \n * Manages fine-grained permissions for plugin security and access control\n */\nexport class PluginPermissionManager {\n private logger: ObjectLogger;\n \n // Plugin permission definitions\n private permissionSets = new Map<string, PluginPermissionSet>();\n \n // Granted permissions (pluginId -> Set of permission IDs)\n private grants = new Map<string, Set<string>>();\n \n // Permission grant details\n private grantDetails = new Map<string, PermissionGrant>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'PermissionManager' });\n }\n\n /**\n * Register permission requirements for a plugin\n */\n registerPermissions(pluginId: string, permissionSet: PluginPermissionSet): void {\n this.permissionSets.set(pluginId, permissionSet);\n \n this.logger.info('Permissions registered for plugin', { \n pluginId,\n permissionCount: permissionSet.permissions.length\n });\n }\n\n /**\n * Grant a permission to a plugin\n */\n grantPermission(\n pluginId: string,\n permissionId: string,\n grantedBy?: string,\n expiresAt?: Date\n ): void {\n // Verify permission exists in plugin's declared permissions\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n throw new Error(`No permissions registered for plugin: ${pluginId}`);\n }\n\n const permission = permissionSet.permissions.find(p => p.id === permissionId);\n if (!permission) {\n throw new Error(`Permission ${permissionId} not declared by plugin ${pluginId}`);\n }\n\n // Create grant\n if (!this.grants.has(pluginId)) {\n this.grants.set(pluginId, new Set());\n }\n this.grants.get(pluginId)!.add(permissionId);\n\n // Store grant details\n const grantKey = `${pluginId}:${permissionId}`;\n this.grantDetails.set(grantKey, {\n permissionId,\n pluginId,\n grantedAt: new Date(),\n grantedBy,\n expiresAt,\n });\n\n this.logger.info('Permission granted', { \n pluginId, \n permissionId,\n grantedBy \n });\n }\n\n /**\n * Revoke a permission from a plugin\n */\n revokePermission(pluginId: string, permissionId: string): void {\n const grants = this.grants.get(pluginId);\n if (grants) {\n grants.delete(permissionId);\n \n const grantKey = `${pluginId}:${permissionId}`;\n this.grantDetails.delete(grantKey);\n\n this.logger.info('Permission revoked', { pluginId, permissionId });\n }\n }\n\n /**\n * Grant all permissions for a plugin\n */\n grantAllPermissions(pluginId: string, grantedBy?: string): void {\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n throw new Error(`No permissions registered for plugin: ${pluginId}`);\n }\n\n for (const permission of permissionSet.permissions) {\n this.grantPermission(pluginId, permission.id, grantedBy);\n }\n\n this.logger.info('All permissions granted', { pluginId, grantedBy });\n }\n\n /**\n * Check if a plugin has a specific permission\n */\n hasPermission(pluginId: string, permissionId: string): boolean {\n const grants = this.grants.get(pluginId);\n if (!grants) {\n return false;\n }\n\n // Check if granted\n if (!grants.has(permissionId)) {\n return false;\n }\n\n // Check expiration\n const grantKey = `${pluginId}:${permissionId}`;\n const grantDetails = this.grantDetails.get(grantKey);\n if (grantDetails?.expiresAt && grantDetails.expiresAt < new Date()) {\n this.revokePermission(pluginId, permissionId);\n return false;\n }\n\n return true;\n }\n\n /**\n * Check if plugin can perform an action on a resource\n */\n checkAccess(\n pluginId: string,\n resource: ResourceType,\n action: PermissionAction,\n resourceId?: string\n ): PermissionCheckResult {\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n return {\n allowed: false,\n reason: 'No permissions registered for plugin',\n };\n }\n\n // Find matching permissions\n const matchingPermissions = permissionSet.permissions.filter(p => {\n // Check resource type\n if (p.resource !== resource) {\n return false;\n }\n\n // Check action\n if (!p.actions.includes(action)) {\n return false;\n }\n\n // Check resource filter if specified\n if (resourceId && p.filter?.resourceIds) {\n if (!p.filter.resourceIds.includes(resourceId)) {\n return false;\n }\n }\n\n return true;\n });\n\n if (matchingPermissions.length === 0) {\n return {\n allowed: false,\n reason: `No permission found for ${action} on ${resource}`,\n };\n }\n\n // Check if any matching permission is granted\n const grantedPermissions = matchingPermissions.filter(p => \n this.hasPermission(pluginId, p.id)\n );\n\n if (grantedPermissions.length === 0) {\n return {\n allowed: false,\n reason: 'Required permissions not granted',\n requiredPermission: matchingPermissions[0].id,\n };\n }\n\n return {\n allowed: true,\n grantedPermissions: grantedPermissions.map(p => p.id),\n };\n }\n\n /**\n * Get all permissions for a plugin\n */\n getPluginPermissions(pluginId: string): PluginPermission[] {\n const permissionSet = this.permissionSets.get(pluginId);\n return permissionSet?.permissions || [];\n }\n\n /**\n * Get granted permissions for a plugin\n */\n getGrantedPermissions(pluginId: string): string[] {\n const grants = this.grants.get(pluginId);\n return grants ? Array.from(grants) : [];\n }\n\n /**\n * Get required but not granted permissions\n */\n getMissingPermissions(pluginId: string): PluginPermission[] {\n const permissionSet = this.permissionSets.get(pluginId);\n if (!permissionSet) {\n return [];\n }\n\n const granted = this.grants.get(pluginId) || new Set();\n \n return permissionSet.permissions.filter(p => \n p.required && !granted.has(p.id)\n );\n }\n\n /**\n * Check if all required permissions are granted\n */\n hasAllRequiredPermissions(pluginId: string): boolean {\n return this.getMissingPermissions(pluginId).length === 0;\n }\n\n /**\n * Get permission grant details\n */\n getGrantDetails(pluginId: string, permissionId: string): PermissionGrant | undefined {\n const grantKey = `${pluginId}:${permissionId}`;\n return this.grantDetails.get(grantKey);\n }\n\n /**\n * Validate permission against scope constraints\n */\n validatePermissionScope(\n permission: PluginPermission,\n context: {\n tenantId?: string;\n userId?: string;\n resourceId?: string;\n }\n ): boolean {\n switch (permission.scope) {\n case 'global':\n return true;\n\n case 'tenant':\n return !!context.tenantId;\n\n case 'user':\n return !!context.userId;\n\n case 'resource':\n return !!context.resourceId;\n\n case 'plugin':\n return true;\n\n default:\n return false;\n }\n }\n\n /**\n * Clear all permissions for a plugin\n */\n clearPluginPermissions(pluginId: string): void {\n this.permissionSets.delete(pluginId);\n \n const grants = this.grants.get(pluginId);\n if (grants) {\n for (const permissionId of grants) {\n const grantKey = `${pluginId}:${permissionId}`;\n this.grantDetails.delete(grantKey);\n }\n this.grants.delete(pluginId);\n }\n\n this.logger.info('All permissions cleared', { pluginId });\n }\n\n /**\n * Shutdown permission manager\n */\n shutdown(): void {\n this.permissionSets.clear();\n this.grants.clear();\n this.grantDetails.clear();\n \n this.logger.info('Permission manager shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport nodePath from 'node:path';\n\nimport type { \n SandboxConfig\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from '../logger.js';\nimport { getMemoryUsage } from '../utils/env.js';\n\n/**\n * Resource Usage Statistics\n */\nexport interface ResourceUsage {\n memory: {\n current: number;\n peak: number;\n limit?: number;\n };\n cpu: {\n current: number;\n average: number;\n limit?: number;\n };\n connections: {\n current: number;\n limit?: number;\n };\n}\n\n/**\n * Sandbox Execution Context\n * Represents an isolated execution environment for a plugin\n */\nexport interface SandboxContext {\n pluginId: string;\n config: SandboxConfig;\n startTime: Date;\n resourceUsage: ResourceUsage;\n}\n\n/**\n * Plugin Sandbox Runtime\n * \n * Provides isolated execution environments for plugins with resource limits\n * and access controls\n */\nexport class PluginSandboxRuntime {\n private static readonly MONITORING_INTERVAL_MS = 5000;\n\n private logger: ObjectLogger;\n \n // Active sandboxes (pluginId -> context)\n private sandboxes = new Map<string, SandboxContext>();\n \n // Resource monitoring intervals\n private monitoringIntervals = new Map<string, NodeJS.Timeout>();\n\n // Per-plugin resource baselines for delta tracking\n private memoryBaselines = new Map<string, number>();\n private cpuBaselines = new Map<string, { user: number; system: number }>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'SandboxRuntime' });\n }\n\n /**\n * Create a sandbox for a plugin\n */\n createSandbox(pluginId: string, config: SandboxConfig): SandboxContext {\n if (this.sandboxes.has(pluginId)) {\n throw new Error(`Sandbox already exists for plugin: ${pluginId}`);\n }\n\n const context: SandboxContext = {\n pluginId,\n config,\n startTime: new Date(),\n resourceUsage: {\n memory: { current: 0, peak: 0, limit: config.memory?.maxHeap },\n cpu: { current: 0, average: 0, limit: config.cpu?.maxCpuPercent },\n connections: { current: 0, limit: config.network?.maxConnections },\n },\n };\n\n this.sandboxes.set(pluginId, context);\n\n // Capture resource baselines for per-plugin delta tracking\n const baselineMemory = getMemoryUsage();\n this.memoryBaselines.set(pluginId, baselineMemory.heapUsed);\n this.cpuBaselines.set(pluginId, process.cpuUsage());\n\n // Start resource monitoring\n this.startResourceMonitoring(pluginId);\n\n this.logger.info('Sandbox created', { \n pluginId,\n level: config.level,\n memoryLimit: config.memory?.maxHeap,\n cpuLimit: config.cpu?.maxCpuPercent\n });\n\n return context;\n }\n\n /**\n * Destroy a sandbox\n */\n destroySandbox(pluginId: string): void {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return;\n }\n\n // Stop monitoring\n this.stopResourceMonitoring(pluginId);\n\n this.memoryBaselines.delete(pluginId);\n this.cpuBaselines.delete(pluginId);\n this.sandboxes.delete(pluginId);\n\n this.logger.info('Sandbox destroyed', { pluginId });\n }\n\n /**\n * Check if resource access is allowed\n */\n checkResourceAccess(\n pluginId: string,\n resourceType: 'file' | 'network' | 'process' | 'env',\n resourcePath?: string\n ): { allowed: boolean; reason?: string } {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return { allowed: false, reason: 'Sandbox not found' };\n }\n\n const { config } = context;\n\n switch (resourceType) {\n case 'file':\n return this.checkFileAccess(config, resourcePath);\n \n case 'network':\n return this.checkNetworkAccess(config, resourcePath);\n \n case 'process':\n return this.checkProcessAccess(config);\n \n case 'env':\n return this.checkEnvAccess(config, resourcePath);\n \n default:\n return { allowed: false, reason: 'Unknown resource type' };\n }\n }\n\n /**\n * Check file system access\n * Uses path.resolve() and path.normalize() to prevent directory traversal.\n */\n private checkFileAccess(\n config: SandboxConfig,\n filePath?: string\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.filesystem) {\n return { allowed: false, reason: 'File system access not configured' };\n }\n\n // If no path specified, check general access\n if (!filePath) {\n return { allowed: config.filesystem.mode !== 'none' };\n }\n\n // Check allowed paths using proper path resolution to prevent directory traversal\n const allowedPaths = config.filesystem.allowedPaths || [];\n const resolvedPath = nodePath.normalize(nodePath.resolve(filePath));\n const isAllowed = allowedPaths.some(allowed => {\n const resolvedAllowed = nodePath.normalize(nodePath.resolve(allowed));\n return resolvedPath.startsWith(resolvedAllowed);\n });\n\n if (allowedPaths.length > 0 && !isAllowed) {\n return { \n allowed: false, \n reason: `Path not in allowed list: ${filePath}` \n };\n }\n\n // Check denied paths using proper path resolution\n const deniedPaths = config.filesystem.deniedPaths || [];\n const isDenied = deniedPaths.some(denied => {\n const resolvedDenied = nodePath.normalize(nodePath.resolve(denied));\n return resolvedPath.startsWith(resolvedDenied);\n });\n\n if (isDenied) {\n return { \n allowed: false, \n reason: `Path is explicitly denied: ${filePath}` \n };\n }\n\n return { allowed: true };\n }\n\n /**\n * Check network access\n * Uses URL parsing to properly validate hostnames.\n */\n private checkNetworkAccess(\n config: SandboxConfig,\n url?: string\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.network) {\n return { allowed: false, reason: 'Network access not configured' };\n }\n\n // Check if network access is enabled\n if (config.network.mode === 'none') {\n return { allowed: false, reason: 'Network access disabled' };\n }\n\n // If no URL specified, check general access\n if (!url) {\n return { allowed: (config.network.mode as string) !== 'none' };\n }\n\n // Parse URL and check hostname against allowed/denied hosts\n let parsedHostname: string;\n try {\n parsedHostname = new URL(url).hostname;\n } catch {\n return { allowed: false, reason: `Invalid URL: ${url}` };\n }\n\n // Check allowed hosts\n const allowedHosts = config.network.allowedHosts || [];\n if (allowedHosts.length > 0) {\n const isAllowed = allowedHosts.some(host => {\n return parsedHostname === host;\n });\n\n if (!isAllowed) {\n return { \n allowed: false, \n reason: `Host not in allowed list: ${url}` \n };\n }\n }\n\n // Check denied hosts\n const deniedHosts = config.network.deniedHosts || [];\n const isDenied = deniedHosts.some(host => {\n return parsedHostname === host;\n });\n\n if (isDenied) {\n return { \n allowed: false, \n reason: `Host is blocked: ${url}` \n };\n }\n\n return { allowed: true };\n }\n\n /**\n * Check process spawning access\n */\n private checkProcessAccess(\n config: SandboxConfig\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.process) {\n return { allowed: false, reason: 'Process access not configured' };\n }\n\n if (!config.process.allowSpawn) {\n return { allowed: false, reason: 'Process spawning not allowed' };\n }\n\n return { allowed: true };\n }\n\n /**\n * Check environment variable access\n */\n private checkEnvAccess(\n config: SandboxConfig,\n varName?: string\n ): { allowed: boolean; reason?: string } {\n if (config.level === 'none') {\n return { allowed: true };\n }\n\n if (!config.process) {\n return { allowed: false, reason: 'Environment access not configured' };\n }\n\n // If no variable specified, check general access\n if (!varName) {\n return { allowed: true };\n }\n\n // For now, allow all env access if process is configured\n // In a real implementation, would check specific allowed vars\n return { allowed: true };\n }\n\n /**\n * Check resource limits\n */\n checkResourceLimits(pluginId: string): { \n withinLimits: boolean; \n violations: string[] \n } {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return { withinLimits: true, violations: [] };\n }\n\n const violations: string[] = [];\n const { resourceUsage, config } = context;\n\n // Check memory limit\n if (config.memory?.maxHeap && \n resourceUsage.memory.current > config.memory.maxHeap) {\n violations.push(`Memory limit exceeded: ${resourceUsage.memory.current} > ${config.memory.maxHeap}`);\n }\n\n // Check CPU limit (would need runtime config)\n if (config.runtime?.resourceLimits?.maxCpu && \n resourceUsage.cpu.current > config.runtime.resourceLimits.maxCpu) {\n violations.push(`CPU limit exceeded: ${resourceUsage.cpu.current}% > ${config.runtime.resourceLimits.maxCpu}%`);\n }\n\n // Check connection limit\n if (config.network?.maxConnections && \n resourceUsage.connections.current > config.network.maxConnections) {\n violations.push(`Connection limit exceeded: ${resourceUsage.connections.current} > ${config.network.maxConnections}`);\n }\n\n return {\n withinLimits: violations.length === 0,\n violations,\n };\n }\n\n /**\n * Get resource usage for a plugin\n */\n getResourceUsage(pluginId: string): ResourceUsage | undefined {\n const context = this.sandboxes.get(pluginId);\n return context?.resourceUsage;\n }\n\n /**\n * Start monitoring resource usage\n */\n private startResourceMonitoring(pluginId: string): void {\n // Monitor at the configured interval\n const interval = setInterval(() => {\n this.updateResourceUsage(pluginId);\n }, PluginSandboxRuntime.MONITORING_INTERVAL_MS);\n\n this.monitoringIntervals.set(pluginId, interval);\n }\n\n /**\n * Stop monitoring resource usage\n */\n private stopResourceMonitoring(pluginId: string): void {\n const interval = this.monitoringIntervals.get(pluginId);\n if (interval) {\n clearInterval(interval);\n this.monitoringIntervals.delete(pluginId);\n }\n }\n\n /**\n * Update resource usage statistics\n * \n * Tracks per-plugin memory and CPU usage using delta from baseline\n * captured at sandbox creation time. This is an approximation since\n * true per-plugin isolation isn't possible in a single Node.js process.\n */\n private updateResourceUsage(pluginId: string): void {\n const context = this.sandboxes.get(pluginId);\n if (!context) {\n return;\n }\n\n // In a real implementation, this would collect actual metrics\n // For now, this is a placeholder structure\n \n // Update memory usage using delta from baseline for per-plugin approximation\n const memoryUsage = getMemoryUsage();\n const memoryBaseline = this.memoryBaselines.get(pluginId) ?? 0;\n const memoryDelta = Math.max(0, memoryUsage.heapUsed - memoryBaseline);\n context.resourceUsage.memory.current = memoryDelta;\n context.resourceUsage.memory.peak = Math.max(\n context.resourceUsage.memory.peak,\n memoryDelta\n );\n\n // Update CPU usage using delta from baseline for per-plugin approximation\n const cpuBaseline = this.cpuBaselines.get(pluginId) ?? { user: 0, system: 0 };\n const cpuCurrent = process.cpuUsage();\n const cpuDeltaUser = cpuCurrent.user - cpuBaseline.user;\n const cpuDeltaSystem = cpuCurrent.system - cpuBaseline.system;\n // Convert microseconds to a percentage approximation over the monitoring interval\n const totalCpuMicros = cpuDeltaUser + cpuDeltaSystem;\n const intervalMicros = PluginSandboxRuntime.MONITORING_INTERVAL_MS * 1000;\n context.resourceUsage.cpu.current = (totalCpuMicros / intervalMicros) * 100;\n // Update baseline for next interval\n this.cpuBaselines.set(pluginId, cpuCurrent);\n\n // Check for violations\n const { withinLimits, violations } = this.checkResourceLimits(pluginId);\n if (!withinLimits) {\n this.logger.warn('Resource limit violations detected', { \n pluginId, \n violations \n });\n }\n }\n\n /**\n * Get all active sandboxes\n */\n getAllSandboxes(): Map<string, SandboxContext> {\n return new Map(this.sandboxes);\n }\n\n /**\n * Shutdown sandbox runtime\n */\n shutdown(): void {\n // Stop all monitoring\n for (const pluginId of this.monitoringIntervals.keys()) {\n this.stopResourceMonitoring(pluginId);\n }\n\n this.sandboxes.clear();\n this.memoryBaselines.clear();\n this.cpuBaselines.clear();\n \n this.logger.info('Sandbox runtime shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n KernelSecurityVulnerability,\n KernelSecurityScanResult\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from '../logger.js';\n\n/**\n * Scan Target\n */\nexport interface ScanTarget {\n pluginId: string;\n version: string;\n files?: string[];\n dependencies?: Record<string, string>;\n}\n\n/**\n * Security Issue\n */\nexport interface SecurityIssue {\n id: string;\n severity: 'critical' | 'high' | 'medium' | 'low' | 'info';\n category: 'vulnerability' | 'malware' | 'license' | 'code-quality' | 'configuration';\n title: string;\n description: string;\n location?: {\n file?: string;\n line?: number;\n column?: number;\n };\n remediation?: string;\n cve?: string;\n cvss?: number;\n}\n\n/**\n * Plugin Security Scanner\n * \n * Scans plugins for security vulnerabilities, malware, and license issues\n */\nexport class PluginSecurityScanner {\n private logger: ObjectLogger;\n \n // Known vulnerabilities database (CVE cache)\n private vulnerabilityDb = new Map<string, KernelSecurityVulnerability>();\n \n // Scan results cache\n private scanResults = new Map<string, KernelSecurityScanResult>();\n\n private passThreshold: number = 70;\n\n constructor(logger: ObjectLogger, config?: { passThreshold?: number }) {\n this.logger = logger.child({ component: 'SecurityScanner' });\n if (config?.passThreshold !== undefined) {\n this.passThreshold = config.passThreshold;\n }\n }\n\n /**\n * Perform a comprehensive security scan on a plugin\n */\n async scan(target: ScanTarget): Promise<KernelSecurityScanResult> {\n this.logger.info('Starting security scan', { \n pluginId: target.pluginId,\n version: target.version \n });\n\n const issues: SecurityIssue[] = [];\n\n try {\n // 1. Scan for code vulnerabilities\n const codeIssues = await this.scanCode(target);\n issues.push(...codeIssues);\n\n // 2. Scan dependencies for known vulnerabilities\n const depIssues = await this.scanDependencies(target);\n issues.push(...depIssues);\n\n // 3. Scan for malware patterns\n const malwareIssues = await this.scanMalware(target);\n issues.push(...malwareIssues);\n\n // 4. Check license compliance\n const licenseIssues = await this.scanLicenses(target);\n issues.push(...licenseIssues);\n\n // 5. Check configuration security\n const configIssues = await this.scanConfiguration(target);\n issues.push(...configIssues);\n\n // Calculate security score (0-100, higher is better)\n const score = this.calculateSecurityScore(issues);\n\n const result: KernelSecurityScanResult = {\n timestamp: new Date().toISOString(),\n scanner: { name: 'ObjectStack Security Scanner', version: '1.0.0' },\n status: score >= this.passThreshold ? 'passed' : 'failed',\n vulnerabilities: issues.map(issue => ({\n id: issue.id,\n severity: issue.severity,\n category: issue.category,\n title: issue.title,\n description: issue.description,\n location: issue.location ? `${issue.location.file}:${issue.location.line}` : undefined,\n remediation: issue.remediation,\n affectedVersions: [],\n exploitAvailable: false,\n patchAvailable: false,\n })),\n summary: {\n totalVulnerabilities: issues.length,\n criticalCount: issues.filter(i => i.severity === 'critical').length,\n highCount: issues.filter(i => i.severity === 'high').length,\n mediumCount: issues.filter(i => i.severity === 'medium').length,\n lowCount: issues.filter(i => i.severity === 'low').length,\n infoCount: issues.filter(i => i.severity === 'info').length,\n },\n };\n\n this.scanResults.set(`${target.pluginId}:${target.version}`, result);\n\n this.logger.info('Security scan complete', { \n pluginId: target.pluginId,\n score,\n status: result.status,\n summary: result.summary\n });\n\n return result;\n } catch (error) {\n this.logger.error('Security scan failed', { \n pluginId: target.pluginId, \n error \n });\n\n throw error;\n }\n }\n\n /**\n * Scan code for vulnerabilities\n */\n private async scanCode(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n // In a real implementation, this would:\n // - Parse code with AST (e.g., using @typescript-eslint/parser)\n // - Check for dangerous patterns (eval, Function constructor, etc.)\n // - Check for XSS vulnerabilities\n // - Check for SQL injection patterns\n // - Check for insecure crypto usage\n // - Check for path traversal vulnerabilities\n\n this.logger.debug('Code scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Scan dependencies for known vulnerabilities\n */\n private async scanDependencies(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n if (!target.dependencies) {\n return issues;\n }\n\n // In a real implementation, this would:\n // - Query npm audit API\n // - Check GitHub Advisory Database\n // - Check Snyk vulnerability database\n // - Check OSV (Open Source Vulnerabilities)\n\n for (const [depName, version] of Object.entries(target.dependencies)) {\n const vulnKey = `${depName}@${version}`;\n const vulnerability = this.vulnerabilityDb.get(vulnKey);\n\n if (vulnerability) {\n issues.push({\n id: `vuln-${vulnerability.cve || depName}`,\n severity: vulnerability.severity,\n category: 'vulnerability',\n title: `Vulnerable dependency: ${depName}`,\n description: `${depName}@${version} has known security vulnerabilities`,\n remediation: vulnerability.fixedIn \n ? `Upgrade to ${vulnerability.fixedIn.join(' or ')}`\n : 'No fix available',\n cve: vulnerability.cve,\n });\n }\n }\n\n this.logger.debug('Dependency scan complete', { \n pluginId: target.pluginId,\n dependencies: Object.keys(target.dependencies).length,\n vulnerabilities: issues.length \n });\n\n return issues;\n }\n\n /**\n * Scan for malware patterns\n */\n private async scanMalware(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n // In a real implementation, this would:\n // - Check for obfuscated code\n // - Check for suspicious network activity patterns\n // - Check for crypto mining patterns\n // - Check for data exfiltration patterns\n // - Use ML-based malware detection\n // - Check file hashes against known malware databases\n\n this.logger.debug('Malware scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Check license compliance\n */\n private async scanLicenses(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n if (!target.dependencies) {\n return issues;\n }\n\n // In a real implementation, this would:\n // - Check license compatibility\n // - Detect GPL contamination\n // - Flag proprietary dependencies\n // - Check for missing licenses\n // - Verify SPDX identifiers\n\n this.logger.debug('License scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Check configuration security\n */\n private async scanConfiguration(target: ScanTarget): Promise<SecurityIssue[]> {\n const issues: SecurityIssue[] = [];\n\n // In a real implementation, this would:\n // - Check for hardcoded secrets\n // - Check for weak permissions\n // - Check for insecure defaults\n // - Check for missing security headers\n // - Check CSP policies\n\n this.logger.debug('Configuration scan complete', { \n pluginId: target.pluginId,\n issuesFound: issues.length \n });\n\n return issues;\n }\n\n /**\n * Calculate security score based on issues\n */\n private calculateSecurityScore(issues: SecurityIssue[]): number {\n // Start with perfect score\n let score = 100;\n\n // Deduct points based on severity\n for (const issue of issues) {\n switch (issue.severity) {\n case 'critical':\n score -= 20;\n break;\n case 'high':\n score -= 10;\n break;\n case 'medium':\n score -= 5;\n break;\n case 'low':\n score -= 2;\n break;\n case 'info':\n score -= 0;\n break;\n }\n }\n\n // Ensure score doesn't go below 0\n return Math.max(0, score);\n }\n\n /**\n * Add a vulnerability to the database\n */\n addVulnerability(\n packageName: string,\n version: string,\n vulnerability: KernelSecurityVulnerability\n ): void {\n const key = `${packageName}@${version}`;\n this.vulnerabilityDb.set(key, vulnerability);\n \n this.logger.debug('Vulnerability added to database', { \n package: packageName, \n version,\n cve: vulnerability.cve \n });\n }\n\n /**\n * Get scan result from cache\n */\n getScanResult(pluginId: string, version: string): KernelSecurityScanResult | undefined {\n return this.scanResults.get(`${pluginId}:${version}`);\n }\n\n /**\n * Clear scan results cache\n */\n clearCache(): void {\n this.scanResults.clear();\n this.logger.debug('Scan results cache cleared');\n }\n\n /**\n * Update vulnerability database from external source\n */\n async updateVulnerabilityDatabase(): Promise<void> {\n this.logger.info('Updating vulnerability database');\n\n // In a real implementation, this would:\n // - Fetch from GitHub Advisory Database\n // - Fetch from npm audit\n // - Fetch from NVD (National Vulnerability Database)\n // - Parse and cache vulnerability data\n\n this.logger.info('Vulnerability database updated', { \n entries: this.vulnerabilityDb.size \n });\n }\n\n /**\n * Shutdown security scanner\n */\n shutdown(): void {\n this.vulnerabilityDb.clear();\n this.scanResults.clear();\n \n this.logger.info('Security scanner shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * api-key — hand-rolled API-key primitives + verifier for `sys_api_key`.\n *\n * better-auth 1.6.x ships no apiKey plugin, so ObjectStack owns the full\n * lifecycle: generation, at-rest hashing, header extraction, validation, and\n * the verify-time principal lookup. This is the SINGLE shared source of truth\n * used by BOTH inbound surfaces — the runtime dispatcher / MCP path\n * (`resolveExecutionContext`) and the REST data API (`@objectstack/rest`) — so\n * the two can never drift on how a key authenticates. It lives in\n * `@objectstack/core` (server-side; both `runtime` and `rest` depend on it,\n * and `core` depends on neither, so there is no cycle).\n *\n * SECURITY (zero-tolerance):\n * - The raw key is returned EXACTLY ONCE, by {@link generateApiKey}. It is\n * never persisted; only `sha256(raw)` (hex) is stored in `sys_api_key.key`.\n * - The raw key and its hash must never enter logs, HTTP responses, error\n * messages, commit messages or comments.\n * - Validation is fail-closed: anything ambiguous (missing, revoked, expired,\n * malformed) resolves to \"no principal\", never to an elevated one.\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\n\n/** Default visible prefix for generated keys (helps users identify a key). */\nexport const API_KEY_PREFIX = 'osk_';\n\n/** Bytes of entropy in the secret portion of a generated key (256 bits). */\nconst API_KEY_ENTROPY_BYTES = 32;\n\n/** Length of the human-visible prefix stored in `sys_api_key.prefix`. */\nconst VISIBLE_PREFIX_LEN = 12;\n\n/**\n * Derive the at-rest hash for an API key. Inbound keys are hashed the same way\n * before the DB lookup. Because the lookup matches an indexed, high-entropy\n * hash exactly, this doubles as a constant-effort comparison: an attacker\n * cannot recover the raw key by probing for partial matches.\n */\nexport function hashApiKey(raw: string): string {\n return createHash('sha256').update(raw, 'utf8').digest('hex');\n}\n\n/** Result of {@link generateApiKey}. `raw` is shown to the user only once. */\nexport interface GeneratedApiKey {\n /** The full secret to hand to the client. NEVER persist this. */\n raw: string;\n /** `sha256(raw)` hex — store this in `sys_api_key.key`. */\n hash: string;\n /** Short non-secret prefix for display/identification (`sys_api_key.prefix`). */\n prefix: string;\n}\n\n/**\n * Generate a fresh API key. Returns the raw secret (caller must surface it to\n * the user exactly once and then discard it), its at-rest hash, and a short\n * non-secret prefix for display.\n */\nexport function generateApiKey(prefix: string = API_KEY_PREFIX): GeneratedApiKey {\n // base64url so the token is URL/header-safe with no padding.\n const secret = randomBytes(API_KEY_ENTROPY_BYTES).toString('base64url');\n const raw = `${prefix}${secret}`;\n return {\n raw,\n hash: hashApiKey(raw),\n prefix: raw.slice(0, VISIBLE_PREFIX_LEN),\n };\n}\n\n/**\n * Extract an API key from request headers. Accepts, in order:\n * - `X-API-Key: <token>`\n * - `Authorization: ApiKey <token>` (case-insensitive scheme)\n * - `Authorization: Bearer <token>` ONLY when `<token>` carries the ObjectStack\n * api-key prefix (`osk_`). Remote MCP clients (Claude Desktop / Cursor /\n * Claude Code) authenticate to `/api/v1/mcp` with the key as a Bearer per the\n * MCP spec, so rejecting Bearer outright made every standard MCP client fail.\n * A better-auth *session* token never starts with `osk_`, so a session Bearer\n * still falls through to the session path — this can't shadow it.\n */\nexport function extractApiKey(headers: any): string | undefined {\n const x = readHeader(headers, 'x-api-key');\n if (x && x.trim()) return x.trim();\n const auth = readHeader(headers, 'authorization');\n if (!auth) return undefined;\n const apiKeyScheme = auth.match(/^ApiKey\\s+(\\S.*)$/i);\n if (apiKeyScheme?.[1]?.trim()) return apiKeyScheme[1].trim();\n // Bearer is accepted only for prefixed api-keys (never for session tokens).\n const bearer = auth.match(/^Bearer\\s+(\\S.*)$/i)?.[1]?.trim();\n if (bearer && bearer.startsWith(API_KEY_PREFIX)) return bearer;\n return undefined;\n}\n\n/** Parse a `scopes` value that may be a JSON-string textarea or a real array. */\nexport function parseScopes(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.filter((s): s is string => typeof s === 'string' && s.length > 0);\n }\n if (typeof value === 'string' && value.trim()) {\n const parsed = safeJsonParse<unknown>(value, []);\n if (Array.isArray(parsed)) {\n return parsed.filter((s): s is string => typeof s === 'string' && s.length > 0);\n }\n }\n return [];\n}\n\n/** Return true when an expiry timestamp is in the past (i.e. the key is dead). */\nexport function isExpired(value: unknown, nowMs: number): boolean {\n if (value == null) return false;\n let ms: number;\n if (typeof value === 'number') {\n // Heuristic: seconds vs milliseconds epoch.\n ms = value < 1e12 ? value * 1000 : value;\n } else if (value instanceof Date) {\n ms = value.getTime();\n } else if (typeof value === 'string') {\n ms = Date.parse(value);\n } else {\n return false;\n }\n if (Number.isNaN(ms)) return false;\n return ms <= nowMs;\n}\n\n/** The principal resolved from a valid `sys_api_key`. */\nexport interface ApiKeyPrincipal {\n userId: string;\n tenantId?: string;\n scopes: string[];\n}\n\n/**\n * Verify an inbound API key against `sys_api_key` and resolve its principal.\n * This is the ONE verify path shared by the dispatcher/MCP and REST surfaces.\n *\n * Fail-closed: returns `undefined` for a missing key, an unusable data engine,\n * a lookup error, or a key that is unknown / revoked / expired / owner-less.\n *\n * @param ql A data engine with `find(object, { where, limit, context })`.\n * @param headers Request headers (Web `Headers` or a plain object).\n * @param nowMs Clock for expiry checks (injectable for tests).\n */\nexport async function resolveApiKeyPrincipal(\n ql: any,\n headers: any,\n nowMs: number = Date.now(),\n): Promise<ApiKeyPrincipal | undefined> {\n const apiKey = extractApiKey(headers);\n if (!apiKey) return undefined;\n if (!ql || typeof ql.find !== 'function') return undefined;\n\n // Match by the indexed at-rest hash only — never query by the raw key.\n let rows: any;\n try {\n rows = await ql.find('sys_api_key', {\n where: { key: hashApiKey(apiKey), revoked: false },\n limit: 1,\n context: { isSystem: true },\n });\n } catch {\n return undefined;\n }\n if (rows && (rows as any).value) rows = (rows as any).value;\n const row = Array.isArray(rows) ? rows[0] : undefined;\n if (!row || row.revoked === true) return undefined;\n\n const expiresAt = row.expires_at ?? row.expiresAt;\n if (isExpired(expiresAt, nowMs)) return undefined;\n\n const userId = row.user_id ?? row.userId;\n if (!userId || typeof userId !== 'string') return undefined;\n\n return {\n userId,\n tenantId: row.organization_id ?? row.organizationId ?? undefined,\n scopes: parseScopes(row.scopes),\n };\n}\n\nfunction readHeader(headers: any, name: string): string | undefined {\n if (!headers) return undefined;\n const lower = name.toLowerCase();\n if (typeof headers.get === 'function') {\n const v = headers.get(name) ?? headers.get(lower);\n return v == null ? undefined : String(v);\n }\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === lower) {\n const v = headers[key];\n return Array.isArray(v) ? v[0] : v == null ? undefined : String(v);\n }\n }\n return undefined;\n}\n\nfunction safeJsonParse<T>(s: string, fallback: T): T {\n try {\n return JSON.parse(s) as T;\n } catch {\n return fallback;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * resolveAuthzContext — the SINGLE source of truth for resolving an inbound\n * request's identity + authorization context (positions, permissions, RLS scoping).\n *\n * Every HTTP entry point (REST server, runtime dispatcher, MCP, any future\n * transport) MUST resolve authorization through this function — never by\n * re-reading `sys_member` / `sys_user_position` / `sys_*_permission_set` itself.\n *\n * Why this exists: authorization resolution used to be DUPLICATED across the\n * REST server (`@objectstack/rest`) and the runtime dispatcher\n * (`@objectstack/runtime`). On a security path, duplicated logic drifts and the\n * drift is silent: the REST copy had quietly omitted `sys_user_position` (so custom\n * roles granted via the ADR-0057 D4 platform-RBAC path didn't apply over REST),\n * `sys_position_permission_set`, `mapMembershipRole` normalization, the\n * platform-admin derivation, and the `ai_seat` synthesis. The API-key half was\n * already shared here (`resolveApiKeyPrincipal`); this completes the extraction\n * by bringing session + role/permission aggregation home too. There is now ONE\n * implementation; both entry points are thin adapters that supply `ql` /\n * `getSession` their own way and delegate here.\n *\n * Fail-closed: every read is defensive. Missing services / tables yield a\n * partial context (even `{ positions: [], permissions: [] }`) — enforcement is the\n * SecurityPlugin's job, never this resolver's.\n */\n\nimport {\n mapMembershipRole,\n BUILTIN_IDENTITY_PLATFORM_ADMIN,\n ADMIN_FULL_ACCESS,\n ORGANIZATION_ADMIN,\n} from '@objectstack/spec';\nimport type { AuthzPosture } from '@objectstack/spec/security';\n\nimport { resolveApiKeyPrincipal } from './api-key.js';\nimport { isGrantActive } from './grant-validity.js';\nimport { derivePosture } from './posture-ladder.js';\n\n/** The transport-agnostic authorization envelope produced from a request. */\nexport interface ResolvedAuthzContext {\n userId?: string;\n tenantId?: string;\n email?: string;\n accessToken?: string;\n positions: string[];\n permissions: string[];\n systemPermissions: string[];\n tabPermissions?: Record<string, 'visible' | 'hidden' | 'default_on' | 'default_off'>;\n /** Fellow-org user IDs for RLS scoping of identity tables (`id IN (...)`). */\n org_user_ids: string[];\n /**\n * [ADR-0095 D2/D3] The monotonic posture rung this principal resolves to,\n * DERIVED once here from held capability grants (never a better-auth role):\n * `PLATFORM_ADMIN` (unscoped `admin_full_access`) > `TENANT_ADMIN`\n * (`organization_admin`) > `MEMBER` (the authenticated floor). `EXTERNAL` is\n * defined/test-locked but never resolved yet (no external principal type —\n * see `posture-ladder.ts`). Present only for an authenticated principal;\n * anonymous requests carry no rung.\n */\n posture?: AuthzPosture;\n}\n\nexport interface ResolveAuthzInput {\n /** Data engine (ObjectQL) exposing `find(object, { where, limit, context })`. */\n ql: any;\n /** Inbound request headers (Web `Headers` or a plain record). */\n headers: any;\n /**\n * Resolve a better-auth session from `headers`, returning `{ user?, session? }`\n * (or undefined). Optional — when omitted or throwing, only the API-key path\n * runs and anonymous requests resolve to an empty context.\n */\n getSession?: (headers: any) => Promise<any> | any;\n /** Clock injection for API-key expiry (tests). */\n nowMs?: number;\n}\n\nfunction safeJsonParse<T>(s: string, fallback: T): T {\n try { return JSON.parse(s) as T; } catch { return fallback; }\n}\n\nasync function tryFind(ql: any, object: string, where: any, limit = 100): Promise<any[]> {\n if (!ql || typeof ql.find !== 'function') return [];\n try {\n let rows = await ql.find(object, { where, limit, context: { isSystem: true } } as any);\n if (rows && (rows as any).value) rows = (rows as any).value;\n return Array.isArray(rows) ? rows : [];\n } catch {\n return [];\n }\n}\n\n/**\n * Resolve the authorization context for an inbound request. Always resolves —\n * never throws. Anonymous requests yield `{ positions: [], permissions: [], ... }`.\n */\nexport async function resolveAuthzContext(input: ResolveAuthzInput): Promise<ResolvedAuthzContext> {\n const { ql, headers } = input;\n const ctx: ResolvedAuthzContext = {\n positions: [],\n permissions: [],\n systemPermissions: [],\n org_user_ids: [],\n };\n\n let userId: string | undefined;\n let tenantId: string | undefined;\n\n // 1. API key (explicit opt-in via header) takes precedence over session.\n const keyPrincipal = await resolveApiKeyPrincipal(ql, headers, input.nowMs);\n if (keyPrincipal) {\n userId = keyPrincipal.userId;\n tenantId = keyPrincipal.tenantId;\n for (const scope of keyPrincipal.scopes) {\n if (!ctx.permissions.includes(scope)) ctx.permissions.push(scope);\n }\n }\n\n // 2. Session / Bearer path — fall back when no API key resolved a user.\n if (!userId && typeof input.getSession === 'function') {\n try {\n const sessionData = await input.getSession(headers);\n userId = sessionData?.user?.id ?? sessionData?.session?.userId;\n tenantId = tenantId ?? sessionData?.session?.activeOrganizationId;\n ctx.accessToken = sessionData?.session?.token ?? ctx.accessToken;\n if (sessionData?.user?.email) ctx.email = String(sessionData.user.email);\n } catch {\n // no auth configured / bad session → anonymous\n }\n }\n\n if (!userId) return ctx;\n ctx.userId = userId;\n if (tenantId) ctx.tenantId = tenantId;\n if (!ql || typeof ql.find !== 'function') return ctx;\n\n // sys_user is needed for both the `current_user.email` fallback (API-key auth,\n // where the session didn't supply an email) and the ai_seat synthesis below.\n // Read the row at most once per resolution — the two reads were a duplicate\n // query on the API-key path.\n let userRowLoaded = false;\n let userRow: any;\n const getUserRow = async (): Promise<any> => {\n if (!userRowLoaded) {\n userRowLoaded = true;\n const rows = await tryFind(ql, 'sys_user', { id: userId }, 1);\n userRow = rows[0];\n }\n return userRow;\n };\n\n // Resolve the caller's unique email for `current_user.email` RLS owner\n // policies when the session path didn't supply it (e.g. API-key auth).\n if (!ctx.email) {\n const u = await getUserRow();\n if (u?.email) ctx.email = String(u.email);\n }\n\n // 3. Organization-administration roles via sys_member (better-auth), normalized\n // to the canonical built-in names (owner→org_owner, admin→org_admin, …).\n // [ADR-0095 D3] This is the ONE PROVISIONING boundary where a better-auth\n // role is read: it is projected into `positions` here, and separately drives\n // the `organization_admin` capability grant (auto-org-admin-grant.ts). No\n // enforcement code path reads the raw role — posture/adjudication run off\n // the resulting capability grants, so the #2836 dual-track cannot recur.\n const memberWhere: any = tenantId\n ? { user_id: userId, organization_id: tenantId }\n : { user_id: userId };\n const members = await tryFind(ql, 'sys_member', memberWhere, 50);\n for (const m of members) {\n if (m.role && typeof m.role === 'string') {\n for (const raw of m.role.split(',').map((s: string) => s.trim()).filter(Boolean)) {\n const r = mapMembershipRole(raw);\n if (!ctx.positions.includes(r)) ctx.positions.push(r);\n }\n }\n }\n\n // Single clock for every validity-window check in this resolution\n // (ADR-0091 D2 — a grant row outside [valid_from, valid_until) does not\n // resolve, fail-closed, with no background job involved).\n const nowMs = input.nowMs ?? Date.now();\n\n // 4. [ADR-0057 D4] Platform-owned RBAC role assignments (sys_user_position) — the\n // source of truth for custom roles, decoupled from sys_member.role.\n // `organization_id = null` = global (cross-tenant); else match active org.\n const userPositionRows = await tryFind(ql, 'sys_user_position', { user_id: userId }, 200);\n for (const ur of userPositionRows) {\n const org = ur.organization_id ?? null;\n if (org && tenantId && org !== tenantId) continue;\n if (!isGrantActive(ur, nowMs)) continue;\n const r = ur.position;\n if (typeof r === 'string' && r && !ctx.positions.includes(r)) ctx.positions.push(r);\n }\n\n // 5. Fellow-org user IDs so RLS can scope identity tables to collaborators.\n if (tenantId) {\n const orgMembers = await tryFind(ql, 'sys_member', { organization_id: tenantId }, 1000);\n const ids = new Set<string>(\n orgMembers\n .map((m) => m.user_id ?? m.userId)\n .filter((v): v is string => typeof v === 'string' && v.length > 0),\n );\n ids.add(userId);\n ctx.org_user_ids = Array.from(ids);\n } else {\n ctx.org_user_ids = [userId];\n }\n\n // 6. Permission sets — user-scoped grants (null org = global, else active org).\n // Rows outside their validity window are dropped BEFORE any derivation, so\n // an expired admin_full_access grant cannot yield platform_admin either.\n const upsRowsAll = await tryFind(ql, 'sys_user_permission_set', { user_id: userId }, 100);\n const upsRows = upsRowsAll.filter((r) => isGrantActive(r, nowMs));\n const psIds = new Set<string>(\n upsRows\n .filter((r) => {\n const org = (r.organization_id ?? r.organizationId) ?? null;\n return !(org && tenantId && org !== tenantId);\n })\n .map((r) => r.permission_set_id ?? r.permissionSetId)\n .filter(Boolean),\n );\n // platform_admin (ADR-0068 D2) is DERIVED from an UNSCOPED admin_full_access\n // USER grant — the single source of truth (no trusted stored boolean).\n const unscopedUserPsIds = new Set<string>(\n upsRows\n .filter((r) => ((r.organization_id ?? r.organizationId) ?? null) === null)\n .map((r) => r.permission_set_id ?? r.permissionSetId)\n .filter(Boolean),\n );\n let hasPlatformAdminGrant = false;\n\n // 5b. [ADR-0090 D5] Audience anchor: every AUTHENTICATED member implicitly\n // holds the built-in `everyone` position, so sets bound to it resolve\n // below exactly like any other position-bound grant — ADDITIVE, with no\n // \"only when the user has nothing else\" cliff.\n if (!ctx.positions.includes('everyone')) ctx.positions.push('everyone');\n\n // 6a. Position-bound permission sets (sys_position_permission_set): a position\n // carries its permission sets.\n if (ctx.positions.length > 0) {\n const positionRows = await tryFind(ql, 'sys_position', { name: { $in: ctx.positions } }, 100);\n const positionIds = positionRows.map((r) => r.id).filter(Boolean);\n if (positionIds.length > 0) {\n const rpsRows = await tryFind(ql, 'sys_position_permission_set', { position_id: { $in: positionIds } }, 500);\n for (const r of rpsRows) {\n const id = r.permission_set_id ?? r.permissionSetId;\n if (id) psIds.add(id);\n }\n }\n }\n\n // 6b. Resolve permission-set details (names → ctx.permissions; system_permissions;\n // tab_permissions merged by highest visibility).\n if (psIds.size > 0) {\n const psRows = await tryFind(ql, 'sys_permission_set', { id: { $in: Array.from(psIds) } }, 500);\n const tabRank: Record<string, number> = { hidden: 0, default_off: 1, default_on: 2, visible: 3 };\n const mergedTabs: Record<string, 'visible' | 'hidden' | 'default_on' | 'default_off'> = {};\n for (const ps of psRows) {\n if (ps.name && !ctx.permissions.includes(ps.name)) ctx.permissions.push(ps.name);\n if (ps.name === ADMIN_FULL_ACCESS && unscopedUserPsIds.has(ps.id)) hasPlatformAdminGrant = true;\n const sysPerms = typeof ps.system_permissions === 'string'\n ? safeJsonParse(ps.system_permissions, [])\n : (ps.system_permissions ?? ps.systemPermissions);\n if (Array.isArray(sysPerms)) {\n for (const p of sysPerms) {\n if (typeof p === 'string' && !ctx.systemPermissions.includes(p)) ctx.systemPermissions.push(p);\n }\n }\n const tabs = typeof ps.tab_permissions === 'string'\n ? safeJsonParse(ps.tab_permissions, {})\n : (ps.tab_permissions ?? ps.tabPermissions);\n if (tabs && typeof tabs === 'object') {\n for (const [app, val] of Object.entries(tabs as Record<string, unknown>)) {\n if (typeof val !== 'string' || !(val in tabRank)) continue;\n const cur = mergedTabs[app];\n if (!cur || tabRank[val] > tabRank[cur]) {\n mergedTabs[app] = val as 'visible' | 'hidden' | 'default_on' | 'default_off';\n }\n }\n }\n }\n if (Object.keys(mergedTabs).length > 0) ctx.tabPermissions = mergedTabs;\n }\n\n // 6c. Project the derived platform_admin built-in role (leads the list).\n if (hasPlatformAdminGrant && !ctx.positions.includes(BUILTIN_IDENTITY_PLATFORM_ADMIN)) {\n ctx.positions.unshift(BUILTIN_IDENTITY_PLATFORM_ADMIN);\n }\n\n // 6d. [ADR-0095 D2/D3] Resolve the posture rung ONCE, from held CAPABILITY\n // grants — never from a better-auth role. `PLATFORM_ADMIN` from the\n // unscoped `admin_full_access` grant (the same `viewAllRecords`/\n // `modifyAllRecords` evidence the superuser bypass trusts); `TENANT_ADMIN`\n // from the `organization_admin` grant (auto-provisioned from the better-\n // auth owner/admin role at §3 above — a provisioning source, not an\n // enforcement input, closing the #2836 dual-track class). Enforcement\n // behavior is unchanged: the per-object Layer 0 exemption + per-side\n // superuser bypass still gate access; posture is the carried, explainable\n // tier. `EXTERNAL` is never derived (no external principal type yet).\n ctx.posture = derivePosture({\n isPlatformAdmin: hasPlatformAdminGrant,\n isTenantAdmin: ctx.permissions.includes(ORGANIZATION_ADMIN),\n });\n\n // 7. [ADR-0024] Env-side AI seat: synthesize the `ai_seat` capability from the\n // boolean sys_user.ai_access (sqlite returns 1/0; memory returns boolean).\n if (!ctx.permissions.includes('ai_seat')) {\n const aiAccess = ((await getUserRow()) as { ai_access?: unknown } | undefined)?.ai_access;\n if (aiAccess === true || aiAccess === 1 || aiAccess === '1') ctx.permissions.push('ai_seat');\n }\n\n return ctx;\n}\n\n// ── Localization (ADR-0053 Phase 2) ─────────────────────────────────────────\n\nfunction isValidTimeZone(tz: string): boolean {\n try { new Intl.DateTimeFormat('en-US', { timeZone: tz }); return true; } catch { return false; }\n}\nfunction coerceTimeZone(value: unknown): string | undefined {\n const s = typeof value === 'string' ? value.trim() : value != null ? String(value).trim() : '';\n return s && isValidTimeZone(s) ? s : undefined;\n}\nfunction coerceLocale(value: unknown): string | undefined {\n const s = typeof value === 'string' ? value.trim() : value != null ? String(value).trim() : '';\n return s || undefined;\n}\nfunction coerceCurrency(value: unknown): string | undefined {\n const s = typeof value === 'string' ? value.trim().toUpperCase() : '';\n return /^[A-Z]{3}$/.test(s) ? s : undefined;\n}\n\nexport interface ResolveLocalizationInput {\n ql: any;\n /** Settings service exposing `get(namespace, key, { tenantId, userId })`. */\n settings?: any;\n tenantId?: string;\n userId?: string;\n}\n\n/**\n * Resolve workspace localization defaults (reference `timezone` / `locale` /\n * `currency`). Canonical path is the `localization` SettingsManifest (cascade:\n * platform default → global → tenant); falls back to direct tenant-scoped\n * `sys_setting` rows, then the built-ins `UTC` / `en-US`. Never throws.\n */\nexport async function resolveLocalizationContext(\n input: ResolveLocalizationInput,\n): Promise<{ timezone: string; locale: string; currency?: string }> {\n const { ql, settings, tenantId, userId } = input;\n try {\n if (settings && typeof settings.get === 'function') {\n const sctx = { tenantId, userId } as any;\n const [tzRes, localeRes, currencyRes] = await Promise.all([\n settings.get('localization', 'timezone', sctx).catch(() => undefined),\n settings.get('localization', 'locale', sctx).catch(() => undefined),\n settings.get('localization', 'currency', sctx).catch(() => undefined),\n ]);\n const tz = coerceTimeZone(tzRes?.value);\n const locale = coerceLocale(localeRes?.value);\n const currency = coerceCurrency(currencyRes?.value);\n if (tz || locale || currency) return { timezone: tz ?? 'UTC', locale: locale ?? 'en-US', currency };\n }\n } catch {\n // settings service unavailable → direct read\n }\n // One read for all three keys instead of a query per key (`$in` on `key`).\n const rows = await tryFind(\n ql,\n 'sys_setting',\n { namespace: 'localization', key: { $in: ['timezone', 'locale', 'currency'] }, scope: 'tenant' },\n 10,\n );\n const valueOf = (k: string) => rows.find((r) => r.key === k)?.value;\n return {\n timezone: coerceTimeZone(valueOf('timezone')) ?? 'UTC',\n locale: coerceLocale(valueOf('locale')) ?? 'en-US',\n currency: coerceCurrency(valueOf('currency')),\n };\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Grant validity windows (ADR-0091 D1/D2).\n *\n * `sys_user_position` and `sys_user_permission_set` rows carry optional\n * `valid_from` / `valid_until` columns. A row outside its window MUST NOT\n * resolve — anywhere, symmetrically: `resolveAuthzContext`, the explain\n * engine's `buildContextForUser`, plugin-sharing's `expandPositionUsers`,\n * and (transitively) the delegated-admin gate's held-scope resolution.\n *\n * Correctness lives HERE, at resolution time — never in a cleanup job\n * (ADR-0049: no unenforced security properties). The window is half-open\n * `[from, until)` in UTC: a grant is inactive before `valid_from` and\n * inactive AT and AFTER `valid_until`. Null/absent bounds mean unbounded,\n * so pre-ADR-0091 rows behave exactly as before.\n *\n * Fail-closed: a bound that is PRESENT but unparseable disables the grant\n * (unlike API-key `isExpired`, which tolerates garbage — an API key is a\n * single credential, a grant row is standing authority).\n */\n\n/**\n * Coerce a stored timestamp to epoch milliseconds.\n * Returns `undefined` for absent (null/undefined/'') values — \"no bound\" —\n * and `NaN` for present-but-unparseable values, which callers treat as\n * out-of-window (fail closed).\n */\nfunction toEpochMs(value: unknown): number | undefined {\n if (value == null || value === '') return undefined;\n if (typeof value === 'number') {\n // Heuristic: seconds vs milliseconds epoch (same rule as api-key.ts).\n return value < 1e12 ? value * 1000 : value;\n }\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string') return Date.parse(value);\n return Number.NaN;\n}\n\n/** The validity-window shape shared by both user-grant tables (ADR-0091 D1). */\nexport interface GrantValidityWindow {\n valid_from?: unknown;\n valid_until?: unknown;\n}\n\n/**\n * True when a grant row is inside its validity window at `nowMs`.\n * The single predicate every resolver uses (ADR-0091 D2):\n * `(valid_from is null or valid_from <= now) and (valid_until is null or valid_until > now)`.\n */\nexport function isGrantActive(row: GrantValidityWindow | null | undefined, nowMs: number): boolean {\n if (!row) return false;\n const from = toEpochMs((row as any).valid_from ?? (row as any).validFrom);\n // NaN comparisons are always false, so an unparseable bound fails closed.\n if (from !== undefined && !(nowMs >= from)) return false;\n const until = toEpochMs((row as any).valid_until ?? (row as any).validUntil);\n if (until !== undefined && !(nowMs < until)) return false;\n return true;\n}\n\n/**\n * True when a grant row carries a `valid_until` that has already passed —\n * i.e. it WAS active and expired (not merely not-yet-active). The explain\n * engine uses this to report the dedicated \"held until … — expired\"\n * contributor state (ADR-0091 D2).\n */\nexport function isGrantExpired(row: GrantValidityWindow | null | undefined, nowMs: number): boolean {\n if (!row) return false;\n const until = toEpochMs((row as any).valid_until ?? (row as any).validUntil);\n if (until === undefined) return false;\n return !(nowMs < until);\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ── The monotonic posture ladder (ADR-0095 D2/D3) ───────────────────────────\n *\n * The principal-tiering enum resolved ONCE in `resolveAuthzContext`\n * (`PLATFORM_ADMIN > TENANT_ADMIN > MEMBER > EXTERNAL`). This module owns two\n * things and deliberately nothing more:\n *\n * 1. **Derivation (D3).** {@link derivePosture} maps held *capability grants*\n * — never a better-auth role — to a rung. `PLATFORM_ADMIN` derives from the\n * unscoped `admin_full_access` grant (the `viewAllRecords`/`modifyAllRecords`\n * evidence the superuser bypass already trusts); `TENANT_ADMIN` from the\n * `organization_admin` grant. The better-auth `role='admin'` is upstream a\n * *provisioning source* of those grants (`auto-org-admin-grant.ts`), so it\n * never re-enters adjudication here — the #2836 dual-track class is closed\n * by construction.\n *\n * 2. **The rung → injection-rule mapping + its tested invariants (D2).** Each\n * rung maps to EXACTLY ONE row-visibility injection rule\n * ({@link POSTURE_INJECTION_RULE}). {@link postureVisibleRows} is the\n * REFERENCE MODEL of those rules over a synthetic row-set — it locks the two\n * properties the ADR requires as invariants: strict nesting (rung n's\n * visible set ⊇ rung n−1's) and the EXTERNAL deny-by-default semantics\n * (explicit shares only, OWD never widens it).\n *\n * This module is NOT the enforcement path. The effective read/write filter is\n * `Layer0(tenant) AND Layer1(business RLS)`, computed in `@objectstack/plugin-\n * security` (`tenant-layer.ts` + `security-plugin.ts`), and the real behavior\n * guard is the `authz-matrix-gate` unit snapshot + the dogfood conformance\n * matrix. The reference model here exists so the ladder's *mathematical*\n * properties can be asserted at the unit layer without an enforcement boot, and\n * so the EXTERNAL rung — which has no enforcement path yet — cannot be\n * reinvented differently when portal/external membership arrives.\n */\n\nimport type { AuthzPosture } from '@objectstack/spec/security';\n\n/**\n * The rung ordering, high privilege → low, matching the spec enum's numeric\n * values (`PLATFORM_ADMIN=3 … EXTERNAL=0`). Visibility grows monotonically UP\n * this ladder (see {@link postureVisibleRows}).\n */\nexport const POSTURE_LADDER = [\n 'PLATFORM_ADMIN',\n 'TENANT_ADMIN',\n 'MEMBER',\n 'EXTERNAL',\n] as const satisfies readonly AuthzPosture[];\n\n/** Numeric rank per rung (mirrors the spec `AuthzPosture` enum values). */\nexport const POSTURE_RANK: Record<AuthzPosture, number> = {\n PLATFORM_ADMIN: 3,\n TENANT_ADMIN: 2,\n MEMBER: 1,\n EXTERNAL: 0,\n};\n\n/**\n * The ONE row-visibility injection rule each rung maps to (ADR-0095 D2). Prose,\n * because the machine artifacts live in enforcement (Layer 0 + the per-rung\n * Layer 1 rule); this is the enumerable contract the explain track reports and\n * {@link postureVisibleRows} models.\n */\nexport const POSTURE_INJECTION_RULE: Record<AuthzPosture, string> = {\n PLATFORM_ADMIN:\n 'Layer 0 exemption where the object posture permits (private / platform-global / better-auth-managed) — crosses the tenant wall; org-scoped like TENANT_ADMIN on ordinary tenant business objects.',\n TENANT_ADMIN:\n 'All rows within the active organization (organization_id == ctx.tenantId); no ownership / depth / sharing narrowing.',\n MEMBER:\n 'Business RLS within the organization — ownership (owner / unit depth), the OWD baseline, and explicit sharing.',\n EXTERNAL:\n 'Explicitly shared rows ONLY — OWD baselines and sharing rules never apply; a misconfiguration can only shrink visibility, never widen it.',\n};\n\n/** Capability-grant evidence the posture derivation consumes (ADR-0095 D3). */\nexport interface PostureEvidence {\n /**\n * Holds the UNSCOPED platform-admin capability grant (`admin_full_access` →\n * `viewAllRecords`/`modifyAllRecords`) — the same evidence the superuser\n * bypass trusts. NOT a better-auth role.\n */\n isPlatformAdmin: boolean;\n /**\n * Holds the org-admin capability grant (`organization_admin`, tenant-scoped\n * `viewAllRecords`/`modifyAllRecords`). Provisioned from the better-auth\n * owner/admin role upstream, consumed here only as a held capability.\n */\n isTenantAdmin: boolean;\n}\n\n/**\n * Resolve the principal's posture rung from held capability grants (ADR-0095 D3).\n *\n * Returns `PLATFORM_ADMIN` | `TENANT_ADMIN` | `MEMBER`. It NEVER returns\n * `EXTERNAL`: no external principal type exists yet (the sharing chain has no\n * portal/guest-share concept — ADR-0095 W4). The `EXTERNAL` rung, its injection\n * rule, and its semantics are defined and test-locked ({@link postureVisibleRows},\n * {@link POSTURE_INJECTION_RULE}) so that when portal/external membership lands\n * (ADR-0093) the derivation gains an EXTERNAL branch HERE without the rung being\n * reinvented. `MEMBER` is the authenticated-principal floor.\n */\nexport function derivePosture(evidence: PostureEvidence): AuthzPosture {\n if (evidence.isPlatformAdmin) return 'PLATFORM_ADMIN';\n if (evidence.isTenantAdmin) return 'TENANT_ADMIN';\n return 'MEMBER';\n}\n\n// ── Reference visibility model (invariant lock, NOT enforcement) ─────────────\n\n/** A synthetic record for the ladder reference model. */\nexport interface LadderRow {\n id: string;\n /** The row's tenant. `undefined` = a non-tenant (platform-global) row. */\n organization_id?: string;\n /** The row's owner (drives the MEMBER ownership disjunct). */\n owner_id?: string;\n /**\n * Whether an OWD-derived source would admit this row for a member (public\n * baseline / criteria sharing). EXTERNAL deliberately ignores this field.\n */\n owdVisible?: boolean;\n /** User ids this row is EXPLICITLY shared to (the only EXTERNAL source). */\n sharedTo?: readonly string[];\n}\n\n/** The principal the reference model evaluates a rung for. */\nexport interface LadderPrincipal {\n userId: string;\n /** The principal's active organization (undefined for an unscoped principal). */\n organizationId?: string;\n}\n\nfunction isSharedTo(row: LadderRow, userId: string): boolean {\n return (row.sharedTo ?? []).includes(userId);\n}\n\n/** EXTERNAL rung: explicitly shared rows ONLY — never OWD, never org-wide. */\nfunction externalVisible(rows: readonly LadderRow[], p: LadderPrincipal): LadderRow[] {\n return rows.filter((r) => isSharedTo(r, p.userId));\n}\n\n/**\n * MEMBER rung: business RLS within the org — ownership OR OWD baseline OR\n * explicit sharing. Composed as `EXTERNAL ∪ (in-org ownership/OWD)` so the\n * EXTERNAL ⊆ MEMBER leg of the nesting invariant holds by construction.\n */\nfunction memberVisible(rows: readonly LadderRow[], p: LadderPrincipal): LadderRow[] {\n const shared = new Set(externalVisible(rows, p));\n return rows.filter(\n (r) =>\n shared.has(r) ||\n (r.organization_id === p.organizationId && (r.owner_id === p.userId || r.owdVisible === true)),\n );\n}\n\n/**\n * TENANT_ADMIN rung: all rows in the active organization. Composed as\n * `MEMBER ∪ (all in-org)` so MEMBER ⊆ TENANT_ADMIN holds by construction.\n */\nfunction tenantAdminVisible(rows: readonly LadderRow[], p: LadderPrincipal): LadderRow[] {\n const member = new Set(memberVisible(rows, p));\n return rows.filter((r) => member.has(r) || r.organization_id === p.organizationId);\n}\n\n/** PLATFORM_ADMIN rung: crosses the tenant wall — every row (⊇ TENANT_ADMIN trivially). */\nfunction platformAdminVisible(rows: readonly LadderRow[]): LadderRow[] {\n return [...rows];\n}\n\n/**\n * Reference model of the per-rung injection rule: the visible-row set a rung\n * would resolve to over `rows` for `principal`. Used to lock the ADR-0095 D2\n * invariants (strict nesting + EXTERNAL deny-by-default). NOT an enforcement\n * path — see the module header.\n */\nexport function postureVisibleRows(\n posture: AuthzPosture,\n rows: readonly LadderRow[],\n principal: LadderPrincipal,\n): LadderRow[] {\n switch (posture) {\n case 'PLATFORM_ADMIN':\n return platformAdminVisible(rows);\n case 'TENANT_ADMIN':\n return tenantAdminVisible(rows, principal);\n case 'MEMBER':\n return memberVisible(rows, principal);\n case 'EXTERNAL':\n return externalVisible(rows, principal);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ADR-0069 — authentication-policy session gate.\n *\n * Some auth policies (password expiry, enforced MFA) must block an\n * authenticated user from PROTECTED RESOURCES until they remediate, while\n * still letting them reach the auth endpoints (change-password, two-factor\n * enrollment, sign-out) and a few UI-bootstrap reads.\n *\n * The posture is computed ONCE, in the auth `customSession` enrichment, and\n * attached to the session user as `user.authGate = { code, message }`. The\n * transport seams (REST middleware, dispatcher) then call\n * {@link evaluateAuthGate} to decide whether THIS request is blocked. Keeping\n * the allow-list + decision in one pure function means the seams can never\n * drift on what is blocked.\n */\n\nexport interface AuthGate {\n /** Stable machine code, e.g. `PASSWORD_EXPIRED` / `MFA_REQUIRED`. */\n code: string;\n /** Human-facing message. */\n message: string;\n}\n\n// Endpoints a gated user MUST still reach to remediate or bootstrap the\n// remediation UI. Matched against the request path (query stripped). Covers\n// both REST (`/api/v1/auth/…`) and dispatcher (`/auth/…`) path shapes.\nconst ALLOW_PREFIXES = ['/api/v1/auth/', '/api/auth/', '/auth/'];\nconst ALLOW_SUFFIXES = ['/health', '/ready', '/discovery', '/me/apps', '/me/localization'];\n\n/** True when `path` is exempt from the auth gate (auth + remediation + health). */\nexport function isAuthGateAllowlisted(rawPath: string | undefined | null): boolean {\n if (!rawPath) return true;\n // Strip query + trailing slashes WITHOUT a regex (avoids ReDoS on a\n // path of many '/'). char 47 = '/'.\n let path = rawPath.split('?')[0] || '/';\n let end = path.length;\n while (end > 1 && path.charCodeAt(end - 1) === 47) end--;\n path = path.slice(0, end) || '/';\n // Any path with an `/auth/` segment is an auth endpoint (covers project-\n // scoped mounts like `/api/v1/environments/:env/auth/...`).\n if (path.includes('/auth/')) return true;\n for (const p of ALLOW_PREFIXES) {\n if (path.startsWith(p) || path === p.replace(/\\/$/, '')) return true;\n }\n for (const s of ALLOW_SUFFIXES) {\n if (path.endsWith(s)) return true;\n }\n return false;\n}\n\n/**\n * Returns the active gate when `sessionUser` carries an `authGate` AND `path`\n * is not allow-listed; otherwise null. Anonymous users (no `authGate`) and\n * allow-listed paths always pass.\n */\nexport function evaluateAuthGate(sessionUser: any, path: string): AuthGate | null {\n const gate = sessionUser?.authGate;\n if (!gate || typeof gate.code !== 'string') return null;\n if (isAuthGateAllowlisted(path)) return null;\n return {\n code: gate.code,\n message:\n typeof gate.message === 'string' && gate.message\n ? gate.message\n : 'Access is blocked by an authentication policy.',\n };\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * #2567 — the single anonymous-deny decision, shared by every HTTP seam.\n *\n * ADR-0056 D2 made the platform deny anonymous callers by default\n * (`requireAuth`). Phase 1 gated each surface (REST `/data`, dispatcher\n * `/graphql` + `/meta`, raw-hono `/data`) but every seam hand-rolled the same\n * `!userId && !isSystem → 401` check. This centralises that DECISION into one\n * pure, tested function — the exact pattern {@link ./auth-gate.ts} established\n * for the ADR-0069 auth-policy gate: keeping the decision in one function means\n * the seams can never drift on who is denied.\n *\n * It deliberately does NOT own identity resolution or the dynamic exemptions\n * (public-form submission, share-link tokens): those run UPSTREAM and set the\n * execution context (a `userId`, or `isSystem`) before a seam calls this, so\n * this function only ever inspects the already-resolved context.\n */\n\nimport { isAuthGateAllowlisted } from './auth-gate.js';\n\n/** HTTP status every seam returns for an anonymous-denied request. */\nexport const ANONYMOUS_DENY_STATUS = 401 as const;\n/** Stable machine code (mirrors the REST `enforceAuth` seam). */\nexport const ANONYMOUS_DENY_CODE = 'unauthenticated' as const;\n/** Human-facing message. */\nexport const ANONYMOUS_DENY_MESSAGE = 'Authentication is required to access this endpoint.';\n/** The single 401 body shape every seam returns: `{ error, message }`. */\nexport const ANONYMOUS_DENY_BODY = {\n error: ANONYMOUS_DENY_CODE,\n message: ANONYMOUS_DENY_MESSAGE,\n} as const;\n\nexport interface AnonymousDenyInput {\n /** The `requireAuth` posture. Falsy ⇒ no-op (demo / single-tenant). */\n requireAuth: boolean | undefined;\n /** Resolved caller id, if any. */\n userId?: string | null;\n /** Internal system context (never set on inbound HTTP; cannot be forged). */\n isSystem?: boolean;\n /** HTTP method — `OPTIONS` (CORS preflight) always passes. */\n method?: string | null;\n /**\n * OPTIONAL request path. When a NON-EMPTY string, a control-plane path\n * (auth / health / ready / discovery — see {@link isAuthGateAllowlisted}) is\n * exempt. Body-routed seams (GraphQL) have no meaningful path and pass\n * `undefined`; see the guard below for why that is load-bearing.\n */\n path?: string | null;\n}\n\n/**\n * True when the request MUST be rejected with 401. The one decision every HTTP\n * seam shares.\n */\nexport function shouldDenyAnonymous(input: AnonymousDenyInput): boolean {\n if (!input.requireAuth) return false; // posture off\n if (typeof input.method === 'string' && input.method.toUpperCase() === 'OPTIONS') {\n return false; // CORS preflight\n }\n if (input.userId || input.isSystem) return false; // authenticated / system\n // Control-plane exemption — ONLY for a real, non-empty path.\n //\n // ⚠️ `isAuthGateAllowlisted(undefined)` returns `true` (it treats \"no path\"\n // as allow-listed for the auth-gate's purposes). A body-routed seam such as\n // GraphQL has no meaningful request path; if it passed `undefined` straight\n // through, the allowlist would exempt EVERY anonymous query and silently\n // reopen exactly the hole #2567 closes. The non-empty guard is mandatory.\n if (typeof input.path === 'string' && input.path.length > 0 && isAuthGateAllowlisted(input.path)) {\n return false;\n }\n return true;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Timezone-aware calendar utilities (ADR-0053 Phase 2).\n *\n * The one primitive everything else builds on is {@link calendarPartsInTz}:\n * the year/month/day an instant falls on *as seen in a reference timezone*.\n * It uses `Intl.DateTimeFormat().formatToParts()` so DST transitions are\n * handled by the platform's tz database — never hand-rolled offset math, which\n * is the classic source of off-by-one-hour bucket errors.\n *\n * This lives in `@objectstack/core` (not `@objectstack/formula`) because both\n * the ObjectQL aggregation engine and the analytics service need it and both\n * already depend on core, whereas neither depends on formula's public surface.\n * (`@objectstack/formula` keeps its own private copy for `today()`/`daysFromNow`\n * to avoid a layering dependency on core.)\n */\n\n/** Calendar-day parts in a reference timezone. `month` is 1-12. */\nexport interface CalendarParts {\n year: number;\n month: number;\n day: number;\n}\n\n/**\n * The year/month/day an instant falls on in `tz`. Throws if `tz` is not a\n * valid IANA zone (callers treat that as a fall-through to UTC).\n */\nexport function calendarPartsInTz(d: Date, tz: string): CalendarParts {\n const parts = new Intl.DateTimeFormat('en-US', {\n timeZone: tz,\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n }).formatToParts(d);\n const get = (t: string) => Number(parts.find((p) => p.type === t)?.value);\n return { year: get('year'), month: get('month'), day: get('day') };\n}\n\n/**\n * The calendar-day parts of an instant, in `tz` when it's a real non-UTC zone,\n * otherwise in UTC. Never throws: an unset, `'UTC'`, or invalid zone falls back\n * to the UTC calendar day. This is the safe entry point for bucketing code that\n * must degrade to the historical UTC behavior rather than error.\n */\nexport function calendarPartsInTzOrUtc(d: Date, tz?: string): CalendarParts {\n if (tz && tz !== 'UTC') {\n try {\n return calendarPartsInTz(d, tz);\n } catch {\n // unknown zone → fall through to UTC\n }\n }\n return {\n year: d.getUTCFullYear(),\n month: d.getUTCMonth() + 1,\n day: d.getUTCDate(),\n };\n}\n\n/**\n * The UTC instant (epoch ms) at which calendar day `ymd` (`YYYY-MM-DD`) *begins*\n * in reference timezone `tz` — i.e. local **midnight** of that day rendered as a\n * UTC instant. The inverse direction of {@link calendarPartsInTz}.\n *\n * DST-safe: the zone offset is read from the platform tz database via\n * `Intl.DateTimeFormat` (never hand-computed), and a two-pass resolution settles\n * the rare case where the offset differs side-to-side of the target instant. An\n * unset, `'UTC'`, invalid, or unparseable input returns plain UTC midnight.\n *\n * Used by date-bucket drill ranges (#1752): a `datetime` field buckets on the\n * reference-tz calendar, so its bucket boundary is that tz's midnight instant.\n */\nexport function zonedDateStartToUtcMs(ymd: string, tz?: string): number {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(ymd);\n const wallAsUtc = m ? Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3])) : NaN;\n if (!tz || tz === 'UTC' || Number.isNaN(wallAsUtc)) return wallAsUtc;\n try {\n // The tz offset (local − UTC, in ms) at instant `t`: read t's wall clock in\n // `tz`, re-interpret those parts as UTC, and subtract t.\n const offsetAt = (t: number): number => {\n const p = new Intl.DateTimeFormat('en-US', {\n timeZone: tz,\n hourCycle: 'h23',\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n }).formatToParts(new Date(t));\n const g = (k: string) => Number(p.find((x) => x.type === k)?.value);\n return Date.UTC(g('year'), g('month') - 1, g('day'), g('hour'), g('minute'), g('second')) - t;\n };\n // Want U such that localParts(U) == midnight, i.e. U = wallAsUtc − offset(U).\n // Iterate from the zero-offset guess; converges in ≤2 steps off a DST edge.\n const off1 = offsetAt(wallAsUtc - offsetAt(wallAsUtc));\n return wallAsUtc - off1;\n } catch {\n return wallAsUtc; // unknown zone → UTC midnight\n }\n}\n\n/**\n * Granularity of a canonical date-bucket key. Mirrors `@objectstack/spec`'s\n * `DateGranularity` enum but kept as a local literal union so this low-level\n * package needs no dependency on spec.\n */\nexport type BucketGranularity = 'day' | 'week' | 'month' | 'quarter' | 'year';\n\n/**\n * ISO-8601 week label (Mon-start weeks, week 1 = the week of the first\n * Thursday) of a UTC calendar day. The forward-direction companion used to\n * *validate* a reconstructed week boundary; it mirrors the week branch of\n * `@objectstack/objectql`'s `bucketDateValue` (kept in lockstep by the\n * round-trip parity test in objectql).\n */\nfunction isoWeekLabelUtc(d: Date): string {\n const target = new Date(d.getTime());\n const dayNum = (target.getUTCDay() + 6) % 7; // Mon=0..Sun=6\n target.setUTCDate(target.getUTCDate() - dayNum + 3); // shift to that week's Thursday\n const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4));\n const weekNo =\n 1 +\n Math.round(\n ((target.getTime() - firstThursday.getTime()) / 86400000 -\n 3 +\n ((firstThursday.getUTCDay() + 6) % 7)) /\n 7,\n );\n return `${target.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;\n}\n\n/**\n * The half-open calendar span `[start, end)` of a canonical date-bucket KEY,\n * as `YYYY-MM-DD` strings (`start` inclusive, `end` exclusive — the next\n * bucket's first day).\n *\n * The input MUST be the canonical key produced by `bucketDateValue` /\n * `buildDateBucketExpr` (`2026`, `2026-Q2`, `2026-06`, `2026-06-15`,\n * `2026-W23`) — NEVER a localized / humanized display label. The span is pure,\n * timezone-naive calendar arithmetic; a caller that needs instant bounds for a\n * `datetime` field in a reference timezone layers that on top (and, per\n * ADR-0053, a `date` field compares against these `YYYY-MM-DD` bounds directly).\n *\n * Returns `null` for the null/empty bucket, an unparseable key, or a key that\n * is shape-valid but out of range (e.g. `2026-13`, a `-W53` in a 52-week year,\n * `2026-02-30`). Callers drop the range and fall back to an unscoped (superset)\n * drill rather than emit a wrong bound.\n */\nexport function bucketKeyToCalendarRange(\n key: string,\n granularity: BucketGranularity,\n): { start: string; end: string } | null {\n if (typeof key !== 'string' || key.length === 0) return null;\n const fmt = (dt: Date) =>\n `${String(dt.getUTCFullYear()).padStart(4, '0')}-${String(dt.getUTCMonth() + 1).padStart(\n 2,\n '0',\n )}-${String(dt.getUTCDate()).padStart(2, '0')}`;\n\n switch (granularity) {\n case 'year': {\n const m = /^(\\d{4})$/.exec(key);\n if (!m) return null;\n const y = Number(m[1]);\n return { start: fmt(new Date(Date.UTC(y, 0, 1))), end: fmt(new Date(Date.UTC(y + 1, 0, 1))) };\n }\n case 'quarter': {\n const m = /^(\\d{4})-Q([1-4])$/.exec(key);\n if (!m) return null;\n const y = Number(m[1]);\n const startMonth = (Number(m[2]) - 1) * 3; // Q1→0, Q2→3, Q3→6, Q4→9\n return {\n start: fmt(new Date(Date.UTC(y, startMonth, 1))),\n end: fmt(new Date(Date.UTC(y, startMonth + 3, 1))), // Date.UTC rolls Q4 into next year\n };\n }\n case 'month': {\n const m = /^(\\d{4})-(\\d{2})$/.exec(key);\n if (!m) return null;\n const mo = Number(m[2]);\n if (mo < 1 || mo > 12) return null;\n const y = Number(m[1]);\n return {\n start: fmt(new Date(Date.UTC(y, mo - 1, 1))),\n end: fmt(new Date(Date.UTC(y, mo, 1))),\n };\n }\n case 'day': {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(key);\n if (!m) return null;\n const y = Number(m[1]);\n const mo = Number(m[2]);\n const d = Number(m[3]);\n const start = new Date(Date.UTC(y, mo - 1, d));\n if (fmt(start) !== key) return null; // reject an impossible day that rolled over\n return { start: key, end: fmt(new Date(Date.UTC(y, mo - 1, d + 1))) };\n }\n case 'week': {\n const m = /^(\\d{4})-W(\\d{2})$/.exec(key);\n if (!m) return null;\n const isoYear = Number(m[1]);\n const week = Number(m[2]);\n if (week < 1 || week > 53) return null;\n // Monday of ISO week 1 is the Monday on/before Jan 4; add (week-1) weeks.\n const jan4 = new Date(Date.UTC(isoYear, 0, 4));\n const jan4Dow = (jan4.getUTCDay() + 6) % 7; // Mon=0..Sun=6\n const start = new Date(jan4.getTime());\n start.setUTCDate(jan4.getUTCDate() - jan4Dow + (week - 1) * 7);\n if (isoWeekLabelUtc(start) !== key) return null; // reject -W53 overflow etc.\n const end = new Date(start.getTime());\n end.setUTCDate(start.getUTCDate() + 7);\n return { start: fmt(start), end: fmt(end) };\n }\n default:\n return null;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * `bulkWrite` — the shared batched-write helper used by BOTH the seed loader\n * (`@objectstack/metadata-protocol`) and the data-import runner\n * (`@objectstack/rest`), so neither reimplements batching, transient-error\n * retry, or per-row degradation. See framework#2678.\n *\n * ObjectQL's engine already does the efficient thing when handed an ARRAY —\n * one `driver.bulkCreate` round-trip plus parent-deduplicated summary\n * recompute (`engine.insert(object, rows[])`) — but seed/import fed it one\n * record at a time, so neither got the benefit. This module re-chunks rows\n * into batches and drives them through a caller-supplied batch-write\n * function, adding:\n *\n * - transient-error retry (network blip / timeout) with exponential\n * backoff, so a dropped connection doesn't silently drop the row (the\n * 2026-07-06 HotCRM incident: a turso `fetch failed` mid-seed dropped rows\n * silently because nothing retried);\n * - per-row degradation when a batch fails for a non-transient (logical /\n * validation) reason, so one bad row can't fail the other N-1 — needed\n * because `driver.bulkCreate` is a single multi-row statement/`Promise.all`\n * on every driver in this repo (sql, memory, mongodb): one bad row fails\n * the whole call;\n * - a stable per-row result keyed by the row's original index, so callers\n * can reassemble output in input order even though rows are processed in\n * batches (and a batch's flush may be interleaved with other, immediate,\n * per-row work such as updates).\n *\n * Delivery semantics: **at-least-once**. Transient retry and per-row\n * degradation both RE-RUN a write whose outcome was unknown — e.g. a turso\n * `fetch failed` that arrived *after* the row was already committed\n * (framework#3149), or a result-count mismatch that voids the batch\n * (framework#3151). A caller that needs exactly-once must make its\n * `writeBatch`/`writeOne` idempotent; both receive an `attempt` counter for\n * exactly this — see the natural-key recheck the seed loader and import\n * runner perform on `attempt > 1`. `writeBatch` MUST also resolve exactly one\n * record per input row, in input order: a short / long / non-array return is\n * rejected as a failed batch (framework#3151), never silently backfilled.\n */\n\nexport interface BulkWriteRowResult<TRecord = any> {\n /** Index into the original `rows` array passed to {@link bulkWrite}. */\n index: number;\n ok: boolean;\n record?: TRecord;\n error?: unknown;\n}\n\nexport interface RetryOptions {\n /** Max attempts for one write (batch or single-row), including the first. Default 3. */\n maxRetries?: number;\n /** Base backoff in ms; doubled each retry, plus jitter. Default 200. */\n backoffBaseMs?: number;\n /** Classifies an error as transient (worth retrying) vs logical (the row/batch is just bad). */\n isTransientError?: (err: unknown) => boolean;\n /** Injectable sleep, for deterministic tests. */\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface BulkWriteOptions<TRow, TRecord = any> extends RetryOptions {\n /** Rows per batch. Default 200 (framework#2678 suggests 100-500). */\n batchSize?: number;\n /**\n * Write one batch. MUST resolve to one record per input row, in the SAME\n * order as `batch` — {@link bulkWrite} correlates `records[i]` back to\n * `batch[i]` positionally (this is how every `bulkCreate` implementation in\n * this repo already behaves: sql's single `INSERT ... VALUES (...), (...)\n * RETURNING *`, memory's `Promise.all`, mongodb's ordered `insertMany`).\n *\n * `ctx.attempt` is the 1-based attempt number. `attempt > 1` means a prior\n * attempt's outcome is UNKNOWN (a transient blip that may have landed after\n * commit) — an exactly-once caller should recheck by natural key and skip\n * rows already present before re-writing (framework#3149).\n */\n writeBatch: (batch: TRow[], ctx: { attempt: number }) => Promise<TRecord[]>;\n /**\n * Write a single row — used only to degrade a failed batch. `ctx.attempt`\n * carries the same recheck signal as {@link writeBatch}.\n */\n writeOne: (row: TRow, ctx: { attempt: number }) => Promise<TRecord>;\n /**\n * Partial-success batch write (framework#3172). When provided it is used\n * INSTEAD of {@link writeBatch}: it must resolve one outcome per input row,\n * in input order — `{ ok: true, record }` for written rows, `{ ok: false,\n * error }` for rows that failed individually (e.g. validation). Per-row\n * failures are final verdicts: bulkWrite records them as-is and does NOT\n * degrade to `writeOne` for them — that is the whole point (a degradation\n * re-run would re-fire beforeInsert hooks on the good rows). Only a THROWN\n * error (a transient infra failure, a result-count mismatch) falls back to\n * the per-row `writeOne` degradation, exactly like `writeBatch`.\n */\n writeBatchPartial?: (\n batch: TRow[],\n ctx: { attempt: number },\n ) => Promise<Array<{ ok: boolean; record?: TRecord; error?: unknown }>>;\n}\n\nconst DEFAULT_BATCH_SIZE = 200;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_BACKOFF_BASE_MS = 200;\n\n/**\n * Transient-error signatures shared by common HTTP/TCP-backed drivers\n * (turso/libsql's fetch-based transport included). Deliberately excludes\n * anything that looks like a validation/constraint error — those must NOT be\n * retried, only degraded to per-row.\n */\nconst TRANSIENT_PATTERNS: RegExp[] = [\n /fetch failed/i,\n /network/i,\n /timed?\\s*out/i,\n /timeout/i,\n /socket hang ?up/i,\n /connection.*(closed|reset|refused|terminated|aborted)/i,\n /\\b(502|503|504)\\b/,\n /server.*unavailable/i,\n /too many connections/i,\n];\n\nconst TRANSIENT_CODES = /^(ECONNRESET|ECONNREFUSED|ECONNABORTED|EPIPE|EAI_AGAIN|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|ENOTFOUND)$/i;\n\n/**\n * Validation / constraint / schema signatures that are DEFINITIVELY logical,\n * never worth retrying. Checked before {@link TRANSIENT_PATTERNS} so a message\n * that happens to mention both (e.g. `CHECK constraint failed: network_zone`,\n * `column network_id is not allowed`) is classified as logical rather than\n * burning retries on a row that will fail identically every time (framework\n * #3150).\n */\nconst NON_TRANSIENT_PATTERNS: RegExp[] = [\n /validation/i,\n /constraint/i,\n /\\brequired\\b/i,\n /\\bunique\\b/i,\n /duplicate/i,\n /not[\\s_-]*null/i,\n /invalid/i,\n /not allowed/i,\n /out of range/i,\n];\n\nexport function defaultIsTransientError(err: unknown): boolean {\n const message = (err as { message?: unknown } | null)?.message;\n const text = typeof message === 'string' ? message : String(err ?? '');\n // A definitive logical signature wins even if a transient word also appears.\n if (NON_TRANSIENT_PATTERNS.some((re) => re.test(text))) return false;\n const code = (err as { code?: unknown } | null)?.code;\n if (typeof code === 'string' && TRANSIENT_CODES.test(code)) return true;\n return TRANSIENT_PATTERNS.some((re) => re.test(text));\n}\n\nconst defaultSleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\ninterface ResolvedRetryOptions {\n maxRetries: number;\n backoffBaseMs: number;\n isTransientError: (err: unknown) => boolean;\n sleep: (ms: number) => Promise<void>;\n}\n\nasync function withRetry<T>(fn: (attempt: number) => Promise<T>, opts: ResolvedRetryOptions): Promise<T> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= opts.maxRetries; attempt++) {\n try {\n return await fn(attempt);\n } catch (err) {\n lastError = err;\n if (attempt >= opts.maxRetries || !opts.isTransientError(err)) throw err;\n const jitter = Math.floor(Math.random() * 50);\n await opts.sleep(opts.backoffBaseMs * 2 ** (attempt - 1) + jitter);\n }\n }\n // Unreachable — the loop above always returns or throws — but keeps TS's\n // control-flow analysis happy about a guaranteed return type.\n throw lastError;\n}\n\n/**\n * Retry a single write (e.g. an `engine.update()` call the seed loader or\n * import runner makes outside the batched-insert path) with the same\n * transient-error backoff {@link bulkWrite} applies to batches — so a\n * network blip doesn't drop an update the way it used to drop an insert.\n */\nexport async function withTransientRetry<T>(fn: (attempt: number) => Promise<T>, opts: RetryOptions = {}): Promise<T> {\n return withRetry(fn, {\n maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),\n backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,\n isTransientError: opts.isTransientError ?? defaultIsTransientError,\n sleep: opts.sleep ?? defaultSleep,\n });\n}\n\n/**\n * Write `rows` through `opts.writeBatch` in chunks of `opts.batchSize`,\n * retrying a whole-batch transient failure with backoff, and degrading to\n * per-row `opts.writeOne` calls (each itself retried) when a batch fails for\n * a non-transient reason — so one bad row can't drop the rest of the batch.\n *\n * Returns one {@link BulkWriteRowResult} per input row, indexed to match\n * `rows`' original order.\n */\nexport async function bulkWrite<TRow, TRecord = any>(\n rows: TRow[],\n opts: BulkWriteOptions<TRow, TRecord>,\n): Promise<BulkWriteRowResult<TRecord>[]> {\n const batchSize = Math.max(1, opts.batchSize ?? DEFAULT_BATCH_SIZE);\n const retryOpts: ResolvedRetryOptions = {\n maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),\n backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,\n isTransientError: opts.isTransientError ?? defaultIsTransientError,\n sleep: opts.sleep ?? defaultSleep,\n };\n\n const results: BulkWriteRowResult<TRecord>[] = new Array(rows.length);\n\n for (let start = 0; start < rows.length; start += batchSize) {\n const batch = rows.slice(start, start + batchSize);\n try {\n // Partial-success path (framework#3172): one call yields a final per-row\n // verdict, so a row that fails validation never triggers the whole-batch\n // degradation that re-runs beforeInsert hooks on its siblings.\n if (opts.writeBatchPartial) {\n const outcomes = await withRetry((attempt) => opts.writeBatchPartial!(batch, { attempt }), retryOpts);\n if (!Array.isArray(outcomes) || outcomes.length !== batch.length) {\n throw Object.assign(\n new Error(\n `bulkWrite: writeBatchPartial returned ${\n Array.isArray(outcomes) ? `${outcomes.length} outcome(s)` : String(typeof outcomes)\n } for a ${batch.length}-row batch — treating batch as failed`,\n ),\n { code: 'ERR_BULK_RESULT_MISMATCH' },\n );\n }\n for (let i = 0; i < batch.length; i++) {\n const o = outcomes[i];\n results[start + i] = o.ok\n ? { index: start + i, ok: true, record: o.record }\n : { index: start + i, ok: false, error: o.error };\n }\n continue;\n }\n const records = await withRetry((attempt) => opts.writeBatch(batch, { attempt }), retryOpts);\n // Contract guard (framework#3151): `writeBatch` must resolve one record\n // per input row. A short / long / non-array return breaks the positional\n // correlation below, so backfilling it would report phantom successes\n // (`record: undefined`) or drop records. Treat the whole batch as failed\n // and fall through to per-row degradation (each row re-attempted via\n // `writeOne`, which under an idempotent caller rechecks before writing).\n // The message deliberately avoids any transient signature so this never\n // reads as a retryable blip — and it is thrown *outside* `withRetry`, so\n // the batch is not retried on it.\n if (!Array.isArray(records) || records.length !== batch.length) {\n throw Object.assign(\n new Error(\n `bulkWrite: writeBatch returned ${\n Array.isArray(records) ? `${records.length} record(s)` : String(typeof records)\n } for a ${batch.length}-row batch — treating batch as failed`,\n ),\n { code: 'ERR_BULK_RESULT_MISMATCH' },\n );\n }\n for (let i = 0; i < batch.length; i++) {\n results[start + i] = { index: start + i, ok: true, record: records[i] };\n }\n } catch (batchErr) {\n // A single-row \"batch\" already IS the per-row attempt — its failure\n // (after transient retry) is the row's final outcome; calling\n // `writeOne` again would just repeat the identical work.\n if (batch.length === 1) {\n results[start] = { index: start, ok: false, error: batchErr };\n continue;\n }\n // The batch failed even after transient retry, or failed for a logical\n // reason retry wouldn't fix. Degrade to per-row so one bad row can't\n // fail the other rows in this batch. Each row still gets its own\n // transient retry — the batch-level failure doesn't tell us which row\n // (if any) was actually the transient one.\n for (let i = 0; i < batch.length; i++) {\n const idx = start + i;\n try {\n const record = await withRetry((attempt) => opts.writeOne(batch[i], { attempt }), retryOpts);\n results[idx] = { index: idx, ok: true, record };\n } catch (err) {\n results[idx] = { index: idx, ok: false, error: err };\n }\n }\n }\n }\n\n return results;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n PluginHealthStatus, \n PluginHealthCheck, \n PluginHealthReport \n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from './logger.js';\nimport type { Plugin } from './types.js';\n\n/**\n * Plugin Health Monitor\n * \n * Monitors plugin health status and performs automatic recovery actions.\n * Implements the advanced lifecycle health monitoring protocol.\n */\nexport class PluginHealthMonitor {\n private logger: ObjectLogger;\n private healthChecks = new Map<string, PluginHealthCheck>();\n private healthStatus = new Map<string, PluginHealthStatus>();\n private healthReports = new Map<string, PluginHealthReport>();\n private checkIntervals = new Map<string, NodeJS.Timeout>();\n private failureCounters = new Map<string, number>();\n private successCounters = new Map<string, number>();\n private restartAttempts = new Map<string, number>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'HealthMonitor' });\n }\n\n /**\n * Register a plugin for health monitoring\n */\n registerPlugin(pluginName: string, config: PluginHealthCheck): void {\n this.healthChecks.set(pluginName, config);\n this.healthStatus.set(pluginName, 'unknown');\n this.failureCounters.set(pluginName, 0);\n this.successCounters.set(pluginName, 0);\n this.restartAttempts.set(pluginName, 0);\n\n this.logger.info('Plugin registered for health monitoring', { \n plugin: pluginName,\n interval: config.interval \n });\n }\n\n /**\n * Start monitoring a plugin\n */\n startMonitoring(pluginName: string, plugin: Plugin): void {\n const config = this.healthChecks.get(pluginName);\n if (!config) {\n this.logger.warn('Cannot start monitoring - plugin not registered', { plugin: pluginName });\n return;\n }\n\n // Clear any existing interval\n this.stopMonitoring(pluginName);\n\n // Set up periodic health checks\n const interval = setInterval(() => {\n this.performHealthCheck(pluginName, plugin, config).catch(error => {\n this.logger.error('Health check failed with error', { \n plugin: pluginName, \n error \n });\n });\n }, config.interval);\n\n this.checkIntervals.set(pluginName, interval);\n this.logger.info('Health monitoring started', { plugin: pluginName });\n\n // Perform initial health check\n this.performHealthCheck(pluginName, plugin, config).catch(error => {\n this.logger.error('Initial health check failed', { \n plugin: pluginName, \n error \n });\n });\n }\n\n /**\n * Stop monitoring a plugin\n */\n stopMonitoring(pluginName: string): void {\n const interval = this.checkIntervals.get(pluginName);\n if (interval) {\n clearInterval(interval);\n this.checkIntervals.delete(pluginName);\n this.logger.info('Health monitoring stopped', { plugin: pluginName });\n }\n }\n\n /**\n * Perform a health check on a plugin\n */\n private async performHealthCheck(\n pluginName: string,\n plugin: Plugin,\n config: PluginHealthCheck\n ): Promise<void> {\n const startTime = Date.now();\n let status: PluginHealthStatus = 'healthy';\n let message: string | undefined;\n const checks: Array<{ name: string; status: 'passed' | 'failed' | 'warning'; message?: string }> = [];\n\n try {\n // Check if plugin has a custom health check method\n if (config.checkMethod && typeof (plugin as any)[config.checkMethod] === 'function') {\n const checkResult = await Promise.race([\n (plugin as any)[config.checkMethod](),\n this.timeout(config.timeout, `Health check timeout after ${config.timeout}ms`)\n ]);\n\n if (checkResult === false || (checkResult && checkResult.status === 'unhealthy')) {\n status = 'unhealthy';\n message = checkResult?.message || 'Custom health check failed';\n checks.push({ name: config.checkMethod, status: 'failed', message });\n } else {\n checks.push({ name: config.checkMethod, status: 'passed' });\n }\n } else {\n // Default health check - just verify plugin is loaded\n checks.push({ name: 'plugin-loaded', status: 'passed' });\n }\n\n // Update counters based on result\n if (status === 'healthy') {\n this.successCounters.set(pluginName, (this.successCounters.get(pluginName) || 0) + 1);\n this.failureCounters.set(pluginName, 0);\n\n // Recover from unhealthy state if we have enough successes\n const currentStatus = this.healthStatus.get(pluginName);\n if (currentStatus === 'unhealthy' || currentStatus === 'degraded') {\n const successCount = this.successCounters.get(pluginName) || 0;\n if (successCount >= config.successThreshold) {\n this.healthStatus.set(pluginName, 'healthy');\n this.logger.info('Plugin recovered to healthy state', { plugin: pluginName });\n } else {\n this.healthStatus.set(pluginName, 'recovering');\n }\n } else {\n this.healthStatus.set(pluginName, 'healthy');\n }\n } else {\n this.failureCounters.set(pluginName, (this.failureCounters.get(pluginName) || 0) + 1);\n this.successCounters.set(pluginName, 0);\n\n const failureCount = this.failureCounters.get(pluginName) || 0;\n if (failureCount >= config.failureThreshold) {\n this.healthStatus.set(pluginName, 'unhealthy');\n this.logger.warn('Plugin marked as unhealthy', { \n plugin: pluginName, \n failures: failureCount \n });\n\n // Attempt auto-restart if configured\n if (config.autoRestart) {\n await this.attemptRestart(pluginName, plugin, config);\n }\n } else {\n this.healthStatus.set(pluginName, 'degraded');\n }\n }\n } catch (error) {\n status = 'failed';\n message = error instanceof Error ? error.message : 'Unknown error';\n this.failureCounters.set(pluginName, (this.failureCounters.get(pluginName) || 0) + 1);\n this.healthStatus.set(pluginName, 'failed');\n \n checks.push({ \n name: 'health-check', \n status: 'failed', \n message: message \n });\n\n this.logger.error('Health check exception', { \n plugin: pluginName, \n error \n });\n }\n\n // Create health report\n const report: PluginHealthReport = {\n status: this.healthStatus.get(pluginName) || 'unknown',\n timestamp: new Date().toISOString(),\n message,\n metrics: {\n uptime: Date.now() - startTime,\n },\n checks: checks.length > 0 ? checks : undefined,\n };\n\n this.healthReports.set(pluginName, report);\n }\n\n /**\n * Attempt to restart a plugin\n */\n private async attemptRestart(\n pluginName: string,\n plugin: Plugin,\n config: PluginHealthCheck\n ): Promise<void> {\n const attempts = this.restartAttempts.get(pluginName) || 0;\n \n if (attempts >= config.maxRestartAttempts) {\n this.logger.error('Max restart attempts reached, giving up', { \n plugin: pluginName, \n attempts \n });\n this.healthStatus.set(pluginName, 'failed');\n return;\n }\n\n this.restartAttempts.set(pluginName, attempts + 1);\n \n // Calculate backoff delay\n const delay = this.calculateBackoff(attempts, config.restartBackoff);\n \n this.logger.info('Scheduling plugin restart', { \n plugin: pluginName, \n attempt: attempts + 1, \n delay \n });\n\n await new Promise(resolve => setTimeout(resolve, delay));\n\n try {\n // Call destroy and init to restart\n if (plugin.destroy) {\n await plugin.destroy();\n }\n \n // Note: Full restart would require kernel context\n // This is a simplified version - actual implementation would need kernel integration\n this.logger.info('Plugin restarted', { plugin: pluginName });\n \n // Reset counters on successful restart\n this.failureCounters.set(pluginName, 0);\n this.successCounters.set(pluginName, 0);\n this.healthStatus.set(pluginName, 'recovering');\n } catch (error) {\n this.logger.error('Plugin restart failed', { \n plugin: pluginName, \n error \n });\n this.healthStatus.set(pluginName, 'failed');\n }\n }\n\n /**\n * Calculate backoff delay for restarts\n */\n private calculateBackoff(attempt: number, strategy: 'fixed' | 'linear' | 'exponential'): number {\n const baseDelay = 1000; // 1 second base\n\n switch (strategy) {\n case 'fixed':\n return baseDelay;\n case 'linear':\n return baseDelay * (attempt + 1);\n case 'exponential':\n return baseDelay * Math.pow(2, attempt);\n default:\n return baseDelay;\n }\n }\n\n /**\n * Get current health status of a plugin\n */\n getHealthStatus(pluginName: string): PluginHealthStatus | undefined {\n return this.healthStatus.get(pluginName);\n }\n\n /**\n * Get latest health report for a plugin\n */\n getHealthReport(pluginName: string): PluginHealthReport | undefined {\n return this.healthReports.get(pluginName);\n }\n\n /**\n * Get all health statuses\n */\n getAllHealthStatuses(): Map<string, PluginHealthStatus> {\n return new Map(this.healthStatus);\n }\n\n /**\n * Shutdown health monitor\n */\n shutdown(): void {\n // Stop all monitoring intervals\n for (const pluginName of this.checkIntervals.keys()) {\n this.stopMonitoring(pluginName);\n }\n \n this.healthChecks.clear();\n this.healthStatus.clear();\n this.healthReports.clear();\n this.failureCounters.clear();\n this.successCounters.clear();\n this.restartAttempts.clear();\n \n this.logger.info('Health monitor shutdown complete');\n }\n\n /**\n * Timeout helper\n */\n private timeout<T>(ms: number, message: string): Promise<T> {\n return new Promise((_, reject) => {\n setTimeout(() => reject(new Error(message)), ms);\n });\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { createHash } from 'node:crypto';\n\nimport type { \n HotReloadConfig, \n PluginStateSnapshot \n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from './logger.js';\nimport type { Plugin } from './types.js';\n\n// Polyfill for UUID generation to support both Node.js and Browser\nconst generateUUID = () => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Basic UUID v4 fallback\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n};\n\n/**\n * Plugin State Manager\n * \n * Handles state persistence and restoration during hot reloads\n */\nclass PluginStateManager {\n private logger: ObjectLogger;\n private stateSnapshots = new Map<string, PluginStateSnapshot>();\n private memoryStore = new Map<string, any>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'StateManager' });\n }\n\n /**\n * Save plugin state before reload\n */\n async saveState(\n pluginId: string,\n version: string,\n state: Record<string, any>,\n config: HotReloadConfig\n ): Promise<string> {\n const snapshot: PluginStateSnapshot = {\n pluginId,\n version,\n timestamp: new Date().toISOString(),\n state,\n metadata: {\n checksum: this.calculateChecksum(state),\n compressed: false,\n },\n };\n\n const snapshotId = generateUUID();\n\n switch (config.stateStrategy) {\n case 'memory':\n this.memoryStore.set(snapshotId, snapshot);\n this.logger.debug('State saved to memory', { pluginId, snapshotId });\n break;\n\n case 'disk':\n // For disk storage, we would write to file system\n // For now, store in memory as fallback\n this.memoryStore.set(snapshotId, snapshot);\n this.logger.debug('State saved to disk (memory fallback)', { pluginId, snapshotId });\n break;\n\n case 'distributed':\n // For distributed storage, would use Redis/etcd\n // For now, store in memory as fallback\n this.memoryStore.set(snapshotId, snapshot);\n this.logger.debug('State saved to distributed store (memory fallback)', { \n pluginId, \n snapshotId \n });\n break;\n\n case 'none':\n this.logger.debug('State persistence disabled', { pluginId });\n break;\n }\n\n this.stateSnapshots.set(pluginId, snapshot);\n return snapshotId;\n }\n\n /**\n * Restore plugin state after reload\n */\n async restoreState(\n pluginId: string,\n snapshotId?: string\n ): Promise<Record<string, any> | undefined> {\n // Try to get from snapshot ID first, otherwise use latest for plugin\n let snapshot: PluginStateSnapshot | undefined;\n\n if (snapshotId) {\n snapshot = this.memoryStore.get(snapshotId);\n } else {\n snapshot = this.stateSnapshots.get(pluginId);\n }\n\n if (!snapshot) {\n this.logger.warn('No state snapshot found', { pluginId, snapshotId });\n return undefined;\n }\n\n // Verify checksum if available\n if (snapshot.metadata?.checksum) {\n const currentChecksum = this.calculateChecksum(snapshot.state);\n if (currentChecksum !== snapshot.metadata.checksum) {\n this.logger.error('State checksum mismatch - data may be corrupted', { \n pluginId,\n expected: snapshot.metadata.checksum,\n actual: currentChecksum\n });\n return undefined;\n }\n }\n\n this.logger.debug('State restored', { pluginId, version: snapshot.version });\n return snapshot.state;\n }\n\n /**\n * Clear state for a plugin\n */\n clearState(pluginId: string): void {\n this.stateSnapshots.delete(pluginId);\n // Note: We don't clear memory store as it might have multiple snapshots\n this.logger.debug('State cleared', { pluginId });\n }\n\n /**\n * Calculate checksum for state verification using SHA-256.\n */\n private calculateChecksum(state: Record<string, any>): string {\n const stateStr = JSON.stringify(state);\n return createHash('sha256').update(stateStr).digest('hex');\n }\n\n /**\n * Shutdown state manager\n */\n shutdown(): void {\n this.stateSnapshots.clear();\n this.memoryStore.clear();\n this.logger.info('State manager shutdown complete');\n }\n}\n\n/**\n * Hot Reload Manager\n * \n * Manages hot reloading of plugins with state preservation\n */\nexport class HotReloadManager {\n private logger: ObjectLogger;\n private stateManager: PluginStateManager;\n private reloadConfigs = new Map<string, HotReloadConfig>();\n private watchHandles = new Map<string, any>();\n private reloadTimers = new Map<string, NodeJS.Timeout>();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'HotReload' });\n this.stateManager = new PluginStateManager(logger);\n }\n\n /**\n * Register a plugin for hot reload\n */\n registerPlugin(pluginName: string, config: HotReloadConfig): void {\n if (!config.enabled) {\n this.logger.debug('Hot reload disabled for plugin', { plugin: pluginName });\n return;\n }\n\n this.reloadConfigs.set(pluginName, config);\n this.logger.info('Plugin registered for hot reload', { \n plugin: pluginName,\n watchPatterns: config.watchPatterns,\n stateStrategy: config.stateStrategy\n });\n }\n\n /**\n * Start watching for changes (requires file system integration)\n */\n startWatching(pluginName: string): void {\n const config = this.reloadConfigs.get(pluginName);\n if (!config || !config.enabled) {\n return;\n }\n\n // Note: Actual file watching would require chokidar or similar\n // This is a placeholder for the integration point\n this.logger.info('File watching started', { \n plugin: pluginName,\n patterns: config.watchPatterns \n });\n }\n\n /**\n * Stop watching for changes\n */\n stopWatching(pluginName: string): void {\n const handle = this.watchHandles.get(pluginName);\n if (handle) {\n // Stop watching (would call chokidar close())\n this.watchHandles.delete(pluginName);\n this.logger.info('File watching stopped', { plugin: pluginName });\n }\n\n // Clear any pending reload timers\n const timer = this.reloadTimers.get(pluginName);\n if (timer) {\n clearTimeout(timer);\n this.reloadTimers.delete(pluginName);\n }\n }\n\n /**\n * Trigger hot reload for a plugin\n */\n async reloadPlugin(\n pluginName: string,\n plugin: Plugin,\n version: string,\n getPluginState: () => Record<string, any>,\n restorePluginState: (state: Record<string, any>) => void\n ): Promise<boolean> {\n const config = this.reloadConfigs.get(pluginName);\n if (!config) {\n this.logger.warn('Cannot reload - plugin not registered', { plugin: pluginName });\n return false;\n }\n\n this.logger.info('Starting hot reload', { plugin: pluginName });\n\n try {\n // Call before reload hooks\n if (config.beforeReload) {\n this.logger.debug('Executing before reload hooks', { \n plugin: pluginName,\n hooks: config.beforeReload \n });\n // Hook execution would be done through kernel's hook system\n }\n\n // Save state if configured\n let snapshotId: string | undefined;\n if (config.preserveState && config.stateStrategy !== 'none') {\n const state = getPluginState();\n snapshotId = await this.stateManager.saveState(\n pluginName,\n version,\n state,\n config\n );\n this.logger.debug('Plugin state saved', { plugin: pluginName, snapshotId });\n }\n\n // Gracefully shutdown the plugin\n if (plugin.destroy) {\n this.logger.debug('Destroying plugin', { plugin: pluginName });\n \n const shutdownPromise = plugin.destroy();\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error('Shutdown timeout')), config.shutdownTimeout);\n });\n\n await Promise.race([shutdownPromise, timeoutPromise]);\n this.logger.debug('Plugin destroyed successfully', { plugin: pluginName });\n }\n\n // At this point, the kernel would reload the plugin module\n // This would be handled by the plugin loader\n this.logger.debug('Plugin module would be reloaded here', { plugin: pluginName });\n\n // Restore state if we saved it\n if (snapshotId && config.preserveState) {\n const restoredState = await this.stateManager.restoreState(pluginName, snapshotId);\n if (restoredState) {\n restorePluginState(restoredState);\n this.logger.debug('Plugin state restored', { plugin: pluginName });\n }\n }\n\n // Call after reload hooks\n if (config.afterReload) {\n this.logger.debug('Executing after reload hooks', { \n plugin: pluginName,\n hooks: config.afterReload \n });\n // Hook execution would be done through kernel's hook system\n }\n\n this.logger.info('Hot reload completed successfully', { plugin: pluginName });\n return true;\n } catch (error) {\n this.logger.error('Hot reload failed', { \n plugin: pluginName, \n error \n });\n return false;\n }\n }\n\n /**\n * Schedule a reload with debouncing\n */\n scheduleReload(\n pluginName: string,\n reloadFn: () => Promise<void>\n ): void {\n const config = this.reloadConfigs.get(pluginName);\n if (!config) {\n return;\n }\n\n // Clear existing timer\n const existingTimer = this.reloadTimers.get(pluginName);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Schedule new reload with debounce\n const timer = setTimeout(() => {\n this.logger.debug('Debounce period elapsed, executing reload', { \n plugin: pluginName \n });\n reloadFn().catch(error => {\n this.logger.error('Scheduled reload failed', { \n plugin: pluginName, \n error \n });\n });\n this.reloadTimers.delete(pluginName);\n }, config.debounceDelay);\n\n this.reloadTimers.set(pluginName, timer);\n this.logger.debug('Reload scheduled with debounce', { \n plugin: pluginName,\n delay: config.debounceDelay \n });\n }\n\n /**\n * Get state manager for direct access\n */\n getStateManager(): PluginStateManager {\n return this.stateManager;\n }\n\n /**\n * Shutdown hot reload manager\n */\n shutdown(): void {\n // Stop all watching\n for (const pluginName of this.watchHandles.keys()) {\n this.stopWatching(pluginName);\n }\n\n // Clear all timers\n for (const timer of this.reloadTimers.values()) {\n clearTimeout(timer);\n }\n\n this.reloadConfigs.clear();\n this.watchHandles.clear();\n this.reloadTimers.clear();\n this.stateManager.shutdown();\n \n this.logger.info('Hot reload manager shutdown complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { \n SemanticVersion,\n VersionConstraint,\n CompatibilityLevel,\n DependencyConflict\n} from '@objectstack/spec/kernel';\nimport type { ObjectLogger } from './logger.js';\n\n/**\n * Semantic Version Parser and Comparator\n * \n * Implements semantic versioning comparison and constraint matching\n */\nexport class SemanticVersionManager {\n /**\n * Parse a version string into semantic version components\n */\n static parse(versionStr: string): SemanticVersion {\n // Remove 'v' prefix if present\n const cleanVersion = versionStr.replace(/^v/, '');\n \n // Match semver pattern: major.minor.patch[-prerelease][+build]\n const match = cleanVersion.match(\n /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([a-zA-Z0-9.-]+))?(?:\\+([a-zA-Z0-9.-]+))?$/\n );\n\n if (!match) {\n throw new Error(`Invalid semantic version: ${versionStr}`);\n }\n\n return {\n major: parseInt(match[1], 10),\n minor: parseInt(match[2], 10),\n patch: parseInt(match[3], 10),\n preRelease: match[4],\n build: match[5],\n };\n }\n\n /**\n * Convert semantic version back to string\n */\n static toString(version: SemanticVersion): string {\n let str = `${version.major}.${version.minor}.${version.patch}`;\n if (version.preRelease) {\n str += `-${version.preRelease}`;\n }\n if (version.build) {\n str += `+${version.build}`;\n }\n return str;\n }\n\n /**\n * Compare two semantic versions\n * Returns: -1 if a < b, 0 if a === b, 1 if a > b\n */\n static compare(a: SemanticVersion, b: SemanticVersion): number {\n // Compare major, minor, patch\n if (a.major !== b.major) return a.major - b.major;\n if (a.minor !== b.minor) return a.minor - b.minor;\n if (a.patch !== b.patch) return a.patch - b.patch;\n\n // Pre-release versions have lower precedence\n if (a.preRelease && !b.preRelease) return -1;\n if (!a.preRelease && b.preRelease) return 1;\n \n // Compare pre-release versions\n if (a.preRelease && b.preRelease) {\n return a.preRelease.localeCompare(b.preRelease);\n }\n\n return 0;\n }\n\n /**\n * Check if version satisfies constraint\n */\n static satisfies(version: SemanticVersion, constraint: VersionConstraint): boolean {\n const constraintStr = constraint as string;\n\n // Any version\n if (constraintStr === '*' || constraintStr === 'latest') {\n return true;\n }\n\n // Exact version\n if (/^[\\d.]+$/.test(constraintStr)) {\n const exact = this.parse(constraintStr);\n return this.compare(version, exact) === 0;\n }\n\n // Caret range (^): Compatible with version\n if (constraintStr.startsWith('^')) {\n const base = this.parse(constraintStr.slice(1));\n return (\n version.major === base.major &&\n this.compare(version, base) >= 0\n );\n }\n\n // Tilde range (~): Approximately equivalent\n if (constraintStr.startsWith('~')) {\n const base = this.parse(constraintStr.slice(1));\n return (\n version.major === base.major &&\n version.minor === base.minor &&\n this.compare(version, base) >= 0\n );\n }\n\n // Greater than or equal\n if (constraintStr.startsWith('>=')) {\n const base = this.parse(constraintStr.slice(2));\n return this.compare(version, base) >= 0;\n }\n\n // Greater than\n if (constraintStr.startsWith('>')) {\n const base = this.parse(constraintStr.slice(1));\n return this.compare(version, base) > 0;\n }\n\n // Less than or equal\n if (constraintStr.startsWith('<=')) {\n const base = this.parse(constraintStr.slice(2));\n return this.compare(version, base) <= 0;\n }\n\n // Less than\n if (constraintStr.startsWith('<')) {\n const base = this.parse(constraintStr.slice(1));\n return this.compare(version, base) < 0;\n }\n\n // Range (1.2.3 - 2.3.4)\n const rangeMatch = constraintStr.match(/^([\\d.]+)\\s*-\\s*([\\d.]+)$/);\n if (rangeMatch) {\n const min = this.parse(rangeMatch[1]);\n const max = this.parse(rangeMatch[2]);\n return this.compare(version, min) >= 0 && this.compare(version, max) <= 0;\n }\n\n return false;\n }\n\n /**\n * Determine compatibility level between two versions\n */\n static getCompatibilityLevel(from: SemanticVersion, to: SemanticVersion): CompatibilityLevel {\n const cmp = this.compare(from, to);\n\n // Same version\n if (cmp === 0) {\n return 'fully-compatible';\n }\n\n // Major version changed - breaking changes\n if (from.major !== to.major) {\n return 'breaking-changes';\n }\n\n // Minor version increased - backward compatible\n if (from.minor < to.minor) {\n return 'backward-compatible';\n }\n\n // Patch version increased - fully compatible\n if (from.patch < to.patch) {\n return 'fully-compatible';\n }\n\n // Downgrade - incompatible\n return 'incompatible';\n }\n}\n\n/**\n * Plugin Dependency Resolver\n * \n * Resolves plugin dependencies using topological sorting and conflict detection\n */\nexport class DependencyResolver {\n private logger: ObjectLogger;\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'DependencyResolver' });\n }\n\n /**\n * Resolve dependencies using topological sort\n */\n resolve(\n plugins: Map<string, { version?: string; dependencies?: string[] }>\n ): string[] {\n const graph = new Map<string, string[]>();\n const inDegree = new Map<string, number>();\n\n // Build dependency graph\n for (const [pluginName, pluginInfo] of plugins) {\n if (!graph.has(pluginName)) {\n graph.set(pluginName, []);\n inDegree.set(pluginName, 0);\n }\n\n const deps = pluginInfo.dependencies || [];\n for (const dep of deps) {\n // Check if dependency exists\n if (!plugins.has(dep)) {\n throw new Error(`Missing dependency: ${pluginName} requires ${dep}`);\n }\n\n // Add edge\n if (!graph.has(dep)) {\n graph.set(dep, []);\n inDegree.set(dep, 0);\n }\n graph.get(dep)!.push(pluginName);\n inDegree.set(pluginName, (inDegree.get(pluginName) || 0) + 1);\n }\n }\n\n // Topological sort using Kahn's algorithm\n const queue: string[] = [];\n const result: string[] = [];\n\n // Add all nodes with no incoming edges\n for (const [node, degree] of inDegree) {\n if (degree === 0) {\n queue.push(node);\n }\n }\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n result.push(node);\n\n // Reduce in-degree for dependent nodes\n const dependents = graph.get(node) || [];\n for (const dependent of dependents) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n \n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n // Check for circular dependencies\n if (result.length !== plugins.size) {\n const remaining = Array.from(plugins.keys()).filter(p => !result.includes(p));\n this.logger.error('Circular dependency detected', { remaining });\n throw new Error(`Circular dependency detected among: ${remaining.join(', ')}`);\n }\n\n this.logger.debug('Dependencies resolved', { order: result });\n return result;\n }\n\n /**\n * Detect dependency conflicts\n */\n detectConflicts(\n plugins: Map<string, { version: string; dependencies?: Record<string, VersionConstraint> }>\n ): DependencyConflict[] {\n const conflicts: DependencyConflict[] = [];\n const versionRequirements = new Map<string, Map<string, VersionConstraint>>();\n\n // Collect all version requirements\n for (const [pluginName, pluginInfo] of plugins) {\n if (!pluginInfo.dependencies) continue;\n\n for (const [depName, constraint] of Object.entries(pluginInfo.dependencies)) {\n if (!versionRequirements.has(depName)) {\n versionRequirements.set(depName, new Map());\n }\n versionRequirements.get(depName)!.set(pluginName, constraint);\n }\n }\n\n // Check for version mismatches\n for (const [depName, requirements] of versionRequirements) {\n const depInfo = plugins.get(depName);\n if (!depInfo) continue;\n\n const depVersion = SemanticVersionManager.parse(depInfo.version);\n const unsatisfied: Array<{ pluginId: string; version: string }> = [];\n\n for (const [requiringPlugin, constraint] of requirements) {\n if (!SemanticVersionManager.satisfies(depVersion, constraint)) {\n unsatisfied.push({\n pluginId: requiringPlugin,\n version: constraint as string,\n });\n }\n }\n\n if (unsatisfied.length > 0) {\n conflicts.push({\n type: 'version-mismatch',\n severity: 'error',\n description: `Version mismatch for ${depName}: detected ${unsatisfied.length} unsatisfied requirements`,\n plugins: [\n { pluginId: depName, version: depInfo.version },\n ...unsatisfied,\n ],\n resolutions: [{\n strategy: 'upgrade',\n description: `Upgrade ${depName} to satisfy all constraints`,\n targetPlugins: [depName],\n automatic: false,\n } as any],\n });\n }\n }\n\n // Check for circular dependencies (will be caught by resolve())\n try {\n this.resolve(new Map(\n Array.from(plugins.entries()).map(([name, info]) => [\n name,\n { version: info.version, dependencies: info.dependencies ? Object.keys(info.dependencies) : [] }\n ])\n ));\n } catch (error) {\n if (error instanceof Error && error.message.includes('Circular dependency')) {\n conflicts.push({\n type: 'circular-dependency',\n severity: 'critical',\n description: error.message,\n plugins: [], // Would need to extract from error\n resolutions: [{\n strategy: 'manual',\n description: 'Remove circular dependency by restructuring plugins',\n automatic: false,\n } as any],\n });\n }\n }\n\n return conflicts;\n }\n\n /**\n * Find best version that satisfies all constraints\n */\n findBestVersion(\n availableVersions: string[],\n constraints: VersionConstraint[]\n ): string | undefined {\n // Parse and sort versions (highest first)\n const versions = availableVersions\n .map(v => ({ str: v, parsed: SemanticVersionManager.parse(v) }))\n .sort((a, b) => -SemanticVersionManager.compare(a.parsed, b.parsed));\n\n // Find highest version that satisfies all constraints\n for (const version of versions) {\n const satisfiesAll = constraints.every(constraint =>\n SemanticVersionManager.satisfies(version.parsed, constraint)\n );\n\n if (satisfiesAll) {\n return version.str;\n }\n }\n\n return undefined;\n }\n\n /**\n * Check if dependencies form a valid DAG (no cycles)\n */\n isAcyclic(dependencies: Map<string, string[]>): boolean {\n try {\n const plugins = new Map(\n Array.from(dependencies.entries()).map(([name, deps]) => [\n name,\n { dependencies: deps }\n ])\n );\n this.resolve(plugins);\n return true;\n } catch {\n return false;\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ObjectLogger } from './logger.js';\n\n/**\n * Namespace entry representing an object/view/flow etc. registered by a package.\n */\nexport interface NamespaceEntry {\n /** The namespace path (e.g. \"objects.project_task\", \"views.task_list\") */\n namespace: string;\n /** The package that owns this namespace */\n packageId: string;\n /** When this entry was registered */\n registeredAt: string;\n}\n\n/**\n * Result of a namespace conflict check.\n */\nexport interface NamespaceConflict {\n /** The conflicting namespace path */\n namespace: string;\n /** The package that currently owns this namespace */\n existingPackageId: string;\n /** The package attempting to register the same namespace */\n incomingPackageId: string;\n /** A suggested alternative name to avoid the conflict */\n suggestion?: string;\n}\n\n/**\n * Result of namespace availability check.\n */\nexport interface NamespaceCheckResult {\n /** Whether all requested namespaces are available */\n available: boolean;\n /** List of conflicts detected */\n conflicts: NamespaceConflict[];\n /** Suggested alternatives for each conflict */\n suggestions: Record<string, string>;\n}\n\n/**\n * Namespace Resolver\n *\n * Manages namespace registration for installed packages and detects collisions\n * during install-time. Each metadata item (object, view, flow, page, etc.)\n * produces a namespace like `objects.<name>` or `views.<name>`.\n *\n * When a new package declares objects, views, or other metadata that would\n * collide with an existing package's metadata, this resolver reports the\n * conflicts and suggests prefixed alternatives.\n */\nexport class NamespaceResolver {\n private logger: ObjectLogger;\n private registry: Map<string, NamespaceEntry> = new Map();\n\n constructor(logger: ObjectLogger) {\n this.logger = logger.child({ component: 'NamespaceResolver' });\n }\n\n /**\n * Register namespaces owned by a package.\n */\n register(packageId: string, namespaces: string[]): void {\n const now = new Date().toISOString();\n for (const ns of namespaces) {\n if (this.registry.has(ns)) {\n const existing = this.registry.get(ns)!;\n if (existing.packageId !== packageId) {\n this.logger.warn('Overwriting namespace entry', { namespace: ns, existing: existing.packageId, incoming: packageId });\n }\n }\n this.registry.set(ns, { namespace: ns, packageId, registeredAt: now });\n this.logger.debug('Namespace registered', { namespace: ns, packageId });\n }\n }\n\n /**\n * Unregister all namespaces belonging to a package.\n */\n unregister(packageId: string): string[] {\n const removed: string[] = [];\n for (const [ns, entry] of this.registry) {\n if (entry.packageId === packageId) {\n this.registry.delete(ns);\n removed.push(ns);\n }\n }\n this.logger.debug('Namespaces unregistered', { packageId, count: removed.length });\n return removed;\n }\n\n /**\n * Check whether a set of namespaces is available for a given package.\n */\n checkAvailability(packageId: string, namespaces: string[]): NamespaceCheckResult {\n const conflicts: NamespaceConflict[] = [];\n const suggestions: Record<string, string> = {};\n\n for (const ns of namespaces) {\n const existing = this.registry.get(ns);\n if (existing && existing.packageId !== packageId) {\n const suggestion = this.suggestAlternative(ns, packageId);\n conflicts.push({\n namespace: ns,\n existingPackageId: existing.packageId,\n incomingPackageId: packageId,\n suggestion,\n });\n suggestions[ns] = suggestion;\n }\n }\n\n return {\n available: conflicts.length === 0,\n conflicts,\n suggestions,\n };\n }\n\n /**\n * Extract namespace strings from a package's metadata definition.\n */\n extractNamespaces(config: Record<string, unknown>): string[] {\n const namespaces: string[] = [];\n const categories = [\n 'objects', 'views', 'pages', 'flows', 'workflows',\n 'apps', 'dashboards', 'reports', 'actions', 'agents',\n ];\n\n for (const category of categories) {\n const items = config[category];\n if (Array.isArray(items)) {\n for (const item of items) {\n const name = (item as Record<string, unknown>)?.name;\n if (typeof name === 'string') {\n namespaces.push(`${category}.${name}`);\n }\n }\n } else if (items && typeof items === 'object') {\n for (const key of Object.keys(items as object)) {\n namespaces.push(`${category}.${key}`);\n }\n }\n }\n\n return namespaces;\n }\n\n /**\n * Get all registered entries.\n */\n getRegistry(): ReadonlyMap<string, NamespaceEntry> {\n return this.registry;\n }\n\n /**\n * Get all namespaces belonging to a specific package.\n */\n getPackageNamespaces(packageId: string): string[] {\n const namespaces: string[] = [];\n for (const [ns, entry] of this.registry) {\n if (entry.packageId === packageId) {\n namespaces.push(ns);\n }\n }\n return namespaces;\n }\n\n /**\n * Generate a prefixed alternative namespace to avoid conflicts.\n */\n private suggestAlternative(ns: string, packageId: string): string {\n // Extract the short package name for prefixing\n const shortName = packageId\n .replace(/^@[^/]+\\//, '')\n .replace(/^plugin-/, '')\n .replace(/-/g, '_');\n\n const parts = ns.split('.');\n if (parts.length >= 2) {\n // e.g. \"objects.task\" → \"objects.crm_task\"\n return `${parts[0]}.${shortName}_${parts.slice(1).join('.')}`;\n }\n return `${shortName}_${ns}`;\n }\n}\n"],"mappings":"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","names":["nodePath","cryptoSign","cryptoVerify","ServiceLifecycle","service","nodePath","import_node_crypto","safeJsonParse","import_node_crypto"]}