@objectstack/objectql 9.1.0 → 9.3.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/seed-loader.ts","../src/build-probes.ts","../src/index.ts","../src/registry.ts","../src/protocol.ts","../src/sys-metadata-repository.ts","../src/metadata-diagnostics.ts","../src/engine.ts","../src/secret-fields.ts","../src/hook-wrappers.ts","../src/hook-metrics.ts","../src/hook-binder.ts","../src/validation/record-validator.ts","../src/validation/rule-validator.ts","../src/in-memory-aggregation.ts","../src/metadata-facade.ts","../src/plugin.ts","../src/kernel-factory.ts","../src/util.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { IDataEngine, IMetadataService, ISeedLoaderService } from '@objectstack/spec/contracts';\nimport type {\n SeedLoaderRequest,\n SeedLoaderResult,\n SeedLoaderConfig,\n SeedLoaderConfigInput,\n ObjectDependencyGraph,\n ObjectDependencyNode,\n ReferenceResolution,\n ReferenceResolutionError,\n SeedLoadResult,\n Seed,\n} from '@objectstack/spec/data';\nimport { SeedLoaderConfigSchema } from '@objectstack/spec/data';\nimport { resolveSeedRecord } from '@objectstack/formula';\n\ninterface Logger {\n info(message: string, meta?: Record<string, any>): void;\n warn(message: string, meta?: Record<string, any>): void;\n error(message: string, error?: Error, meta?: Record<string, any>): void;\n debug(message: string, meta?: Record<string, any>): void;\n}\n\n/** Default field used for externalId matching on target objects */\nconst DEFAULT_EXTERNAL_ID_FIELD = 'name';\n\n/**\n * SeedLoaderService — Runtime implementation of ISeedLoaderService\n *\n * Provides metadata-driven seed data loading with:\n * - Automatic lookup/master_detail reference resolution via externalId\n * - Topological dependency ordering (parents before children)\n * - Multi-pass loading for circular references\n * - Dry-run validation mode\n * - Upsert support honoring SeedSchema mode\n * - Actionable error reporting\n */\nexport class SeedLoaderService implements ISeedLoaderService {\n private engine: IDataEngine;\n private metadata: IMetadataService;\n private logger: Logger;\n\n constructor(engine: IDataEngine, metadata: IMetadataService, logger: Logger) {\n this.engine = engine;\n this.metadata = metadata;\n this.logger = logger;\n }\n\n // ==========================================================================\n // Public API\n // ==========================================================================\n\n async load(request: SeedLoaderRequest): Promise<SeedLoaderResult> {\n const startTime = Date.now();\n const config = request.config;\n const allErrors: ReferenceResolutionError[] = [];\n const allResults: SeedLoadResult[] = [];\n\n // 1. Filter datasets by environment\n const datasets = this.filterByEnv(request.seeds, config.env);\n\n if (datasets.length === 0) {\n return this.buildEmptyResult(config, Date.now() - startTime);\n }\n\n // 2. Build dependency graph\n const objectNames = datasets.map(d => d.object);\n const graph = await this.buildDependencyGraph(objectNames);\n\n this.logger.info('[SeedLoader] Dependency graph built', {\n objects: objectNames.length,\n insertOrder: graph.insertOrder,\n circularDeps: graph.circularDependencies.length,\n });\n\n // 3. Order datasets by topological insert order\n const orderedDatasets = this.orderDatasets(datasets, graph.insertOrder);\n\n // 4. Build reference lookup map from metadata (field → target object)\n const refMap = this.buildReferenceMap(graph);\n\n // 5. Pass 1: Insert/upsert records, resolving references\n const insertedRecords = new Map<string, Map<string, string>>(); // object → externalIdValue → internalId\n const deferredUpdates: DeferredUpdate[] = [];\n\n for (const dataset of orderedDatasets) {\n const result = await this.loadDataset(\n dataset, config, refMap, insertedRecords, deferredUpdates, allErrors\n );\n allResults.push(result);\n\n if (config.haltOnError && result.errored > 0) {\n this.logger.warn('[SeedLoader] Halting on first error', { object: dataset.object });\n break;\n }\n }\n\n // 6. Pass 2: Resolve deferred references (circular dependencies)\n if (config.multiPass && deferredUpdates.length > 0 && !config.dryRun) {\n this.logger.info('[SeedLoader] Pass 2: resolving deferred references', {\n count: deferredUpdates.length,\n });\n await this.resolveDeferredUpdates(deferredUpdates, insertedRecords, allResults, allErrors, config.organizationId);\n }\n\n // 7. Build final result\n const durationMs = Date.now() - startTime;\n return this.buildResult(config, graph, allResults, allErrors, durationMs);\n }\n\n async buildDependencyGraph(objectNames: string[]): Promise<ObjectDependencyGraph> {\n const nodes: ObjectDependencyNode[] = [];\n const objectSet = new Set(objectNames);\n\n for (const objectName of objectNames) {\n const objDef = await this.metadata.getObject(objectName) as any;\n const dependsOn: string[] = [];\n const references: ReferenceResolution[] = [];\n\n if (objDef && objDef.fields) {\n const fields = objDef.fields as Record<string, any>;\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n if (\n (fieldDef.type === 'lookup' || fieldDef.type === 'master_detail') &&\n fieldDef.reference\n ) {\n const targetObject = fieldDef.reference as string;\n\n // Track dependency ordering only for objects within the graph\n if (objectSet.has(targetObject) && !dependsOn.includes(targetObject)) {\n dependsOn.push(targetObject);\n }\n\n // Track ALL references for resolution (target may exist in database)\n references.push({\n field: fieldName,\n targetObject,\n targetField: DEFAULT_EXTERNAL_ID_FIELD,\n fieldType: fieldDef.type as 'lookup' | 'master_detail',\n });\n }\n }\n }\n\n nodes.push({ object: objectName, dependsOn, references });\n }\n\n // Topological sort\n const { insertOrder, circularDependencies } = this.topologicalSort(nodes);\n\n return { nodes, insertOrder, circularDependencies };\n }\n\n async validate(datasets: Seed[], config?: SeedLoaderConfigInput): Promise<SeedLoaderResult> {\n const parsedConfig = SeedLoaderConfigSchema.parse({ ...config, dryRun: true });\n return this.load({ seeds: datasets, config: parsedConfig });\n }\n\n // ==========================================================================\n // Internal: Seed Loading\n // ==========================================================================\n\n private async loadDataset(\n dataset: Seed,\n config: SeedLoaderConfig,\n refMap: Map<string, ReferenceResolution[]>,\n insertedRecords: Map<string, Map<string, string>>,\n deferredUpdates: DeferredUpdate[],\n allErrors: ReferenceResolutionError[],\n ): Promise<SeedLoadResult> {\n const objectName = dataset.object;\n const mode = dataset.mode || config.defaultMode;\n const externalId = dataset.externalId || 'name';\n\n let inserted = 0;\n let updated = 0;\n let skipped = 0;\n let errored = 0;\n let referencesResolved = 0;\n let referencesDeferred = 0;\n const errors: ReferenceResolutionError[] = [];\n\n // Ensure the object's record map exists\n if (!insertedRecords.has(objectName)) {\n insertedRecords.set(objectName, new Map());\n }\n\n // Pre-load existing records for upsert matching. When a target\n // organization is set, scope the lookup so each tenant gets its\n // own copy (otherwise upsert would clobber other tenants' rows\n // that share the same natural key — e.g. `name: 'Acme Corp'`).\n let existingRecords: Map<string, any> | undefined;\n if ((mode === 'upsert' || mode === 'update' || mode === 'ignore') && !config.dryRun) {\n existingRecords = await this.loadExistingRecords(\n objectName,\n externalId,\n config.organizationId,\n );\n }\n\n // Get reference resolutions for this object\n const objectRefs = refMap.get(objectName) || [];\n\n // Pin a single `now()` snapshot for the entire dataset so multi-pass\n // loads see one logical clock — the M9 determinism guarantee for seeds.\n const seedNow = new Date();\n\n // Identity/context bound to seed CEL expressions. `os.user` / `os.org`\n // resolve from here, so `owner_id: cel\\`os.user.id\\`` works. When no\n // identity is supplied, `os.user` / `os.org` are simply unbound and any\n // record that references them fails loudly below (rather than silently\n // writing a raw Expression envelope into the column).\n const seedIdentity = config.identity;\n const baseEvalCtx = {\n now: seedNow,\n user: seedIdentity?.user,\n // Fall back to the per-tenant organizationId so `os.org.id` resolves\n // during per-org replay even without an explicit identity.org.\n org: seedIdentity?.org ?? (config.organizationId ? { id: config.organizationId } : undefined),\n env: config.env,\n };\n\n for (let i = 0; i < dataset.records.length; i++) {\n // Resolve any embedded Expression envelopes (e.g. `cel\\`daysFromNow(30)\\``,\n // `cel\\`os.user.id\\``) BEFORE reference resolution so downstream lookups\n // see resolved values.\n const seedResult = resolveSeedRecord(\n dataset.records[i] as Record<string, never>,\n baseEvalCtx,\n );\n if (!seedResult.ok) {\n // LOUD FAILURE: a record whose dynamic values cannot be resolved is\n // dropped — but never silently. Record an actionable error (so it\n // surfaces in result.errors and flips success=false) instead of\n // writing the unresolved Expression envelope into the database.\n errored++;\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: '(expression)',\n targetObject: objectName,\n targetField: '(expression)',\n attemptedValue: dataset.records[i],\n recordIndex: i,\n message:\n `Cannot resolve dynamic seed values for ${objectName} record #${i}: ${seedResult.error.message}. ` +\n 'Records using cel`os.user.id` / cel`os.org.id` require a seed identity — ' +\n 'ensure a system/admin user exists before seeding (see SeedLoaderConfig.identity).',\n };\n errors.push(error);\n allErrors.push(error);\n this.logger.warn(`[SeedLoader] ${error.message}`);\n continue;\n }\n const record = { ...(seedResult.value as Record<string, unknown>) };\n\n // Per-tenant tagging: when a target org is set, stamp every\n // seeded row with it (unless the record itself already supplies\n // an explicit organization_id — respect dataset author overrides).\n // Skipped objects that don't declare `organization_id` will have\n // the extra key silently ignored by the engine.\n if (config.organizationId && record['organization_id'] == null) {\n record['organization_id'] = config.organizationId;\n }\n\n // Resolve references\n for (const ref of objectRefs) {\n const fieldValue = record[ref.field];\n if (fieldValue === undefined || fieldValue === null) continue;\n\n // LOUD FAILURE: a reference must be a natural-key string (or an\n // internal id). An object value — e.g. the wrapper `{ externalId: 'X' }`\n // — never resolves: it would otherwise fall through unresolved and reach\n // the driver as a non-bindable value (\"SQLite3 can only bind ...\"). This\n // used to be silently skipped (and only crashed on a persistent DB's\n // update path), so catch it here and report the actionable fix instead.\n if (typeof fieldValue === 'object') {\n const wrapped = (fieldValue as Record<string, unknown>).externalId;\n const hint =\n wrapped !== undefined\n ? ` Pass the natural key directly: ${ref.field}: ${JSON.stringify(wrapped)}.`\n : ` Pass the target's ${ref.targetField} value as a plain string.`;\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n message:\n `Invalid reference for ${objectName}.${ref.field}: expected a ` +\n `${ref.targetObject}.${ref.targetField} natural-key string but got an object.${hint}`,\n };\n errors.push(error);\n allErrors.push(error);\n this.logger.warn(`[SeedLoader] ${error.message}`, { recordIndex: i });\n // Drop the unresolvable value so it never reaches the driver.\n record[ref.field] = null;\n continue;\n }\n\n // Skip if value looks like an internal ID (not a natural key)\n if (typeof fieldValue !== 'string' || this.looksLikeInternalId(fieldValue)) continue;\n\n // Try to resolve via already-inserted records\n const targetMap = insertedRecords.get(ref.targetObject);\n const resolvedId = targetMap?.get(String(fieldValue));\n\n if (resolvedId) {\n record[ref.field] = resolvedId;\n referencesResolved++;\n } else if (!config.dryRun) {\n // Try to resolve from existing data in the database\n const dbId = await this.resolveFromDatabase(ref.targetObject, ref.targetField, fieldValue, config.organizationId);\n if (dbId) {\n record[ref.field] = dbId;\n referencesResolved++;\n } else if (config.multiPass) {\n // Defer to pass 2\n record[ref.field] = null;\n deferredUpdates.push({\n objectName,\n recordExternalId: String(record[externalId] ?? ''),\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n });\n referencesDeferred++;\n } else {\n // Cannot resolve - record error\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n message: `Cannot resolve reference: ${objectName}.${ref.field} = '${fieldValue}' → ${ref.targetObject}.${ref.targetField} not found`,\n };\n errors.push(error);\n allErrors.push(error);\n }\n } else {\n // Dry-run: attempt resolution, report error if not found\n const targetMap2 = insertedRecords.get(ref.targetObject);\n if (!targetMap2?.has(String(fieldValue))) {\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n message: `[dry-run] Reference may not resolve: ${objectName}.${ref.field} = '${fieldValue}' → ${ref.targetObject}.${ref.targetField}`,\n };\n errors.push(error);\n allErrors.push(error);\n }\n }\n }\n\n // Insert/upsert the record\n if (!config.dryRun) {\n try {\n const result = await this.writeRecord(\n objectName, record, mode, externalId, existingRecords\n );\n\n if (result.action === 'inserted') inserted++;\n else if (result.action === 'updated') updated++;\n else if (result.action === 'skipped') skipped++;\n\n // Track the inserted/updated record's ID for reference resolution\n const externalIdValue = String(record[externalId] ?? '');\n const internalId = result.id;\n if (externalIdValue && internalId) {\n insertedRecords.get(objectName)!.set(externalIdValue, String(internalId));\n }\n } catch (err: any) {\n // LOUD FAILURE: write errors were previously only counted +\n // warn-logged, so dropped rows were invisible in result.errors and\n // the boot summary. Surface them as actionable errors too, so the\n // overall load is marked unsuccessful and the reason is reported.\n errored++;\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: '(write)',\n targetObject: objectName,\n targetField: externalId,\n attemptedValue: record[externalId] ?? null,\n recordIndex: i,\n message: `Failed to write ${objectName} record #${i} (${externalId}=${String(record[externalId] ?? '')}): ${err.message}`,\n };\n errors.push(error);\n allErrors.push(error);\n this.logger.warn(`[SeedLoader] ${error.message}`, { recordIndex: i });\n }\n } else {\n // Dry-run: simulate insert tracking\n const externalIdValue = String(record[externalId] ?? '');\n if (externalIdValue) {\n insertedRecords.get(objectName)!.set(externalIdValue, `dry-run-id-${i}`);\n }\n inserted++; // Count as \"would be inserted\"\n }\n }\n\n return {\n object: objectName,\n mode,\n inserted,\n updated,\n skipped,\n errored,\n total: dataset.records.length,\n referencesResolved,\n referencesDeferred,\n errors,\n };\n }\n\n // ==========================================================================\n // Internal: Reference Resolution\n // ==========================================================================\n\n private async resolveFromDatabase(\n targetObject: string,\n targetField: string,\n value: unknown,\n organizationId?: string,\n ): Promise<string | null> {\n try {\n const where: Record<string, unknown> = { [targetField]: value };\n // Per-tenant replay: when scoping is requested, only consider\n // rows that belong to the target tenant so cross-tenant rows\n // never get borrowed as a \"resolved\" reference (would silently\n // create a cross-org FK).\n if (organizationId) where.organization_id = organizationId;\n const records = await this.engine.find(targetObject, {\n where,\n fields: ['id'],\n limit: 1,\n context: { isSystem: true },\n } as any);\n if (records && records.length > 0) {\n return String(records[0].id || records[0]._id);\n }\n } catch {\n // Target object may not exist yet\n }\n return null;\n }\n\n private async resolveDeferredUpdates(\n deferredUpdates: DeferredUpdate[],\n insertedRecords: Map<string, Map<string, string>>,\n allResults: SeedLoadResult[],\n allErrors: ReferenceResolutionError[],\n organizationId?: string,\n ): Promise<void> {\n for (const deferred of deferredUpdates) {\n // Try to resolve from inserted records\n const targetMap = insertedRecords.get(deferred.targetObject);\n let resolvedId = targetMap?.get(String(deferred.attemptedValue));\n\n // Try database fallback\n if (!resolvedId) {\n resolvedId = (await this.resolveFromDatabase(\n deferred.targetObject, deferred.targetField, deferred.attemptedValue, organizationId\n )) ?? undefined;\n }\n\n if (resolvedId) {\n // Find the record and update the reference\n const objectRecordMap = insertedRecords.get(deferred.objectName);\n const recordId = objectRecordMap?.get(deferred.recordExternalId);\n\n if (recordId) {\n try {\n await this.engine.update(deferred.objectName, {\n id: recordId,\n [deferred.field]: resolvedId,\n }, { context: { isSystem: true } } as any);\n\n // Update result stats\n const resultEntry = allResults.find(r => r.object === deferred.objectName);\n if (resultEntry) {\n resultEntry.referencesResolved++;\n resultEntry.referencesDeferred--;\n }\n } catch (err: any) {\n this.logger.warn('[SeedLoader] Failed to resolve deferred reference', {\n object: deferred.objectName,\n field: deferred.field,\n error: err.message,\n });\n }\n }\n } else {\n // Still unresolved after pass 2\n const error: ReferenceResolutionError = {\n sourceObject: deferred.objectName,\n field: deferred.field,\n targetObject: deferred.targetObject,\n targetField: deferred.targetField,\n attemptedValue: deferred.attemptedValue,\n recordIndex: deferred.recordIndex,\n message: `Deferred reference unresolved after pass 2: ${deferred.objectName}.${deferred.field} = '${deferred.attemptedValue}' → ${deferred.targetObject}.${deferred.targetField} not found`,\n };\n\n const resultEntry = allResults.find(r => r.object === deferred.objectName);\n if (resultEntry) {\n resultEntry.errors.push(error);\n }\n allErrors.push(error);\n }\n }\n }\n\n // ==========================================================================\n // Internal: Write Operations\n // ==========================================================================\n\n /**\n * Seed writes always run as a privileged system context. This bypasses\n * RBAC checks (so seeds can target system tables like `sys_*`) and\n * disables the SecurityPlugin's auto-injection of `organization_id` /\n * `owner_id` — seeds either declare those fields explicitly per\n * record, or are intentionally cross-tenant / global.\n */\n private static readonly SEED_OPTIONS = { context: { isSystem: true } } as const;\n\n private async writeRecord(\n objectName: string,\n record: Record<string, unknown>,\n mode: string,\n externalId: string,\n existingRecords?: Map<string, any>,\n ): Promise<{ action: 'inserted' | 'updated' | 'skipped'; id?: string }> {\n const externalIdValue = record[externalId];\n const existing = existingRecords?.get(String(externalIdValue ?? ''));\n const opts = SeedLoaderService.SEED_OPTIONS as any;\n\n switch (mode) {\n case 'insert': {\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n\n case 'update': {\n if (!existing) {\n return { action: 'skipped' };\n }\n const id = this.extractId(existing);\n await this.engine.update(objectName, { ...record, id }, opts);\n return { action: 'updated', id };\n }\n\n case 'upsert': {\n if (existing) {\n const id = this.extractId(existing);\n await this.engine.update(objectName, { ...record, id }, opts);\n return { action: 'updated', id };\n } else {\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n }\n\n case 'ignore': {\n if (existing) {\n return { action: 'skipped', id: this.extractId(existing) };\n }\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n\n case 'replace': {\n // Replace mode: just insert (caller should have cleared the table)\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n\n default: {\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n }\n }\n\n // ==========================================================================\n // Internal: Dependency Graph\n // ==========================================================================\n\n /**\n * Kahn's algorithm for topological sort with cycle detection.\n */\n private topologicalSort(\n nodes: ObjectDependencyNode[],\n ): { insertOrder: string[]; circularDependencies: string[][] } {\n const inDegree = new Map<string, number>();\n const adjacency = new Map<string, string[]>();\n const objectSet = new Set(nodes.map(n => n.object));\n\n // Initialize\n for (const node of nodes) {\n inDegree.set(node.object, 0);\n adjacency.set(node.object, []);\n }\n\n // Build adjacency list and in-degree counts\n for (const node of nodes) {\n for (const dep of node.dependsOn) {\n // Exclude self-references from ordering (e.g., employee.manager_id → employee).\n // Self-referencing fields are still tracked in node.references for resolution.\n if (objectSet.has(dep) && dep !== node.object) {\n adjacency.get(dep)!.push(node.object);\n inDegree.set(node.object, (inDegree.get(node.object) || 0) + 1);\n }\n }\n }\n\n // Kahn's algorithm\n const queue: string[] = [];\n for (const [obj, degree] of inDegree) {\n if (degree === 0) queue.push(obj);\n }\n\n const insertOrder: string[] = [];\n while (queue.length > 0) {\n const current = queue.shift()!;\n insertOrder.push(current);\n\n for (const neighbor of (adjacency.get(current) || [])) {\n const newDegree = (inDegree.get(neighbor) || 0) - 1;\n inDegree.set(neighbor, newDegree);\n if (newDegree === 0) {\n queue.push(neighbor);\n }\n }\n }\n\n // Detect circular dependencies\n const circularDependencies: string[][] = [];\n const remaining = nodes.filter(n => !insertOrder.includes(n.object));\n\n if (remaining.length > 0) {\n // Find cycles using DFS\n const cycles = this.findCycles(remaining);\n circularDependencies.push(...cycles);\n\n // Add remaining objects to insertOrder (they'll need multi-pass)\n for (const node of remaining) {\n if (!insertOrder.includes(node.object)) {\n insertOrder.push(node.object);\n }\n }\n }\n\n return { insertOrder, circularDependencies };\n }\n\n private findCycles(nodes: ObjectDependencyNode[]): string[][] {\n const cycles: string[][] = [];\n const nodeMap = new Map(nodes.map(n => [n.object, n]));\n const visited = new Set<string>();\n const inStack = new Set<string>();\n\n const dfs = (current: string, path: string[]) => {\n if (inStack.has(current)) {\n // Found a cycle\n const cycleStart = path.indexOf(current);\n if (cycleStart !== -1) {\n cycles.push([...path.slice(cycleStart), current]);\n }\n return;\n }\n if (visited.has(current)) return;\n\n visited.add(current);\n inStack.add(current);\n path.push(current);\n\n const node = nodeMap.get(current);\n if (node) {\n for (const dep of node.dependsOn) {\n if (nodeMap.has(dep)) {\n dfs(dep, [...path]);\n }\n }\n }\n\n inStack.delete(current);\n };\n\n for (const node of nodes) {\n if (!visited.has(node.object)) {\n dfs(node.object, []);\n }\n }\n\n return cycles;\n }\n\n // ==========================================================================\n // Internal: Helpers\n // ==========================================================================\n\n private filterByEnv(datasets: Seed[], env?: string): Seed[] {\n if (!env) return datasets;\n return datasets.filter(d => (d.env as string[]).includes(env));\n }\n\n private orderDatasets(datasets: Seed[], insertOrder: string[]): Seed[] {\n const orderMap = new Map(insertOrder.map((name, i) => [name, i]));\n return [...datasets].sort((a, b) => {\n const orderA = orderMap.get(a.object) ?? Number.MAX_SAFE_INTEGER;\n const orderB = orderMap.get(b.object) ?? Number.MAX_SAFE_INTEGER;\n return orderA - orderB;\n });\n }\n\n private buildReferenceMap(graph: ObjectDependencyGraph): Map<string, ReferenceResolution[]> {\n const map = new Map<string, ReferenceResolution[]>();\n for (const node of graph.nodes) {\n if (node.references.length > 0) {\n map.set(node.object, node.references);\n }\n }\n return map;\n }\n\n private async loadExistingRecords(\n objectName: string,\n externalId: string,\n organizationId?: string,\n ): Promise<Map<string, any>> {\n const map = new Map<string, any>();\n try {\n const findArgs: Record<string, unknown> = {\n fields: ['id', externalId],\n context: { isSystem: true },\n };\n // Per-tenant replay: restrict to the target tenant's own rows\n // so upsert key matching never returns another tenant's record\n // (would silently steal/overwrite rows across orgs).\n if (organizationId) findArgs.where = { organization_id: organizationId };\n const records = await this.engine.find(objectName, findArgs as any);\n for (const record of records || []) {\n const key = String(record[externalId] ?? '');\n if (key) {\n map.set(key, record);\n }\n }\n } catch {\n // Object may not have records yet\n }\n return map;\n }\n\n private looksLikeInternalId(value: string): boolean {\n // UUID v4 pattern\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {\n return true;\n }\n // MongoDB ObjectId pattern (24 hex chars)\n if (/^[0-9a-f]{24}$/i.test(value)) {\n return true;\n }\n return false;\n }\n\n private extractId(record: any): string | undefined {\n if (!record) return undefined;\n return String(record.id || record._id || '');\n }\n\n private buildEmptyResult(config: SeedLoaderConfig, durationMs: number): SeedLoaderResult {\n return {\n success: true,\n dryRun: config.dryRun,\n dependencyGraph: { nodes: [], insertOrder: [], circularDependencies: [] },\n results: [],\n errors: [],\n summary: {\n objectsProcessed: 0,\n totalRecords: 0,\n totalInserted: 0,\n totalUpdated: 0,\n totalSkipped: 0,\n totalErrored: 0,\n totalReferencesResolved: 0,\n totalReferencesDeferred: 0,\n circularDependencyCount: 0,\n durationMs,\n },\n };\n }\n\n private buildResult(\n config: SeedLoaderConfig,\n graph: ObjectDependencyGraph,\n results: SeedLoadResult[],\n errors: ReferenceResolutionError[],\n durationMs: number,\n ): SeedLoaderResult {\n const summary = {\n objectsProcessed: results.length,\n totalRecords: results.reduce((sum, r) => sum + r.total, 0),\n totalInserted: results.reduce((sum, r) => sum + r.inserted, 0),\n totalUpdated: results.reduce((sum, r) => sum + r.updated, 0),\n totalSkipped: results.reduce((sum, r) => sum + r.skipped, 0),\n totalErrored: results.reduce((sum, r) => sum + r.errored, 0),\n totalReferencesResolved: results.reduce((sum, r) => sum + r.referencesResolved, 0),\n totalReferencesDeferred: results.reduce((sum, r) => sum + r.referencesDeferred, 0),\n circularDependencyCount: graph.circularDependencies.length,\n durationMs,\n };\n\n const hasErrors = errors.length > 0 || summary.totalErrored > 0;\n\n return {\n success: !hasErrors,\n dryRun: config.dryRun,\n dependencyGraph: graph,\n results,\n errors,\n summary,\n };\n }\n}\n\n// ==========================================================================\n// Internal Types\n// ==========================================================================\n\ninterface DeferredUpdate {\n objectName: string;\n recordExternalId: string;\n field: string;\n targetObject: string;\n targetField: string;\n attemptedValue: unknown;\n recordIndex: number;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n//\n// ADR-0038 L3 — runtime probes: after a publish, exercise the published app\n// the way a user would (one real read per artifact) and report what is\n// actually broken AT RUNTIME. Schema-valid ≠ renders ≠ returns data: the\n// 2026-06-10/11 incident set shipped seeds that never materialized, dataset\n// queries that returned 0 on populated objects, and \"Published!\" states the\n// runtime couldn't read back — all invisible until something actually\n// queried. These probes are that something, run by the build pipeline (not\n// the user), generalizing the `seedApplied` pattern to the whole artifact\n// graph.\n//\n// Every finding is a BuildIssue (the ADR-0038 verification contract — same\n// shape the cloud L1 graph lint emits) with `layer: 'runtime'`, so agents,\n// chat surfaces, and eval harnesses consume one stream regardless of which\n// verification plane found the problem.\n\n/** One runtime-verification finding (ADR-0038 BuildIssue, layer 'runtime'). */\nexport interface RuntimeBuildIssue {\n layer: 'runtime';\n severity: 'error' | 'warning';\n /** The artifact whose runtime behaviour is broken. */\n artifact: { type: string; name: string };\n /** What it exercised, when narrower than the artifact (e.g. a widget). */\n ref?: { type: string; name: string; member?: string };\n /** 'seed_not_applied' | 'view_read_failed' | 'empty_query' | 'widget_query_failed' | 'probes_unavailable' */\n code: string;\n message: string;\n fix?: string;\n}\n\n/** Aggregate result of one post-publish probe pass. */\nexport interface BuildProbeReport {\n /** Findings, empty when every probe passed. */\n issues: RuntimeBuildIssue[];\n /** How many probes actually ran, per plane (0s mean nothing to probe). */\n checked: { seeds: number; views: number; widgets: number };\n}\n\n/** The single read the probes need from the data engine. */\nexport interface ProbeEngine {\n find(objectName: string, query: unknown): Promise<Array<Record<string, unknown>>>;\n}\n\n/** Optional analytics surface — when absent, widget probes degrade to a warning. */\nexport interface ProbeAnalytics {\n queryDataset(dataset: unknown, selection: unknown, context?: unknown): Promise<unknown>;\n}\n\nexport interface RunBuildProbesOptions {\n engine: ProbeEngine;\n /** Read an ACTIVE (published) item body by type+name; undefined when absent. */\n getItem: (type: string, name: string) => Promise<unknown | undefined>;\n /** The just-published artifact set (publishPackageDrafts' `published`). */\n published: Array<{ type: string; name: string }>;\n /**\n * The kernel's analytics service, when one is mounted. Widget probes run\n * the SAME `queryDataset` path the dashboard renderer hits — absent\n * service means widgets can't be probed (one aggregate warning, not\n * per-widget noise).\n */\n analytics?: ProbeAnalytics;\n /** Threaded into engine/analytics reads (tenant scoping). */\n organizationId?: string | null;\n}\n\ntype Rec = Record<string, unknown>;\n\nfunction asRec(v: unknown): Rec | undefined {\n return v && typeof v === 'object' && !Array.isArray(v) ? (v as Rec) : undefined;\n}\n\nfunction asArr(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\n\n/** Result rows of a queryDataset call, tolerant of {rows}/{data}/array shapes. */\nfunction resultRows(result: unknown): unknown[] {\n if (Array.isArray(result)) return result;\n const r = asRec(result);\n if (!r) return [];\n if (Array.isArray(r.rows)) return r.rows;\n if (Array.isArray(r.data)) return r.data;\n return [];\n}\n\n/** True when the object has at least one row (probe read, isSystem). */\nasync function hasRows(\n engine: ProbeEngine,\n objectName: string,\n organizationId?: string | null,\n): Promise<boolean> {\n const rows = await engine.find(objectName, {\n fields: ['id'],\n limit: 1,\n ...(organizationId ? { where: { organization_id: organizationId } } : {}),\n context: { isSystem: true },\n });\n return Array.isArray(rows) && rows.length > 0;\n}\n\n/**\n * Run the L3 runtime probes over a just-published artifact set:\n *\n * • per published `seed` — its target object must have rows now\n * (`seed_not_applied`: the rows were promised but never materialized);\n * • per published `view` — a limit-1 read through the same engine the\n * renderer uses must not throw (`view_read_failed`);\n * • per published `dashboard` widget — its real dataset selection must\n * execute (`widget_query_failed`) and must not return empty on an object\n * that HAS rows (`empty_query` — the four-layer staging incident class).\n *\n * All probes are reads (limit-1 / single aggregate); a probe crash is\n * reported, never thrown — verification must not break the publish it\n * verifies.\n */\nexport async function runBuildProbes(opts: RunBuildProbesOptions): Promise<BuildProbeReport> {\n const issues: RuntimeBuildIssue[] = [];\n const checked = { seeds: 0, views: 0, widgets: 0 };\n const { engine, getItem, published, analytics, organizationId } = opts;\n\n // Memoized active-item reads (a dashboard and its widgets share datasets).\n const itemCache = new Map<string, unknown | undefined>();\n const readItem = async (type: string, name: string): Promise<unknown | undefined> => {\n const key = `${type} ${name}`;\n if (itemCache.has(key)) return itemCache.get(key);\n let item: unknown | undefined;\n try {\n item = await getItem(type, name);\n } catch {\n item = undefined;\n }\n itemCache.set(key, item);\n return item;\n };\n\n // ── Seeds: rows must exist after publish ────────────────────────────────\n for (const p of published.filter((x) => x.type === 'seed')) {\n const body = asRec(await readItem('seed', p.name));\n const objectName = typeof body?.object === 'string' ? body.object : undefined;\n if (!objectName) continue;\n checked.seeds += 1;\n try {\n if (!(await hasRows(engine, objectName, organizationId))) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'seed', name: p.name },\n ref: { type: 'object', name: objectName },\n code: 'seed_not_applied',\n message: `Seed \"${p.name}\" was published but object \"${objectName}\" has no rows — the sample data never materialized.`,\n fix: `Check the publish response's seedApplied for the load error, fix the seed rows (field names/types), and republish the seed.`,\n });\n }\n } catch (e) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'seed', name: p.name },\n ref: { type: 'object', name: objectName },\n code: 'seed_not_applied',\n message: `Seed \"${p.name}\" probe could not read object \"${objectName}\": ${String((e as Error)?.message ?? e)}`,\n });\n }\n }\n\n // ── Views: the renderer's read path must not throw ──────────────────────\n for (const p of published.filter((x) => x.type === 'view')) {\n const body = asRec(await readItem('view', p.name));\n const config = asRec(body?.config);\n const dataObj = asRec(config?.data)?.object;\n const objectName =\n typeof body?.object === 'string' ? body.object\n : typeof dataObj === 'string' ? dataObj\n : undefined;\n if (!objectName) continue;\n checked.views += 1;\n try {\n await engine.find(objectName, {\n fields: ['id'],\n limit: 1,\n ...(organizationId ? { where: { organization_id: organizationId } } : {}),\n context: { isSystem: true },\n });\n } catch (e) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'view', name: p.name },\n ref: { type: 'object', name: objectName },\n code: 'view_read_failed',\n message: `View \"${p.name}\" cannot read object \"${objectName}\": ${String((e as Error)?.message ?? e)} — it will render as an error for every user.`,\n fix: `Verify object \"${objectName}\" published successfully (its table must exist) and that the view's binding is correct.`,\n });\n }\n }\n\n // ── Dashboard widgets: the real dataset selection must return data ──────\n const dashboards = published.filter((x) => x.type === 'dashboard');\n let widgetsToProbe = 0;\n for (const p of dashboards) {\n const body = asRec(await readItem('dashboard', p.name));\n const widgets = asArr(body?.widgets).map(asRec).filter((w): w is Rec => !!w);\n const datasetBound = widgets.filter((w) => typeof w.dataset === 'string' && w.dataset);\n widgetsToProbe += datasetBound.length;\n if (!analytics || typeof analytics.queryDataset !== 'function') continue;\n\n for (const w of datasetBound) {\n const widgetId = String(w.id ?? w.title ?? '?');\n const dsName = w.dataset as string;\n const dataset = asRec(await readItem('dataset', dsName));\n if (!dataset) continue; // dangling dataset is an L1 (graph) finding, not a runtime one\n checked.widgets += 1;\n\n // The widget's own selection when present, else the dataset's\n // first measure — the same default the renderer falls back to.\n const measures = asArr(w.values).filter((v): v is string => typeof v === 'string' && v.length > 0);\n const firstMeasure = asRec(asArr(dataset.measures)[0])?.name;\n const selection = {\n measures: measures.length ? measures : typeof firstMeasure === 'string' ? [firstMeasure] : [],\n dimensions: [],\n limit: 1,\n };\n if (selection.measures.length === 0) continue; // nothing selectable — schema/graph problem\n\n const objectName = typeof dataset.object === 'string' ? dataset.object : undefined;\n try {\n const result = await analytics.queryDataset(dataset, selection, undefined);\n const rows = resultRows(result);\n if (rows.length === 0 && objectName && (await hasRows(engine, objectName, organizationId))) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'dashboard', name: p.name },\n ref: { type: 'dataset', name: dsName, member: widgetId },\n code: 'empty_query',\n message: `Dashboard \"${p.name}\" widget \"${widgetId}\" returns NO data from dataset \"${dsName}\" although object \"${objectName}\" has rows — the widget will render empty for every user.`,\n fix: `Run the dataset query directly to see the compiled strategy/SQL; check the dataset's measure/dimension field bindings against object \"${objectName}\".`,\n });\n }\n } catch (e) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'dashboard', name: p.name },\n ref: { type: 'dataset', name: dsName, member: widgetId },\n code: 'widget_query_failed',\n message: `Dashboard \"${p.name}\" widget \"${widgetId}\" query against dataset \"${dsName}\" failed: ${String((e as Error)?.message ?? e)}`,\n fix: `Fix the dataset definition (or the widget's values/dimensions) so the query compiles, then republish.`,\n });\n }\n }\n }\n\n // Widgets existed but no analytics service was mounted — say so ONCE\n // (silence would read as \"probed and passed\", which it was not).\n if (widgetsToProbe > 0 && (!analytics || typeof analytics.queryDataset !== 'function')) {\n issues.push({\n layer: 'runtime',\n severity: 'warning',\n artifact: { type: 'dashboard', name: dashboards.map((d) => d.name).join(', ') },\n code: 'probes_unavailable',\n message: `${widgetsToProbe} dashboard widget(s) could not be probed: no analytics service is mounted on this kernel.`,\n });\n }\n\n return { issues, checked };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n// Export Registry\nexport { \n SchemaRegistry,\n applySystemFields,\n computeFQN,\n parseFQN,\n RESERVED_NAMESPACES,\n DEFAULT_OWNER_PRIORITY,\n DEFAULT_EXTENDER_PRIORITY,\n} from './registry.js';\nexport type { ObjectContributor, SchemaRegistryOptions } from './registry.js';\n\n// Export Protocol Implementation\nexport { ObjectStackProtocolImplementation } from './protocol.js';\n\n// ADR-0008 PR-10b: MetadataRepository wrapper over the existing sys_metadata table.\nexport { SysMetadataRepository } from './sys-metadata-repository.js';\nexport type { SysMetadataEngine, SysMetadataRepositoryOptions } from './sys-metadata-repository.js';\n\n// Export Engine\nexport { ObjectQL, ObjectRepository, ScopedContext } from './engine.js';\nexport type { ObjectQLHostContext, HookHandler, HookEntry, OperationContext, EngineMiddleware } from './engine.js';\n\n// Export in-memory aggregation fallback (used by engine.aggregate when the\n// driver lacks native groupBy/aggregations support; also useful for tests).\nexport { applyInMemoryAggregation, bucketDateValue } from './in-memory-aggregation.js';\n\n// Export Hook Binder & Wrappers (declarative-metadata → engine glue)\nexport { bindHooksToEngine } from './hook-binder.js';\nexport type { BindHooksOptions, BindHooksResult } from './hook-binder.js';\nexport { wrapDeclarativeHook } from './hook-wrappers.js';\nexport type { WrapDeclarativeOptions } from './hook-wrappers.js';\n\n// Export Validation\nexport { ValidationError, validateRecord } from './validation/record-validator.js';\nexport type { FieldValidationError } from './validation/record-validator.js';\nexport { evaluateValidationRules, needsPriorRecord, legalNextStates } from './validation/rule-validator.js';\nexport type { EvaluateRulesOptions } from './validation/rule-validator.js';\nexport {\n InMemoryHookMetricsRecorder,\n noopHookMetricsRecorder,\n} from './hook-metrics.js';\nexport type {\n HookMetricsRecorder,\n HookMetricLabel,\n HookMetricOutcome,\n HookSkipReason,\n} from './hook-metrics.js';\n\n// Export MetadataFacade\nexport { MetadataFacade } from './metadata-facade.js';\n\n// Export Plugin Shim\nexport { ObjectQLPlugin } from './plugin.js';\n\n// Export Kernel Factory\nexport { createObjectQLKernel } from './kernel-factory.js';\nexport type { ObjectQLKernelOptions } from './kernel-factory.js';\n\n// Export secret-field channel helpers (for hosts / privileged consumers)\nexport {\n SECRET_REF_PREFIX,\n SECRET_MASK,\n makeSecretRef,\n isSecretRef,\n parseSecretRef,\n collectSecretFields,\n} from './secret-fields.js';\n\n// Export Utilities\nexport {\n toTitleCase,\n convertIntrospectedSchemaToObjects,\n} from './util.js';\nexport type {\n IntrospectedColumn,\n IntrospectedForeignKey,\n IntrospectedTable,\n IntrospectedSchema,\n} from './util.js';\n\n// Seed loader — materializes `seed` metadata into rows (used by publishMetaItem\n// and the runtime dispatcher/app plugins).\nexport { SeedLoaderService } from './seed-loader.js';\n\n// ADR-0038 L3 — post-publish runtime probes (one real read per published\n// artifact); findings are BuildIssue-shaped with layer 'runtime'.\nexport { runBuildProbes } from './build-probes.js';\nexport type { RuntimeBuildIssue, BuildProbeReport, RunBuildProbesOptions } from './build-probes.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ServiceObject, ObjectSchema, ObjectOwnership } from '@objectstack/spec/data';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport { ObjectStackManifest, ManifestSchema, InstalledPackage, InstalledPackageSchema } from '@objectstack/spec/kernel';\nimport { AppSchema } from '@objectstack/spec/ui';\nimport { applyProtection } from '@objectstack/spec/shared';\n\n/**\n * Reserved namespaces that do not get FQN prefix applied.\n * Objects in these namespaces keep their short names (e.g., \"user\" — short name IS the canonical key).\n */\nexport const RESERVED_NAMESPACES = new Set(['base', 'system']);\n\n/**\n * Default priorities for ownership types.\n */\nexport const DEFAULT_OWNER_PRIORITY = 100;\nexport const DEFAULT_EXTENDER_PRIORITY = 200;\n\n/**\n * Contributor Record\n * Tracks how a package contributes to an object (own or extend).\n */\nexport interface ObjectContributor {\n packageId: string;\n namespace: string;\n ownership: ObjectOwnership;\n priority: number;\n definition: ServiceObject;\n}\n\n/**\n * Compute canonical registry key for an object.\n *\n * Under the current naming convention, object names are canonical identifiers\n * and are used as-is (no namespace__ prefix). The namespace parameter is\n * retained for backward compatibility but no longer affects the returned key.\n *\n * @param namespace - The package namespace (unused, kept for API compatibility)\n * @param shortName - The object's name (already the canonical identifier)\n * @returns The object name unchanged\n *\n * @example\n * computeFQN('crm', 'account') // => 'account'\n * computeFQN(undefined, 'task') // => 'task'\n */\nexport function computeFQN(_namespace: string | undefined, shortName: string): string {\n return shortName;\n}\n\n/**\n * Parse FQN back to namespace and short name.\n * \n * @param fqn - Object name (e.g., \"account\" or legacy \"crm__account\" for backward compat)\n * @returns { namespace, shortName } - namespace is undefined for unprefixed names\n */\nexport function parseFQN(fqn: string): { namespace: string | undefined; shortName: string } {\n const idx = fqn.indexOf('__');\n if (idx === -1) {\n return { namespace: undefined, shortName: fqn };\n }\n return {\n namespace: fqn.slice(0, idx),\n shortName: fqn.slice(idx + 2),\n };\n}\n\n/**\n * Deep merge two ServiceObject definitions.\n * Fields are merged additively. Other props: later value wins.\n */\nfunction mergeObjectDefinitions(base: ServiceObject, extension: Partial<ServiceObject>): ServiceObject {\n const merged = { ...base };\n\n // Merge fields additively\n if (extension.fields) {\n merged.fields = { ...base.fields, ...extension.fields };\n }\n\n // Merge validations additively\n if (extension.validations) {\n merged.validations = [...(base.validations || []), ...extension.validations];\n }\n\n // Merge indexes additively\n if (extension.indexes) {\n merged.indexes = [...(base.indexes || []), ...extension.indexes];\n }\n\n // Override scalar props (last writer wins)\n if (extension.label !== undefined) merged.label = extension.label;\n if (extension.pluralLabel !== undefined) merged.pluralLabel = extension.pluralLabel;\n if (extension.description !== undefined) merged.description = extension.description;\n\n return merged;\n}\n\n/**\n * Global Schema Registry\n * Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)\n * \n * ## Namespace & Ownership Model\n * \n * Objects use a namespace-based FQN system:\n * - `namespace`: Short identifier from package manifest (e.g., \"crm\", \"todo\")\n * - `name`: canonical object name (e.g., \"account\", \"sys_user\")\n * - Reserved namespaces (`base`, `system`) don't get prefixed\n * \n * Ownership modes:\n * - `own`: One package owns the object (creates the table, defines base schema)\n * - `extend`: Multiple packages can extend an object (add fields, merge by priority)\n * \n * ## Package vs App Distinction\n * - **Package**: The unit of installation, stored under type 'package'.\n * Each InstalledPackage wraps a ManifestSchema with lifecycle state.\n * - **App**: A UI navigation shell (AppSchema), registered under type 'apps'.\n * Apps are extracted from packages during registration.\n * - A package may contain 0, 1, or many apps.\n */\nexport type RegistryLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\n/**\n * Construction options for {@link SchemaRegistry}.\n */\nexport interface SchemaRegistryOptions {\n /**\n * Whether the host kernel runs in multi-tenant mode. The `organization_id`\n * column itself is auto-injected regardless of this flag (lookup →\n * sys_organization, on every registered object that doesn't already declare\n * it, isn't `managedBy` an external subsystem, and hasn't opted out via\n * `systemFields`/`tenancy.enabled:false`). When `true` the injected column\n * is additionally INDEXED — single-tenant stacks skip the index since\n * nothing ever filters by organization.\n *\n * Sourced from the `OS_MULTI_TENANT` env var when not explicitly set —\n * matches how the SecurityPlugin and CLI startup banner pick the mode.\n * Default is `false` (single-tenant) so local `dev`/`start` runs seed\n * demo data inline at boot; set `OS_MULTI_TENANT=true` for cloud /\n * production multi-org deployments. Pass an explicit boolean to override\n * (useful in tests).\n */\n multiTenant?: boolean;\n}\n\n/**\n * Augment a registered object with implicit system fields.\n *\n * Returns a *new* schema object when fields are added; returns the input\n * unchanged when nothing applies (the cheap path for system tables).\n *\n * Author-declared fields always win — we splice the system fields at the\n * front of the field map, so any same-named author field overwrites them\n * via the natural `{ ...sys, ...authored }` merge.\n *\n * Currently injects:\n * - `organization_id` — always provisioned (unless the object opts out via\n * `systemFields`/`tenancy.enabled:false` or is `better-auth` managed) so\n * the column never depends on the global multi-tenant flag. Required-false;\n * org-scoping populates it on insert in multi-tenant mode, and it stays\n * NULL on single-tenant stacks. Only the column's INDEX is gated on\n * `multiTenant` (no per-tenant filtering exists single-tenant).\n * - `created_at` / `created_by` / `updated_at` / `updated_by` — audit\n * fields. Marked `system: true, readonly: true` so detail views can\n * surface them in a dedicated \"System Information\" section while\n * edit forms / drawers filter them out. The driver populates the\n * timestamps; the `*_by` lookups are filled by the runtime when an\n * authenticated session is present (NULL otherwise — e.g. seeded\n * rows).\n */\nexport function applySystemFields(\n schema: ServiceObject,\n opts: { multiTenant: boolean }\n): ServiceObject {\n // 1. Hard opt-out at object level (e.g. seed/migration tables).\n if ((schema as any).systemFields === false) return schema;\n\n // 2. Skip only `better-auth` managed tables. Their column layout is\n // driven by better-auth's own migrations (sys_user, sys_session,\n // sys_organization, …) and injecting extra columns here would\n // collide with what better-auth expects. Other `managedBy` buckets\n // (`platform`, `config`, `system`, `append-only`) all need the\n // tenant + audit columns for multi-tenant isolation and time-travel\n // history — withholding them silently broke RLS reads on\n // sys_audit_log / sys_activity (the SecurityPlugin's\n // field-existence safety net dropped `organization_id =\n // current_user.organization_id` as \"field missing\", producing\n // RLS_DENY_FILTER → 0 rows for every non-admin caller).\n if (schema.managedBy === 'better-auth') return schema;\n\n const sf =\n typeof (schema as any).systemFields === 'object' && (schema as any).systemFields !== null\n ? ((schema as any).systemFields as { tenant?: boolean; audit?: boolean })\n : undefined;\n\n // Honor explicit opt-out via either `systemFields.tenant === false`\n // OR `tenancy.enabled === false`. The latter is the schema-level\n // declaration that the table is a shared/global catalog (e.g.\n // sys_package — the Marketplace registry). Without this, the\n // registry would still inject `organization_id`, and the\n // SecurityPlugin's RLS layer would filter every cross-org read down\n // to 0 rows even though the schema explicitly disabled multi-tenancy.\n const tenancyDisabled = (schema as any).tenancy?.enabled === false;\n // The `organization_id` COLUMN is provisioned unconditionally (subject only\n // to the explicit opt-outs above) — its existence no longer depends on the\n // global multi-tenant flag. Decoupling \"does the column exist\" from \"is\n // tenancy enabled\" is what stops sudo writers (audit / messaging / inbox /\n // outbox …) from failing with \"no column named organization_id\" on\n // single-tenant stacks: they can always stamp the column, it just stays NULL\n // when no tenant context exists. The multi-tenant flag now governs only\n // whether the column is INDEXED — on a single-tenant DB nothing ever filters\n // by organization, so the index would be dead weight.\n const wantTenant = sf?.tenant !== false && !tenancyDisabled;\n const wantAudit = sf?.audit !== false;\n\n const additions: Record<string, any> = {};\n\n if (wantTenant && !schema.fields?.organization_id) {\n additions.organization_id = {\n type: 'lookup',\n reference: 'sys_organization',\n label: 'Organization',\n required: false,\n indexed: opts.multiTenant,\n hidden: true,\n readonly: true,\n system: true,\n description:\n 'Tenant scope (auto-populated by org-scoping on insert; NULL on single-tenant stacks).',\n };\n }\n\n if (wantAudit) {\n if (!schema.fields?.created_at) {\n additions.created_at = {\n type: 'datetime',\n label: 'Created At',\n required: false,\n readonly: true,\n system: true,\n description: 'Timestamp when the record was created (auto-populated by the driver).',\n };\n }\n if (!schema.fields?.created_by) {\n additions.created_by = {\n type: 'lookup',\n reference: 'sys_user',\n label: 'Created By',\n required: false,\n readonly: true,\n system: true,\n description: 'User who created the record (populated when an authenticated session is present).',\n };\n }\n if (!schema.fields?.updated_at) {\n additions.updated_at = {\n type: 'datetime',\n label: 'Last Modified At',\n required: false,\n readonly: true,\n system: true,\n description: 'Timestamp of the most recent modification (auto-populated by the driver).',\n };\n }\n if (!schema.fields?.updated_by) {\n additions.updated_by = {\n type: 'lookup',\n reference: 'sys_user',\n label: 'Last Modified By',\n required: false,\n readonly: true,\n system: true,\n description: 'User who last modified the record (populated when an authenticated session is present).',\n };\n }\n }\n\n if (Object.keys(additions).length === 0) return schema;\n\n return {\n ...schema,\n fields: { ...additions, ...(schema.fields ?? {}) },\n };\n}\n\nexport class SchemaRegistry {\n // ==========================================\n // Logging control\n // ==========================================\n\n /** Controls verbosity of registry console messages. Default: 'info'. */\n private _logLevel: RegistryLogLevel = 'info';\n\n /** Whether to auto-inject multi-tenant system fields. */\n private readonly multiTenant: boolean;\n\n constructor(options: SchemaRegistryOptions = {}) {\n if (options.multiTenant !== undefined) {\n this.multiTenant = options.multiTenant;\n } else {\n // Mirror the SecurityPlugin / CLI banner default (env-driven, off by default).\n this.multiTenant =\n String(readEnvWithDeprecation('OS_MULTI_ORG_ENABLED', 'OS_MULTI_TENANT') ?? 'false').toLowerCase() !== 'false';\n }\n }\n\n get logLevel(): RegistryLogLevel { return this._logLevel; }\n set logLevel(level: RegistryLogLevel) { this._logLevel = level; }\n\n private log(msg: string): void {\n if (this._logLevel === 'silent' || this._logLevel === 'error' || this._logLevel === 'warn') return;\n console.log(msg);\n }\n\n // ==========================================\n // Object-specific storage (Ownership Model)\n // ==========================================\n\n /** FQN → Contributor[] (all packages that own/extend this object) */\n private objectContributors = new Map<string, ObjectContributor[]>();\n\n /** FQN → Merged ServiceObject (cached, invalidated on changes) */\n private mergedObjectCache = new Map<string, ServiceObject>();\n\n /** Namespace → Set<PackageId> (multiple packages can share a namespace) */\n private namespaceRegistry = new Map<string, Set<string>>();\n\n // ==========================================\n // Generic metadata storage (non-object types)\n // ==========================================\n\n /** Type → Name/ID → MetadataItem */\n private metadata = new Map<string, Map<string, any>>();\n\n /**\n * App name → navigation contributions (ADR-0029 D7).\n *\n * Lets packages inject nav items into apps they do not own (the UI analog\n * of object extenders). Merged into the owning app's `navigation` tree on\n * read in {@link getApp} / {@link getAllApps} by group id + priority.\n */\n private appNavContributions = new Map<string, Array<{ packageId?: string; group?: string; priority: number; items: any[] }>>();\n\n /**\n * Package ids that must be installed in a DISABLED state. Seeded once at\n * boot (from persisted state) BEFORE any package registration so that every\n * registration path — boot artifact, marketplace rehydrate, local import —\n * honors persisted disable state uniformly without a fragile post-boot\n * re-application hook. See {@link setInitialDisabledPackageIds} and\n * {@link installPackage}.\n */\n private initialDisabledPackageIds = new Set<string>();\n\n /**\n * Seed the set of package ids that should be installed disabled. Call this\n * before package registration begins; later `installPackage` calls for these\n * ids land in the `disabled` state. Replaces any previously seeded set.\n */\n setInitialDisabledPackageIds(ids: Iterable<string>): void {\n this.initialDisabledPackageIds = new Set(ids);\n }\n\n // ==========================================\n // Namespace Management\n // ==========================================\n\n /**\n * Register a namespace for a package.\n * Multiple packages can share the same namespace (e.g. 'sys').\n */\n registerNamespace(namespace: string, packageId: string): void {\n if (!namespace) return;\n\n let owners = this.namespaceRegistry.get(namespace);\n if (!owners) {\n owners = new Set();\n this.namespaceRegistry.set(namespace, owners);\n }\n owners.add(packageId);\n this.log(`[Registry] Registered namespace: ${namespace} → ${packageId}`);\n }\n\n /**\n * Unregister a namespace when a package is uninstalled.\n */\n unregisterNamespace(namespace: string, packageId: string): void {\n const owners = this.namespaceRegistry.get(namespace);\n if (owners) {\n owners.delete(packageId);\n if (owners.size === 0) {\n this.namespaceRegistry.delete(namespace);\n }\n this.log(`[Registry] Unregistered namespace: ${namespace} ← ${packageId}`);\n }\n }\n\n /**\n * Get the packages that use a namespace.\n */\n getNamespaceOwner(namespace: string): string | undefined {\n const owners = this.namespaceRegistry.get(namespace);\n if (!owners || owners.size === 0) return undefined;\n // Return the first registered package for backwards compatibility\n return owners.values().next().value;\n }\n\n /**\n * Get all packages that share a namespace.\n */\n getNamespaceOwners(namespace: string): string[] {\n const owners = this.namespaceRegistry.get(namespace);\n return owners ? Array.from(owners) : [];\n }\n\n // ==========================================\n // Object Registration (Ownership Model)\n // ==========================================\n\n /**\n * Register an object with ownership semantics.\n * \n * @param schema - The object definition\n * @param packageId - The owning package ID\n * @param namespace - The package namespace (for FQN computation)\n * @param ownership - 'own' (single owner) or 'extend' (additive merge)\n * @param priority - Merge priority (lower applied first, higher wins on conflict)\n * \n * @throws Error if trying to 'own' an object that already has an owner\n */\n registerObject(\n schema: ServiceObject,\n packageId: string,\n namespace?: string,\n ownership: ObjectOwnership = 'own',\n priority: number = ownership === 'own' ? DEFAULT_OWNER_PRIORITY : DEFAULT_EXTENDER_PRIORITY\n ): string {\n // Apply system-field injection (multi-tenant org_id, future owner/audit)\n // BEFORE FQN computation and contributor storage so every consumer of\n // the registered schema (driver syncSchema, REST projector, hooks)\n // sees the same canonical shape. Author-declared fields win — see\n // applySystemFields().\n schema = applySystemFields(schema, { multiTenant: this.multiTenant });\n\n const shortName = schema.name;\n const fqn = computeFQN(namespace, shortName);\n\n // Ensure namespace is registered\n if (namespace) {\n this.registerNamespace(namespace, packageId);\n }\n\n // Get or create contributor list\n let contributors = this.objectContributors.get(fqn);\n if (!contributors) {\n contributors = [];\n this.objectContributors.set(fqn, contributors);\n }\n\n // Validate ownership rules\n if (ownership === 'own') {\n const existingOwner = contributors.find(c => c.ownership === 'own');\n if (existingOwner && existingOwner.packageId !== packageId) {\n throw new Error(\n `Object \"${fqn}\" is already owned by package \"${existingOwner.packageId}\". ` +\n `Package \"${packageId}\" cannot claim ownership. Use 'extend' to add fields.`\n );\n }\n // Remove existing owner contribution from same package (re-registration)\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'own');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n console.warn(`[Registry] Re-registering owned object: ${fqn} from ${packageId}`);\n }\n } else {\n // extend mode: remove existing extension from same package\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'extend');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n }\n }\n\n // ADR-0010 §3.7 — translate the author-facing `protection` block\n // into the private `_lock` envelope and stamp package provenance\n // on the schema before it lands in the contributor list. Mirrors\n // registerItem() so object schemas surface lock fields on GET.\n applyProtection(schema as any, { packageId });\n\n // Add new contributor\n const contributor: ObjectContributor = {\n packageId,\n namespace: namespace || '',\n ownership,\n priority,\n definition: { ...schema, name: fqn }, // Store with FQN as name\n };\n contributors.push(contributor);\n\n // Sort by priority (ascending: lower priority applied first)\n contributors.sort((a, b) => a.priority - b.priority);\n\n // Invalidate merge cache\n this.mergedObjectCache.delete(fqn);\n\n this.log(`[Registry] Registered object: ${fqn} (${ownership}, priority=${priority}) from ${packageId}`);\n return fqn;\n }\n\n /**\n * Resolve an object by FQN, merging all contributions.\n * Returns the merged object or undefined if not found.\n */\n resolveObject(fqn: string): ServiceObject | undefined {\n // Check cache first\n const cached = this.mergedObjectCache.get(fqn);\n if (cached) return cached;\n\n const contributors = this.objectContributors.get(fqn);\n if (!contributors || contributors.length === 0) {\n return undefined;\n }\n\n // Find owner (must exist for a valid object)\n const ownerContrib = contributors.find(c => c.ownership === 'own');\n if (!ownerContrib) {\n console.warn(`[Registry] Object \"${fqn}\" has extenders but no owner. Skipping.`);\n return undefined;\n }\n\n // Start with owner's definition\n let merged = { ...ownerContrib.definition };\n\n // Apply extensions in priority order (already sorted)\n for (const contrib of contributors) {\n if (contrib.ownership === 'extend') {\n merged = mergeObjectDefinitions(merged, contrib.definition);\n }\n }\n\n // Cache the result\n this.mergedObjectCache.set(fqn, merged);\n return merged;\n }\n\n /**\n * Get object by name (short name canonical, FQN supported for disambiguation).\n *\n * Short names are canonical for user code, AI generation, and most lookups.\n * FQN is accepted as an explicit fallback for cross-package disambiguation\n * when two packages contribute objects with the same short name.\n *\n * Resolution order:\n * 1. Exact name match — the name IS the canonical key.\n * If multiple packages contribute the same short name, a warning is logged\n * and the first match wins — disambiguate by passing the FQN explicitly.\n * 2. Legacy FQN match (e.g., 'crm__account') — backward compat.\n */\n getObject(name: string): ServiceObject | undefined {\n // Canonical: short name lookup\n const matches: string[] = [];\n for (const fqn of this.objectContributors.keys()) {\n const { shortName } = parseFQN(fqn);\n if (shortName === name) {\n matches.push(fqn);\n }\n }\n if (matches.length > 0) {\n if (matches.length > 1) {\n console.warn(\n `[SchemaRegistry] Ambiguous short name \"${name}\" matches: ${matches.join(', ')}. ` +\n `Returning first match. Use FQN to disambiguate.`\n );\n }\n return this.resolveObject(matches[0]);\n }\n\n // Fallback: explicit FQN\n return this.resolveObject(name);\n }\n\n /**\n * Get all registered objects (merged).\n * \n * @param packageId - Optional filter: only objects contributed by this package\n */\n getAllObjects(packageId?: string): ServiceObject[] {\n const results: ServiceObject[] = [];\n\n for (const fqn of this.objectContributors.keys()) {\n // If filtering by package, check if this package contributes\n if (packageId) {\n const contributors = this.objectContributors.get(fqn);\n const hasContribution = contributors?.some(c => c.packageId === packageId);\n if (!hasContribution) continue;\n }\n\n const merged = this.resolveObject(fqn);\n if (merged) {\n // Tag with contributor info for UI\n (merged as any)._packageId = this.getObjectOwner(fqn)?.packageId;\n results.push(merged);\n }\n }\n\n return results;\n }\n\n /**\n * Get all contributors for an object.\n */\n getObjectContributors(fqn: string): ObjectContributor[] {\n return this.objectContributors.get(fqn) || [];\n }\n\n /**\n * Get the owner contributor for an object.\n */\n getObjectOwner(fqn: string): ObjectContributor | undefined {\n const contributors = this.objectContributors.get(fqn);\n return contributors?.find(c => c.ownership === 'own');\n }\n\n /**\n * ADR-0029 K0 — assert every registered object resolves to exactly one\n * owner.\n *\n * A second `own` from a different package is already rejected eagerly in\n * {@link registerObject} (it throws). This is the install-time backstop\n * called once all packages are registered (kernel bootstrap complete),\n * and it additionally catches the case `registerObject` cannot: an object\n * that has only `extend` contributions and **no owner** — which would\n * otherwise resolve to nothing. Surfacing it here turns a silent\n * \"extend a non-existent object\" into a clear bootstrap error.\n *\n * This is the invariant the kernel-decomposition (ADR-0029) relies on:\n * the `sys` namespace is shared across many first-party plugins, but each\n * object name has exactly one owner.\n *\n * @throws Error listing every object whose owner count is not exactly 1.\n */\n assertSingleOwnerPerObject(): void {\n const violations: string[] = [];\n for (const [fqn, contributors] of this.objectContributors.entries()) {\n const owners = contributors.filter(c => c.ownership === 'own');\n if (owners.length === 0) {\n const extenders = contributors.map(c => c.packageId).join(', ') || '(none)';\n violations.push(\n `Object \"${fqn}\" has no owner — only extend contributions from [${extenders}]. ` +\n `Exactly one package must register it with ownership 'own'.`\n );\n } else if (owners.length > 1) {\n const names = owners.map(c => c.packageId).join(', ');\n violations.push(\n `Object \"${fqn}\" has ${owners.length} owners [${names}] — exactly one is allowed.`\n );\n }\n }\n if (violations.length > 0) {\n throw new Error(\n `[Registry] single-owner-per-object check failed (ADR-0029):\\n ` +\n violations.join('\\n ')\n );\n }\n }\n\n /**\n * Unregister all objects contributed by a package.\n * \n * @throws Error if trying to uninstall an owner that has extenders\n */\n unregisterObjectsByPackage(packageId: string, force: boolean = false): void {\n for (const [fqn, contributors] of this.objectContributors.entries()) {\n // Find this package's contributions\n const packageContribs = contributors.filter(c => c.packageId === packageId);\n \n for (const contrib of packageContribs) {\n if (contrib.ownership === 'own' && !force) {\n // Check if there are extenders from other packages\n const otherExtenders = contributors.filter(\n c => c.packageId !== packageId && c.ownership === 'extend'\n );\n if (otherExtenders.length > 0) {\n throw new Error(\n `Cannot uninstall package \"${packageId}\": object \"${fqn}\" is extended by ` +\n `${otherExtenders.map(c => c.packageId).join(', ')}. Uninstall extenders first.`\n );\n }\n }\n\n // Remove contribution\n const idx = contributors.indexOf(contrib);\n if (idx !== -1) {\n contributors.splice(idx, 1);\n this.log(`[Registry] Removed ${contrib.ownership} contribution to ${fqn} from ${packageId}`);\n }\n }\n\n // Clean up empty contributor lists\n if (contributors.length === 0) {\n this.objectContributors.delete(fqn);\n }\n\n // Invalidate cache\n this.mergedObjectCache.delete(fqn);\n }\n }\n\n // ==========================================\n // Generic Metadata (Non-Object Types)\n // ==========================================\n\n /**\n * Universal Register Method for non-object metadata.\n */\n registerItem<T>(type: string, item: T, keyField: keyof T = 'name' as keyof T, packageId?: string) {\n if (!this.metadata.has(type)) {\n this.metadata.set(type, new Map());\n }\n const collection = this.metadata.get(type)!;\n const baseName = String(item[keyField]);\n\n // ADR-0010 §3.7 — translate the author-facing `protection` block\n // into the private `_lock` envelope and stamp package provenance.\n // Centralised with the artifact loader path in metadata/plugin.ts\n // so both load paths produce identical lock state.\n applyProtection(item as any, { packageId });\n\n // Validation Hook\n try {\n this.validate(type, item);\n } catch (e: any) {\n console.error(`[Registry] Validation failed for ${type} ${baseName}: ${e.message}`);\n }\n\n // Use composite key (packageId:name) when packageId is provided\n const storageKey = packageId ? `${packageId}:${baseName}` : baseName;\n\n if (collection.has(storageKey)) {\n this.log(`[Registry] Overwriting ${type}: ${storageKey}`);\n }\n\n // Artifact-vs-DB collision warning. When a code package ships an item\n // whose name already exists as a DB-only entry (registered earlier\n // without a packageId — typically rehydrated from sys_metadata by\n // loadMetaFromDb / getMetaItems), the runtime overlay layer makes\n // the DB row silently shadow the new artifact value. That is correct\n // ADR-0005 behavior, but the silent shadowing can surprise package\n // authors and operators. Log a single warning so the situation is\n // discoverable in startup logs.\n if (packageId && collection.has(baseName)) {\n const dbOnly = collection.get(baseName) as any;\n if (dbOnly && !dbOnly._packageId) {\n console.warn(\n `[Registry] Collision: ${type}/${baseName} ships from package ` +\n `\"${packageId}\" but a runtime-authored row with the same name already ` +\n `exists in sys_metadata. The runtime row will shadow the package value ` +\n `(ADR-0005 overlay precedence). Rename one, or delete the sys_metadata ` +\n `row if the package value should win.`,\n );\n }\n }\n\n collection.set(storageKey, item);\n this.log(`[Registry] Registered ${type}: ${storageKey}`);\n }\n\n /**\n * Validate Metadata against Spec Zod Schemas\n */\n validate(type: string, item: any): unknown {\n if (type === 'object') {\n return ObjectSchema.parse(item);\n }\n if (type === 'app') {\n return AppSchema.parse(item);\n }\n if (type === 'package') {\n return InstalledPackageSchema.parse(item);\n }\n if (type === 'plugin') {\n return ManifestSchema.parse(item);\n }\n return true;\n }\n\n /**\n * Universal Unregister Method\n */\n unregisterItem(type: string, name: string) {\n const collection = this.metadata.get(type);\n if (!collection) {\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n return;\n }\n if (collection.has(name)) {\n collection.delete(name);\n this.log(`[Registry] Unregistered ${type}: ${name}`);\n return;\n }\n // Scan composite keys\n for (const key of collection.keys()) {\n if (key.endsWith(`:${name}`)) {\n collection.delete(key);\n this.log(`[Registry] Unregistered ${type}: ${key}`);\n return;\n }\n }\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n }\n\n /**\n * Universal Get Method\n */\n getItem<T>(type: string, name: string): T | undefined {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getObject(name) as unknown as T | undefined;\n }\n \n const collection = this.metadata.get(type);\n if (!collection) return undefined;\n const direct = collection.get(name);\n if (direct) return direct as T;\n // Scan for composite keys\n for (const [key, item] of collection) {\n if (key.endsWith(`:${name}`)) {\n return item as T;\n }\n }\n return undefined;\n }\n\n /**\n * Universal List Method\n */\n listItems<T>(type: string, packageId?: string): T[] {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getAllObjects(packageId) as unknown as T[];\n }\n\n const items = Array.from(this.metadata.get(type)?.values() || []) as T[];\n let result = items;\n if (packageId) {\n result = result.filter((item: any) => item._packageId === packageId);\n }\n // Hide metadata owned by a disabled package so the console (app switcher,\n // view lists, dashboards, …) stops surfacing it after a disable. The\n // `package` type itself is never filtered — the Packages page must still\n // list disabled packages so they can be re-enabled. Disable is reversible:\n // items remain registered and reappear on enable.\n if (type !== 'package') {\n result = result.filter((item: any) => !this.isPackageDisabled((item as any)?._packageId));\n }\n return result;\n }\n\n /**\n * Whether a package has been explicitly disabled. Unknown packages and\n * items with no owning package are treated as enabled.\n */\n isPackageDisabled(packageId?: string): boolean {\n if (!packageId) return false;\n const pkg = this.getPackage(packageId);\n return pkg?.enabled === false || pkg?.status === 'disabled';\n }\n\n /**\n * Get all registered metadata types (Kinds)\n */\n getRegisteredTypes(): string[] {\n const types = Array.from(this.metadata.keys());\n // Always include 'object' even if stored separately\n if (!types.includes('object') && this.objectContributors.size > 0) {\n types.push('object');\n }\n return types;\n }\n\n // ==========================================\n // Package Management\n // ==========================================\n\n installPackage(manifest: ObjectStackManifest, settings?: Record<string, any>): InstalledPackage {\n const now = new Date().toISOString();\n const disabled = this.initialDisabledPackageIds.has(manifest.id);\n const pkg: InstalledPackage = {\n manifest,\n status: disabled ? 'disabled' : 'installed',\n enabled: !disabled,\n installedAt: now,\n updatedAt: now,\n ...(disabled ? { statusChangedAt: now } : {}),\n settings,\n };\n \n // Register namespace if present\n if (manifest.namespace) {\n this.registerNamespace(manifest.namespace, manifest.id);\n }\n \n if (!this.metadata.has('package')) {\n this.metadata.set('package', new Map());\n }\n const collection = this.metadata.get('package')!;\n if (collection.has(manifest.id)) {\n console.warn(`[Registry] Overwriting package: ${manifest.id}`);\n }\n collection.set(manifest.id, pkg);\n this.log(`[Registry] Installed package: ${manifest.id} (${manifest.name})`);\n return pkg;\n }\n\n uninstallPackage(id: string): boolean {\n const pkg = this.getPackage(id);\n if (!pkg) {\n console.warn(`[Registry] Package not found for uninstall: ${id}`);\n return false;\n }\n\n // Unregister namespace\n if (pkg.manifest.namespace) {\n this.unregisterNamespace(pkg.manifest.namespace, id);\n }\n\n // Unregister objects (will throw if extenders exist)\n this.unregisterObjectsByPackage(id);\n\n // Remove package record\n const collection = this.metadata.get('package');\n if (collection) {\n collection.delete(id);\n this.log(`[Registry] Uninstalled package: ${id}`);\n return true;\n }\n return false;\n }\n\n getPackage(id: string): InstalledPackage | undefined {\n return this.metadata.get('package')?.get(id) as InstalledPackage | undefined;\n }\n\n getAllPackages(): InstalledPackage[] {\n return this.listItems<InstalledPackage>('package');\n }\n\n enablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = true;\n pkg.status = 'installed';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Enabled package: ${id}`);\n }\n return pkg;\n }\n\n disablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = false;\n pkg.status = 'disabled';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Disabled package: ${id}`);\n }\n return pkg;\n }\n\n // ==========================================\n // App Helpers\n // ==========================================\n\n registerApp(app: any, packageId?: string) {\n this.registerItem('app', app, 'name', packageId);\n }\n\n getApp(name: string): any {\n const app = this.getItem('app', name);\n if (!app) return app;\n return this.applyNavContributions(app);\n }\n\n getAllApps(): any[] {\n return this.listItems('app').map((app: any) => this.applyNavContributions(app));\n }\n\n // ==========================================\n // App navigation contributions (ADR-0029 D7)\n // ==========================================\n\n /**\n * Register a navigation contribution — a package injecting nav items into\n * an app it does not own (the UI-layer analog of object `extend`).\n *\n * Contributions are merged into the target app's `navigation` tree lazily\n * on read ({@link getApp} / {@link getAllApps}) by group id + priority, so\n * registration order does not matter and the owning app can be registered\n * before or after its contributors.\n */\n registerAppNavContribution(\n contribution: { app: string; group?: string; priority?: number; items?: any[] },\n packageId?: string,\n ): void {\n if (!contribution || !contribution.app) return;\n const list = this.appNavContributions.get(contribution.app) ?? [];\n list.push({\n packageId,\n group: contribution.group,\n priority: contribution.priority ?? 200,\n items: Array.isArray(contribution.items) ? contribution.items : [],\n });\n this.appNavContributions.set(contribution.app, list);\n this.log(\n `[Registry] Navigation contribution: ${packageId ?? '(unknown)'} -> ${contribution.app}` +\n (contribution.group ? `/${contribution.group}` : '') +\n ` (${list[list.length - 1].items.length} items)`,\n );\n }\n\n /** Contributions registered for an app (empty array when none). */\n getAppNavContributions(appName: string): Array<{ packageId?: string; group?: string; priority: number; items: any[] }> {\n return this.appNavContributions.get(appName) ?? [];\n }\n\n /**\n * Return a copy of `app` with all registered navigation contributions\n * merged into its `navigation` tree. The stored app is never mutated, so\n * repeated reads stay idempotent.\n *\n * Public so the protocol serving path (`getMetaItems` / `getMetaItem` for\n * `app`) can merge contributions the same way `getApp` / `getAllApps` do —\n * the REST app endpoints read through the protocol, not these helpers, so\n * the merge must be reachable from there too (ADR-0029 D7).\n */\n applyNavContributions(app: any): any {\n const contributions = this.appNavContributions.get(app?.name);\n if (!contributions || contributions.length === 0) return app;\n\n const cloned = structuredClone(app);\n const nav: any[] = Array.isArray(cloned.navigation) ? cloned.navigation : (cloned.navigation = []);\n\n // Lower priority applied first — mirrors object extender ordering.\n const sorted = [...contributions].sort((a, b) => a.priority - b.priority);\n for (const c of sorted) {\n if (!c.items.length) continue;\n if (c.group) {\n const group = this.findNavGroup(nav, c.group);\n if (group) {\n if (!Array.isArray(group.children)) group.children = [];\n group.children.push(...c.items);\n } else {\n this.log(\n `[Registry] Navigation contribution from \"${c.packageId ?? '(unknown)'}\" targets ` +\n `missing group \"${c.group}\" in app \"${app.name}\" — appending at top level.`,\n );\n nav.push(...c.items);\n }\n } else {\n nav.push(...c.items);\n }\n }\n return cloned;\n }\n\n /** Depth-first search for a `type: 'group'` nav item by id. */\n private findNavGroup(items: any[], groupId: string): any | undefined {\n for (const item of items) {\n if (item && item.id === groupId && item.type === 'group') return item;\n if (item && Array.isArray(item.children)) {\n const found = this.findNavGroup(item.children, groupId);\n if (found) return found;\n }\n }\n return undefined;\n }\n\n // ==========================================\n // Plugin Helpers\n // ==========================================\n\n registerPlugin(manifest: ObjectStackManifest) {\n this.registerItem('plugin', manifest, 'id');\n }\n\n getAllPlugins(): ObjectStackManifest[] {\n return this.listItems<ObjectStackManifest>('plugin');\n }\n\n // ==========================================\n // Kind Helpers\n // ==========================================\n\n registerKind(kind: { id: string, globs: string[] }) {\n this.registerItem('kind', kind, 'id');\n }\n \n getAllKinds(): { id: string, globs: string[] }[] {\n return this.listItems('kind');\n }\n\n // ==========================================\n // Reset (for testing)\n // ==========================================\n\n /**\n * Invalidate the merged-schema cache for a single FQN (or short name).\n *\n * Call this from event-driven consumers (ADR-0008 M0 PR-7) when an\n * upstream metadata change makes the cached merged definition stale.\n * The contributor list is preserved — only the cached merge result is\n * dropped, so the next `resolveObject(fqn)` recomputes from scratch.\n *\n * Accepts either an FQN (`acme__contact`) or a bare short name\n * (`contact`); for the latter, all entries whose suffix matches the\n * name are invalidated.\n */\n invalidate(fqnOrName: string): void {\n if (this.mergedObjectCache.has(fqnOrName)) {\n this.mergedObjectCache.delete(fqnOrName);\n return;\n }\n // Short-name path: drop any cached merge whose FQN ends with `__<name>` or equals `<name>`.\n const suffix = `__${fqnOrName}`;\n for (const fqn of Array.from(this.mergedObjectCache.keys())) {\n if (fqn === fqnOrName || fqn.endsWith(suffix)) {\n this.mergedObjectCache.delete(fqn);\n }\n }\n }\n\n /** Drop every entry from the merged-schema cache. */\n invalidateAll(): void {\n this.mergedObjectCache.clear();\n }\n\n /**\n * Clear all registry state. Use only for testing.\n */\n reset(): void {\n this.objectContributors.clear();\n this.mergedObjectCache.clear();\n this.namespaceRegistry.clear();\n this.metadata.clear();\n this.appNavContributions.clear();\n this.log('[Registry] Reset complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport type { ObjectQL } from './engine.js';\nimport { SysMetadataRepository, type SysMetadataEngine } from './sys-metadata-repository.js';\nimport { ConflictError } from '@objectstack/metadata-core';\nimport type {\n BatchUpdateRequest,\n BatchUpdateResponse,\n UpdateManyDataRequest,\n DeleteManyDataRequest,\n InstallPackageRequest,\n InstallPackageResponse\n} from '@objectstack/spec/api';\nimport type { MetadataCacheRequest, MetadataCacheResponse, ServiceInfo, ApiRoutes, WellKnownCapabilities } from '@objectstack/spec/api';\nimport type { IFeedService } from '@objectstack/spec/contracts';\nimport { parseFilterAST, isFilterAST } from '@objectstack/spec/data';\nimport { PLURAL_TO_SINGULAR, SINGULAR_TO_PLURAL } from '@objectstack/spec/shared';\nimport { type FormView, isAggregatedViewContainer } from '@objectstack/spec/ui';\nimport { METADATA_FORM_REGISTRY } from '@objectstack/spec/system';\nimport { DEFAULT_METADATA_TYPE_REGISTRY, getMetadataTypeSchema, getMetadataTypeActions } from '@objectstack/spec/kernel';\nimport {\n extractProtection,\n evaluateLockForWrite,\n evaluateLockForDelete,\n resolveLockState,\n type MetadataLock,\n type MetadataProvenance,\n} from '@objectstack/spec/kernel';\nimport { z } from 'zod';\nimport {\n computeMetadataDiagnostics,\n decorateMetadataItem,\n decorateMetadataItems,\n type MetadataDiagnostics,\n} from './metadata-diagnostics.js';\n\n/**\n * Canonical Zod schema per metadata type lives in\n * `@objectstack/spec/kernel/metadata-type-schemas` and is exposed through\n * {@link getMetadataTypeSchema}. Both save-time validation\n * ({@link resolveOverlaySchema}) and the `/meta/types/:type` JSON Schema\n * emitter consult that single source of truth, so adding a new\n * metadata-type schema requires editing exactly one file (or calling\n * `registerMetadataTypeSchema()` from a plugin).\n */\n// (TYPE_TO_SCHEMA removed — use `getMetadataTypeSchema(type)` directly.)\n\n/**\n * Canonical {@link FormView} layout per metadata type. Sourced from the\n * shared {@link METADATA_FORM_REGISTRY} in `@objectstack/spec/system` so\n * the runtime form payload, the i18n extractor, and Studio all read from\n * a single source of truth.\n *\n * Types without an entry render with the auto-generated single-section\n * layout derived from their JSON Schema (acceptable for simple types).\n */\nconst TYPE_TO_FORM: Readonly<Record<string, FormView>> = METADATA_FORM_REGISTRY;\n\n/**\n * Convert a Zod schema to a JSON Schema, returning `undefined` if conversion\n * fails (e.g. unsupported constructs). Cached per schema reference.\n */\nconst _jsonSchemaCache = new WeakMap<z.ZodTypeAny, Record<string, unknown> | null>();\nfunction toJsonSchemaSafe(schema: z.ZodTypeAny): Record<string, unknown> | undefined {\n const cached = _jsonSchemaCache.get(schema);\n if (cached !== undefined) return cached ?? undefined;\n try {\n const result = z.toJSONSchema(schema, { unrepresentable: 'any' }) as Record<string, unknown>;\n _jsonSchemaCache.set(schema, result);\n return result;\n } catch {\n _jsonSchemaCache.set(schema, null);\n return undefined;\n }\n}\n\n/**\n * Hand-crafted fallback JSON Schemas for metadata types whose Zod schema\n * cannot be safely converted via `z.toJSONSchema()` (e.g. due to recursive\n * references or non-representable constructs like `z.lazy()` chains).\n *\n * These mirror the shape consumed by the corresponding `*.form.ts` layouts,\n * so the SchemaForm renderer can still produce a real form (instead of\n * falling back to the raw JSON editor). All fields use lenient types\n * (`string | object | array`) because the widget hint in the form layout\n * is what actually drives the UI control selection — the JSON Schema is\n * only used to (a) seed defaults and (b) report which property names exist.\n */\nconst HAND_CRAFTED_SCHEMAS: Record<string, Record<string, unknown>> = {\n object: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n pluralLabel: { type: 'string' },\n icon: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n active: { type: 'boolean', default: true },\n isSystem: { type: 'boolean', default: false },\n abstract: { type: 'boolean', default: false },\n datasource: { type: 'string' },\n fields: {\n // Canonical Object.fields is a name-keyed map\n // (Record<string, FieldDefinition>) — insertion order is\n // display order. The SchemaForm engine recognises\n // `additionalProperties` as a Record and dispatches to\n // the `record` form-field renderer (ADR-0007). The form\n // layout in `object.form.ts` declares `type: 'record'`\n // so the inner `additionalProperties` schema is used to\n // shape each value.\n type: 'object',\n default: {},\n additionalProperties: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n type: { type: 'string' },\n required: { type: 'boolean', default: false },\n unique: { type: 'boolean', default: false },\n defaultValue: {},\n description: { type: 'string' },\n },\n required: ['type'],\n },\n },\n capabilities: { type: 'object', additionalProperties: true },\n },\n required: ['name'],\n additionalProperties: true,\n },\n action: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n objectName: { type: 'string' },\n icon: { type: 'string' },\n type: { type: 'string', enum: ['url', 'flow', 'api', 'script'] },\n variant: { type: 'string', enum: ['primary', 'secondary', 'danger', 'ghost', 'outline'] },\n target: { type: 'string' },\n method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] },\n body: {\n type: 'array',\n default: [],\n items: {\n type: 'object',\n properties: {\n line: { type: 'string' },\n },\n },\n },\n params: {\n type: 'array',\n default: [],\n items: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n type: { type: 'string' },\n required: { type: 'boolean', default: false },\n },\n required: ['name'],\n },\n },\n confirmText: { type: 'string' },\n successMessage: { type: 'string' },\n refreshAfter: { type: 'boolean', default: true },\n locations: {\n type: 'array',\n default: [],\n items: {\n type: 'object',\n properties: {\n location: { type: 'string' },\n },\n },\n },\n component: { type: 'string' },\n visible: { type: 'string' },\n disabled: { type: 'string' },\n shortcut: { type: 'string' },\n bulkEnabled: { type: 'boolean', default: false },\n aiExposed: { type: 'boolean', default: false },\n recordIdParam: { type: 'string' },\n recordIdField: { type: 'string' },\n bodyShape: { type: 'string', enum: ['flat', 'nested'] },\n },\n required: ['name', 'label', 'type'],\n additionalProperties: true,\n },\n // Validation rules live inside `object.validations[]`. The canonical\n // ValidationRuleSchema is a discriminated union of 9 variants; the\n // generic SchemaForm renderer treats unions as opaque JSON, so we\n // ship a *flat* form-friendly schema covering the common base\n // properties plus every variant-specific field as optional. Save-time\n // validation is unaffected — the union schema is still authoritative\n // at write time.\n validation: {\n type: 'object',\n properties: {\n // --- Base fields (all variants) ---\n name: { type: 'string', description: 'Unique rule name (snake_case)' },\n label: { type: 'string' },\n description: { type: 'string' },\n type: {\n type: 'string',\n enum: [\n 'script',\n 'unique',\n 'state_machine',\n 'format',\n 'cross_field',\n 'json',\n 'async',\n 'custom',\n 'conditional',\n ],\n default: 'script',\n description: 'Validation variant',\n },\n active: { type: 'boolean', default: true },\n events: {\n type: 'array',\n items: { type: 'string', enum: ['insert', 'update', 'delete'] },\n default: ['insert', 'update'],\n },\n priority: { type: 'number', default: 100, minimum: 0, maximum: 9999 },\n severity: {\n type: 'string',\n enum: ['error', 'warning', 'info'],\n default: 'error',\n },\n message: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n // --- Variant-specific (all optional, gated by `type`) ---\n condition: {\n type: 'string',\n description: 'CEL predicate (type=script). True ⇒ validation fails.',\n },\n fields: {\n type: 'array',\n items: { type: 'string' },\n description: 'Fields (type=unique / cross_field).',\n },\n scope: { type: 'string', description: 'CEL scope predicate (type=unique).' },\n caseSensitive: { type: 'boolean', default: true },\n field: { type: 'string', description: 'Single field (type=state_machine / format).' },\n transitions: {\n type: 'object',\n additionalProperties: { type: 'array', items: { type: 'string' } },\n description: 'Map { OldState: [AllowedNewStates] } (type=state_machine).',\n },\n regex: { type: 'string', description: 'Regex (type=format).' },\n format: {\n type: 'string',\n enum: ['email', 'url', 'phone', 'json'],\n description: 'Built-in format (type=format).',\n },\n url: { type: 'string', description: 'Endpoint URL (type=async).' },\n handler: { type: 'string', description: 'Handler reference (type=custom).' },\n when: { type: 'string', description: 'Outer condition (type=conditional).' },\n },\n required: ['name', 'type', 'message'],\n additionalProperties: true,\n },\n};\n\n/**\n * Zod schemas used to validate overlay items before they are persisted into\n * `sys_metadata` by {@link ObjectStackProtocolImplementation.saveMetaItem}.\n *\n * Single source of truth: the spec-side {@link getMetadataTypeSchema}\n * registry (`@objectstack/spec/kernel/metadata-type-schemas`). Every\n * metadata type whose payload should round-trip through Studio's\n * generic editor maps to its canonical Zod schema there; this function\n * is a plural→singular adapter on top of it.\n *\n * Validation policy:\n * - `safeParse` is used so we can craft a 422 with structured `issues`.\n * - We do NOT replace the persisted document with `parsed.data`; the\n * original payload is stored verbatim so Studio-only auxiliary fields\n * (e.g. `isPinned`, `isDefault`, `sortOrder`) survive the round-trip.\n * - Types without a registered schema (the wiring-layer types\n * `function`/`service`/`router`, and any plugin types that have not\n * yet called `registerMetadataTypeSchema()`) fall through unvalidated.\n */\nfunction resolveOverlaySchema(type: string, _item: unknown): z.ZodTypeAny | null {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n return getMetadataTypeSchema(singular) ?? null;\n}\n\n/**\n * Guarantee a `view` body carries a top-level `name`.\n *\n * {@link ObjectStackProtocolImplementation.getMetaItems} only surfaces a\n * sys_metadata overlay row when its parsed body has a top-level `name` (objects\n * and dashboards include one; some view producers — notably loose `{ list }`\n * fragments — do not, so the view is silently dropped from the object's view\n * list and never appears as a tab). We stamp the save name here, at the single\n * write chokepoint, without otherwise reshaping the document.\n *\n * Deliberately does NOT convert shape: both the `defineView` container form\n * (`{ list, listViews, … }`) and the `{ name, object, viewKind, config }`\n * record form are valid and the console consumes both — reshaping a container\n * into a record risks producing an invalid record (e.g. a non-`<object>.<key>`\n * name). Structural validity is enforced separately by the view metadata schema\n * during the spec-validation step. No-op for non-view types and bodies that\n * already carry a `name`.\n */\nexport function normalizeViewMetadata(type: string, item: unknown, saveName: string): unknown {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (singular !== 'view') return item;\n if (!item || typeof item !== 'object' || Array.isArray(item)) return item;\n const it = item as Record<string, unknown>;\n return it.name ? it : { ...it, name: saveName };\n}\n\n/**\n * ADR-0010 §3.3 — Overlay the artifact's metadata-protection envelope\n * onto a returned item so artifact-level lock/packageId/provenance\n * always wins over whatever was persisted in the `sys_metadata` overlay\n * row. Returns `item` unchanged when no artifact baseline is available.\n *\n * The artifact's `_lock`, `_lockReason`, `_packageId`, `_packageVersion`,\n * and `_provenance` are the source of truth — an overlay copy may\n * pre-date the artifact's protection declaration and would otherwise\n * mask it.\n */\nfunction mergeArtifactProtection(item: unknown, artifactItem: unknown): unknown {\n if (item === undefined || item === null) return item;\n if (artifactItem === undefined || artifactItem === null) return item;\n const a = artifactItem as Record<string, unknown>;\n if (typeof a !== 'object') return item;\n const out: Record<string, unknown> = { ...(item as Record<string, unknown>) };\n if (a._lock !== undefined) out._lock = a._lock;\n if (a._lockReason !== undefined) out._lockReason = a._lockReason;\n if (a._lockDocsUrl !== undefined) out._lockDocsUrl = a._lockDocsUrl;\n if (a._lockSource !== undefined) out._lockSource = a._lockSource;\n if (a._packageId !== undefined) out._packageId = a._packageId;\n if (a._packageVersion !== undefined) out._packageVersion = a._packageVersion;\n if (a._provenance !== undefined) out._provenance = a._provenance;\n return out;\n}\n\n/**\n * Simple hash function for ETag generation (browser-compatible)\n * Uses a basic hash algorithm instead of crypto.createHash\n */\nfunction simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(16);\n}\n\n/**\n * Thrown by `updateData` / `deleteData` when the caller supplies an\n * `expectedVersion` that does not match the current record's `updated_at`.\n *\n * The HTTP layer maps this to `409 Conflict` with code `CONCURRENT_UPDATE`,\n * and includes both the current server-side version and the current record\n * payload so the client can render an informed conflict-resolution UI\n * (\"Reload latest\" vs. \"Overwrite anyway\").\n *\n * NOTE: This is an *application-level* compare-and-set — not an atomic\n * storage-layer CAS. There is a small TOCTOU window between the version\n * check and the subsequent write. For the conflict frequency this targets\n * (different users seconds-to-minutes apart in B2B record editing) this\n * is more than adequate; a future revision can push the check into the\n * driver's UPDATE statement (`WHERE id=? AND updated_at=?`) for true\n * atomicity.\n */\nexport class ConcurrentUpdateError extends Error {\n readonly code = 'CONCURRENT_UPDATE';\n readonly status = 409;\n readonly currentVersion: string | null;\n readonly currentRecord: unknown;\n constructor(opts: { currentVersion: string | null; currentRecord: unknown; message?: string }) {\n super(opts.message ?? 'Record was modified by another user');\n this.name = 'ConcurrentUpdateError';\n this.currentVersion = opts.currentVersion;\n this.currentRecord = opts.currentRecord;\n }\n}\n\n/**\n * Normalises a version token for comparison. Strips RFC-7232-style quotes\n * (`\"…\"`) that an HTTP `If-Match` header may carry, trims whitespace, and\n * returns null for empty / nullish input.\n */\nfunction normaliseVersionToken(v: unknown): string | null {\n if (v === null || v === undefined) return null;\n const s = String(v).trim();\n if (!s) return null;\n if (s.length >= 2 && s.startsWith('\"') && s.endsWith('\"')) {\n return s.slice(1, -1);\n }\n return s;\n}\n\n/**\n * Service Configuration for Discovery\n * Maps service names to their routes and plugin providers\n */\nconst SERVICE_CONFIG: Record<string, { route: string; plugin: string }> = {\n auth: { route: '/api/v1/auth', plugin: 'plugin-auth' },\n automation: { route: '/api/v1/automation', plugin: 'plugin-automation' },\n cache: { route: '/api/v1/cache', plugin: 'plugin-redis' },\n queue: { route: '/api/v1/queue', plugin: 'plugin-bullmq' },\n job: { route: '/api/v1/jobs', plugin: 'job-scheduler' },\n ui: { route: '/api/v1/ui', plugin: 'ui-plugin' },\n workflow: { route: '/api/v1/workflow', plugin: 'plugin-workflow' },\n realtime: { route: '/api/v1/realtime', plugin: 'plugin-realtime' },\n notification: { route: '/api/v1/notifications', plugin: 'plugin-notifications' },\n ai: { route: '/api/v1/ai', plugin: 'plugin-ai' },\n i18n: { route: '/api/v1/i18n', plugin: 'service-i18n' },\n graphql: { route: '/graphql', plugin: 'plugin-graphql' }, // GraphQL uses /graphql by convention (not versioned REST)\n 'file-storage': { route: '/api/v1/storage', plugin: 'plugin-storage' },\n search: { route: '/api/v1/search', plugin: 'plugin-search' },\n};\n\n/**\n * Phase 3a-references: hand-curated reference path registry.\n *\n * Maps a *target* metadata type to the list of *source* type+path tuples\n * that may point at it. Used by {@link findReferencesToMeta} to scan all\n * loaded metadata and surface \"what depends on this?\" before a user\n * deletes or renames an artifact.\n *\n * Path syntax:\n * - `'foo'` → item.foo\n * - `'foo.bar'` → item.foo.bar\n * - `'foo[]'` → each element of array item.foo\n * - `'foo[].bar'` → bar of each element of array item.foo\n * - `'foo{}'` → each value of Record item.foo\n * - `'foo{}.bar'` → bar of each value of Record item.foo\n *\n * Coverage is intentionally narrow — covers the highest-value references\n * for MVP. Add more entries as new editors are built.\n */\nconst REFERENCE_PATHS: Record<string, Array<{ fromType: string; paths: string[]; kind: string }>> = {\n object: [\n { fromType: 'view', paths: ['object', 'objectName'], kind: 'view' },\n { fromType: 'dashboard', paths: ['widgets[].object', 'widgets[].objectName'], kind: 'dashboard widget' },\n { fromType: 'flow', paths: ['object', 'context.object', 'trigger.object', 'targetObject'], kind: 'flow' },\n { fromType: 'workflow', paths: ['object', 'targetObject'], kind: 'workflow' },\n { fromType: 'permission', paths: ['objects[].name', 'objects[].object'], kind: 'permission' },\n { fromType: 'app', paths: ['navItems[].objectName', 'navItems[].object', 'tabs[].objectName', 'tabs[].object'], kind: 'app nav' },\n { fromType: 'page', paths: ['object', 'objectName'], kind: 'page' },\n { fromType: 'report', paths: ['object', 'objectName'], kind: 'report' },\n { fromType: 'action', paths: ['object', 'objectName'], kind: 'action' },\n { fromType: 'validation', paths: ['object', 'objectName'], kind: 'validation' },\n { fromType: 'hook', paths: ['object', 'objectName'], kind: 'hook' },\n { fromType: 'object', paths: ['fields[].referenceTo', 'fields{}.referenceTo', 'fields{}.reference'], kind: 'field reference' },\n ],\n view: [\n { fromType: 'dashboard', paths: ['widgets[].view', 'widgets[].viewName'], kind: 'dashboard widget' },\n { fromType: 'app', paths: ['navItems[].viewName', 'tabs[].viewName'], kind: 'app nav' },\n { fromType: 'page', paths: ['viewName'], kind: 'page' },\n ],\n tool: [\n { fromType: 'agent', paths: ['tools[]', 'tools[].name'], kind: 'agent tool' },\n ],\n skill: [\n { fromType: 'agent', paths: ['skills[]', 'skills[].name'], kind: 'agent skill' },\n ],\n flow: [\n { fromType: 'app', paths: ['navItems[].flowName', 'tabs[].flowName'], kind: 'app nav' },\n ],\n dashboard: [\n { fromType: 'app', paths: ['navItems[].dashboardName', 'tabs[].dashboardName'], kind: 'app nav' },\n ],\n page: [\n { fromType: 'app', paths: ['navItems[].pageName', 'tabs[].pageName'], kind: 'app nav' },\n ],\n};\n\n/**\n * Extract one or more string values from `item` at `path`. Supports\n * `'a.b'` (nested object access) and `'a[].b'` (array element access).\n * Returns an empty array if any segment is missing.\n */\nfunction extractPathValues(item: unknown, path: string): string[] {\n if (!item || typeof item !== 'object') return [];\n const segments = path.split('.');\n let current: unknown[] = [item];\n for (const rawSeg of segments) {\n let kind: 'value' | 'array' | 'record' = 'value';\n let seg = rawSeg;\n if (seg.endsWith('[]')) {\n kind = 'array';\n seg = seg.slice(0, -2);\n } else if (seg.endsWith('{}')) {\n kind = 'record';\n seg = seg.slice(0, -2);\n }\n const next: unknown[] = [];\n for (const node of current) {\n if (!node || typeof node !== 'object') continue;\n let value: unknown;\n if (seg === '') {\n value = node;\n } else {\n value = (node as Record<string, unknown>)[seg];\n }\n if (value === undefined || value === null) continue;\n if (kind === 'array') {\n if (Array.isArray(value)) {\n for (const v of value) next.push(v);\n }\n } else if (kind === 'record') {\n if (Array.isArray(value)) {\n for (const v of value) next.push(v);\n } else if (typeof value === 'object') {\n for (const v of Object.values(value as Record<string, unknown>)) next.push(v);\n }\n } else {\n next.push(value);\n }\n }\n current = next;\n if (current.length === 0) return [];\n }\n // Coerce final values to strings, dropping non-string non-object leaves.\n const out: string[] = [];\n for (const v of current) {\n if (typeof v === 'string' && v.length > 0) out.push(v);\n else if (v && typeof v === 'object' && 'name' in (v as any) && typeof (v as any).name === 'string') {\n out.push((v as any).name);\n }\n }\n return out;\n}\n\n/**\n * Phase 3a-destructive: detect changes between an existing object schema\n * and an incoming overlay that would break runtime data — removed fields,\n * field type narrowing, required toggled on without a default. Returned\n * issues are surfaced as HTTP 409 `destructive_change` unless the caller\n * sets `force: true`, letting the admin UI render a warning dialog before\n * proceeding.\n *\n * Scope is intentionally narrow for MVP: covers the most common\n * data-loss footguns for `object` and `field` types. Subsequent passes\n * can layer in relationship changes, enum-value removals, etc.\n */\n/**\n * Shallow JSON diff used by `diffMetaItem`. Compares the top-level\n * keys of `from` vs `to`; primitive value changes are reported as\n * `changed`, nested objects/arrays that differ structurally are also\n * reported as a single `changed` entry (deep structural diffs are out\n * of scope — Studio renders the full bodies for a side-by-side view).\n */\nfunction diffShallow(\n from: Record<string, unknown>,\n to: Record<string, unknown>,\n): {\n added: Array<{ path: string; value: unknown }>;\n removed: Array<{ path: string; value: unknown }>;\n changed: Array<{ path: string; from: unknown; to: unknown }>;\n} {\n const added: Array<{ path: string; value: unknown }> = [];\n const removed: Array<{ path: string; value: unknown }> = [];\n const changed: Array<{ path: string; from: unknown; to: unknown }> = [];\n const fromKeys = new Set(Object.keys(from ?? {}));\n const toKeys = new Set(Object.keys(to ?? {}));\n for (const k of toKeys) {\n if (!fromKeys.has(k)) {\n added.push({ path: k, value: (to as any)[k] });\n } else {\n const a = (from as any)[k];\n const b = (to as any)[k];\n const aStr = JSON.stringify(a);\n const bStr = JSON.stringify(b);\n if (aStr !== bStr) {\n changed.push({ path: k, from: a, to: b });\n }\n }\n }\n for (const k of fromKeys) {\n if (!toKeys.has(k)) {\n removed.push({ path: k, value: (from as any)[k] });\n }\n }\n return { added, removed, changed };\n}\n\nfunction detectDestructiveObjectChanges(prev: any, next: any): Array<{\n code: string;\n field?: string;\n message: string;\n}> {\n if (!prev || typeof prev !== 'object' || !next || typeof next !== 'object') return [];\n const prevFields = (prev.fields && typeof prev.fields === 'object') ? prev.fields as Record<string, any> : {};\n const nextFields = (next.fields && typeof next.fields === 'object') ? next.fields as Record<string, any> : {};\n\n const issues: Array<{ code: string; field?: string; message: string }> = [];\n\n // Removed fields — silently dropping a column is a data-loss event.\n for (const fname of Object.keys(prevFields)) {\n // Skip system fields — those are managed by applySystemFields and\n // re-injected on every registerObject call; they will look \"removed\"\n // in any user-supplied overlay.\n if (prevFields[fname]?.system) continue;\n if (!(fname in nextFields)) {\n issues.push({\n code: 'field_removed',\n field: fname,\n message: `Field '${fname}' removed — existing data in this column will become inaccessible.`,\n });\n }\n }\n\n // Field type changes — narrowing or incompatible conversions.\n const TYPE_COMPATIBILITY: Record<string, Set<string>> = {\n text: new Set(['textarea', 'markdown', 'html', 'code']),\n number: new Set([]),\n boolean: new Set([]),\n date: new Set(['datetime']),\n datetime: new Set(['date']),\n };\n for (const fname of Object.keys(nextFields)) {\n const prevField = prevFields[fname];\n const nextField = nextFields[fname];\n if (!prevField) continue; // brand-new field — non-destructive\n const prevType = prevField.type;\n const nextType = nextField.type;\n if (prevType && nextType && prevType !== nextType) {\n const compatible = TYPE_COMPATIBILITY[prevType]?.has(nextType);\n if (!compatible) {\n issues.push({\n code: 'field_type_change',\n field: fname,\n message: `Field '${fname}' type changed from '${prevType}' to '${nextType}' — existing values may not convert cleanly.`,\n });\n }\n }\n // required toggled on without a default — new inserts will start\n // to fail validation, and any null rows already in the table will\n // fail on next save.\n if (!prevField.required && nextField.required && nextField.defaultValue === undefined) {\n issues.push({\n code: 'field_required_no_default',\n field: fname,\n message: `Field '${fname}' is now required but has no default value — existing rows with null values may fail validation.`,\n });\n }\n }\n return issues;\n}\n\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: ObjectQL;\n private getServicesRegistry?: () => Map<string, any>;\n private getFeedService?: () => IFeedService | undefined;\n /**\n * Project scope applied to sys_metadata reads/writes. When undefined\n * (single-kernel deployments), rows land in / come from the\n * platform-global bucket (`environment_id IS NULL`). When set, every\n * saveMetaItem insert/update and loadMetaFromDb query is filtered by\n * `environment_id = environmentId`, so per-project kernels see only their own\n * metadata even if several projects share the same physical database.\n */\n private environmentId?: string;\n\n /**\n * Lazily-instantiated SysMetadataRepository per organization. Keyed by\n * `${organizationId ?? '__env__'}`. Repositories are stateful — they\n * carry the per-org `seqCounter` and watch subscribers — so we cache\n * them rather than constructing one per call.\n */\n private overlayRepos = new Map<string, SysMetadataRepository>();\n\n constructor(\n engine: IDataEngine,\n getServicesRegistry?: () => Map<string, any>,\n getFeedService?: () => IFeedService | undefined,\n environmentId?: string,\n ) {\n this.engine = engine as ObjectQL;\n this.getServicesRegistry = getServicesRegistry;\n this.getFeedService = getFeedService;\n this.environmentId = environmentId;\n }\n\n /**\n * Lazily obtain a SysMetadataRepository for the given organization.\n * Env-wide overlays (organizationId == null) share a singleton under\n * the `__env__` key.\n */\n private getOverlayRepo(organizationId: string | null): SysMetadataRepository {\n const key = organizationId ?? '__env__';\n let repo = this.overlayRepos.get(key);\n if (!repo) {\n repo = new SysMetadataRepository({\n engine: this.engine as unknown as SysMetadataEngine,\n organizationId,\n orgLabel: organizationId ?? 'env',\n });\n this.overlayRepos.set(key, repo);\n }\n return repo;\n }\n\n /**\n * One-time guard for ensuring the overlay-uniqueness UNIQUE INDEX exists\n * on `sys_metadata`. ADR-0005: scopes overlays by\n * `(type, name, organization_id, environment_id, scope)` for active rows only.\n * Idempotent SQL — safe to attempt on every protocol instance.\n *\n * Inlined here (rather than importing from @objectstack/metadata/migrations)\n * to avoid a circular dependency: metadata already depends on objectql.\n */\n private overlayIndexEnsured = false;\n private async ensureOverlayIndex(): Promise<void> {\n if (this.overlayIndexEnsured) return;\n this.overlayIndexEnsured = true;\n try {\n const engineAny = this.engine as any;\n let driver: any = engineAny?.driver ?? engineAny?.getDriver?.();\n if (!driver && engineAny?.drivers instanceof Map) {\n for (const candidate of engineAny.drivers.values()) {\n if (\n candidate &&\n (typeof (candidate as any).raw === 'function' ||\n typeof (candidate as any).execute === 'function')\n ) {\n driver = candidate;\n break;\n }\n }\n }\n if (!driver) return;\n const exec = async (sql: string): Promise<void> => {\n if (typeof (driver as any).raw === 'function') {\n await (driver as any).raw(sql);\n } else if (typeof (driver as any).execute === 'function') {\n await (driver as any).execute(sql);\n } else {\n throw new Error('driver has neither raw nor execute');\n }\n };\n // ADR-0005 (revised 2026-05): per-env DBs replace the old\n // \"per-project\" isolation, so `environment_id` is no longer a\n // discriminator. Overlay uniqueness is `(type, name,\n // organization_id)` filtered to active rows. Drop the legacy\n // composite index first so the new partial UNIQUE can claim\n // the same name — DROP INDEX IF EXISTS is idempotent.\n try { await exec(\"DROP INDEX IF EXISTS idx_sys_metadata_overlay_active\"); } catch { /* best-effort */ }\n const partialSql =\n \"CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active \" +\n \"ON sys_metadata (type, name, organization_id) \" +\n \"WHERE state = 'active'\";\n const fallbackSql =\n \"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active \" +\n \"ON sys_metadata (type, name, organization_id)\";\n try {\n await exec(partialSql);\n } catch (err: any) {\n const msg = err instanceof Error ? err.message : String(err);\n if (/partial|where clause|syntax/i.test(msg)) {\n try {\n await exec(fallbackSql);\n } catch {\n // ignore — non-essential optimization\n }\n }\n // \"already exists\" or anything else: best-effort\n }\n // Mirror the same partial-UNIQUE for draft rows so a second\n // simultaneous draft cannot be inserted for the same\n // (type,name,org). The unique-active index above already\n // guards published rows; the two never collide because the\n // `state` predicate disambiguates them.\n const draftPartialSql =\n \"CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft \" +\n \"ON sys_metadata (type, name, organization_id) \" +\n \"WHERE state = 'draft'\";\n try {\n await exec(draftPartialSql);\n } catch (err: any) {\n const msg = err instanceof Error ? err.message : String(err);\n if (/partial|where clause|syntax/i.test(msg)) {\n try {\n await exec(\n \"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft \" +\n \"ON sys_metadata (type, name, organization_id)\",\n );\n } catch {\n // ignore — best effort\n }\n }\n }\n } catch {\n // ignore — index is an optimization, not a correctness invariant\n }\n }\n\n /**\n * Exposes the project scope the protocol is bound to. Consumers like\n * the HTTP dispatcher use this to decide whether to trust the process-\n * wide SchemaRegistry or whether they must route a read through the\n * protocol's environment_id-filtered lookup.\n */\n getProjectId(): string | undefined {\n return this.environmentId;\n }\n\n private requireFeedService(): IFeedService {\n const svc = this.getFeedService?.();\n if (!svc) {\n throw new Error('Feed service not available. Install and register service-feed to enable feed operations.');\n }\n return svc;\n }\n\n async getDiscovery() {\n // Get registered services from kernel if available\n const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : new Map();\n \n // Build dynamic service info with proper typing\n const services: Record<string, ServiceInfo> = {\n // --- Kernel-provided (objectql is an example kernel implementation) ---\n metadata: { enabled: true, status: 'available' as const, route: '/api/v1/meta', provider: 'objectql' },\n data: { enabled: true, status: 'available' as const, route: '/api/v1/data', provider: 'objectql' },\n analytics: { enabled: true, status: 'available' as const, route: '/api/v1/analytics', provider: 'objectql' },\n };\n\n // Check which services are actually registered\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n // Service is registered and available\n services[serviceName] = {\n enabled: true,\n status: 'available' as const,\n route: config.route,\n provider: config.plugin,\n };\n } else {\n // Service is not registered\n services[serviceName] = {\n enabled: false,\n status: 'unavailable' as const,\n message: `Install ${config.plugin} to enable`,\n };\n }\n }\n\n // Build routes from services — a flat convenience map for client routing\n const serviceToRouteKey: Record<string, keyof ApiRoutes> = {\n auth: 'auth',\n automation: 'automation',\n ui: 'ui',\n workflow: 'workflow',\n realtime: 'realtime',\n notification: 'notifications',\n ai: 'ai',\n i18n: 'i18n',\n graphql: 'graphql',\n 'file-storage': 'storage',\n };\n\n const optionalRoutes: Partial<ApiRoutes> = {\n analytics: '/api/v1/analytics',\n };\n\n // Add routes for available plugin services\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n const routeKey = serviceToRouteKey[serviceName];\n if (routeKey) {\n optionalRoutes[routeKey] = config.route;\n }\n }\n }\n\n // Add feed service status\n if (registeredServices.has('feed')) {\n services['feed'] = {\n enabled: true,\n status: 'available' as const,\n route: '/api/v1/data',\n provider: 'service-feed',\n };\n } else {\n services['feed'] = {\n enabled: false,\n status: 'unavailable' as const,\n message: 'Install service-feed to enable',\n };\n }\n\n const routes: ApiRoutes = {\n data: '/api/v1/data',\n metadata: '/api/v1/meta',\n ...optionalRoutes,\n };\n\n // Build well-known capabilities from registered services.\n // DiscoverySchema defines capabilities as Record<string, { enabled, features?, description? }>\n // (hierarchical format). We also keep a flat WellKnownCapabilities for backward compat.\n const wellKnown: WellKnownCapabilities = {\n feed: registeredServices.has('feed'),\n comments: registeredServices.has('feed'),\n automation: registeredServices.has('automation'),\n cron: registeredServices.has('job'),\n search: registeredServices.has('search'),\n export: registeredServices.has('automation') || registeredServices.has('queue'),\n chunkedUpload: registeredServices.has('file-storage'),\n };\n\n // Convert flat booleans → hierarchical capability objects\n const capabilities: Record<string, { enabled: boolean; description?: string }> = {};\n for (const [key, enabled] of Object.entries(wellKnown)) {\n capabilities[key] = { enabled };\n }\n\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n routes,\n services,\n capabilities,\n };\n }\n\n async getMetaTypes() {\n const schemaTypes = this.engine.registry.getRegisteredTypes();\n\n // Also include types from MetadataService (runtime-registered: agent, tool, etc.)\n let runtimeTypes: string[] = [];\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.getRegisteredTypes === 'function') {\n runtimeTypes = await metadataService.getRegisteredTypes();\n }\n } catch {\n // MetadataService not available\n }\n\n const allTypes = Array.from(new Set([...schemaTypes, ...runtimeTypes]));\n\n // Phase 3a-1: enrich response with per-type registry metadata so admin\n // UI can render directory pages, filter by domain, decide which types\n // expose write actions, etc. Existing clients keep working — the\n // `types: string[]` field is preserved alongside the new `entries`.\n //\n // Phase 3a-env-writable: `OS_METADATA_WRITABLE` env var (comma\n // separated singular type names) flips `allowOrgOverride` on listed\n // types so admins can self-serve. The same env var is consulted by\n // `isOverlayAllowed()` at write time — they must stay in sync.\n const writableOverrides = ObjectStackProtocolImplementation.envWritableTypes();\n const registryByType = new Map(\n DEFAULT_METADATA_TYPE_REGISTRY.map((e) => [e.type, e] as const)\n );\n\n const entries = allTypes.map((type) => {\n const singular = (PLURAL_TO_SINGULAR[type] ?? type) as string;\n // Phase 3a-schema: emit a JSON Schema per type so the generic\n // metadata admin UI can render real forms (no more raw-JSON\n // textareas for new resources). The canonical schema for every\n // built-in (and plugin-registered) metadata type lives in the\n // central `getMetadataTypeSchema()` registry; we delegate so\n // Studio's editor and the runtime overlay validator stay in\n // lock-step (one source of truth).\n const zodSchema = getMetadataTypeSchema(singular);\n const schema = (zodSchema ? toJsonSchemaSafe(zodSchema) : undefined)\n ?? HAND_CRAFTED_SCHEMAS[singular];\n const form = TYPE_TO_FORM[singular];\n\n // Type-level actions: merge the registry's declarative actions\n // with any plugin-registered overlay (`registerMetadataTypeActions`).\n // This is the single accessor — a host plugin (e.g. the private\n // datasource-admin backend) contributes its `test_connection`\n // button here, co-located with the route handler it calls, so the\n // button only appears when the backend that serves it is installed.\n const typeActions = getMetadataTypeActions(singular);\n\n const base = registryByType.get(singular as any);\n if (base) {\n const isEnvOverridden = writableOverrides.has(singular);\n return {\n ...base,\n type: singular,\n schemaId: singular, // API client expects schemaId field\n allowOrgOverride: base.allowOrgOverride || isEnvOverridden,\n overrideSource: isEnvOverridden && !base.allowOrgOverride\n ? 'env' as const\n : 'registry' as const,\n schema,\n form,\n // Override the spread `base.actions` with the merged view\n // (declarative + plugin-registered). Omit when empty to\n // preserve the prior \"no actions key\" response shape.\n ...(typeActions.length ? { actions: typeActions } : {}),\n };\n }\n // Runtime-registered type with no registry entry — synthesise a\n // minimal descriptor so the UI can still surface it.\n return {\n type: singular,\n schemaId: singular, // API client expects schemaId field\n label: singular,\n description: undefined,\n filePatterns: [],\n supportsOverlay: false,\n allowOrgOverride: writableOverrides.has(singular),\n allowRuntimeCreate: true,\n supportsVersioning: false,\n executionPinned: false,\n loadOrder: 1000,\n domain: 'system' as const,\n overrideSource: writableOverrides.has(singular) ? 'env' as const : 'registry' as const,\n schema,\n form,\n // Plugin-registered actions on a type with no registry entry.\n ...(typeActions.length ? { actions: typeActions } : {}),\n };\n }).sort((a, b) => {\n if (a.domain !== b.domain) return a.domain.localeCompare(b.domain);\n return a.type.localeCompare(b.type);\n });\n\n return { types: allTypes, entries };\n }\n\n /**\n * Sweep all (or filtered) metadata types and report entries that\n * fail spec validation. Powers the Studio governance view\n * (`GET /api/v1/meta/diagnostics`) and `os doctor`-style CLI\n * checks.\n *\n * `severity` defaults to `'error'` — only entries with at least\n * one Zod error issue are returned. `'warning'` includes\n * everything we surface (warnings are reserved for a future lint\n * layer on top of spec validation).\n *\n * `type` may be either a singular (`'view'`) or plural (`'views'`)\n * identifier; the underlying `getMetaItems` already normalises.\n *\n * Implementation note: leverages the `_diagnostics` already\n * decorated onto items by `getMetaItems()` to avoid running\n * `safeParse()` twice. For types whose schema is unregistered we\n * skip silently (they cannot be validated and should not appear\n * as \"valid\" either — they are simply opaque to this report).\n */\n async getMetaDiagnostics(request: {\n type?: string;\n severity?: 'error' | 'warning';\n organizationId?: string;\n packageId?: string;\n } = {}): Promise<{\n entries: Array<{ type: string; name: string; diagnostics: MetadataDiagnostics }>;\n total: number;\n scannedTypes: number;\n scannedItems: number;\n /**\n * Per-type aggregate stats — count of items and the list of\n * packages contributing to each type. Computed in the same\n * sweep so the Studio directory page can render tile counts\n * and a package filter in one round-trip.\n */\n stats: Record<string, { count: number; locked: number; packages: string[] }>;\n }> {\n const includeWarnings = request.severity === 'warning';\n const targetTypes = request.type\n ? [request.type]\n : DEFAULT_METADATA_TYPE_REGISTRY\n .filter((e) => getMetadataTypeSchema(e.type))\n .map((e) => e.type);\n\n const entries: Array<{ type: string; name: string; diagnostics: MetadataDiagnostics }> = [];\n const stats: Record<string, { count: number; locked: number; packages: string[] }> = {};\n let scannedItems = 0;\n\n for (const t of targetTypes) {\n let listed: any;\n try {\n listed = await this.getMetaItems({\n type: t,\n organizationId: request.organizationId,\n packageId: request.packageId,\n } as any);\n } catch {\n // Type not listable in this kernel scope — skip.\n continue;\n }\n const items: any[] = Array.isArray(listed?.items)\n ? listed.items\n : Array.isArray(listed)\n ? listed\n : [];\n const pkgSet = new Set<string>();\n let lockedCount = 0;\n for (const item of items) {\n scannedItems += 1;\n const pkg = (item?._packageId ?? null) as string | null;\n if (pkg) pkgSet.add(pkg);\n const lock = item?._lock as string | undefined;\n if (lock && lock !== 'none') lockedCount += 1;\n const diag: MetadataDiagnostics | undefined =\n item?._diagnostics ?? computeMetadataDiagnostics(t, item);\n if (!diag) continue;\n if (diag.valid && !includeWarnings) continue;\n if (diag.valid && includeWarnings && !diag.warnings?.length) continue;\n entries.push({\n type: t,\n name: typeof item?.name === 'string' ? item.name : '<unknown>',\n diagnostics: diag,\n });\n }\n stats[t] = { count: items.length, locked: lockedCount, packages: [...pkgSet].sort() };\n }\n\n return {\n entries,\n total: entries.length,\n scannedTypes: targetTypes.length,\n scannedItems,\n stats,\n };\n }\n\n async getMetaItems(request: { type: string; packageId?: string; organizationId?: string; previewDrafts?: boolean }) {\n const { packageId } = request;\n let items: unknown[] = [];\n\n // Unscoped kernels (control plane): read everything from SchemaRegistry.\n // Scoped (project) kernels: skip user-project entries in SchemaRegistry to\n // prevent cross-project leakage, but DO include scope:'system' packages\n // (plugin-auth, plugin-security, plugin-audit, …) — those are globally\n // shared and must be visible at every project's meta endpoint.\n if (this.environmentId === undefined) {\n items = [...this.engine.registry.listItems(request.type, packageId)];\n // Normalize singular/plural using explicit mapping\n if (items.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) items = [...this.engine.registry.listItems(alt, packageId)];\n }\n } else {\n // For project kernels: the SchemaRegistry is owned by THIS\n // kernel's ObjectQL instance (not shared across projects in the\n // process), so we can safely include every package — system\n // plugins (auth/security/audit) and the project's own app\n // package alike. The `_packageId` tag added by `listItems`\n // (registry.ts) is preserved for the sidebar to compute the\n // correct navigation URL.\n items = [...this.engine.registry.listItems(request.type, packageId)];\n if (items.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) items = [...this.engine.registry.listItems(alt, packageId)];\n }\n }\n\n // Always consult the DB so metadata persisted by the seeder /\n // bulkRegister shows up even when the registry already has unrelated\n // entries (the previous fallback-only logic meant per-env metadata\n // was never surfaced whenever system-bridged items populated the\n // registry). Deduplicate against whatever the registry returned.\n //\n // ADR-0005 (revised 2026-05): isolation is now per-organization, since\n // each env has its own physical DB. We surface both org-scoped overlays\n // (when an active org is provided) and env-wide (organization_id IS NULL)\n // overlays; org-scoped rows win on name collision.\n try {\n const orgId = (request as any).organizationId as string | undefined;\n const queryByOrg = async (oid: string | null): Promise<any[]> => {\n const whereClause: Record<string, unknown> = {\n type: request.type,\n state: 'active',\n organization_id: oid,\n };\n if (packageId) whereClause.package_id = packageId;\n let rs = await this.engine.find('sys_metadata', { where: whereClause });\n if ((!rs || rs.length === 0)) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = { type: alt, state: 'active', organization_id: oid };\n if (packageId) altWhere.package_id = packageId;\n rs = await this.engine.find('sys_metadata', { where: altWhere });\n }\n }\n return rs ?? [];\n };\n const envWideRecords = await queryByOrg(null);\n const orgRecords = orgId ? await queryByOrg(orgId) : [];\n // org-specific rows override env-wide rows on name collision\n const mergedMap = new Map<string, any>();\n for (const r of envWideRecords) mergedMap.set(r.name, r);\n for (const r of orgRecords) mergedMap.set(r.name, r);\n const records = Array.from(mergedMap.values());\n if (records && records.length > 0) {\n const byName = new Map<string, any>();\n for (const existing of items) {\n const entry = existing as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n byName.set(entry.name, entry);\n }\n }\n for (const record of records) {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n if (data && typeof data === 'object' && 'name' in data) {\n // Surface the persisted software-package binding so the\n // sidebar package filter and provenance classification\n // see overlay rows the same way they see registry items.\n const recPkg = (record as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && (data as any)._packageId === undefined) {\n (data as any)._packageId = recPkg;\n }\n byName.set(data.name, data);\n }\n // Only hydrate the global registry for unscoped calls —\n // scoped project entries must not leak process-wide.\n if (this.environmentId === undefined) {\n this.engine.registry.registerItem(request.type, data, 'name' as any);\n }\n }\n items = Array.from(byName.values());\n }\n } catch {\n // DB not available — fall through with whatever we already have.\n }\n\n // ADR-0033 draft-overlay preview: when the caller opts in (admin-gated\n // upstream — see http-dispatcher), overlay `state='draft'` rows on top of\n // the active result so the rendered console can preview pending changes\n // BEFORE publish (instead of only reading them as a JSON diff). Draft rows\n // WIN over active on name collision, and draft-only items (e.g. a brand-new\n // AI-authored object) surface too. Each overlaid item is tagged `_draft:true`\n // so the UI can badge it and show the \"PREVIEW — drafts\" banner. We do NOT\n // hydrate the SchemaRegistry from drafts — drafts must never leak into the\n // process-wide registry or to non-preview reads.\n if (request.previewDrafts) {\n try {\n const orgId = (request as any).organizationId as string | undefined;\n const queryDrafts = async (oid: string | null): Promise<any[]> => {\n const whereClause: Record<string, unknown> = { type: request.type, state: 'draft', organization_id: oid };\n if (packageId) whereClause.package_id = packageId;\n let rs = await this.engine.find('sys_metadata', { where: whereClause });\n if (!rs || rs.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = { type: alt, state: 'draft', organization_id: oid };\n if (packageId) altWhere.package_id = packageId;\n rs = await this.engine.find('sys_metadata', { where: altWhere });\n }\n }\n return rs ?? [];\n };\n const draftRecords = [...(await queryDrafts(null)), ...(orgId ? await queryDrafts(orgId) : [])];\n if (draftRecords.length > 0) {\n const byName = new Map<string, any>();\n for (const existing of items) {\n const entry = existing as any;\n if (entry && typeof entry === 'object' && 'name' in entry) byName.set(entry.name, entry);\n }\n for (const record of draftRecords) {\n const data = typeof record.metadata === 'string' ? JSON.parse(record.metadata) : record.metadata;\n if (data && typeof data === 'object' && 'name' in data) {\n const recPkg = (record as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && (data as any)._packageId === undefined) (data as any)._packageId = recPkg;\n (data as any)._draft = true;\n byName.set(data.name, data);\n }\n }\n items = Array.from(byName.values());\n }\n } catch {\n // DB unavailable — serve the active result unchanged.\n }\n }\n\n // Merge with MetadataService (runtime-registered items: agents, tools, etc.)\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.list === 'function') {\n let runtimeItems = await metadataService.list(request.type);\n // When filtering by packageId, only include runtime items that\n // belong to the requested package. MetadataService.list() returns\n // items from ALL packages, so we must filter here to respect the\n // package scope requested by the caller (e.g., Studio sidebar).\n if (packageId && runtimeItems && runtimeItems.length > 0) {\n runtimeItems = runtimeItems.filter((item: any) => item?._packageId === packageId);\n }\n if (runtimeItems && runtimeItems.length > 0) {\n // Merge, avoiding duplicates by name\n const itemMap = new Map<string, any>();\n for (const item of items) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n itemMap.set(entry.name, entry);\n }\n }\n for (const item of runtimeItems) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n // Do not overwrite entries already present in the\n // map: those came from sys_metadata (customization\n // overlays) or the SchemaRegistry and must win\n // over the MetadataService's artifact baseline.\n // Without this guard, saved per-org dashboard /\n // view overlays disappear from list endpoints on\n // refresh (detail endpoint kept showing the\n // overlay because it uses a different code path).\n if (!itemMap.has(entry.name)) {\n itemMap.set(entry.name, entry);\n }\n }\n }\n items = Array.from(itemMap.values());\n }\n }\n } catch {\n // MetadataService not available or doesn't support this type\n }\n\n // Hide metadata owned by a disabled package. `listItems` already drops\n // disabled-package items from the SchemaRegistry, but the DB overlay and\n // MetadataService merges above can re-introduce them (e.g. an app/view\n // persisted in sys_metadata). Re-apply the filter on the final merged\n // set so a disabled package's metadata stops surfacing in the console.\n // Never filter `package` (the Packages page must list disabled packages\n // to re-enable them) nor `object`/`objects` (filtering objects would\n // break data queries that depend on their schema).\n if (\n request.type !== 'package' &&\n request.type !== 'object' &&\n request.type !== 'objects'\n ) {\n items = (items as any[]).filter(\n (it) => !this.engine.registry.isPackageDisabled((it as any)?._packageId),\n );\n }\n\n // Canonical-shape exposure (ADR-0017, \"Object has-many View\"): a\n // `defineView` document is kept in the registry under the bare\n // `<object>` key for defensive single-item reads, but it is NOT a\n // first-class, independently addressable view — the registrar expands\n // it into independent ViewItems (each carrying `viewKind` + `config`).\n // Never surface the aggregated `{ list, form, listViews }` container\n // through enumeration so every list consumer (Studio metadata list,\n // REST `GET /meta/view`, AI schema retriever) sees exactly one\n // canonical entry per named view and never the legacy wrapper shape.\n if (request.type === 'view' || request.type === 'views') {\n items = (items as any[]).filter((it) => !isAggregatedViewContainer(it));\n }\n\n // Merge registered navigation contributions into each served app\n // (ADR-0029 D7). The setup app is a shell of empty group anchors;\n // platform-objects and capability plugins inject their menu entries as\n // contributions, merged lazily on read. REST app endpoints read through\n // this path (not registry.getAllApps), so the merge must happen here too\n // or every contributed group renders empty.\n if (request.type === 'app' || request.type === 'apps') {\n items = (items as any[]).map((app) => this.engine.registry.applyNavContributions(app));\n }\n\n return {\n type: request.type,\n items: decorateMetadataItems(\n request.type,\n (items as any[]).map((it) => {\n const a = this.lookupArtifactItem(\n request.type,\n (it as any)?.name,\n );\n return mergeArtifactProtection(it, a) as any;\n }),\n ),\n };\n }\n\n async getMetaItem(request: { type: string, name: string, packageId?: string, organizationId?: string, state?: 'active' | 'draft', previewDrafts?: boolean }) {\n let item: unknown;\n const orgId = request.organizationId;\n // Studio's editor opens a draft buffer with `state: 'draft'`;\n // runtime loaders omit it and get the live published row.\n const readState: 'active' | 'draft' = request.state === 'draft' ? 'draft' : 'active';\n\n // ADR-0033 draft-overlay preview (non-strict): when the caller opts in\n // (admin-gated upstream), prefer a `state='draft'` row if one exists, else\n // fall back to the active read below. This differs from the strict\n // `state:'draft'` mode, which 404s (`no_draft`) when no draft exists — the\n // render path must degrade to the published value, not error. The draft\n // item is tagged `_draft:true` so the UI can badge it.\n if (request.previewDrafts && readState !== 'draft') {\n try {\n const findDraft = async (oid: string | null): Promise<any | undefined> => {\n const rec = await this.engine.findOne('sys_metadata', {\n where: { type: request.type, name: request.name, state: 'draft', organization_id: oid },\n });\n if (rec) return rec;\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n return await this.engine.findOne('sys_metadata', {\n where: { type: alt, name: request.name, state: 'draft', organization_id: oid },\n });\n }\n return undefined;\n };\n const draftRec = (orgId ? await findDraft(orgId) : undefined) ?? await findDraft(null);\n if (draftRec) {\n const draftItem = typeof draftRec.metadata === 'string'\n ? JSON.parse(draftRec.metadata)\n : draftRec.metadata;\n if (draftItem && typeof draftItem === 'object') {\n const recPkg = (draftRec as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && (draftItem as any)._packageId === undefined) (draftItem as any)._packageId = recPkg;\n (draftItem as any)._draft = true;\n }\n return { type: request.type, name: request.name, item: decorateMetadataItem(request.type, draftItem) };\n }\n } catch {\n // DB unavailable — fall through to the active read.\n }\n }\n\n // 1. Customization overlay lookup (sys_metadata).\n // Per ADR-0005 (revised), org-scoped row wins; env-wide\n // (organization_id IS NULL) row is the fallback before falling\n // through to the in-memory registry / MetadataService.\n try {\n const findOverlay = async (oid: string | null): Promise<any | undefined> => {\n const where: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n state: readState,\n organization_id: oid,\n };\n const rec = await this.engine.findOne('sys_metadata', { where });\n if (rec) return rec;\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = {\n type: alt,\n name: request.name,\n state: readState,\n organization_id: oid,\n };\n return await this.engine.findOne('sys_metadata', { where: altWhere });\n }\n return undefined;\n };\n const record = (orgId ? await findOverlay(orgId) : undefined)\n ?? await findOverlay(null);\n if (record) {\n item = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Surface the persisted software-package binding (parity with\n // the list path in getMetaItems) so provenance/UI can read it.\n const recPkg = (record as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && item && typeof item === 'object' && (item as any)._packageId === undefined) {\n (item as any)._packageId = recPkg;\n }\n }\n } catch {\n // DB not available — fall through to registry / MetadataService\n }\n\n // Draft reads stop here — they intentionally do NOT fall through\n // to the runtime registry / MetadataService (which only know\n // about published values). When the draft row is missing we\n // throw `no_draft` (HTTP 404) so the REST contract is identical\n // to `POST /publish` on an empty slot: clients use a single\n // status code to decide \"no pending edit\" without sniffing\n // envelope shape. See ADR-0005 §draft-lifecycle.\n if (readState === 'draft') {\n if (item === undefined) {\n const err: any = new Error(\n `[no_draft] No pending draft exists for ${request.type}/${request.name}.`,\n );\n err.code = 'no_draft';\n err.status = 404;\n throw err;\n }\n return { type: request.type, name: request.name, item: decorateMetadataItem(request.type, item) };\n }\n\n // 2. MetadataService (runtime-registered items: HMR-updated view/page/\n // dashboard/agent/tool, plus FilesystemLoader-sourced items). This\n // is consulted BEFORE the in-memory SchemaRegistry because the\n // registry is a boot-time cache populated by `loadMetadataFromService`\n // and is NOT invalidated on `MetadataManager.register()` (which is\n // how the CLI dev watcher pushes recompiled metadata into the\n // running server). Without this ordering, edits to `*.view.ts`\n // source files appear to take effect (MetadataManager learns the\n // new value) but reads continue to return the stale registry copy.\n if (item === undefined) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n const fromService = await metadataService.get(request.type, request.name);\n if (fromService !== undefined && fromService !== null) {\n item = fromService;\n } else {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altFromService = await metadataService.get(alt, request.name);\n if (altFromService !== undefined && altFromService !== null) {\n item = altFromService;\n }\n }\n }\n }\n } catch {\n // MetadataService not available — fall through\n }\n }\n\n // 3. In-memory SchemaRegistry (artifact-loaded out-of-box values, and\n // items that bypass MetadataService — e.g. some object-schema\n // extension chains registered by AppPlugin directly).\n // Both control-plane (unscoped) and project kernels consult the\n // registry. The previous guard that skipped the registry for\n // project kernels was meant to prevent cross-project leakage at\n // the LIST level — but for a single-item lookup the kernel's own\n // `engine.registry` is project-local (each ObjectQL instance has\n // its own SchemaRegistry), so reading from it is safe and\n // necessary. Without this, project-kernel callers of\n // `GET /api/v1/meta/object/<name>` 404 even though the object is\n // registered and visible via the list endpoint.\n if (item === undefined) {\n item = this.engine.registry.getItem(request.type, request.name);\n if (item === undefined) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) item = this.engine.registry.getItem(alt, request.name);\n }\n }\n\n // Merge registered navigation contributions into a served app\n // (ADR-0029 D7) — parity with the getMetaItems list path so a\n // single-app fetch (GET /meta/app/<name>) also sees the contributed\n // menu entries, not just the empty group-anchor shell.\n if ((request.type === 'app' || request.type === 'apps') && item) {\n item = this.engine.registry.applyNavContributions(item);\n }\n\n // ADR-0010 §3.3 — artifact-level protection (lock/packageId) always\n // wins over any overlay row. The metadata service may return a\n // persisted overlay copy that pre-dates the artifact's `_lock`\n // declaration; we must consult the in-memory artifact registry\n // directly and let its protection envelope override.\n const artifactItem = this.lookupArtifactItem(request.type, request.name);\n const decorated = decorateMetadataItem(\n request.type,\n mergeArtifactProtection(item, artifactItem),\n );\n // ADR-0010 — surface lock/provenance flags so Studio can render\n // the correct affordances without a second round trip.\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n const lockState = resolveLockState(decorated, artifactBacked);\n return {\n type: request.type,\n name: request.name,\n item: decorated,\n lock: lockState.lock,\n ...(lockState.lockReason !== undefined ? { lockReason: lockState.lockReason } : {}),\n ...(lockState.lockSource !== undefined ? { lockSource: lockState.lockSource } : {}),\n ...(lockState.lockDocsUrl !== undefined ? { lockDocsUrl: lockState.lockDocsUrl } : {}),\n ...(lockState.provenance !== undefined ? { provenance: lockState.provenance } : {}),\n ...(lockState.packageId !== undefined ? { packageId: lockState.packageId } : {}),\n ...(lockState.packageVersion !== undefined ? { packageVersion: lockState.packageVersion } : {}),\n editable: lockState.editable,\n deletable: lockState.deletable,\n resettable: lockState.resettable,\n };\n }\n\n /**\n * Phase 3a-layered-get: return the 3 layers of a metadata item\n * separately — `code` (artifact-loaded baseline), `overlay` (per-org\n * customisation row, if any), and `effective` (what `getMetaItem`\n * would return, i.e. overlay-wins merge).\n *\n * Drives the \"Code default vs Overlay vs Effective\" diff tab in the\n * generic Metadata Resource Edit page. Admins can see exactly what\n * was customised and reset selectively.\n *\n * `code` is null if no artifact baseline exists; `overlay` is null if\n * no sys_metadata row exists for the requested scope; `effective` is\n * never null when either layer exists.\n */\n async getMetaItemLayered(request: {\n type: string;\n name: string;\n packageId?: string;\n organizationId?: string;\n }): Promise<{\n type: string;\n name: string;\n code: unknown | null;\n overlay: unknown | null;\n overlayScope: 'org' | 'env' | null;\n effective: unknown | null;\n /**\n * Load-time validation result for the effective payload — same\n * shape attached to getMetaItems/getMetaItem by\n * decorateMetadataItem. Undefined for types without a registered\n * Zod schema (function/service/router). Lets the Studio edit\n * page surface invalid-metadata banners + inline field errors\n * without a second round-trip.\n */\n _diagnostics?: MetadataDiagnostics;\n // ── ADR-0010 protection envelope ──\n lock: MetadataLock;\n lockReason?: string;\n lockSource?: 'artifact' | 'package' | 'env-forced' | 'overlay';\n lockDocsUrl?: string;\n provenance?: MetadataProvenance;\n packageId?: string;\n packageVersion?: string;\n editable: boolean;\n deletable: boolean;\n resettable: boolean;\n }> {\n const orgId = request.organizationId;\n\n // ── code layer: MetadataService.get + registry, BYPASSING overlay ──\n let code: unknown | null = null;\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n let fromService = await metadataService.get(request.type, request.name);\n if (fromService === undefined || fromService === null) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) fromService = await metadataService.get(alt, request.name);\n }\n if (fromService !== undefined && fromService !== null) code = fromService;\n }\n } catch {\n // ignore\n }\n if (code === null) {\n let regItem = this.engine.registry.getItem(request.type, request.name);\n if (regItem === undefined) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) regItem = this.engine.registry.getItem(alt, request.name);\n }\n if (regItem !== undefined) code = regItem;\n }\n\n // ── overlay layer: sys_metadata row (org-scoped wins, then env-wide) ──\n let overlay: unknown | null = null;\n let overlayScope: 'org' | 'env' | null = null;\n try {\n const findOverlay = async (oid: string | null) => {\n const where: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n state: 'active',\n organization_id: oid,\n };\n let rec = await this.engine.findOne('sys_metadata', { where });\n if (!rec) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n rec = await this.engine.findOne('sys_metadata', {\n where: { ...where, type: alt },\n });\n }\n }\n return rec;\n };\n if (orgId) {\n const rec = await findOverlay(orgId);\n if (rec) {\n overlay = typeof rec.metadata === 'string' ? JSON.parse(rec.metadata) : rec.metadata;\n overlayScope = 'org';\n }\n }\n if (overlay === null) {\n const rec = await findOverlay(null);\n if (rec) {\n overlay = typeof rec.metadata === 'string' ? JSON.parse(rec.metadata) : rec.metadata;\n overlayScope = 'env';\n }\n }\n } catch {\n // DB unavailable — overlay stays null\n }\n\n const effective: unknown | null = overlay ?? code;\n\n const _diagnostics =\n effective !== null && effective !== undefined\n ? computeMetadataDiagnostics(request.type, effective)\n : undefined;\n\n // ADR-0010 — surface lock/provenance flags so the Studio editor\n // can render the correct affordances without a second round trip.\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n // Lock resolution: artifact wins over overlay, matching getEffectiveLock.\n const lockSource: any = code ?? overlay ?? {};\n const lockState = resolveLockState(lockSource, artifactBacked);\n\n return {\n type: request.type,\n name: request.name,\n code,\n overlay,\n overlayScope,\n effective,\n ...(_diagnostics ? { _diagnostics } : {}),\n lock: lockState.lock,\n ...(lockState.lockReason !== undefined ? { lockReason: lockState.lockReason } : {}),\n ...(lockState.lockSource !== undefined ? { lockSource: lockState.lockSource } : {}),\n ...(lockState.lockDocsUrl !== undefined ? { lockDocsUrl: lockState.lockDocsUrl } : {}),\n ...(lockState.provenance !== undefined ? { provenance: lockState.provenance } : {}),\n ...(lockState.packageId !== undefined ? { packageId: lockState.packageId } : {}),\n ...(lockState.packageVersion !== undefined ? { packageVersion: lockState.packageVersion } : {}),\n editable: lockState.editable,\n deletable: lockState.deletable,\n resettable: lockState.resettable,\n };\n }\n\n /**\n * ADR-0010 §3.6 / Phase 4.1 — read the metadata-protection audit log\n * for a single item. Returns the most-recent rows of\n * `sys_metadata_audit` for this (type, name) tuple, sorted newest\n * first. Refused (`denied`) and forced (`forced`) writes both appear\n * here — they never reach the `history` endpoint, which only tracks\n * successful body snapshots.\n *\n * The table is provisioned by `platform-objects` and is the\n * compliance surface for the lock-enforcement story. When the\n * environment has not yet provisioned the table (legacy install\n * prior to ADR-0010) the call returns `{ events: [] }` instead of\n * raising, keeping the Studio tab harmless.\n */\n async auditMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string | null;\n limit?: number;\n }): Promise<{\n events: Array<{\n id: unknown;\n occurredAt: string;\n actor: string;\n source: string | null;\n operation: 'save' | 'publish' | 'rollback' | 'delete' | 'reset';\n outcome: 'allowed' | 'denied' | 'forced';\n code: string;\n lockState: MetadataLock | null;\n lockOverridden: boolean;\n requestId: string | null;\n note: string | null;\n }>;\n }> {\n const singular = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const limit = Math.min(\n Math.max(1, request.limit ?? 100),\n 500,\n );\n try {\n // Org-scoped lookup: include rows for the specific org AND\n // env-wide (organization_id IS NULL) rows so the editor\n // sees both tenant overlays and env-level package writes.\n const where: Record<string, unknown> = {\n type: singular,\n name: request.name,\n };\n const rows = await this.engine.find('sys_metadata_audit', {\n where,\n orderBy: [{ field: 'occurred_at', direction: 'desc' }],\n limit,\n } as any);\n const events = (Array.isArray(rows) ? rows : []).map((r: any) => ({\n id: r.id,\n occurredAt:\n typeof r.occurred_at === 'string'\n ? r.occurred_at\n : r.occurred_at instanceof Date\n ? r.occurred_at.toISOString()\n : String(r.occurred_at ?? ''),\n actor: String(r.actor ?? 'system'),\n source: r.source ?? null,\n operation: r.operation,\n outcome: r.outcome,\n code: String(r.code ?? ''),\n lockState: (r.lock_state ?? null) as MetadataLock | null,\n lockOverridden: Boolean(r.lock_overridden),\n requestId: r.request_id ?? null,\n note: r.note ?? null,\n }));\n return { events };\n } catch (err: any) {\n // Table not provisioned (legacy env) or driver doesn't\n // expose `find` — return empty rather than 500ing the tab.\n console.warn(\n `[Protocol] auditMetaItem read failed for ${request.type}/${request.name}: ${err?.message ?? err}`,\n );\n return { events: [] };\n }\n }\n\n async getUiView(request: { object: string, type: 'list' | 'form' }) {\n const schema = this.engine.registry.getObject(request.object);\n if (!schema) throw new Error(`Object ${request.object} not found`);\n\n const fields = schema.fields || {};\n const fieldKeys = Object.keys(fields);\n\n if (request.type === 'list') {\n // Intelligent Column Selection\n // 1. Always include 'name' or name-like fields\n // 2. Limit to 6 columns by default\n const priorityFields = ['name', 'title', 'label', 'subject', 'email', 'status', 'type', 'category', 'created_at'];\n \n let columns = fieldKeys.filter(k => priorityFields.includes(k));\n \n // If few priority fields, add others until 5\n if (columns.length < 5) {\n const remaining = fieldKeys.filter(k => !columns.includes(k) && k !== 'id' && !fields[k].hidden);\n columns = [...columns, ...remaining.slice(0, 5 - columns.length)];\n }\n \n // Sort columns by priority then alphabet or schema order\n // For now, just keep them roughly in order they appear in schema or priority list\n \n return {\n list: {\n type: 'grid' as const,\n object: request.object,\n label: schema.label || schema.name,\n columns: columns.map(f => ({\n field: f,\n label: fields[f]?.label || f,\n sortable: true\n })),\n sort: fields['created_at'] ? ([{ field: 'created_at', order: 'desc' }] as any) : undefined,\n searchableFields: columns.slice(0, 3) // Make first few textual columns searchable\n }\n };\n } else {\n // Form View Generation\n // Simple single-section layout for now\n const formFields = fieldKeys\n .filter(k => k !== 'id' && k !== 'created_at' && k !== 'updated_at' && !fields[k].hidden)\n .map(f => ({\n field: f,\n label: fields[f]?.label,\n required: fields[f]?.required,\n readonly: fields[f]?.readonly,\n type: fields[f]?.type,\n // Default to 2 columns for most, 1 for textareas\n colSpan: (fields[f]?.type === 'textarea' || fields[f]?.type === 'html') ? 2 : 1\n }));\n\n return {\n form: {\n type: 'simple' as const,\n object: request.object,\n label: `Edit ${schema.label || schema.name}`,\n sections: [\n {\n label: 'General Information',\n columns: 2 as const,\n collapsible: false,\n collapsed: false,\n fields: formFields\n }\n ]\n }\n };\n }\n }\n\n async findData(request: { object: string, query?: any, context?: any }) {\n const options: any = { ...request.query };\n // Forward the dispatcher's ExecutionContext so RBAC/RLS middleware\n // can apply per-request enforcement. The protocol layer is purely\n // a normalizer — it must never strip security context.\n if (request.context !== undefined) {\n options.context = request.context;\n }\n\n // ====================================================================\n // Normalize legacy params → QueryAST standard (where/fields/orderBy/offset/expand)\n // ====================================================================\n\n // OData-style `$`-prefixed params → bare aliases that the rest of\n // this function knows how to normalize. Without this step, params\n // like `?$top=2&$orderby=...` survive into the catch-all\n // implicit-filter pass below and get merged into `where` as\n // bogus field-equality predicates (e.g. `where.$top = \"2\"`),\n // which silently returns zero rows for every list endpoint.\n for (const [dollar, bare] of [\n ['$top', 'top'],\n ['$skip', 'skip'],\n ['$orderby', 'orderBy'],\n ['$select', 'select'],\n ['$count', 'count'],\n ] as const) {\n if (options[dollar] != null && options[bare] == null) {\n options[bare] = options[dollar];\n }\n delete options[dollar];\n }\n\n // Numeric fields — normalize top → limit, skip → offset\n if (options.top != null) {\n options.limit = Number(options.top);\n delete options.top;\n }\n if (options.skip != null) {\n options.offset = Number(options.skip);\n delete options.skip;\n }\n if (options.limit != null) options.limit = Number(options.limit);\n if (options.offset != null) options.offset = Number(options.offset);\n\n // Select → fields: comma-separated string → array\n if (typeof options.select === 'string') {\n options.fields = options.select.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(options.select)) {\n options.fields = options.select;\n }\n if (options.select !== undefined) delete options.select;\n\n // Sort/orderBy → orderBy: string → SortNode[] array\n const sortValue = options.orderBy ?? options.sort;\n if (typeof sortValue === 'string') {\n const parsed = sortValue.split(',').map((part: string) => {\n const trimmed = part.trim();\n if (trimmed.startsWith('-')) {\n return { field: trimmed.slice(1), order: 'desc' as const };\n }\n const [field, order] = trimmed.split(/\\s+/);\n return { field, order: (order?.toLowerCase() === 'desc' ? 'desc' : 'asc') as 'asc' | 'desc' };\n }).filter((s: any) => s.field);\n options.orderBy = parsed;\n } else if (Array.isArray(sortValue)) {\n options.orderBy = sortValue;\n }\n delete options.sort;\n\n // Filter/filters/$filter → where: normalize all filter aliases\n const filterValue = options.filter ?? options.filters ?? options.$filter ?? options.where;\n delete options.filter;\n delete options.filters;\n delete options.$filter;\n\n if (filterValue !== undefined) {\n let parsedFilter = filterValue;\n // JSON string → object\n if (typeof parsedFilter === 'string') {\n try { parsedFilter = JSON.parse(parsedFilter); } catch { /* keep as-is */ }\n }\n // Filter AST array → FilterCondition object\n if (isFilterAST(parsedFilter)) {\n parsedFilter = parseFilterAST(parsedFilter);\n }\n options.where = parsedFilter;\n }\n\n // Populate/expand/$expand → expand (Record<string, QueryAST>)\n const populateValue = options.populate;\n const expandValue = options.$expand ?? options.expand;\n const expandNames: string[] = [];\n if (typeof populateValue === 'string') {\n expandNames.push(...populateValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(populateValue)) {\n expandNames.push(...populateValue);\n }\n if (!expandNames.length && expandValue) {\n if (typeof expandValue === 'string') {\n expandNames.push(...expandValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(expandValue)) {\n expandNames.push(...expandValue);\n }\n }\n delete options.populate;\n delete options.$expand;\n // Clean up non-object expand (e.g. string) BEFORE the Record conversion\n // below, so that populate-derived names can create the expand Record even\n // when a legacy string expand was also present.\n if (typeof options.expand !== 'object' || options.expand === null) {\n delete options.expand;\n }\n // Only set expand if not already an object (advanced usage)\n if (expandNames.length > 0 && !options.expand) {\n options.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n options.expand[rel] = { object: rel };\n }\n }\n\n // Boolean fields\n for (const key of ['distinct', 'count']) {\n if (options[key] === 'true') options[key] = true;\n else if (options[key] === 'false') options[key] = false;\n }\n \n // Flat field filters: REST-style query params like ?id=abc&status=open\n // After extracting all known query parameters, any remaining keys are\n // treated as implicit field-level equality filters merged into `where`.\n const knownParams = new Set([\n 'top', 'limit', 'offset',\n 'orderBy',\n 'fields',\n 'where',\n 'expand',\n 'distinct', 'count',\n 'aggregations', 'groupBy',\n 'search', 'context', 'cursor',\n ]);\n if (!options.where) {\n const implicitFilters: Record<string, unknown> = {};\n for (const key of Object.keys(options)) {\n if (!knownParams.has(key)) {\n implicitFilters[key] = options[key];\n delete options[key];\n }\n }\n if (Object.keys(implicitFilters).length > 0) {\n options.where = implicitFilters;\n }\n }\n \n // Route to engine.aggregate() when the query has GROUP BY / aggregations.\n // engine.find() does not do in-memory aggregation fallback, so without\n // this branch a spec-shape aggregate request would silently return\n // ungrouped raw rows on drivers (e.g. SqlDriver) that don't natively\n // honor groupBy/aggregations in find().\n const hasGroupBy = Array.isArray(options.groupBy) && options.groupBy.length > 0;\n const hasAggregations = Array.isArray(options.aggregations) && options.aggregations.length > 0;\n if (hasGroupBy || hasAggregations) {\n const records = await this.engine.aggregate(request.object, {\n where: options.where,\n groupBy: options.groupBy,\n aggregations: options.aggregations,\n context: options.context,\n } as any);\n // Apply limit client-side (EngineAggregateOptions doesn't carry limit)\n const limited = typeof options.limit === 'number' && options.limit > 0\n ? records.slice(0, options.limit)\n : records;\n return {\n object: request.object,\n records: limited,\n total: limited.length,\n hasMore: false,\n };\n }\n\n const records = await this.engine.find(request.object, options);\n // Spec: FindDataResponseSchema — only `records` is returned.\n // OData `value` adaptation (if needed) is handled in the HTTP dispatch layer.\n return {\n object: request.object,\n records,\n total: records.length,\n hasMore: false\n };\n }\n\n async getData(request: { object: string, id: string, expand?: string | string[], select?: string | string[], context?: any }) {\n const queryOptions: any = {\n where: { id: request.id }\n };\n if (request.context !== undefined) {\n queryOptions.context = request.context;\n }\n\n // Support fields for single-record retrieval\n if (request.select) {\n queryOptions.fields = typeof request.select === 'string'\n ? request.select.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.select;\n }\n\n // Support expand for single-record retrieval\n if (request.expand) {\n const expandNames = typeof request.expand === 'string'\n ? request.expand.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.expand;\n queryOptions.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n queryOptions.expand[rel] = { object: rel };\n }\n }\n\n const result = await this.engine.findOne(request.object, queryOptions);\n if (result) {\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n const err = new Error(`Record ${request.id} not found in ${request.object}`) as Error & {\n code?: string;\n status?: number;\n object?: string;\n };\n err.code = 'RECORD_NOT_FOUND';\n err.status = 404;\n err.object = request.object;\n throw err;\n }\n\n async createData(request: { object: string, data: any, context?: any }) {\n const result = await this.engine.insert(\n request.object,\n request.data,\n request.context !== undefined ? { context: request.context } as any : undefined,\n );\n return {\n object: request.object,\n id: result.id,\n record: result\n };\n }\n\n async updateData(request: { object: string, id: string, data: any, expectedVersion?: string, context?: any }) {\n await this.assertVersionMatch(request.object, request.id, request.expectedVersion, request.context);\n const opts: any = { where: { id: request.id } };\n if (request.context !== undefined) opts.context = request.context;\n const result = await this.engine.update(request.object, request.data, opts);\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n\n async deleteData(request: { object: string, id: string, expectedVersion?: string, context?: any }) {\n await this.assertVersionMatch(request.object, request.id, request.expectedVersion, request.context);\n const opts: any = { where: { id: request.id } };\n if (request.context !== undefined) opts.context = request.context;\n await this.engine.delete(request.object, opts);\n return {\n object: request.object,\n id: request.id,\n success: true\n };\n }\n\n /**\n * Optimistic Concurrency Control gate shared by updateData/deleteData.\n *\n * When the caller passes a non-empty `expectedVersion` token (typically\n * the `updated_at` value they read), this fetches the current record\n * and compares its `updated_at` against the token. Mismatch → throw\n * `ConcurrentUpdateError` which the REST layer maps to 409.\n *\n * Behaviour:\n * - Empty/missing token → no check (opt-in semantics; existing callers\n * that haven't yet adopted OCC are unaffected).\n * - Record not found → no check; downstream `engine.update` will\n * surface the usual `RECORD_NOT_FOUND` 404. We intentionally do not\n * treat \"missing record\" as a concurrency conflict.\n * - Record has no `updated_at` field (timestamps disabled) → no check.\n * Logging would be noisy here; OCC is opt-in and the absence of a\n * version column is an explicit \"this object doesn't support OCC\"\n * signal.\n */\n private async assertVersionMatch(\n object: string,\n id: string,\n expectedVersion: string | undefined,\n context: any\n ): Promise<void> {\n const expected = normaliseVersionToken(expectedVersion);\n if (!expected) return;\n const findOpts: any = { where: { id } };\n if (context !== undefined) findOpts.context = context;\n const current = await this.engine.findOne(object, findOpts);\n if (!current) return;\n const currentVersion = normaliseVersionToken((current as any).updated_at);\n if (!currentVersion) return;\n if (currentVersion !== expected) {\n throw new ConcurrentUpdateError({\n currentVersion,\n currentRecord: current,\n message: `Record ${object}/${id} was modified by another user (current version ${currentVersion}, expected ${expected})`,\n });\n }\n }\n\n // ==========================================\n // Global Search (M10.5)\n // ==========================================\n /**\n * Cross-object substring search across all registered objects that opt in\n * via `enable.searchable !== false` and `enable.apiEnabled !== false`.\n * Searches text-like fields (text/textarea/email/url/phone/markdown/html/string)\n * whose `searchable: true` flag is set, falling back to the object's\n * `displayNameField` (or `name`) when no fields are explicitly searchable.\n *\n * The query is split into whitespace-separated terms; each term must match\n * (case-insensitive LIKE) at least one searchable field. RBAC/RLS is\n * enforced by forwarding the caller's `context` to `engine.find` so users\n * only see records they are entitled to read.\n */\n async searchAll(request: {\n q: string;\n objects?: string[];\n limit?: number;\n perObject?: number;\n context?: any;\n }): Promise<{\n query: string;\n hits: Array<{\n object: string;\n id: string;\n title: string;\n snippet?: string;\n record: any;\n }>;\n totalObjects: number;\n totalHits: number;\n truncated: boolean;\n }> {\n const q = (request.q ?? '').trim();\n if (!q) {\n return { query: '', hits: [], totalObjects: 0, totalHits: 0, truncated: false };\n }\n\n const overallLimit = Math.max(1, Math.min(100, Number(request.limit ?? 20)));\n const perObject = Math.max(1, Math.min(25, Number(request.perObject ?? 5)));\n const objectsFilter = request.objects && request.objects.length\n ? new Set(request.objects)\n : null;\n\n // Tokenise: each token must match (LIKE %term%) at least one searchable field\n const terms = q.split(/\\s+/).filter(Boolean).slice(0, 8);\n\n const allObjects = (this.engine as any).registry?.getAllObjects?.() ?? [];\n const hits: Array<{ object: string; id: string; title: string; snippet?: string; record: any }> = [];\n let objectsScanned = 0;\n\n for (const obj of allObjects) {\n if (hits.length >= overallLimit) break;\n if (!obj?.name) continue;\n if (objectsFilter && !objectsFilter.has(obj.name)) continue;\n\n // Skip platform/system tables and opt-outs\n const enable = obj.enable ?? {};\n if (enable.searchable === false) continue;\n if (enable.apiEnabled === false) continue;\n // Skip noisy system tables by name prefix\n if (obj.name.startsWith('sys_audit_log')\n || obj.name.startsWith('sys_activity')\n || obj.name.startsWith('sys_session')\n || obj.name.startsWith('sys_presence')\n || obj.name.startsWith('sys_metadata')\n || obj.name.startsWith('sys_account')) {\n continue;\n }\n\n const fieldsRaw = obj.fields;\n const fields: Array<{ name: string; type: string; searchable?: boolean }> =\n Array.isArray(fieldsRaw)\n ? fieldsRaw\n : (fieldsRaw && typeof fieldsRaw === 'object'\n ? Object.entries(fieldsRaw).map(([name, f]: [string, any]) => ({ name, ...(f || {}) }))\n : []);\n const TEXT_TYPES = new Set(['text', 'textarea', 'string', 'email', 'url', 'phone', 'markdown', 'html']);\n const fieldByName = new Map(fields.map(f => [f.name, f]));\n const hasField = (n: string) => fieldByName.has(n);\n // Resolve title for a record using titleFormat → displayNameField →\n // common conventional fields → id. titleFormat supports simple\n // `{field}` placeholders (the `template` dialect); unresolved\n // placeholders fall through to the next strategy.\n const titleFormatSource = (obj.titleFormat && (obj.titleFormat.source || obj.titleFormat))\n || undefined;\n const renderTitle = (row: any): string => {\n if (typeof titleFormatSource === 'string') {\n let allResolved = true;\n const rendered = titleFormatSource.replace(/\\{\\{?\\s*([a-zA-Z0-9_.]+)\\s*\\}?\\}/g, (_m, key) => {\n const v = row[key];\n if (v == null || v === '') { allResolved = false; return ''; }\n return String(v);\n }).trim();\n if (rendered && allResolved) return rendered;\n if (rendered) return rendered.replace(/\\s+-\\s+$/, '').replace(/^\\s+-\\s+/, '').trim() || row.id;\n }\n const candidates = [\n obj.displayNameField,\n 'name', 'full_name', 'title', 'subject', 'label', 'company',\n ].filter((c): c is string => typeof c === 'string' && hasField(c));\n for (const c of candidates) {\n const v = row[c];\n if (v != null && String(v).trim()) return String(v);\n }\n const fn = row.first_name, ln = row.last_name;\n if (fn || ln) return `${fn ?? ''} ${ln ?? ''}`.trim();\n return String(row.id);\n };\n\n const titleFieldName = obj.displayNameField\n || (hasField('name') ? 'name' : undefined)\n || (hasField('title') ? 'title' : undefined)\n || fields.find(f => TEXT_TYPES.has(f.type))?.name;\n\n let searchableFields = fields\n .filter(f => f && TEXT_TYPES.has(f.type) && f.searchable === true)\n .map(f => f.name as string);\n\n // Fallback: if no field is explicitly searchable, scan the title field\n if (searchableFields.length === 0 && titleFieldName) {\n searchableFields = [titleFieldName];\n }\n if (searchableFields.length === 0) continue;\n\n objectsScanned++;\n\n // Build AND-of-OR filter: every term must hit at least one field.\n // ObjectQL exposes case-insensitive substring matching via `$contains`.\n const andClauses = terms.map(term => ({\n $or: searchableFields.map(f => ({ [f]: { $contains: term } })),\n }));\n const where = andClauses.length === 1 ? andClauses[0] : { $and: andClauses };\n\n try {\n const opts: any = {\n where,\n limit: perObject,\n orderBy: [{ field: 'updated_at', direction: 'desc' }],\n };\n if (request.context !== undefined) opts.context = request.context;\n\n const rows = await this.engine.find(obj.name, opts);\n for (const row of rows || []) {\n if (hits.length >= overallLimit) break;\n const title = renderTitle(row);\n // Build snippet from first searchable field that contains a term\n let snippet: string | undefined;\n for (const f of searchableFields) {\n const v = row[f];\n if (typeof v === 'string' && v) {\n const lc = v.toLowerCase();\n const idx = terms.map(t => lc.indexOf(t.toLowerCase())).find(i => i >= 0);\n if (idx != null && idx >= 0) {\n const start = Math.max(0, idx - 30);\n const end = Math.min(v.length, idx + 90);\n snippet = (start > 0 ? '…' : '') + v.slice(start, end) + (end < v.length ? '…' : '');\n break;\n }\n }\n }\n hits.push({\n object: obj.name,\n id: row.id,\n title,\n snippet,\n record: row,\n });\n }\n } catch {\n // RBAC denial or driver hiccup — skip silently per object\n continue;\n }\n }\n\n return {\n query: q,\n hits,\n totalObjects: objectsScanned,\n totalHits: hits.length,\n truncated: hits.length >= overallLimit,\n };\n }\n\n // ==========================================\n // Lead Convert (M10.6)\n // ==========================================\n /**\n * Convert a qualified Lead into an Account + Contact (+ optional\n * Opportunity) and mark the Lead as converted. Mirrors the Salesforce\n * lead-conversion model:\n *\n * - If `accountId` is provided, the lead's company info is NOT used\n * to create a new account; the new contact and opportunity link to\n * the existing account instead.\n * - If `contactId` is provided, no new contact is created either —\n * useful when the lead is a new contact at an existing account.\n * - `createOpportunity` defaults to true; pass `false` to convert\n * without producing an opportunity (some teams convert \"logos\n * only\" first).\n * - Lead is updated atomically: `is_converted=true`,\n * `converted_account`/`converted_contact`/`converted_opportunity`\n * pointers, `converted_date`, and `status='converted'`.\n *\n * Atomicity is enforced via the default driver's transaction support\n * when available; otherwise a best-effort compensation (delete\n * already-created child records on failure) is attempted. Permission\n * checks on each child object are inherited from the caller's\n * execution context so SecurityPlugin still gates account/contact/\n * opportunity creates.\n */\n async convertLead(request: {\n leadId: string;\n accountId?: string;\n contactId?: string;\n createOpportunity?: boolean;\n opportunity?: {\n name?: string;\n amount?: number;\n close_date?: string;\n stage?: string;\n };\n convertedStatus?: string;\n context?: any;\n }): Promise<{\n lead: any;\n account: any;\n contact: any;\n opportunity: any | null;\n }> {\n const leadId = String(request.leadId || '').trim();\n if (!leadId) {\n const err: any = new Error('leadId is required');\n err.status = 400;\n err.code = 'INVALID_REQUEST';\n throw err;\n }\n const ctx = request.context;\n const ctxOpt = ctx !== undefined ? { context: ctx } : undefined;\n\n // Load lead\n const lead = await this.engine.findOne('lead', { where: { id: leadId }, ...(ctxOpt as any) } as any);\n if (!lead) {\n const err: any = new Error(`Lead '${leadId}' not found`);\n err.status = 404;\n err.code = 'LEAD_NOT_FOUND';\n throw err;\n }\n if (lead.is_converted) {\n const err: any = new Error(`Lead '${leadId}' is already converted`);\n err.status = 409;\n err.code = 'LEAD_ALREADY_CONVERTED';\n throw err;\n }\n\n // Wrap the whole conversion in a single DB transaction so that a\n // partial failure (e.g. opportunity insert fails after we've\n // already created the account/contact) rolls back atomically\n // instead of leaving orphan rows. Falls back to direct execution\n // on drivers without transaction support — in that case the\n // operations are still ordered so callers see the same partial\n // state we'd get from any non-atomic sequence.\n const runConversion = async (trxCtx: any) => {\n const opCtx = trxCtx ?? ctx;\n const trxCtxOpt = opCtx !== undefined ? { context: opCtx } : undefined;\n\n // 1) Account\n let account: any;\n if (request.accountId) {\n account = await this.engine.findOne('account', { where: { id: request.accountId }, ...(trxCtxOpt as any) } as any);\n if (!account) {\n const err: any = new Error(`Account '${request.accountId}' not found`);\n err.status = 404;\n err.code = 'ACCOUNT_NOT_FOUND';\n throw err;\n }\n } else {\n const accountPayload: Record<string, any> = {\n name: lead.company || `${lead.first_name ?? ''} ${lead.last_name ?? ''}`.trim() || 'Untitled Account',\n };\n if (lead.industry) accountPayload.industry = lead.industry;\n if (lead.annual_revenue) accountPayload.annual_revenue = lead.annual_revenue;\n if (lead.number_of_employees) accountPayload.employees = lead.number_of_employees;\n if (lead.website) accountPayload.website = lead.website;\n if (lead.phone) accountPayload.phone = lead.phone;\n if (lead.address) accountPayload.billing_address = lead.address;\n if (lead.owner) accountPayload.owner = lead.owner;\n account = await this.engine.insert('account', accountPayload, trxCtxOpt as any);\n }\n\n // 2) Contact\n let contact: any;\n if (request.contactId) {\n contact = await this.engine.findOne('contact', { where: { id: request.contactId }, ...(trxCtxOpt as any) } as any);\n if (!contact) {\n const err: any = new Error(`Contact '${request.contactId}' not found`);\n err.status = 404;\n err.code = 'CONTACT_NOT_FOUND';\n throw err;\n }\n } else {\n const contactPayload: Record<string, any> = {\n first_name: lead.first_name ?? '',\n last_name: lead.last_name ?? lead.company ?? 'Unknown',\n };\n if (lead.salutation) contactPayload.salutation = lead.salutation;\n if (lead.email) contactPayload.email = lead.email;\n if (lead.phone) contactPayload.phone = lead.phone;\n if (lead.mobile) contactPayload.mobile = lead.mobile;\n if (lead.title) contactPayload.title = lead.title;\n if (lead.address) contactPayload.mailing_address = lead.address;\n if (lead.owner) contactPayload.owner = lead.owner;\n if (account?.id) contactPayload.account = account.id;\n contact = await this.engine.insert('contact', contactPayload, trxCtxOpt as any);\n }\n\n // 3) Opportunity (optional)\n let opportunity: any | null = null;\n const shouldCreateOpp = request.createOpportunity !== false;\n if (shouldCreateOpp) {\n const oppOverrides = request.opportunity ?? {};\n const defaultName = oppOverrides.name\n || `${account?.name ?? lead.company ?? 'Lead'} - New Opportunity`;\n const defaultClose = oppOverrides.close_date\n || new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);\n const oppPayload: Record<string, any> = {\n name: defaultName,\n stage: oppOverrides.stage ?? 'qualification',\n close_date: defaultClose,\n };\n if (oppOverrides.amount !== undefined) oppPayload.amount = oppOverrides.amount;\n else if (lead.annual_revenue) oppPayload.amount = lead.annual_revenue;\n if (account?.id) oppPayload.account = account.id;\n if (contact?.id) oppPayload.primary_contact = contact.id;\n if (lead.owner) oppPayload.owner = lead.owner;\n if (lead.lead_source) oppPayload.lead_source = lead.lead_source;\n opportunity = await this.engine.insert('opportunity', oppPayload, trxCtxOpt as any);\n }\n\n // 4) Mark lead converted\n const leadUpdate: Record<string, any> = {\n is_converted: true,\n status: request.convertedStatus ?? 'converted',\n converted_account: account?.id ?? null,\n converted_contact: contact?.id ?? null,\n converted_opportunity: opportunity?.id ?? null,\n converted_date: new Date().toISOString(),\n };\n const updatedLead = await this.engine.update('lead', leadUpdate, {\n where: { id: leadId },\n ...(trxCtxOpt as any),\n } as any);\n\n return {\n lead: updatedLead ?? { ...lead, ...leadUpdate },\n account,\n contact,\n opportunity,\n };\n };\n\n return (this.engine as any).transaction(runConversion, ctx);\n }\n\n // ==========================================\n // Metadata Caching\n // ==========================================\n\n async getMetaItemCached(request: { type: string, name: string, cacheRequest?: MetadataCacheRequest, locale?: string }): Promise<MetadataCacheResponse> {\n try {\n // Delegate to getMetaItem so the customization-overlay read order\n // (sys_metadata → registry → MetadataService) is honoured here too\n // (ADR-0005). Without this, cached reads silently bypass overlays.\n const result = await this.getMetaItem({ type: request.type, name: request.name });\n const item = (result as any)?.item;\n\n if (!item) {\n throw new Error(`Metadata item ${request.type}/${request.name} not found`);\n }\n\n // Calculate ETag (simple hash of the stringified metadata).\n //\n // The ETag MUST vary by locale. The REST layer translates the\n // response body *after* this validator check, so an ETag computed\n // only from the (untranslated) content would let a language switch\n // match the prior `If-None-Match` and return `304 Not Modified`\n // carrying a stale-locale body — labels/headers stuck in the old\n // language until a hard refresh (issue #1319). Folding the resolved\n // locale into the hash gives each locale a distinct validator.\n const content = JSON.stringify(item);\n const hash = simpleHash(request.locale ? `${request.locale}\u0000${content}` : content);\n const etag = { value: hash, weak: false };\n\n // Check If-None-Match header\n if (request.cacheRequest?.ifNoneMatch) {\n const clientEtag = request.cacheRequest.ifNoneMatch.replace(/^\"(.*)\"$/, '$1').replace(/^W\\/\"(.*)\"$/, '$1');\n if (clientEtag === hash) {\n // Return 304 Not Modified\n return {\n notModified: true,\n etag,\n };\n }\n }\n\n // Return full metadata with cache headers\n return {\n data: item,\n etag,\n lastModified: new Date().toISOString(),\n cacheControl: {\n directives: ['public', 'max-age'],\n maxAge: 3600, // 1 hour\n },\n notModified: false,\n };\n } catch (error: any) {\n throw error;\n }\n }\n\n // ==========================================\n // Batch Operations\n // ==========================================\n\n async batchData(request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {\n const { object, request: batchReq } = request;\n const { operation, records, options } = batchReq;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n switch (operation) {\n case 'create': {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n succeeded++;\n break;\n }\n case 'update': {\n if (!record.id) throw new Error('Record id is required for update');\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n break;\n }\n case 'upsert': {\n // Try update first, then create if not found\n if (record.id) {\n try {\n const existing = await this.engine.findOne(object, { where: { id: record.id } });\n if (existing) {\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n } else {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } catch {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } else {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n }\n succeeded++;\n break;\n }\n case 'delete': {\n if (!record.id) throw new Error('Record id is required for delete');\n await this.engine.delete(object, { where: { id: record.id } });\n results.push({ id: record.id, success: true });\n succeeded++;\n break;\n }\n default:\n results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });\n failed++;\n }\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (options?.atomic) {\n // Abort remaining operations on first failure in atomic mode\n break;\n }\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation,\n total: records.length,\n succeeded,\n failed,\n results: options?.returnRecords !== false ? results : results.map(r => ({ id: r.id, success: r.success, error: r.error })),\n } as BatchUpdateResponse;\n }\n \n async createManyData(request: { object: string, records: any[] }): Promise<any> {\n const records = await this.engine.insert(request.object, request.records);\n return {\n object: request.object,\n records,\n count: records.length\n };\n }\n \n async updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse> {\n const { object, records, options } = request;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n const updated = await this.engine.update(object, record.data, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation: 'update',\n total: records.length,\n succeeded,\n failed,\n results,\n } as BatchUpdateResponse;\n }\n\n async analyticsQuery(request: any): Promise<any> {\n // Map AnalyticsQuery (cube-style) to engine aggregation.\n // cube name maps to object name; measures → aggregations; dimensions → groupBy.\n const { query, cube } = request;\n const object = cube;\n\n // Build groupBy from dimensions\n const groupBy = query.dimensions || [];\n\n // Build aggregations from measures\n // Measures can be simple field names like \"count\" or \"field_name.sum\"\n // Or cube-defined measure names. We support: field.function or just function(field).\n const aggregations: Array<{ field: string; method: string; alias: string }> = [];\n if (query.measures) {\n for (const measure of query.measures) {\n // Support formats: \"count\", \"amount.sum\", \"revenue.avg\"\n if (measure === 'count' || measure === 'count_all') {\n aggregations.push({ field: '*', method: 'count', alias: 'count' });\n } else if (measure.includes('.')) {\n const [field, method] = measure.split('.');\n aggregations.push({ field, method, alias: `${field}_${method}` });\n } else {\n // Treat as count of the field\n aggregations.push({ field: measure, method: 'sum', alias: measure });\n }\n }\n }\n\n // Build filter from analytics filters\n let filter: any = undefined;\n if (query.filters && query.filters.length > 0) {\n const conditions: any[] = query.filters.map((f: any) => {\n const op = this.mapAnalyticsOperator(f.operator);\n if (f.values && f.values.length === 1) {\n return { [f.member]: { [op]: f.values[0] } };\n } else if (f.values && f.values.length > 1) {\n return { [f.member]: { $in: f.values } };\n }\n return { [f.member]: { [op]: true } };\n });\n filter = conditions.length === 1 ? conditions[0] : { $and: conditions };\n }\n\n // Execute via engine.aggregate (which delegates to driver.find with groupBy/aggregations)\n const rows = await this.engine.aggregate(object, {\n where: filter,\n groupBy: groupBy.length > 0 ? groupBy : undefined,\n aggregations: aggregations.length > 0\n ? aggregations.map(a => ({ function: a.method as any, field: a.field, alias: a.alias }))\n : [{ function: 'count' as any, alias: 'count' }],\n });\n\n // Build field metadata\n const fields = [\n ...groupBy.map((d: string) => ({ name: d, type: 'string' })),\n ...aggregations.map(a => ({ name: a.alias, type: 'number' })),\n ];\n\n return {\n success: true,\n data: {\n rows,\n fields,\n },\n };\n }\n\n async getAnalyticsMeta(request: any): Promise<any> {\n // Auto-generate cube metadata from registered objects in SchemaRegistry.\n // Each object becomes a cube; number fields → measures; other fields → dimensions.\n const objects = this.engine.registry.listItems('object');\n const cubeFilter = request?.cube;\n\n const cubes: any[] = [];\n for (const obj of objects) {\n const schema = obj as any;\n if (cubeFilter && schema.name !== cubeFilter) continue;\n\n const measures: Record<string, any> = {};\n const dimensions: Record<string, any> = {};\n const fields = schema.fields || {};\n\n // Always add a count measure\n measures['count'] = {\n name: 'count',\n label: 'Count',\n type: 'count',\n sql: '*',\n };\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n const fd = fieldDef as any;\n const fieldType = fd.type || 'text';\n\n if (['number', 'currency', 'percent'].includes(fieldType)) {\n // Numeric fields become both measures and dimensions\n measures[`${fieldName}_sum`] = {\n name: `${fieldName}_sum`,\n label: `${fd.label || fieldName} (Sum)`,\n type: 'sum',\n sql: fieldName,\n };\n measures[`${fieldName}_avg`] = {\n name: `${fieldName}_avg`,\n label: `${fd.label || fieldName} (Avg)`,\n type: 'avg',\n sql: fieldName,\n };\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'number',\n sql: fieldName,\n };\n } else if (['date', 'datetime'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'time',\n sql: fieldName,\n granularities: ['day', 'week', 'month', 'quarter', 'year'],\n };\n } else if (['boolean'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'boolean',\n sql: fieldName,\n };\n } else {\n // text, select, lookup, etc. → dimension\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'string',\n sql: fieldName,\n };\n }\n }\n\n cubes.push({\n name: schema.name,\n title: schema.label || schema.name,\n description: schema.description,\n sql: schema.name,\n measures,\n dimensions,\n public: true,\n });\n }\n\n return {\n success: true,\n data: { cubes },\n };\n }\n\n private mapAnalyticsOperator(op: string): string {\n const map: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$contains',\n notContains: '$notContains',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n set: '$ne',\n notSet: '$eq',\n };\n return map[op] || '$eq';\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the \"automation\" service.');\n }\n\n async deleteManyData(request: DeleteManyDataRequest): Promise<any> {\n // This expects deleting by IDs.\n return this.engine.delete(request.object, {\n where: { id: { $in: request.ids } },\n ...request.options\n });\n }\n\n /**\n * Metadata types that are customer-overridable via {@link saveMetaItem}/\n * {@link deleteMetaItem} in project-kernel mode. Derived from the canonical\n * registry in {@link DEFAULT_METADATA_TYPE_REGISTRY}: a type opts in by\n * setting `allowOrgOverride: true` on its registry entry. The set is\n * augmented with the plural form of every singular so callers using REST\n * conventions (`/api/v1/meta/views/...`) get the same gate. See ADR-0005\n * §\"Whitelist enforcement\" for the rationale and the per-type rollout\n * checklist.\n */\n private static readonly OVERLAY_ALLOWED_TYPES: ReadonlySet<string> = (() => {\n const out = new Set<string>();\n for (const entry of DEFAULT_METADATA_TYPE_REGISTRY) {\n if (!entry.allowOrgOverride) continue;\n out.add(entry.type);\n const plural = SINGULAR_TO_PLURAL[entry.type];\n if (plural) out.add(plural);\n }\n return out;\n })();\n\n /**\n * Phase 3a-env-writable: parse `OS_METADATA_WRITABLE` once.\n * Comma-separated singular type names. When the env var is set, the\n * listed types get treated as `allowOrgOverride: true` regardless of\n * their static registry entry. This is the runtime escape hatch admins\n * use to enable Studio-side editing of types whose protocol-level flag\n * is still false (object, field, permission, …).\n *\n * Memoised at first call. Tests can override by clearing the cache via\n * {@link ObjectStackProtocolImplementation.resetEnvWritableCache}.\n */\n private static _envWritableTypes: Set<string> | null = null;\n private static envWritableTypes(): ReadonlySet<string> {\n if (this._envWritableTypes !== null) return this._envWritableTypes;\n const raw = readEnvWithDeprecation('OS_METADATA_WRITABLE', 'OBJECTSTACK_METADATA_WRITABLE') || '';\n const set = new Set<string>();\n for (const tok of raw.split(',')) {\n const t = tok.trim();\n if (!t) continue;\n const singular = PLURAL_TO_SINGULAR[t] ?? t;\n set.add(singular);\n const plural = SINGULAR_TO_PLURAL[singular];\n if (plural) set.add(plural);\n }\n this._envWritableTypes = set;\n return set;\n }\n\n /** Test hook — clear the memoised env-writable cache. */\n static resetEnvWritableCache(): void {\n this._envWritableTypes = null;\n }\n\n /**\n * Types that opt into runtime creation of brand-new items (ADR-0005\n * extension — two-tier model). A type may have\n * `allowOrgOverride: false` (cannot overlay artifact-shipped items)\n * yet still set `allowRuntimeCreate: true` (users can author new\n * items in `sys_metadata`). The two flags are orthogonal; see\n * {@link isArtifactBacked} for how the protocol decides which gate\n * applies to a given save/delete.\n */\n /**\n * Set of type names that have a static entry in\n * `DEFAULT_METADATA_TYPE_REGISTRY`. Anything outside this set is\n * runtime-registered (plugin-provided types like `theme`, `api`,\n * `connector`) — the listing endpoint at `getMetaTypes()` synthesises\n * those with `allowRuntimeCreate: true`, so this gate must agree.\n */\n private static readonly STATIC_REGISTRY_TYPES: ReadonlySet<string> = (() => {\n const out = new Set<string>();\n for (const entry of DEFAULT_METADATA_TYPE_REGISTRY) {\n out.add(entry.type);\n const plural = SINGULAR_TO_PLURAL[entry.type];\n if (plural) out.add(plural);\n }\n return out;\n })();\n\n private static readonly RUNTIME_CREATE_ALLOWED_TYPES: ReadonlySet<string> = (() => {\n const out = new Set<string>();\n for (const entry of DEFAULT_METADATA_TYPE_REGISTRY) {\n if (!entry.allowRuntimeCreate) continue;\n out.add(entry.type);\n const plural = SINGULAR_TO_PLURAL[entry.type];\n if (plural) out.add(plural);\n }\n return out;\n })();\n\n /** Normalize plural→singular before consulting the allow-list. */\n private static isOverlayAllowed(type: string): boolean {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (this.OVERLAY_ALLOWED_TYPES.has(singular)\n || this.OVERLAY_ALLOWED_TYPES.has(type)) {\n return true;\n }\n const env = this.envWritableTypes();\n return env.has(singular) || env.has(type);\n }\n\n /** Does this type permit creating brand-new (artifact-free) items? */\n private static isRuntimeCreateAllowed(type: string): boolean {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (this.RUNTIME_CREATE_ALLOWED_TYPES.has(singular)\n || this.RUNTIME_CREATE_ALLOWED_TYPES.has(type)) {\n return true;\n }\n // Runtime-registered types (no static registry entry) are\n // synthesised by getMetaTypes() with allowRuntimeCreate=true;\n // mirror that here so /api/v1/meta and PUT /api/v1/meta agree.\n if (!this.STATIC_REGISTRY_TYPES.has(singular)\n && !this.STATIC_REGISTRY_TYPES.has(type)) {\n return true;\n }\n return false;\n }\n\n /**\n * Does an artifact (npm-package-loaded) item exist at `(type, name)`?\n *\n * The schema registry's `_packageId` tag is set only when\n * `registerItem(..., packageId)` is called with a truthy packageId\n * — and only artifact loaders do that. DB-rehydrated items\n * (sys_metadata rows registered back into the registry by\n * `getMetaItems` / `loadMetaFromDb`) call `registerItem` without a\n * packageId, so they carry no `_packageId` and are correctly\n * excluded here.\n *\n * Used by the two-tier authorization model to distinguish\n * \"overlaying a packaged item\" (requires `allowOrgOverride`) from\n * \"authoring a DB-only item\" (requires only `allowRuntimeCreate`).\n */\n private isArtifactBacked(type: string, name: string): boolean {\n const registry = (this.engine as any)?.registry;\n if (!registry || typeof registry.getItem !== 'function') {\n // No registry available (test fixtures with partial engine\n // mocks). Treat as no artifact backing — safer for create paths\n // and the type-level gates still apply.\n return false;\n }\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n const item = registry.getItem(singular, name) ?? registry.getItem(type, name);\n if (!item || !item._packageId) return false;\n // `loadMetaFromDb` (line ~3092) registers DB-only objects with\n // a synthetic `'sys_metadata'` packageId so the registry can\n // distinguish them from purely transient entries. That sentinel\n // is NOT an artifact origin — exclude it here so DB-only objects\n // continue to behave as runtime-authored items.\n return item._packageId !== 'sys_metadata';\n }\n\n // ───────────────────────────────────────────────────────────────────\n // ADR-0010 — metadata protection (Phase 1: L3 item-level lock)\n // ───────────────────────────────────────────────────────────────────\n\n /**\n * Look up an item from the artifact registry across both the requested\n * type and its singular/plural twin. Returns `undefined` when the\n * registry is unavailable or the item is not artifact-backed.\n */\n private lookupArtifactItem(type: string, name: string): unknown {\n const registry = (this.engine as any)?.registry;\n if (!registry || typeof registry.getItem !== 'function') return undefined;\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n return registry.getItem(singular, name) ?? registry.getItem(type, name);\n }\n\n /**\n * Resolve the effective `_lock` for an item by consulting the\n * artifact registry first, then the persisted overlay row. Artifact\n * always wins — by design, an overlay cannot loosen a packaged\n * lock (ADR-0010 §3.3).\n *\n * Returns `'none'` when nothing is locked, which is the common\n * case. Safe to call when `environmentId` is undefined (control-\n * plane bootstrap) — the lock check is only meaningful in tenant\n * scope and the caller is expected to also gate on `environmentId`.\n */\n private async getEffectiveLock(\n type: string,\n name: string,\n organizationId: string | null | undefined,\n ): Promise<{\n lock: MetadataLock;\n lockReason: string | undefined;\n lockSource: 'artifact' | 'overlay' | undefined;\n }> {\n // 1. Artifact wins.\n const registry = (this.engine as any)?.registry;\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n let artifactItem: any;\n if (registry && typeof registry.getItem === 'function') {\n artifactItem = registry.getItem(singular, name) ?? registry.getItem(type, name);\n }\n if (artifactItem && artifactItem._packageId && artifactItem._packageId !== 'sys_metadata') {\n const p = extractProtection(artifactItem);\n if (p.lock !== 'none') {\n return { lock: p.lock, lockReason: p.lockReason, lockSource: 'artifact' };\n }\n }\n // 2. Overlay row.\n try {\n const where: Record<string, unknown> = {\n type,\n name,\n state: 'active',\n organization_id: organizationId ?? null,\n };\n const row = await this.engine.findOne('sys_metadata', { where });\n if (row) {\n const body = typeof row.metadata === 'string' ? JSON.parse(row.metadata) : row.metadata;\n const p = extractProtection(body);\n if (p.lock !== 'none') {\n return { lock: p.lock, lockReason: p.lockReason, lockSource: 'overlay' };\n }\n }\n } catch {\n // DB unavailable — fall through to 'none'.\n }\n return { lock: 'none', lockReason: undefined, lockSource: undefined };\n }\n\n /**\n * Best-effort audit-row writer (ADR-0010 §3.6). Failures here are\n * logged but never block the underlying decision: an environment\n * without the audit table provisioned (legacy installs before this\n * ADR landed) still answers normal API calls, just without the\n * compliance trail. Phase 2 will make the audit table a hard\n * dependency.\n */\n private async recordMetadataAudit(entry: {\n type: string;\n name: string;\n organizationId?: string | null;\n operation: 'save' | 'publish' | 'rollback' | 'delete' | 'reset';\n outcome: 'allowed' | 'denied' | 'forced';\n code: string;\n lockState?: MetadataLock;\n lockOverridden?: boolean;\n actor?: string;\n source?: string;\n requestId?: string;\n note?: string;\n }): Promise<void> {\n try {\n await this.engine.insert('sys_metadata_audit', {\n occurred_at: new Date().toISOString(),\n actor: entry.actor ?? 'system',\n source: entry.source ?? 'protocol',\n type: PLURAL_TO_SINGULAR[entry.type] ?? entry.type,\n name: entry.name,\n organization_id: entry.organizationId ?? null,\n operation: entry.operation,\n outcome: entry.outcome,\n code: entry.code,\n lock_state: entry.lockState ?? 'none',\n lock_overridden: entry.lockOverridden ?? false,\n request_id: entry.requestId ?? null,\n note: entry.note ?? null,\n } as any);\n } catch (err: any) {\n // Don't promote audit-table failures to API errors. Log so\n // operators can spot a misconfigured deployment.\n console.warn(\n `[Protocol] sys_metadata_audit write failed for ${entry.type}/${entry.name}: ${err?.message ?? err}`,\n );\n }\n }\n\n /**\n * Phase 1 L3 enforcement for write operations (save / publish /\n * rollback). Returns null on allow. Returns the structured `Error`\n * the caller should `throw` on deny — also records the denial in\n * the audit log so refused attempts are visible in compliance\n * reports (refused writes never reach sys_metadata_history).\n */\n private async assertLockAllowsWrite(args: {\n type: string;\n name: string;\n organizationId?: string;\n operation: 'save' | 'publish' | 'rollback';\n actor?: string;\n source?: string;\n requestId?: string;\n }): Promise<Error | null> {\n if (this.environmentId === undefined) return null;\n const state = await this.getEffectiveLock(args.type, args.name, args.organizationId ?? null);\n const refusal = evaluateLockForWrite(state.lock);\n if (!refusal) return null;\n const reason = state.lockReason ?? refusal.reason;\n const err = new Error(\n `[item_locked] ${args.type}/${args.name} is locked (_lock=${state.lock}${state.lockSource ? `, source=${state.lockSource}` : ''}). `\n + `${reason} — See ADR-0010 §3.3.`,\n );\n (err as any).code = 'item_locked';\n (err as any).status = 403;\n (err as any).lock = state.lock;\n (err as any).lockReason = reason;\n await this.recordMetadataAudit({\n type: args.type,\n name: args.name,\n organizationId: args.organizationId ?? null,\n operation: args.operation,\n outcome: 'denied',\n code: 'item_locked',\n lockState: state.lock,\n actor: args.actor,\n source: args.source ?? `protocol.${args.operation}MetaItem`,\n requestId: args.requestId,\n note: reason,\n });\n return err;\n }\n\n /** Counterpart of {@link assertLockAllowsWrite} for delete. */\n private async assertLockAllowsDelete(args: {\n type: string;\n name: string;\n organizationId?: string;\n actor?: string;\n source?: string;\n requestId?: string;\n }): Promise<Error | null> {\n if (this.environmentId === undefined) return null;\n const state = await this.getEffectiveLock(args.type, args.name, args.organizationId ?? null);\n const refusal = evaluateLockForDelete(state.lock);\n if (!refusal) return null;\n const reason = state.lockReason ?? refusal.reason;\n const err = new Error(\n `[item_locked] ${args.type}/${args.name} is locked (_lock=${state.lock}${state.lockSource ? `, source=${state.lockSource}` : ''}). `\n + `${reason} — See ADR-0010 §3.3.`,\n );\n (err as any).code = 'item_locked';\n (err as any).status = 403;\n (err as any).lock = state.lock;\n (err as any).lockReason = reason;\n await this.recordMetadataAudit({\n type: args.type,\n name: args.name,\n organizationId: args.organizationId ?? null,\n operation: 'delete',\n outcome: 'denied',\n code: 'item_locked',\n lockState: state.lock,\n actor: args.actor,\n source: args.source ?? 'protocol.deleteMetaItem',\n requestId: args.requestId,\n note: reason,\n });\n return err;\n }\n\n /**\n * Mirror an object-type overlay write into the in-memory engine\n * registry so subsequent CRUD finds the new schema. Idempotent and\n * safe to call after a successful persistence call. For the legacy\n * write path this is invoked BEFORE persistence (historical behavior\n * preserved); for the PR-10d.3 repository path it is invoked only\n * AFTER `put()` resolves successfully, so a failed write — DB error,\n * optimistic-lock conflict, validation failure — never leaks a\n * stale schema into the registry.\n */\n private applyObjectRegistryMutation(request: { type: string; name: string; item?: any }): void {\n if (request.type !== 'object' && request.type !== 'objects') return;\n this.engine.registry.registerItem(request.type, request.item, 'name');\n try {\n this.engine.registry.registerObject(request.item as any, 'sys_metadata');\n } catch (err: any) {\n console.warn(\n `[Protocol] registerObject failed for ${request.name}: ${err?.message ?? err}`,\n );\n }\n }\n\n /**\n * Ensure a just-PUBLISHED object's physical table exists so it is usable\n * for data CRUD immediately — without a server restart. Registering the\n * object (above) only updates the in-memory registry; the table is created\n * by the driver's schema sync, which otherwise only runs at boot. Without\n * this, inserting into a freshly-published object fails with \"no such\n * table\" (surfaced as `object_not_found`) until the next restart.\n * Best-effort + non-fatal: drivers without DDL (or read-only datasources)\n * simply no-op, and a sync failure must not abort the publish.\n */\n private async ensureObjectStorage(type: string, name: string): Promise<void> {\n if (type !== 'object' && type !== 'objects') return;\n try {\n await this.engine.syncObjectSchema(name);\n } catch (err: any) {\n console.warn(`[Protocol] table sync failed for object '${name}': ${err?.message ?? err}`);\n }\n }\n\n /**\n * Inverse of {@link ensureObjectStorage}: drop an object's physical table.\n * DESTRUCTIVE — deletes the table and all its rows. Only invoked when a\n * delete explicitly opts into storage teardown (see {@link deleteMetaItem}'s\n * `dropStorage`), so publishing an object solely to preview it can be undone\n * without leaving an orphan table. Best-effort: a failure is logged, not\n * thrown — the metadata delete already succeeded, and a stray table is\n * reclaimed by the next sync/drop rather than blocking the delete.\n */\n private async dropObjectStorage(type: string, name: string): Promise<void> {\n if (type !== 'object' && type !== 'objects') return;\n try {\n await this.engine.dropObjectSchema(name);\n } catch (err: any) {\n console.warn(`[Protocol] table drop failed for object '${name}': ${err?.message ?? err}`);\n }\n }\n\n /**\n * Guard for storage teardown on delete. Drops a physical table only when\n * the caller opted in AND it is safe: object types only (others have no\n * table), active state only (drafts were never materialised), and never a\n * `sys_`-prefixed platform table.\n */\n private shouldDropStorage(type: string, name: string, dropStorage: boolean | undefined, state: 'active' | 'draft'): boolean {\n if (!dropStorage) return false;\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (singular !== 'object') return false;\n if (state !== 'active') return false;\n if (name.startsWith('sys_')) return false;\n return true;\n }\n\n async saveMetaItem(request: { type: string, name: string, item?: any, organizationId?: string, parentVersion?: string | null, actor?: string, force?: boolean, mode?: 'draft' | 'publish', packageId?: string | null }) {\n if (!request.item) {\n throw new Error('Item data is required');\n }\n // Per-item lifecycle (ADR-0005 §\"Drafts\"). Default is `'publish'`\n // (legacy semantics — save goes straight live) to keep callers\n // that predate the draft/publish split working. Studio's\n // designer surface opts into staged drafts by sending\n // `?mode=draft`; the `POST /publish` endpoint then promotes it.\n const mode: 'draft' | 'publish' = request.mode === 'draft' ? 'draft' : 'publish';\n\n // ADR-0005 (extended — two-tier model): project-kernel customization is\n // gated by per-item provenance, not just the type-level flag.\n //\n // • Item exists as a packaged artifact → require `allowOrgOverride`\n // (writing here would overlay code-shipped behaviour; gated for\n // security on executable types like hook/trigger/validation).\n // • Item does NOT exist as an artifact → require `allowRuntimeCreate`\n // OR `allowOrgOverride`. This lets users author brand-new hooks /\n // validations / triggers without unlocking the artifact-shadowing\n // capability. Returns `not_creatable` (vs `not_overridable`) so\n // the UI can present a tailored message.\n if (this.environmentId !== undefined) {\n const overlayAllowed = ObjectStackProtocolImplementation.isOverlayAllowed(request.type);\n const runtimeCreateAllowed = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(request.type);\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n if (artifactBacked && !overlayAllowed) {\n const err = new Error(\n `[not_overridable] Metadata item '${request.type}/${request.name}' is provided by a code package `\n + `and the type has not opted into per-org overlay writes (allowOrgOverride=false). `\n + `Edit the source artifact and redeploy, or set OS_METADATA_WRITABLE to grant a runtime escape hatch. `\n + `See docs/adr/0005-metadata-customization-overlay.md.`\n );\n (err as any).code = 'not_overridable';\n (err as any).status = 403;\n throw err;\n }\n if (!artifactBacked && !overlayAllowed && !runtimeCreateAllowed) {\n const err = new Error(\n `[not_creatable] Metadata type '${request.type}' does not allow runtime creation `\n + `(allowRuntimeCreate=false, allowOrgOverride=false). New items of this type must be defined in source code.`\n );\n (err as any).code = 'not_creatable';\n (err as any).status = 403;\n throw err;\n }\n\n // ADR-0010 L3 — per-item lock. Artifact `_lock` (or persisted\n // overlay `_lock`) blocks save independent of the L1 type-level\n // flag. Records the denial in `sys_metadata_audit` before\n // throwing so refused attempts are visible in compliance reports.\n const lockErr = await this.assertLockAllowsWrite({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n operation: 'save',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.saveMetaItem',\n });\n if (lockErr) throw lockErr;\n }\n\n // Phase 3a-destructive: for object/field writes, diff against the\n // current schema and 409 if the change would drop data — unless the\n // caller has acknowledged the risk with `force: true`. The admin UI\n // surfaces the structured `issues` payload in a confirmation dialog.\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!request.force && (singularType === 'object' || singularType === 'field')) {\n try {\n const existing = await this.getMetaItem({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n } as any);\n const prev = (existing as any)?.item;\n if (prev) {\n const issues = detectDestructiveObjectChanges(prev, request.item);\n if (issues.length > 0) {\n const summary = issues.slice(0, 3).map((i) => i.message).join('; ');\n const err = new Error(\n `[destructive_change] ${request.type}/${request.name} would drop or transform existing data: ${summary}`\n + (issues.length > 3 ? ` (+${issues.length - 3} more)` : '')\n + ` — re-submit with ?force=true to proceed.`\n );\n (err as any).code = 'destructive_change';\n (err as any).status = 409;\n (err as any).issues = issues;\n throw err;\n }\n }\n } catch (err: any) {\n if (err?.code === 'destructive_change') throw err;\n // Other errors during the diff lookup are non-fatal —\n // they just skip the safety check.\n }\n }\n\n // Defense-in-depth: reject the layered *read* envelope as a write body.\n //\n // `getMetaItemLayered` returns a 3-state diagnostic shape\n // `{ type, name, code, overlay, overlayScope, effective, ... }` for the\n // Studio designer's `?layers=true` GET. That envelope is NOT a metadata\n // body — but a designer surface that lacks a dedicated editor for a\n // given type can accidentally PUT the envelope straight back, which (if\n // the per-type Zod schema below is unavailable — e.g. a type with no\n // registered schema, or a stale `@objectstack/spec` build that predates\n // the type being added to the registry) would persist an all-null stub\n // and surface as a metadata diagnostic error in the admin UI. The\n // simultaneous presence of `code`, `overlay`, `overlayScope`, and\n // `effective` is unique to the layered envelope and never appears in a\n // real metadata body, so we reject it here regardless of type/schema.\n {\n const it = request.item as Record<string, unknown>;\n const looksLikeLayeredEnvelope =\n it && typeof it === 'object' && !Array.isArray(it)\n && 'code' in it && 'overlay' in it && 'overlayScope' in it && 'effective' in it;\n if (looksLikeLayeredEnvelope) {\n const err = new Error(\n `[invalid_metadata] ${request.type}/${request.name}: the request body is a layered read `\n + `envelope ({ code, overlay, overlayScope, effective }), not a metadata body. `\n + `Unwrap and send the effective/overlay document instead — the layered shape is read-only `\n + `(GET ?layers=true) and must never be persisted.`\n );\n (err as any).code = 'invalid_metadata';\n (err as any).status = 422;\n throw err;\n }\n }\n\n // Normalize loose `view` bodies to the canonical record shape BEFORE\n // validation + persistence, so no producer (AI tools, hand-authoring,\n // Studio) can persist a view that validates but the console can't bind\n // or render (missing top-level name/object/viewKind). See\n // {@link normalizeViewMetadata}.\n request.item = normalizeViewMetadata(request.type, request.item, request.name);\n\n // Spec-conformance check: if a Zod schema is registered for this\n // overlay type (see OVERLAY_VALIDATION_SCHEMAS), validate the payload\n // before persisting. We surface invalid payloads as `422\n // invalid_metadata` with structured Zod issues so the Studio form can\n // highlight the offending field. The original `item` is kept verbatim\n // — `parsed.data` would strip Studio-only auxiliary fields (e.g.\n // isPinned, isDefault, sortOrder) that intentionally ride along with\n // the overlay document. ADR-0005 §\"Validation\".\n {\n const schema = resolveOverlaySchema(request.type, request.item);\n if (schema) {\n const parsed = schema.safeParse(request.item);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i: z.ZodIssue) => ({\n path: i.path.join('.'),\n message: i.message,\n code: i.code,\n }));\n const summary = issues.slice(0, 3)\n .map((i: { path: string; message: string }) => `${i.path || '<root>'}: ${i.message}`)\n .join('; ');\n const err = new Error(\n `[invalid_metadata] ${request.type}/${request.name} failed spec validation: ${summary}`\n + (issues.length > 3 ? ` (+${issues.length - 3} more)` : '')\n );\n (err as any).code = 'invalid_metadata';\n (err as any).status = 422;\n (err as any).issues = issues;\n throw err;\n }\n }\n }\n\n // 1. Update the in-memory registry (runtime cache) ONLY for the\n // `object` type — schema definitions feed engine.syncSchema and\n // must be reflected immediately for CRUD to work. For all other\n // metadata types (view, dashboard, ...) we deliberately do NOT\n // mutate the artifact-loaded registry — sys_metadata is the\n // authoritative overlay store and `getMetaItem` consults it\n // first (ADR-0005). Mutating the registry here would create a\n // \"stale overlay\" hazard: `deleteMetaItem` cannot restore the\n // original artifact value because it was overwritten in-place.\n // 1. (deferred) — Object-type runtime-registry mutation used to happen\n // here unconditionally. Moved to AFTER successful persistence\n // (PR-10d.3 rubber-duck #3): a failed put() — DB error, optimistic\n // conflict, validation — must not leave a stale object schema in\n // the in-memory registry. See `applyObjectRegistryMutation` below.\n\n // 2. Persist to sys_metadata as a customization overlay row.\n // ADR-0005 (revised 2026-05): isolation key is `organization_id`\n // (each env = its own DB, so environment_id is redundant). Org-scoped\n // rows belong to the active organization in the request; env-wide\n // overlays are written with organization_id = NULL.\n await this.ensureOverlayIndex();\n\n // ADR-0008 — overlay-allowed metadata types ALWAYS route through the\n // repository write path: every mutation appends to the change log\n // and emits a watch event with a monotonic `seq` (which Studio /\n // browser clients consume for HMR). Non-overlay-allowed types\n // (`object`, `flow`, `agent`, ...) take the legacy raw-engine path\n // below — this preserves the control-plane bootstrap semantic where\n // `saveMetaItem` is permitted by the outer protocol gate to write\n // any metadata type when `environmentId` is undefined (the repository's\n // `assertAllowed()` would 403 those writes).\n //\n // PR-10d.6 (this PR) removed the `useRepositoryWritePath` flag.\n // For overlay-allowed types the repo path is no longer opt-out-able.\n //\n // Callers that omit `parentVersion` get backward-compatible\n // \"last-write-wins\" semantics: we read the current row's checksum\n // and use it as the parent, so the conflict check tautologically\n // passes (best-effort — racy under concurrent writes; explicit\n // optimistic-lock is opt-in via `parentVersion`).\n // Callers that pass an explicit `parentVersion` (e.g. Studio after\n // reading an item) get true optimistic-lock conflict detection\n // surfaced as a 409.\n const singularTypeForRepo = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const overlayAllowedForRepo = ObjectStackProtocolImplementation.isOverlayAllowed(singularTypeForRepo);\n const runtimeCreateAllowedForRepo = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularTypeForRepo);\n const useRepoPath = overlayAllowedForRepo || runtimeCreateAllowedForRepo;\n if (useRepoPath) {\n const artifactBacked = this.isArtifactBacked(singularTypeForRepo, request.name);\n const intent: 'override-artifact' | 'runtime-only' = artifactBacked\n ? 'override-artifact'\n : 'runtime-only';\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const ref = {\n type: singularTypeForRepo,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.put>[0];\n let parentVersion: string | null;\n if (request.parentVersion !== undefined) {\n parentVersion = request.parentVersion;\n } else {\n // Parent is scoped to the lifecycle we're about to write:\n // a draft's parent is the current draft hash (or null\n // for the first draft); a publish's parent is the\n // current published hash.\n const current = await repo.get(ref, { state: mode === 'draft' ? 'draft' : 'active' });\n parentVersion = current?.hash ?? null;\n }\n try {\n const result = await repo.put(ref, request.item, {\n parentVersion,\n actor: request.actor ?? 'system',\n source: 'protocol.saveMetaItem',\n intent,\n state: mode === 'draft' ? 'draft' : 'active',\n ...(request.packageId !== undefined ? { packageId: request.packageId } : {}),\n });\n // Persistence succeeded — NOW it's safe to mutate the\n // in-memory object registry. If put() had thrown, the\n // registry would still reflect the prior state. Drafts\n // are NOT live: don't propagate them into the runtime\n // object registry (would defeat the staging buffer).\n if (mode === 'publish') {\n this.applyObjectRegistryMutation(request);\n await this.ensureObjectStorage(request.type, request.name);\n }\n // ADR-0010 — success audit (best-effort).\n await this.recordMetadataAudit({\n type: request.type,\n name: request.name,\n organizationId: orgId,\n operation: 'save',\n outcome: 'allowed',\n code: 'ok',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.saveMetaItem',\n note: mode === 'draft' ? 'draft' : 'active',\n });\n return {\n success: true,\n version: result.version,\n seq: result.seq,\n state: mode === 'draft' ? 'draft' : 'active',\n message: orgId\n ? `Saved customization overlay (org=${orgId}, state=${mode === 'draft' ? 'draft' : 'active'}) — type=${request.type}, name=${request.name} [seq=${result.seq}]`\n : `Saved customization overlay (env-wide, state=${mode === 'draft' ? 'draft' : 'active'}) — type=${request.type}, name=${request.name} [seq=${result.seq}]`,\n };\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict = new Error(\n `[metadata_conflict] ${request.type}/${request.name} has been modified since you loaded it. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n (conflict as any).code = 'metadata_conflict';\n (conflict as any).status = 409;\n (conflict as any).expectedParent = err.expectedParent;\n (conflict as any).actualHead = err.actualHead;\n throw conflict;\n }\n throw err;\n }\n }\n\n // Legacy raw-engine path — taken when the type is NOT overlay-allowed\n // (control-plane bootstrap of `object`/`flow`/etc. when `environmentId` is\n // undefined). This branch is intentionally retained: the repository\n // write path's `assertAllowed()` would 403 these types. There is no\n // change-log / HMR machinery for non-overlay metadata because\n // control-plane mutations are bootstrap-only and not subject to\n // per-org overlay semantics.\n //\n // Note: the registry mutation for the legacy path happens BEFORE\n // persistence (preserved historical behaviour). The overlay-allowed\n // path moved it to AFTER persistence in PR-10d.3 (rubber-duck #3).\n this.applyObjectRegistryMutation(request);\n\n try {\n const now = new Date().toISOString();\n const orgId = request.organizationId ?? null;\n const scopedWhere: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n organization_id: orgId,\n state: 'active',\n };\n const existing = await this.engine.findOne('sys_metadata', {\n where: scopedWhere,\n });\n\n if (existing) {\n const updateRow: Record<string, unknown> = {\n metadata: JSON.stringify(request.item),\n updated_at: now,\n version: (existing.version || 0) + 1,\n state: 'active',\n };\n // Preserve an existing non-null package binding; only fill when\n // unset (mirror of SysMetadataRepository.put semantics).\n const existingPkg = (existing as { package_id?: string | null }).package_id ?? null;\n const nextPkg = existingPkg ?? request.packageId ?? null;\n if (nextPkg !== null) updateRow.package_id = nextPkg;\n await this.engine.update('sys_metadata', updateRow, {\n where: { id: existing.id }\n });\n } else {\n // Use crypto.randomUUID() when available (modern browsers and Node ≥ 14.17);\n // fall back to a time+random ID for older or restricted environments.\n const id = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : `meta_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n const row: Record<string, unknown> = {\n id,\n name: request.name,\n type: request.type,\n // `scope` enum is ['system','platform','user']; per-org\n // overlays use 'platform' as the informational tag. The\n // authoritative isolation key is `organization_id`.\n scope: 'platform',\n metadata: JSON.stringify(request.item),\n state: 'active',\n version: 1,\n created_at: now,\n updated_at: now,\n organization_id: orgId,\n };\n if (request.packageId) row.package_id = request.packageId;\n await this.engine.insert('sys_metadata', row);\n }\n\n return {\n success: true,\n message: orgId\n ? `Saved customization overlay (org=${orgId}) — type=${request.type}, name=${request.name}`\n : `Saved customization overlay (env-wide) — type=${request.type}, name=${request.name}`,\n };\n } catch (dbError: any) {\n // DB write failed — surface as an error rather than silently\n // succeeding (regression from the pre-ADR-0005 \"silent loss\" bug).\n console.error(\n `[Protocol] sys_metadata persistence failed for ${request.type}/${request.name}: ${dbError.message}`,\n );\n const err = new Error(\n `Failed to persist customization overlay to sys_metadata: ${dbError.message}. `\n + `In-memory registry was updated but will be lost on restart.`,\n );\n (err as any).code = 'overlay_persistence_failed';\n (err as any).status = 500;\n throw err;\n }\n }\n\n /**\n * Yield the durable change-log for a single metadata item — every\n * put/delete recorded in `sys_metadata_history` for `(org, type, name)`,\n * in event_seq order. Powers the Studio \"History\" tab and any\n * client-side audit timeline.\n *\n * Returns `[]` for non-overlay-allowed types (the legacy raw-engine\n * path doesn't record history) instead of throwing — callers can treat\n * \"no history\" uniformly.\n */\n async historyMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string;\n sinceSeq?: number;\n limit?: number;\n }): Promise<{ events: import('@objectstack/metadata-core').MetadataEvent[] }> {\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!ObjectStackProtocolImplementation.isOverlayAllowed(singularType)\n && !ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularType)) {\n return { events: [] };\n }\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const ref = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.history>[0];\n\n const events: import('@objectstack/metadata-core').MetadataEvent[] = [];\n const opts: { sinceSeq?: number; limit?: number } = {};\n if (request.sinceSeq !== undefined) opts.sinceSeq = request.sinceSeq;\n if (request.limit !== undefined) opts.limit = request.limit;\n for await (const ev of repo.history(ref, opts)) events.push(ev);\n return { events };\n }\n\n /**\n * Promote the pending draft overlay to the live (`active`) row.\n * Records a history event with `op='publish'`. 404 (`[no_draft]`)\n * when there is nothing to publish.\n */\n async publishMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string;\n actor?: string;\n message?: string;\n /**\n * INTERNAL — `publishPackageDrafts` publishes many drafts and batch-applies\n * every seed body in ONE loader pass afterwards (cross-seed references need\n * multi-pass over the whole set), so it suppresses the per-item apply here.\n */\n _skipSeedApply?: boolean;\n }): Promise<{\n success: boolean;\n version: string;\n seq: number;\n message?: string;\n /**\n * Present when a `seed` draft was published: the result of materializing\n * its rows. Publishing the metadata ALWAYS succeeds independently — a\n * seed-load problem is surfaced here, never thrown, so callers (and UIs)\n * must check `seedApplied.success` instead of assuming data went live.\n */\n seedApplied?: {\n success: boolean;\n inserted: number;\n updated: number;\n error?: string;\n errors?: unknown[];\n };\n }> {\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!ObjectStackProtocolImplementation.isOverlayAllowed(singularType)\n && !ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularType)) {\n const err: any = new Error(\n `[not_overridable] Metadata type '${request.type}' is not draftable — no overlay/runtime-create permission.`,\n );\n err.code = 'not_overridable';\n err.status = 403;\n throw err;\n }\n // ADR-0010 L3 — lock blocks publish too (publishing is a write).\n const _publishLockErr = await this.assertLockAllowsWrite({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n operation: 'publish',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.publishMetaItem',\n });\n if (_publishLockErr) throw _publishLockErr;\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const artifactBacked = this.isArtifactBacked(singularType, request.name);\n const intent: 'override-artifact' | 'runtime-only' = artifactBacked\n ? 'override-artifact' : 'runtime-only';\n const ref = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.promoteDraft>[0];\n try {\n const result = await repo.promoteDraft(ref, {\n actor: request.actor ?? 'system',\n source: 'protocol.publishMetaItem',\n ...(request.message ? { message: request.message } : {}),\n intent,\n });\n // Drafts skipped the registry mutation; on publish we now\n // refresh the runtime object registry so live behaviour\n // catches up immediately (matches saveMetaItem's\n // post-persistence registry update path).\n this.applyObjectRegistryMutation({\n type: request.type,\n name: request.name,\n item: result.item.body,\n });\n // Create the object's table now so it's CRUD-able without a restart.\n await this.ensureObjectStorage(request.type, request.name);\n const response: {\n success: boolean;\n version: string;\n seq: number;\n message?: string;\n seedApplied?: { success: boolean; inserted: number; updated: number; error?: string; errors?: unknown[] };\n } = {\n success: true,\n version: result.version,\n seq: result.seq,\n message: `Published draft — type=${request.type}, name=${request.name} [seq=${result.seq}]`,\n };\n // Publishing a `seed` is what makes its rows live — materialize them\n // NOW (best-effort, never fails the publish) so every publish path\n // (per-ref REST publish, the home banner, package publish-drafts)\n // lands data, not just metadata. The body is already in hand from\n // the promote — no read-back, so no org-scope resolution pitfalls.\n if (singularType === 'seed' && !request._skipSeedApply) {\n response.seedApplied = await this.applySeedBodies([result.item.body], orgId);\n }\n return response;\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict: any = new Error(\n `[metadata_conflict] ${request.type}/${request.name} published row advanced while you held the draft. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n conflict.code = 'metadata_conflict';\n conflict.status = 409;\n conflict.expectedParent = err.expectedParent;\n conflict.actualHead = err.actualHead;\n throw conflict;\n }\n throw err;\n }\n }\n\n /**\n * Materialize published `seed` bodies into data rows via the SeedLoaderService\n * (externalId-keyed upsert, multi-pass for cross-seed references). Passing ALL\n * of a publish's seed bodies in ONE call lets a child seed reference a parent\n * seed's rows regardless of publish order. Best-effort: any failure is\n * returned, never thrown — publishing metadata must not be blocked by a data\n * problem, but the caller surfaces `seedApplied` so the failure is LOUD.\n */\n private async applySeedBodies(\n bodies: unknown[],\n organizationId: string | null,\n ): Promise<{ success: boolean; inserted: number; updated: number; error?: string; errors?: unknown[] }> {\n try {\n const seeds = bodies.filter(\n (b: any) => b && typeof b.object === 'string' && Array.isArray(b.records),\n );\n if (seeds.length === 0) {\n return { success: false, inserted: 0, updated: 0, error: 'seed apply: no readable seed bodies' };\n }\n const { SeedLoaderService } = await import('./seed-loader.js');\n const { SeedLoaderRequestSchema } = await import('@objectstack/spec/data');\n // The loader only needs `getObject` from IMetadataService (dependency\n // graph + field introspection); satisfy it from the protocol's own\n // metadata reads so no kernel service lookup is required.\n const metadataAdapter = {\n getObject: async (name: string) => {\n const wrapper: any = await (this as any).getMetaItem({\n type: 'object',\n name,\n ...(organizationId ? { organizationId } : {}),\n });\n return wrapper?.item ?? wrapper ?? null;\n },\n };\n const loader = new SeedLoaderService(\n this.engine as any,\n metadataAdapter as any,\n console as any,\n );\n const request = SeedLoaderRequestSchema.parse({\n seeds,\n config: {\n defaultMode: 'upsert',\n multiPass: true,\n ...(organizationId ? { organizationId } : {}),\n },\n });\n const r = await loader.load(request);\n return {\n success: r.success,\n inserted: r.summary.totalInserted,\n updated: r.summary.totalUpdated,\n ...(r.errors?.length ? { errors: r.errors } : {}),\n };\n } catch (e: any) {\n return { success: false, inserted: 0, updated: 0, error: e?.message ?? 'seed apply failed' };\n }\n }\n\n /**\n * List pending DRAFT metadata (ADR-0033) for the org, optionally narrowed\n * by `packageId` and/or `type`. The list reads of `getMetaItems` only see\n * the ACTIVE registry; this exposes what an AI authored but a human hasn't\n * published yet, so the console can show a \"pending changes\" surface and a\n * just-built app package isn't displayed as empty. No body is returned.\n */\n async listDrafts(request?: {\n packageId?: string;\n type?: string;\n organizationId?: string;\n }): Promise<{\n drafts: Array<{\n type: string;\n name: string;\n packageId: string | null;\n updatedAt: string | null;\n updatedBy: string | null;\n }>;\n }> {\n await this.ensureOverlayIndex();\n const orgId = request?.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const drafts = await repo.listDrafts({\n ...(request?.type ? { type: PLURAL_TO_SINGULAR[request.type] ?? request.type } : {}),\n ...(request?.packageId ? { packageId: request.packageId } : {}),\n });\n return { drafts };\n }\n\n /**\n * Publish every pending DRAFT bound to a package in one shot (ADR-0033) —\n * the \"publish whole app\" action. Promotes each draft→active by reusing the\n * per-item {@link publishMetaItem} primitive (which runs the overridable /\n * lock guards and refreshes the runtime registry), so this needs NO\n * `metadata` service (unlike `MetadataService.publishPackage`, which reads\n * the in-memory registry and 503s when that service is absent). Per-item\n * failures are collected and do NOT abort the rest.\n */\n async publishPackageDrafts(request: {\n packageId: string;\n organizationId?: string;\n actor?: string;\n }): Promise<{\n success: boolean;\n publishedCount: number;\n failedCount: number;\n published: Array<{ type: string; name: string; version: string }>;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n /** Aggregate result of materializing every published `seed` (absent when no seeds). */\n seedApplied?: { success: boolean; inserted: number; updated: number; error?: string; errors?: unknown[] };\n /**\n * ADR-0038 L3 — post-publish runtime probe report (absent when nothing\n * was publishable). One real read per published artifact: seeded\n * objects must have rows, views must be readable, dashboard widgets'\n * dataset selections must execute and return data. `issues` carries\n * BuildIssue-shaped findings (layer 'runtime') for the agent / chat\n * health surfaces; probes never fail the publish itself.\n */\n probes?: import('./build-probes.js').BuildProbeReport;\n }> {\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const drafts = await repo.listDrafts({ packageId: request.packageId });\n\n const published: Array<{ type: string; name: string; version: string }> = [];\n const failed: Array<{ type: string; name: string; error: string; code?: string }> = [];\n\n // Structure first, seeds LAST — a seed's rows can only land after its\n // object's table exists (publishMetaItem creates it). Within the seeds we\n // batch-apply every body in ONE loader pass below (multi-pass reference\n // resolution across the whole set), so per-item apply is suppressed.\n const ordered = [\n ...drafts.filter((d) => d.type !== 'seed'),\n ...drafts.filter((d) => d.type === 'seed'),\n ];\n const seedBodies: unknown[] = [];\n\n for (const d of ordered) {\n try {\n if (d.type === 'seed') {\n // Capture the body BEFORE promote (the draft row is deleted by\n // the promote, and a post-publish read-back has org-scope\n // resolution pitfalls — reading the draft is unambiguous).\n const ref = { type: d.type, name: d.name, org: orgId ?? 'env' } as unknown as Parameters<typeof repo.get>[0];\n const draft = await repo.get(ref, { state: 'draft' });\n if (draft?.body) seedBodies.push(draft.body);\n }\n const r = await this.publishMetaItem({\n type: d.type,\n name: d.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n message: `publish app package '${request.packageId}'`,\n _skipSeedApply: true,\n });\n published.push({ type: d.type, name: d.name, version: r.version });\n } catch (e: any) {\n failed.push({\n type: d.type,\n name: d.name,\n error: e?.message ?? 'publish failed',\n ...(e?.code ? { code: e.code } : {}),\n });\n }\n }\n\n const seedApplied = seedBodies.length > 0 ? await this.applySeedBodies(seedBodies, orgId) : undefined;\n\n // ADR-0038 L3: exercise what was just published — one real read per\n // artifact — so \"Published!\" can never again mean \"and silently\n // broken\". Best-effort by design: a probe crash is swallowed (the\n // publish already happened and must report as such), and findings ride\n // the response for the agent / chat health card to act on.\n let probes: import('./build-probes.js').BuildProbeReport | undefined;\n if (published.length > 0) {\n try {\n const { runBuildProbes } = await import('./build-probes.js');\n const analytics = this.getServicesRegistry?.().get('analytics');\n probes = await runBuildProbes({\n engine: this.engine as any,\n getItem: async (type, name) => {\n const wrapper: any = await (this as any).getMetaItem({\n type,\n name,\n ...(orgId ? { organizationId: orgId } : {}),\n });\n return wrapper?.item ?? wrapper ?? undefined;\n },\n published,\n ...(analytics && typeof analytics.queryDataset === 'function' ? { analytics } : {}),\n organizationId: orgId,\n });\n } catch {\n probes = undefined;\n }\n }\n\n return {\n success: failed.length === 0 && published.length > 0,\n publishedCount: published.length,\n failedCount: failed.length,\n published,\n failed,\n ...(seedApplied ? { seedApplied } : {}),\n ...(probes ? { probes } : {}),\n };\n }\n\n /**\n * Discard every pending DRAFT bound to a package — the NON-destructive\n * inverse of {@link publishPackageDrafts}. Drops only `state='draft'` rows\n * (via the per-item delete primitive), reverting the package to its last\n * published baseline; active/published metadata and physical tables are\n * left untouched.\n *\n * Use case: \"I edited this app for a while and it turned out worse than\n * before — abandon all my changes.\" Routes through the sys_metadata path\n * (no metadata-service dependency, unlike `POST /packages/:id/revert`).\n */\n async discardPackageDrafts(request: {\n packageId: string;\n organizationId?: string;\n actor?: string;\n }): Promise<{\n success: boolean;\n discardedCount: number;\n failedCount: number;\n discarded: Array<{ type: string; name: string }>;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n }> {\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const drafts = await repo.listDrafts({ packageId: request.packageId });\n\n const discarded: Array<{ type: string; name: string }> = [];\n const failed: Array<{ type: string; name: string; error: string; code?: string }> = [];\n\n for (const d of drafts) {\n try {\n await this.deleteMetaItem({\n type: d.type,\n name: d.name,\n state: 'draft',\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n });\n discarded.push({ type: d.type, name: d.name });\n } catch (e: any) {\n failed.push({\n type: d.type,\n name: d.name,\n error: e?.message ?? 'discard failed',\n ...(e?.code ? { code: e.code } : {}),\n });\n }\n }\n\n return {\n success: failed.length === 0 && discarded.length > 0,\n discardedCount: discarded.length,\n failedCount: failed.length,\n discarded,\n failed,\n };\n }\n\n /**\n * Delete an ENTIRE package: every `sys_metadata` row bound to it (active\n * AND draft) and — by default — the physical table of each object it\n * defined. DESTRUCTIVE: removes the app and its data. Use case: \"I don't\n * want this package anymore.\"\n *\n * Set `keepData: true` to remove the metadata but preserve object tables.\n * The `sys_`-table guard in {@link deleteMetaItem} still applies, so\n * platform storage is never dropped. Drafts are removed before active rows\n * so each object's table is torn down once. Per-item failures are collected\n * without aborting the rest.\n */\n async deletePackage(request: {\n packageId: string;\n organizationId?: string;\n actor?: string;\n keepData?: boolean;\n }): Promise<{\n success: boolean;\n deletedCount: number;\n failedCount: number;\n deleted: Array<{ type: string; name: string; state: string }>;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n }> {\n const where: Record<string, unknown> = { package_id: request.packageId };\n if (request.organizationId) where.organization_id = request.organizationId;\n const rows = (await this.engine.find('sys_metadata', { where })) as any[];\n\n const dropStorage = request.keepData !== true;\n // Delete drafts before active so an object's table is dropped once (on\n // the active delete), not pre-empted by a draft delete.\n const ordered = [...rows].sort((a, b) => (a.state === 'draft' ? 0 : 1) - (b.state === 'draft' ? 0 : 1));\n\n const deleted: Array<{ type: string; name: string; state: string }> = [];\n const failed: Array<{ type: string; name: string; error: string; code?: string }> = [];\n\n for (const row of ordered) {\n const state: 'active' | 'draft' = row.state === 'draft' ? 'draft' : 'active';\n try {\n await this.deleteMetaItem({\n type: row.type,\n name: row.name,\n state,\n ...(row.organization_id ? { organizationId: row.organization_id } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n ...(dropStorage ? { dropStorage: true } : {}),\n });\n deleted.push({ type: row.type, name: row.name, state });\n } catch (e: any) {\n failed.push({\n type: row.type,\n name: row.name,\n error: e?.message ?? 'delete failed',\n ...(e?.code ? { code: e.code } : {}),\n });\n }\n }\n\n return {\n success: failed.length === 0 && deleted.length > 0,\n deletedCount: deleted.length,\n failedCount: failed.length,\n deleted,\n failed,\n };\n }\n\n /**\n * Restore the body recorded at history `toVersion` as the new\n * live row. Writes a history event with `op='revert'`. 404\n * (`[version_not_found]`) when the target version doesn't exist;\n * 409 (`[version_not_restorable]`) when the target is a delete\n * tombstone (no body to bring back).\n */\n async rollbackMetaItem(request: {\n type: string;\n name: string;\n toVersion: number;\n organizationId?: string;\n actor?: string;\n message?: string;\n }): Promise<{\n success: boolean;\n version: string;\n seq: number;\n restoredFromVersion: number;\n message?: string;\n }> {\n if (!Number.isFinite(request.toVersion) || request.toVersion < 1) {\n const err: any = new Error(\n `[invalid_request] rollbackMetaItem requires a positive integer 'toVersion' (got ${request.toVersion}).`,\n );\n err.code = 'invalid_request';\n err.status = 400;\n throw err;\n }\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!ObjectStackProtocolImplementation.isOverlayAllowed(singularType)\n && !ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularType)) {\n const err: any = new Error(\n `[not_overridable] Metadata type '${request.type}' is not revertable — no overlay/runtime-create permission.`,\n );\n err.code = 'not_overridable';\n err.status = 403;\n throw err;\n }\n // ADR-0010 L3 — lock blocks rollback (writes a new active row).\n const _rollbackLockErr = await this.assertLockAllowsWrite({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n operation: 'rollback',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.rollbackMetaItem',\n });\n if (_rollbackLockErr) throw _rollbackLockErr;\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const artifactBacked = this.isArtifactBacked(singularType, request.name);\n const intent: 'override-artifact' | 'runtime-only' = artifactBacked\n ? 'override-artifact' : 'runtime-only';\n const ref = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.restoreVersion>[0];\n try {\n const result = await repo.restoreVersion(ref, request.toVersion, {\n actor: request.actor ?? 'system',\n source: 'protocol.rollbackMetaItem',\n ...(request.message ? { message: request.message } : {}),\n intent,\n });\n this.applyObjectRegistryMutation({\n type: request.type,\n name: request.name,\n item: result.item.body,\n });\n return {\n success: true,\n version: result.version,\n seq: result.seq,\n restoredFromVersion: request.toVersion,\n message: `Reverted to version ${request.toVersion} — type=${request.type}, name=${request.name} [seq=${result.seq}]`,\n };\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict: any = new Error(\n `[metadata_conflict] ${request.type}/${request.name} advanced during rollback. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n conflict.code = 'metadata_conflict';\n conflict.status = 409;\n conflict.expectedParent = err.expectedParent;\n conflict.actualHead = err.actualHead;\n throw conflict;\n }\n throw err;\n }\n }\n\n /**\n * Compute a shallow structural diff between two historical\n * versions of a metadata item. Either side may be omitted: when\n * `toVersion` is undefined the current active body is used; when\n * `fromVersion` is undefined the immediately previous history row\n * is used. Returns `{ added, removed, changed }` keyed by JSON\n * pointer-style paths for primitive leaves; nested objects/arrays\n * are reported as a single change record.\n */\n async diffMetaItem(request: {\n type: string;\n name: string;\n fromVersion?: number;\n toVersion?: number;\n organizationId?: string;\n }): Promise<{\n type: string;\n name: string;\n fromVersion: number | null;\n toVersion: number | null;\n added: Array<{ path: string; value: unknown }>;\n removed: Array<{ path: string; value: unknown }>;\n changed: Array<{ path: string; from: unknown; to: unknown }>;\n }> {\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const orgId = request.organizationId ?? null;\n const events = (await this.historyMetaItem({\n type: singularType,\n name: request.name,\n ...(orgId ? { organizationId: orgId } : {}),\n })).events;\n const versions = events\n .map((ev: any) => (ev as any).version as number | undefined)\n .filter((v): v is number => typeof v === 'number');\n // The `historyMetaItem` MetadataEvent shape doesn't carry the\n // per-(type,name) `version` directly — re-fetch via the repo\n // to read the underlying history rows with their version.\n const repo = this.getOverlayRepo(orgId);\n const fullRef = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as { type: string; name: string; org: string };\n const histRows: Array<{ version: number; body: Record<string, unknown> | null }> = [];\n try {\n const engineAny = this.engine as any;\n const rows = await engineAny.find('sys_metadata_history', {\n where: {\n organization_id: orgId,\n type: singularType,\n name: request.name,\n },\n });\n rows.sort((a: any, b: any) => (a.version ?? 0) - (b.version ?? 0));\n for (const r of rows) {\n const body = r.metadata == null\n ? null\n : (typeof r.metadata === 'string' ? JSON.parse(r.metadata) : r.metadata);\n histRows.push({ version: r.version ?? 0, body });\n }\n } catch {\n // history table unavailable — fall through with empty list\n }\n const byVersion = new Map<number, Record<string, unknown> | null>();\n for (const r of histRows) byVersion.set(r.version, r.body);\n\n let fromBody: Record<string, unknown> | null = null;\n let toBody: Record<string, unknown> | null = null;\n let fromVersion: number | null = null;\n let toVersion: number | null = null;\n\n if (request.toVersion !== undefined) {\n toVersion = request.toVersion;\n toBody = byVersion.get(request.toVersion) ?? null;\n } else {\n const current = await repo.get(fullRef as any, { state: 'active' });\n toBody = current ? (current.body as Record<string, unknown>) : null;\n toVersion = histRows.length ? histRows[histRows.length - 1]!.version : null;\n }\n if (request.fromVersion !== undefined) {\n fromVersion = request.fromVersion;\n fromBody = byVersion.get(request.fromVersion) ?? null;\n } else if (toVersion !== null) {\n // Use the version immediately preceding `toVersion`\n const sorted = histRows.map((r) => r.version).filter((v) => v < toVersion!);\n if (sorted.length) {\n fromVersion = sorted[sorted.length - 1]!;\n fromBody = byVersion.get(fromVersion) ?? null;\n }\n }\n const diff = diffShallow(fromBody ?? {}, toBody ?? {});\n const _used = versions; void _used;\n return {\n type: request.type,\n name: request.name,\n fromVersion,\n toVersion,\n ...diff,\n };\n }\n\n /**\n * Remove a customization overlay row for the given metadata item, so the\n * next read falls through to the artifact-loaded default. Implements the\n * \"Reset to factory default\" semantic from ADR-0005. Whitelist is shared\n * with {@link saveMetaItem}.\n */\n async deleteMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string;\n parentVersion?: string | null;\n actor?: string;\n state?: 'active' | 'draft';\n /**\n * When true, also drop the object's physical table after the metadata\n * is removed (object + active only; never `sys_`). Default false keeps\n * delete non-destructive to data. Used by the \"discard a previewed\n * object\" flow so a publish-to-preview leaves no orphan table.\n */\n dropStorage?: boolean;\n }): Promise<{\n success: boolean;\n message?: string;\n reset?: boolean;\n seq?: number;\n }> {\n // Two-tier authorization for delete (mirrors saveMetaItem).\n // • Artifact-backed item → delete becomes a tombstone overlay,\n // requires `allowOrgOverride`.\n // • DB-only item → hard delete of a user-created row,\n // requires `allowRuntimeCreate` (or `allowOrgOverride`).\n if (this.environmentId !== undefined) {\n const overlayAllowed = ObjectStackProtocolImplementation.isOverlayAllowed(request.type);\n const runtimeCreateAllowed = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(request.type);\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n if (artifactBacked && !overlayAllowed) {\n const err = new Error(\n `[not_overridable] Metadata item '${request.type}/${request.name}' is provided by a code package `\n + `and the type has not opted into per-org overlay writes. `\n + `See docs/adr/0005-metadata-customization-overlay.md.`\n );\n (err as any).code = 'not_overridable';\n (err as any).status = 403;\n throw err;\n }\n if (!artifactBacked && !overlayAllowed && !runtimeCreateAllowed) {\n const err = new Error(\n `[not_creatable] Metadata type '${request.type}' does not allow runtime creation or deletion.`\n );\n (err as any).code = 'not_creatable';\n (err as any).status = 403;\n throw err;\n }\n\n // ADR-0010 L3 — lock blocks delete.\n const lockErr = await this.assertLockAllowsDelete({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.deleteMetaItem',\n });\n if (lockErr) throw lockErr;\n }\n\n const singularTypeForRepo = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const overlayAllowedForRepoDel = ObjectStackProtocolImplementation.isOverlayAllowed(singularTypeForRepo);\n const runtimeCreateAllowedForRepoDel = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularTypeForRepo);\n const useRepoPath = overlayAllowedForRepoDel || runtimeCreateAllowedForRepoDel;\n\n // ADR-0008 — overlay-allowed types route through SysMetadataRepository\n // so the delete (a) is wrapped in engine.transaction(), (b) appends a\n // tombstone row to sys_metadata_history, and (c) emits a watch event\n // with a monotonic `seq` for HMR. Non-overlay-allowed types (only\n // reachable in control-plane bootstrap mode where environmentId is\n // undefined) take the legacy raw-engine path below — the repository's\n // `assertAllowed()` whitelist would 403 those deletes.\n if (useRepoPath) {\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const ref = {\n type: singularTypeForRepo,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.delete>[0];\n\n try {\n const targetState: 'active' | 'draft' = request.state === 'draft' ? 'draft' : 'active';\n // Probe first — \"no overlay exists\" is a success/no-op, not\n // a conflict. The repo would otherwise throw ConflictError.\n const current = await repo.get(ref, { state: targetState });\n if (!current) {\n return {\n success: true,\n reset: false,\n message: targetState === 'draft'\n ? `No pending draft for ${request.type}/${request.name}.`\n : `No customization overlay found for ${request.type}/${request.name} — already at artifact default.`,\n };\n }\n\n // Last-write-wins parent resolution unless the caller pinned\n // an explicit version (Studio's \"Reset\" button is unpinned;\n // a future \"delete vN\" flow can pass parentVersion).\n const parentVersion: string = request.parentVersion !== undefined\n ? (request.parentVersion ?? current.hash)\n : current.hash;\n\n const result = await repo.delete(ref, {\n parentVersion,\n actor: request.actor ?? 'system',\n source: 'protocol.deleteMetaItem',\n intent: this.isArtifactBacked(singularTypeForRepo, request.name)\n ? 'override-artifact'\n : 'runtime-only',\n state: targetState,\n });\n\n // Refresh the in-memory artifact-side state on control-plane\n // kernels (same logic as the legacy branch — see comments\n // there for why this only runs when environmentId === undefined).\n if (this.environmentId === undefined) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n const artifactItem = await metadataService.get(request.type, request.name);\n if (artifactItem !== undefined) {\n this.engine.registry.registerItem(request.type, artifactItem, 'name');\n }\n }\n } catch {\n // Best-effort registry refresh; next read fixes it anyway\n }\n }\n\n // Storage teardown (opt-in): drop the now-orphaned physical table\n // for a discarded object so a publish-to-preview leaves no residue.\n if (this.shouldDropStorage(request.type, request.name, request.dropStorage, targetState)) {\n await this.dropObjectStorage(singularTypeForRepo, request.name);\n }\n\n // ADR-0010 — success audit (best-effort).\n await this.recordMetadataAudit({\n type: request.type,\n name: request.name,\n organizationId: orgId,\n operation: 'delete',\n outcome: 'allowed',\n code: 'ok',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.deleteMetaItem',\n note: targetState,\n });\n\n return {\n success: true,\n reset: true,\n seq: result.seq,\n message: (request.state === 'draft')\n ? `Draft discarded — ${request.type}/${request.name}. [seq=${result.seq}]`\n : `Customization overlay deleted — ${request.type}/${request.name} reset to artifact default. [seq=${result.seq}]`,\n };\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict = new Error(\n `[metadata_conflict] ${request.type}/${request.name} has been modified since you loaded it. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n (conflict as any).code = 'metadata_conflict';\n (conflict as any).status = 409;\n (conflict as any).expectedParent = err.expectedParent;\n (conflict as any).actualHead = err.actualHead;\n throw conflict;\n }\n const e = new Error(`Failed to delete customization overlay: ${err.message ?? err}`);\n (e as any).status = err?.status ?? 500;\n throw e;\n }\n }\n\n // ── Legacy raw-engine path: only reachable in control-plane bootstrap\n // (environmentId === undefined) for non-overlay-allowed types like\n // `object`, `flow`, `agent`. No history row, no watch event — these\n // types don't participate in the change-log model.\n const scopedWhere: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n organization_id: request.organizationId ?? null,\n };\n\n try {\n const existing = await this.engine.findOne('sys_metadata', { where: scopedWhere });\n if (!existing) {\n return {\n success: true,\n reset: false,\n message: `No customization overlay found for ${request.type}/${request.name} — already at artifact default.`,\n };\n }\n await this.engine.delete('sys_metadata', { where: { id: existing.id } });\n\n // Storage teardown (opt-in) — see the repo-path branch above.\n {\n const targetState: 'active' | 'draft' = request.state === 'draft' ? 'draft' : 'active';\n if (this.shouldDropStorage(request.type, request.name, request.dropStorage, targetState)) {\n await this.dropObjectStorage(PLURAL_TO_SINGULAR[request.type] ?? request.type, request.name);\n }\n }\n\n if (this.environmentId === undefined) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n const artifactItem = await metadataService.get(request.type, request.name);\n if (artifactItem !== undefined) {\n this.engine.registry.registerItem(request.type, artifactItem, 'name');\n }\n }\n } catch {\n // Best-effort registry refresh; next read fixes it anyway\n }\n }\n\n return {\n success: true,\n reset: true,\n message: `Customization overlay deleted — ${request.type}/${request.name} reset to artifact default.`,\n };\n } catch (err: any) {\n const e = new Error(`Failed to delete customization overlay: ${err.message}`);\n (e as any).status = 500;\n throw e;\n }\n }\n\n /**\n * Hydrate SchemaRegistry from the database on startup.\n * Loads all active metadata records and registers them in the in-memory registry.\n * Safe to call repeatedly — idempotent (latest DB record wins).\n *\n * Per ADR-0005, project-kernel mode ALSO hydrates from sys_metadata —\n * customization overlay rows must survive restart. Scope filter\n * (`environment_id = this.environmentId ?? null`) keeps tenants isolated.\n */\n async loadMetaFromDb(): Promise<{ loaded: number; errors: number }> {\n let loaded = 0;\n let errors = 0;\n try {\n // ADR-0005 (revised 2026-05): hydrate only env-wide rows\n // (organization_id IS NULL). Per-org overlays are loaded on\n // demand by getMetaItem to avoid cross-org leakage into the\n // process-wide SchemaRegistry.\n const where: Record<string, unknown> = {\n state: 'active',\n organization_id: null,\n };\n const records = await this.engine.find('sys_metadata', { where });\n for (const record of records) {\n try {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Normalize DB type to singular (DB may store legacy plural forms)\n const normalizedType = PLURAL_TO_SINGULAR[record.type] ?? record.type;\n if (normalizedType === 'object') {\n this.engine.registry.registerObject(data as any, record.packageId || 'sys_metadata');\n } else {\n this.engine.registry.registerItem(normalizedType, data, 'name' as any);\n }\n loaded++;\n } catch (e) {\n errors++;\n console.warn(`[Protocol] Failed to hydrate ${record.type}/${record.name}: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n } catch (e: any) {\n // \"no such table\" is expected on first run before migrations execute — not an error.\n if (!/no such table/i.test(e.message ?? '')) {\n console.warn(`[Protocol] DB hydration skipped: ${e.message}`);\n }\n }\n return { loaded, errors };\n }\n\n // ==========================================\n // Metadata References (Phase 3a-references)\n // ==========================================\n\n /**\n * Scan all loaded metadata for references pointing at the given\n * `{type, name}` target. Returns one row per referring artifact with\n * the path that produced the hit, so the admin UI can render an\n * \"Used by\" panel before destructive actions (rename / delete /\n * type-narrowing).\n *\n * Coverage is driven by the hand-curated {@link REFERENCE_PATHS}\n * registry. Types not present in the registry simply return no hits\n * — the engine never throws.\n */\n async findReferencesToMeta(request: {\n type: string;\n name: string;\n organizationId?: string;\n }): Promise<{\n references: Array<{\n type: string;\n name: string;\n label?: string;\n path: string;\n kind: string;\n }>;\n }> {\n const singularTarget = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const targetName = request.name;\n const matchers = REFERENCE_PATHS[singularTarget];\n if (!matchers || matchers.length === 0) {\n return { references: [] };\n }\n\n const seen = new Set<string>(); // dedup key: `${fromType}|${itemName}|${path}`\n const out: Array<{ type: string; name: string; label?: string; path: string; kind: string }> = [];\n\n // Walk distinct source types in parallel.\n await Promise.all(\n matchers.map(async (matcher) => {\n let items: unknown[] = [];\n try {\n const result = await this.getMetaItems({\n type: matcher.fromType,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n });\n items = (result?.items ?? []) as unknown[];\n } catch {\n return;\n }\n for (const raw of items) {\n if (!raw || typeof raw !== 'object') continue;\n const sourceName = (raw as any).name as string | undefined;\n if (!sourceName) continue;\n // Don't list an item as a reference to itself unless the\n // self-reference is meaningful (e.g. object→field path).\n const isSelfReference = matcher.fromType === singularTarget && sourceName === targetName;\n for (const path of matcher.paths) {\n const values = extractPathValues(raw, path);\n if (!values.includes(targetName)) continue;\n if (isSelfReference && !path.includes('[]') && !path.includes('{}')) continue;\n const key = `${matcher.fromType}|${sourceName}|${path}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const label = (raw as any).label as string | undefined;\n out.push({\n type: matcher.fromType,\n name: sourceName,\n ...(label ? { label } : {}),\n path,\n kind: matcher.kind,\n });\n }\n }\n }),\n );\n\n // Stable sort: by type, then by name.\n out.sort((a, b) => a.type.localeCompare(b.type) || a.name.localeCompare(b.name));\n\n return { references: out };\n }\n\n // ==========================================\n // Feed Operations\n // ==========================================\n\n async listFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n return { success: true, data: result };\n }\n\n async createFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.createFeedItem({\n object: request.object,\n recordId: request.recordId,\n type: request.type,\n actor: { type: 'user', id: 'current_user' },\n body: request.body,\n mentions: request.mentions,\n parentId: request.parentId,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async updateFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.updateFeedItem(request.feedId, {\n body: request.body,\n mentions: request.mentions,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async deleteFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n await svc.deleteFeedItem(request.feedId);\n return { success: true, data: { feedId: request.feedId } };\n }\n\n async addReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.addReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async removeReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.removeReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async pinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated pin/unpin — use updateFeedItem to persist pin state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: new Date().toISOString() } };\n }\n\n async unpinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: false } };\n }\n\n async starFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated star/unstar — verify item exists then return state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: true, starredAt: new Date().toISOString() } };\n }\n\n async unstarFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: false } };\n }\n\n async searchFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Search delegates to listFeed with filter since IFeedService doesn't have a dedicated search\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n // Filter by query text in body\n const queryLower = (request.query || '').toLowerCase();\n const filtered = result.items.filter((item: any) =>\n item.body?.toLowerCase().includes(queryLower)\n );\n return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };\n }\n\n async getChangelog(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Changelog retrieves field_change type feed items\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: 'changes_only',\n limit: request.limit,\n cursor: request.cursor,\n });\n const entries = result.items.map((item: any) => ({\n id: item.id,\n object: item.object,\n recordId: item.recordId,\n actor: item.actor,\n changes: item.changes || [],\n timestamp: item.createdAt,\n source: item.source,\n }));\n return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };\n }\n\n async feedSubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const subscription = await svc.subscribe({\n object: request.object,\n recordId: request.recordId,\n userId: 'current_user',\n events: request.events,\n channels: request.channels,\n });\n return { success: true, data: subscription };\n }\n\n async feedUnsubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const unsubscribed = await svc.unsubscribe(request.object, request.recordId, 'current_user');\n return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };\n }\n\n /**\n * Install a package from a manifest — the single canonical write primitive\n * for the package subsystem (ADR-0033 consolidation).\n *\n * It writes BOTH stores that the runtime keeps for packages, so a package\n * surfaces consistently no matter which read path is used:\n * 1. the in-memory `SchemaRegistry` (what the dispatcher's\n * `/api/v1/packages` list/detail and `getMetaItems({type:'package'})`\n * read — i.e. what Studio's package selector shows), and\n * 2. the durable `sys_packages` table via the optional `package` service\n * (so the package survives a restart; that service re-hydrates these\n * rows back into the registry on boot).\n *\n * The DB write is best-effort and non-fatal: when the `package` service is\n * absent (e.g. the `marketplace` capability is off) the package is still\n * registered in-memory and visible for the lifetime of the process.\n */\n async installPackage(request: InstallPackageRequest): Promise<InstallPackageResponse> {\n const manifest = request.manifest;\n const pkg = this.engine.registry.installPackage(manifest as any, request.settings);\n\n // Best-effort durable persistence to `sys_packages`.\n try {\n const services = this.getServicesRegistry?.();\n const pkgSvc = services?.get('package') as\n | { publish?: (data: { manifest: unknown; metadata: unknown }) => Promise<unknown> }\n | undefined;\n if (pkgSvc?.publish && (manifest as any)?.version) {\n await pkgSvc.publish({ manifest, metadata: {} });\n }\n } catch (e) {\n // Non-fatal: registry write already succeeded; log and continue.\n console.warn(\n `[protocol.installPackage] sys_packages persist skipped for '${(manifest as any)?.id}': ${(e as Error)?.message}`,\n );\n }\n\n return { package: pkg as any, message: `Installed package: ${(manifest as any)?.id}` };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ADR-0008 PR-10b — `SysMetadataRepository`.\n *\n * Wraps the existing `sys_metadata` table behind the canonical\n * `MetadataRepository` interface. Implements the *single-row update*\n * semantics that ADR-0005 already ships — append-only event-log\n * persistence is M1 work.\n *\n * What this layer DOES (M0 + M1):\n * - get / put / delete / list against `sys_metadata`\n * - tenancy scope = `organization_id` (per-org overlays only;\n * project/branch concepts removed — see ADR-0008 §0 amendment)\n * - hash stamping with `hashSpec` (PR-10a guarantees stability)\n * - watch() implemented via an in-memory event broadcaster fed by\n * every successful put/delete on THIS instance\n * - whitelist enforcement: refuses to persist types whose registry\n * entry has `allowOrgOverride: false` (Prime Directive #8)\n * - **M1**: every successful put/delete appends a durable row to\n * `sys_metadata_history` inside the same engine.transaction() as the\n * parent `sys_metadata` write. No-op puts (identical hash) skip the\n * history write. Failed optimistic-lock checks abort before any\n * write reaches the database.\n * - **M1**: history() yields events from the durable log, ordered by\n * per-(org,type,name) `version` ASC.\n *\n * What this layer does NOT do (and will not, by design):\n * - cross-replica push notifications (LISTEN/NOTIFY, pub/sub, etc.).\n * The watch() contract is scoped to the local repository instance.\n * Multi-replica deployments are not a supported topology for the\n * metadata overlay — see ADR-0008 §11.\n * - hashSpec backfill for legacy rows missing `checksum`\n *\n * Schema mapping (ADR-0008 PR-10d.2):\n * Repository concept sys_metadata column\n * ─────────────────────── ───────────────────\n * body → metadata (JSON string)\n * hash (sha256) → checksum (text(64))\n * monotonic version int → version (number)\n * org isolation → organization_id (lookup)\n * actor → updated_by (lookup, optional)\n *\n * Composition: PR-10c will compose\n * `LayeredRepository([FileSystemRepository, SysMetadataRepository])`\n * and the manager bridge will route reads through that. Until then this\n * file is intentionally NOT wired into any production path — it has its\n * own test surface so we can build confidence before flipping the\n * switch.\n */\n\nimport { hashSpec, ConflictError } from '@objectstack/metadata-core';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport type {\n MetadataRepository,\n MetaRef,\n MetadataItem,\n MetadataItemHeader,\n MetadataEvent,\n MetadataWriteIntent,\n PutOptions,\n PutResult,\n DeleteOptions,\n DeleteResult,\n ListFilter,\n WatchFilter,\n HistoryOptions,\n} from '@objectstack/metadata-core';\nimport { DEFAULT_METADATA_TYPE_REGISTRY } from '@objectstack/spec/kernel';\nimport { PLURAL_TO_SINGULAR, SINGULAR_TO_PLURAL } from '@objectstack/spec/shared';\n\n/**\n * Overlay-row lifecycle state.\n *\n * - `'active'` → the published, live overlay. `getMetaItem` (the\n * default read path) and runtime loaders observe this row.\n * - `'draft'` → an unpublished pending change. Lives alongside the\n * active row (one of each per `(org,type,name)`). Promoted to\n * `active` via {@link SysMetadataRepository.promoteDraft}.\n *\n * Other lifecycle values defined on `sys_metadata.state` (`'archived'`,\n * `'deprecated'`) are not yet plumbed through the overlay write path;\n * they remain reserved for future flows (item retirement, freeze).\n */\nexport type OverlayState = 'active' | 'draft';\n\n/**\n * Extended history operation tag. The base `'create' | 'update' |\n * 'delete'` operations are emitted by the canonical put/delete paths.\n * `'publish'` is recorded when a draft is promoted, `'revert'` when a\n * historical version is restored. Both are surfaced as MetadataEvent\n * `.op` values via `history()`.\n */\nexport type ExtendedOperation = 'create' | 'update' | 'publish' | 'revert' | 'delete';\n\n/**\n * Sub-set of the ObjectQL engine shape we depend on. Kept narrow so\n * tests can stub it with a plain mock. Mirrors the real engine's\n * `options.context` pattern so transactions can thread through.\n */\nexport interface SysMetadataEngine {\n find(\n table: string,\n options: { where: Record<string, unknown>; limit?: number; orderBy?: any; context?: any },\n ): Promise<any[]>;\n findOne(\n table: string,\n options: { where: Record<string, unknown>; context?: any },\n ): Promise<any | null>;\n insert(\n table: string,\n data: Record<string, unknown>,\n options?: { context?: any },\n ): Promise<{ id: string }>;\n update(\n table: string,\n data: Record<string, unknown>,\n options: { where: Record<string, unknown>; context?: any },\n ): Promise<{ id: string }>;\n delete(\n table: string,\n options: { where: Record<string, unknown>; context?: any },\n ): Promise<{ deleted: number }>;\n /**\n * Optional. Falls through to direct callback invocation if the\n * underlying driver lacks ACID support (matches the real\n * `ObjectQL.transaction` semantics). Repository code must not rely on\n * rollback for correctness against in-memory drivers.\n */\n transaction?<T>(callback: (trxCtx: any) => Promise<T>, baseContext?: any): Promise<T>;\n}\n\nexport interface SysMetadataRepositoryOptions {\n engine: SysMetadataEngine;\n /**\n * Tenancy scope. `null` writes to env-wide overlay rows; a string\n * scopes to one organization (the supported shared-DB tenant model\n * — see ADR-0005 amendment).\n */\n organizationId?: string | null;\n /** Org label embedded in returned MetaRefs. Defaults to organizationId or `\"system\"`. */\n orgLabel?: string;\n}\n\n/** Derived from registry — single source of truth (Prime Directive #8). */\nconst OVERLAY_ALLOWED_TYPES: ReadonlySet<string> = new Set(\n DEFAULT_METADATA_TYPE_REGISTRY\n .filter((e) => e.allowOrgOverride)\n .map((e) => e.type),\n);\n\n/**\n * Types that opt into runtime creation of brand-new items (two-tier\n * model — ADR-0005 extension). These items live only in `sys_metadata`;\n * there is no artifact backing them and `allowOrgOverride` need not be\n * granted on the type. Used by `assertAllowed()` when called with\n * `intent: 'runtime-only'` — a signal from the protocol layer that it\n * has already verified the absence of an artifact-shadowing collision.\n */\n/**\n * Set of type names that have an *explicit* entry in the static registry.\n * Anything outside this set is a runtime-registered type (e.g. plugin-\n * provided `theme`, `api`, `connector`, …) — the listing endpoint\n * (`getMetaTypes()` in protocol.ts) synthesises a descriptor with\n * `allowRuntimeCreate: true` for those, so the write gate must agree.\n */\nconst STATIC_REGISTRY_TYPES: ReadonlySet<string> = new Set(\n DEFAULT_METADATA_TYPE_REGISTRY.map((e) => e.type),\n);\n\nconst RUNTIME_CREATE_ALLOWED_TYPES: ReadonlySet<string> = new Set(\n DEFAULT_METADATA_TYPE_REGISTRY\n .filter((e) => e.allowRuntimeCreate)\n .map((e) => e.type),\n);\n\n/**\n * Phase 3a-env-writable: parse `OS_METADATA_WRITABLE` (comma-\n * separated singular type names). Memoised; tests can reset via\n * {@link resetEnvWritableMetadataTypes}. Mirrors the same helper in\n * ObjectStackProtocolImplementation — both gates must consult the same\n * elevated set so the env-var escape hatch is applied consistently\n * regardless of which write path a caller takes.\n */\nlet _envWritableMetadataTypes: Set<string> | null = null;\nfunction envWritableMetadataTypes(): ReadonlySet<string> {\n if (_envWritableMetadataTypes !== null) return _envWritableMetadataTypes;\n const raw = readEnvWithDeprecation('OS_METADATA_WRITABLE', 'OBJECTSTACK_METADATA_WRITABLE') || '';\n const set = new Set<string>();\n for (const tok of raw.split(',')) {\n const t = tok.trim();\n if (!t) continue;\n const singular = PLURAL_TO_SINGULAR[t] ?? t;\n set.add(singular);\n const plural = SINGULAR_TO_PLURAL[singular];\n if (plural) set.add(plural);\n }\n _envWritableMetadataTypes = set;\n return set;\n}\n\n/** Test hook — clear the memoised env-writable cache. */\nexport function resetEnvWritableMetadataTypes(): void {\n _envWritableMetadataTypes = null;\n}\n\nexport class SysMetadataRepository implements MetadataRepository {\n private readonly engine: SysMetadataEngine;\n private readonly organizationId: string | null;\n private readonly orgLabel: string;\n\n /**\n * Local seq counter for in-memory watch() event broadcasts. Mirrors\n * the durable `event_seq` we write into `sys_metadata_history` on\n * each successful put/delete — assigned AFTER the transaction commits\n * so we never broadcast events that got rolled back.\n */\n private seqCounter = 0;\n private readonly watchers = new Set<(evt: MetadataEvent) => void>();\n private closed = false;\n\n /** Table name for the durable event log. */\n private readonly historyTable = 'sys_metadata_history';\n\n constructor(opts: SysMetadataRepositoryOptions) {\n this.engine = opts.engine;\n this.organizationId = opts.organizationId ?? null;\n this.orgLabel = opts.orgLabel ?? (opts.organizationId ?? 'system');\n }\n\n /**\n * Run `cb` inside `engine.transaction(...)` if the engine supports it,\n * otherwise fall through to a direct call. Matches the real\n * `ObjectQL.transaction` semantics — in-memory drivers (and our test\n * fakes) get no rollback, which is acceptable because production\n * always runs on a SQL driver with real ACID.\n */\n private async withTxn<T>(cb: (ctx: any) => Promise<T>): Promise<T> {\n if (typeof this.engine.transaction === 'function') {\n return this.engine.transaction(cb);\n }\n return cb(undefined);\n }\n\n /**\n * Read the current overlay row. Returns null if no row exists —\n * callers (e.g. LayeredRepository) fall through to lower layers.\n *\n * `opts.state` selects which lifecycle row to read: defaults to the\n * live published row (`'active'`). Pass `'draft'` to read the pending\n * unpublished revision (if any).\n */\n async get(ref: MetaRef, opts?: { state?: OverlayState }): Promise<MetadataItem | null> {\n this.assertOpen();\n const state = opts?.state ?? 'active';\n const row = await this.engine.findOne('sys_metadata', {\n where: this.whereFor(ref, state),\n });\n if (!row) return null;\n return this.rowToItem(ref, row);\n }\n\n /**\n * Resolve a historical version by content hash (ADR-0009).\n *\n * Looks up `sys_metadata_history` by `(organization_id, type, name,\n * checksum)`. Returns null if no row matches. `executionPinned` types\n * are guaranteed to find their body here because history GC skips\n * them.\n */\n async getByHash(ref: MetaRef, hash: string): Promise<MetadataItem | null> {\n this.assertOpen();\n const full = this.fullRef(ref);\n const row = await this.engine.findOne(this.historyTable, {\n where: {\n organization_id: this.organizationId,\n type: full.type,\n name: full.name,\n checksum: hash,\n },\n });\n if (!row) return null;\n const rawBody = (row as any).metadata;\n if (rawBody === null || rawBody === undefined) {\n // Tombstone — body is gone, do not resurrect.\n return null;\n }\n const body =\n typeof rawBody === 'string' ? JSON.parse(rawBody) : (rawBody as Record<string, unknown>);\n return {\n ref: { ...full, version: undefined },\n body: body as Record<string, unknown>,\n hash,\n parentHash: (row as any).previous_checksum ?? null,\n authoredBy: (row as any).recorded_by ?? 'unknown',\n authoredAt: (row as any).recorded_at ?? new Date(0).toISOString(),\n message: (row as any).change_note ?? undefined,\n seq: ((row as any).event_seq as number) ?? 0,\n };\n }\n\n async put(\n ref: MetaRef,\n spec: unknown,\n opts: PutOptions & { state?: OverlayState; opType?: ExtendedOperation },\n ): Promise<PutResult> {\n this.assertOpen();\n this.assertAllowed(ref.type, opts.intent);\n\n const state: OverlayState = opts.state ?? 'active';\n const body = (spec ?? {}) as Record<string, unknown>;\n const hash = hashSpec(body);\n\n // Run all reads + writes inside one transaction so the optimistic\n // lock, the parent-row mutation, and the history append are atomic.\n const result = await this.withTxn(async (ctx) => {\n const existing = await this.engine.findOne('sys_metadata', {\n where: this.whereFor(ref, state),\n context: ctx,\n });\n const existingHash: string | null = existing?.checksum ?? null;\n if (opts.parentVersion !== existingHash) {\n throw new ConflictError(this.fullRef(ref), opts.parentVersion, existingHash);\n }\n\n // No-op short-circuit: identical body → no write, no history row,\n // no event. We re-yield the existing item so callers see the\n // canonical hash but the seqCounter is unchanged.\n if (existing && existingHash === hash) {\n const item = this.rowToItem(ref, existing);\n return { skipped: true as const, version: hash, seq: item.seq, item };\n }\n\n const now = new Date().toISOString();\n const baseOp: 'create' | 'update' = existing ? 'update' : 'create';\n const op: ExtendedOperation = opts.opType ?? baseOp;\n\n // Per-(org,type,name) lineage counter. Use MAX from history so\n // delete+recreate continues incrementing instead of restarting\n // at 1 (which the prior `sys_metadata.version` semantics did).\n const version = await this.nextItemVersion(ref, ctx);\n // Per-org monotonic event log cursor.\n const eventSeq = await this.nextEventSeq(ctx);\n\n const parentRowData: Record<string, unknown> = {\n type: ref.type,\n name: ref.name,\n organization_id: this.organizationId,\n metadata: JSON.stringify(body),\n checksum: hash,\n state,\n version,\n updated_at: now,\n };\n // Software-package binding (Studio package authoring workspace).\n // Create: stamp with the requested package (or null). Update: preserve\n // an existing non-null binding so an edit made with a different package\n // selected never silently re-binds the row; only fill a null binding.\n if (existing) {\n const existingPkg = (existing as { package_id?: string | null }).package_id ?? null;\n parentRowData.package_id = existingPkg ?? opts.packageId ?? null;\n } else {\n parentRowData.package_id = opts.packageId ?? null;\n }\n if (existing) {\n const existingId = (existing as { id?: string }).id;\n if (existingId === undefined) {\n throw new Error(\n `SysMetadataRepository.put: existing row for ${ref.type}/${ref.name} has no id column`,\n );\n }\n await this.engine.update('sys_metadata', parentRowData, {\n where: { id: existingId },\n context: ctx,\n });\n } else {\n parentRowData.created_at = now;\n await this.engine.insert('sys_metadata', parentRowData, { context: ctx });\n }\n\n // Durable history append — same transaction, so the parent write\n // and the audit row commit together or roll back together.\n await this.engine.insert(\n this.historyTable,\n {\n id: this.uuid(),\n event_seq: eventSeq,\n type: ref.type,\n name: ref.name,\n version,\n operation_type: op,\n metadata: JSON.stringify(body),\n checksum: hash,\n previous_checksum: existingHash,\n change_note: opts.message,\n source: opts.source ?? 'sys-metadata-repo',\n organization_id: this.organizationId,\n recorded_by: opts.actor,\n recorded_at: now,\n },\n { context: ctx },\n );\n\n const item: MetadataItem = {\n ref: this.fullRef(ref),\n body,\n hash,\n parentHash: existingHash,\n authoredBy: opts.actor,\n authoredAt: now,\n message: opts.message,\n seq: eventSeq,\n };\n\n return {\n skipped: false as const,\n version: hash,\n seq: eventSeq,\n item,\n op,\n existingHash,\n now,\n source: opts.source ?? 'sys-metadata-repo',\n message: opts.message,\n actor: opts.actor,\n };\n });\n\n if (result.skipped) {\n return { version: result.version, seq: result.seq, item: result.item };\n }\n\n // Broadcast AFTER commit. seqCounter tracks the durable event_seq\n // so watch() consumers and history() consumers see the same cursor.\n this.seqCounter = result.seq;\n // Drafts are explicitly NOT broadcast — the watch() stream models\n // the live overlay surface. A draft is a private staging buffer\n // until `promoteDraft()` records a `publish` event. Subscribers\n // (cache layers, HMR clients) should not react to drafts.\n if (state === 'active') {\n this.broadcast({\n seq: result.seq,\n op: result.op,\n ref: this.fullRef(ref),\n hash: result.version,\n parentHash: result.existingHash,\n actor: result.actor,\n message: result.message,\n ts: result.now,\n source: result.source,\n });\n }\n\n return { version: result.version, seq: result.seq, item: result.item };\n }\n\n async delete(\n ref: MetaRef,\n opts: DeleteOptions & { state?: OverlayState },\n ): Promise<DeleteResult> {\n this.assertOpen();\n this.assertAllowed(ref.type, opts.intent);\n\n const state: OverlayState = opts.state ?? 'active';\n const result = await this.withTxn(async (ctx) => {\n const existing = await this.engine.findOne('sys_metadata', {\n where: this.whereFor(ref, state),\n context: ctx,\n });\n if (!existing) {\n throw new ConflictError(this.fullRef(ref), opts.parentVersion, null);\n }\n const existingHash: string | null = existing.checksum ?? null;\n if (opts.parentVersion !== existingHash) {\n throw new ConflictError(this.fullRef(ref), opts.parentVersion, existingHash);\n }\n\n const existingId = (existing as { id?: string }).id;\n if (existingId === undefined) {\n throw new Error(\n `SysMetadataRepository.delete: existing row for ${ref.type}/${ref.name} has no id column`,\n );\n }\n\n const now = new Date().toISOString();\n // Draft deletions are a private buffer flush — they don't get a\n // history event (no audit value, and no parent for replay). Only\n // active-row deletes write a tombstone.\n let version = 0;\n let eventSeq = 0;\n if (state === 'active') {\n version = await this.nextItemVersion(ref, ctx);\n eventSeq = await this.nextEventSeq(ctx);\n }\n\n await this.engine.delete('sys_metadata', {\n where: { id: existingId },\n context: ctx,\n });\n\n if (state === 'active') {\n // Tombstone row — metadata/checksum are intentionally null.\n // Identity is preserved via (organization_id, type, name, version);\n // the parent row's id is not retained.\n await this.engine.insert(\n this.historyTable,\n {\n id: this.uuid(),\n event_seq: eventSeq,\n type: ref.type,\n name: ref.name,\n version,\n operation_type: 'delete',\n metadata: null,\n checksum: null,\n previous_checksum: existingHash,\n change_note: opts.message,\n source: opts.source ?? 'sys-metadata-repo',\n organization_id: this.organizationId,\n recorded_by: opts.actor,\n recorded_at: now,\n },\n { context: ctx },\n );\n }\n\n return {\n eventSeq,\n existingHash,\n now,\n source: opts.source ?? 'sys-metadata-repo',\n message: opts.message,\n actor: opts.actor,\n };\n });\n\n if (state === 'active') {\n this.seqCounter = result.eventSeq;\n this.broadcast({\n seq: result.eventSeq,\n op: 'delete',\n ref: this.fullRef(ref),\n hash: null,\n parentHash: result.existingHash,\n actor: result.actor,\n message: result.message,\n ts: result.now,\n source: result.source,\n });\n }\n\n return { seq: result.eventSeq };\n }\n\n /**\n * Promote the pending draft row for `ref` into the live (`active`)\n * overlay. Atomic: reads the draft inside the same transaction, runs\n * the canonical `put` to upsert the active row (which appends a\n * history event with `operation_type='publish'`), then deletes the\n * draft row.\n *\n * Errors if no draft exists (callers should 404). The active row's\n * `parentVersion` is computed from the current active hash so this\n * also surfaces optimistic-lock conflicts when something else has\n * published in between (e.g. another admin reverted to an older\n * version since the draft was authored).\n */\n async promoteDraft(\n ref: MetaRef,\n opts: { actor: string; source?: string; message?: string; intent?: MetadataWriteIntent },\n ): Promise<{ version: string; seq: number; item: MetadataItem }> {\n this.assertOpen();\n const draft = await this.get(ref, { state: 'draft' });\n if (!draft) {\n const err: any = new Error(\n `[no_draft] No pending draft exists for ${ref.type}/${ref.name} — nothing to publish.`,\n );\n err.code = 'no_draft';\n err.status = 404;\n throw err;\n }\n const currentActive = await this.get(ref, { state: 'active' });\n const result = await this.put(ref, draft.body, {\n parentVersion: currentActive?.hash ?? null,\n actor: opts.actor,\n source: opts.source ?? 'sys-metadata-repo.publish',\n message: opts.message ?? `publish draft (hash ${draft.hash})`,\n intent: opts.intent ?? 'override-artifact',\n state: 'active',\n opType: 'publish',\n });\n // Drop the draft row — it has been promoted. Tolerate races where\n // a second publisher already drained it.\n try {\n await this.delete(ref, {\n parentVersion: draft.hash,\n actor: opts.actor,\n source: opts.source ?? 'sys-metadata-repo.publish',\n intent: opts.intent ?? 'override-artifact',\n state: 'draft',\n });\n } catch {\n // best-effort: a concurrent publisher may have already drained\n // the draft; the active row's authoritative content is intact.\n }\n return result;\n }\n\n /**\n * Restore the body recorded in history at `targetVersion` (per-org\n * lineage counter) as the new active row. Writes a history event\n * with `operation_type='revert'` so the audit trail captures the\n * intent. Does NOT touch any draft row.\n *\n * Throws `[version_not_found]` (404) if the target version row is\n * missing or is a delete tombstone (no body to restore).\n */\n async restoreVersion(\n ref: MetaRef,\n targetVersion: number,\n opts: { actor: string; source?: string; message?: string; intent?: MetadataWriteIntent },\n ): Promise<{ version: string; seq: number; item: MetadataItem }> {\n this.assertOpen();\n const full = this.fullRef(ref);\n const row = await this.engine.findOne(this.historyTable, {\n where: {\n organization_id: this.organizationId,\n type: full.type,\n name: full.name,\n version: targetVersion,\n },\n });\n if (!row) {\n const err: any = new Error(\n `[version_not_found] No history row at version ${targetVersion} for ${ref.type}/${ref.name}.`,\n );\n err.code = 'version_not_found';\n err.status = 404;\n throw err;\n }\n const raw = (row as any).metadata;\n if (raw === null || raw === undefined) {\n const err: any = new Error(\n `[version_not_restorable] Version ${targetVersion} for ${ref.type}/${ref.name} is a delete tombstone — nothing to restore.`,\n );\n err.code = 'version_not_restorable';\n err.status = 409;\n throw err;\n }\n const body = typeof raw === 'string' ? JSON.parse(raw) : (raw as Record<string, unknown>);\n const currentActive = await this.get(ref, { state: 'active' });\n return this.put(ref, body, {\n parentVersion: currentActive?.hash ?? null,\n actor: opts.actor,\n source: opts.source ?? 'sys-metadata-repo.revert',\n message: opts.message ?? `revert to version ${targetVersion}`,\n intent: opts.intent ?? 'override-artifact',\n state: 'active',\n opType: 'revert',\n });\n }\n\n async *list(filter: ListFilter): AsyncIterable<MetadataItemHeader> {\n this.assertOpen();\n const where: Record<string, unknown> = {\n organization_id: this.organizationId,\n state: 'active',\n };\n if (filter.type) where.type = filter.type;\n const rows = await this.engine.find('sys_metadata', {\n where,\n limit: filter.limit,\n });\n for (const row of rows) {\n if (filter.nameContains && !String(row.name).includes(filter.nameContains)) continue;\n const item = this.rowToItem(\n { ...this.fullRef({ type: row.type, name: row.name } as MetaRef) },\n row,\n );\n // Strip body for the header projection.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { body, ...header } = item;\n yield header;\n }\n }\n\n /**\n * List pending DRAFT rows (ADR-0033) for this org, optionally narrowed by\n * `type` and/or `packageId`. Unlike {@link list} (which is hard-scoped to\n * `state='active'`), this reads `state='draft'` so the console can surface\n * what an AI authored but a human hasn't published yet. Returns a light\n * header projection (no body) suitable for a \"pending changes\" list.\n */\n async listDrafts(filter?: {\n type?: string;\n packageId?: string;\n }): Promise<\n Array<{\n type: string;\n name: string;\n packageId: string | null;\n updatedAt: string | null;\n updatedBy: string | null;\n }>\n > {\n this.assertOpen();\n const where: Record<string, unknown> = {\n organization_id: this.organizationId,\n state: 'draft',\n };\n if (filter?.type) where.type = filter.type;\n if (filter?.packageId) where.package_id = filter.packageId;\n const rows = await this.engine.find('sys_metadata', { where });\n return (rows as any[]).map((row) => ({\n type: row.type,\n name: row.name,\n packageId: row.package_id ?? null,\n updatedAt: row.updated_at ?? row.created_at ?? null,\n updatedBy: row.updated_by ?? row.created_by ?? null,\n }));\n }\n\n /**\n * Yield every history event for `(org, type?, name?)` from the\n * durable log, ordered by per-(type,name) `version` ascending. When\n * `filter.type`/`filter.name` are unset the consumer gets the full\n * org-scoped event stream — still ordered by version within each\n * (type,name) bucket, then by `recorded_at` across buckets (we sort\n * client-side because the test engine doesn't honor `orderBy`).\n */\n async *history(ref: MetaRef, opts?: HistoryOptions): AsyncIterable<MetadataEvent> {\n this.assertOpen();\n const full = this.fullRef(ref);\n const where: Record<string, unknown> = {\n organization_id: this.organizationId,\n type: full.type,\n name: full.name,\n };\n const rows = await this.engine.find(this.historyTable, { where });\n rows.sort((a: any, b: any) => {\n const va = typeof a.event_seq === 'number' ? a.event_seq : 0;\n const vb = typeof b.event_seq === 'number' ? b.event_seq : 0;\n return va - vb;\n });\n let yielded = 0;\n for (const row of rows) {\n if (opts?.sinceSeq !== undefined && (row.event_seq ?? 0) <= opts.sinceSeq) continue;\n if (opts?.limit !== undefined && yielded >= opts.limit) break;\n yielded++;\n yield {\n seq: (row.event_seq as number) ?? 0,\n op: (row.operation_type as MetadataEvent['op']) ?? 'update',\n ref: full,\n hash: (row.checksum as string | null) ?? null,\n parentHash: (row.previous_checksum as string | null) ?? null,\n version: typeof row.version === 'number' ? row.version : undefined,\n actor: (row.recorded_by as string | undefined) ?? 'unknown',\n message: (row.change_note as string | undefined) ?? undefined,\n ts: (row.recorded_at as string) ?? new Date(0).toISOString(),\n source: (row.source as string | undefined) ?? 'sys-metadata-repo',\n };\n }\n }\n\n /**\n * Live event stream. Fires for every successful put/delete on THIS\n * instance — cross-replica fan-out is M1. Manual AsyncIterator (not\n * an async generator) so we can deterministically tear down via\n * `iter.return()`, matching the pattern used by InMemoryRepository.\n */\n watch(filter: WatchFilter, since?: number): AsyncIterable<MetadataEvent> {\n const self = this;\n return {\n [Symbol.asyncIterator]: () => {\n const queue: MetadataEvent[] = [];\n let pendingResolve: ((r: IteratorResult<MetadataEvent>) => void) | null = null;\n let stopped = false;\n\n const dispatch = (evt: MetadataEvent) => {\n if (stopped) return;\n if (!self.matchesFilter(evt, filter)) return;\n if (since !== undefined && evt.seq <= since) return;\n if (pendingResolve) {\n const r = pendingResolve;\n pendingResolve = null;\n r({ value: evt, done: false });\n } else {\n queue.push(evt);\n }\n };\n self.watchers.add(dispatch);\n\n return {\n next(): Promise<IteratorResult<MetadataEvent>> {\n if (stopped) return Promise.resolve({ value: undefined as any, done: true });\n const buffered = queue.shift();\n if (buffered) return Promise.resolve({ value: buffered, done: false });\n return new Promise((resolve) => {\n pendingResolve = resolve;\n });\n },\n return(): Promise<IteratorResult<MetadataEvent>> {\n stopped = true;\n self.watchers.delete(dispatch);\n if (pendingResolve) {\n const r = pendingResolve;\n pendingResolve = null;\n r({ value: undefined as any, done: true });\n }\n return Promise.resolve({ value: undefined as any, done: true });\n },\n };\n },\n };\n }\n\n /** Shut down all watch iterators. */\n close(): void {\n this.closed = true;\n // Drain watchers — each one's `return()` removes itself.\n const snapshot = Array.from(this.watchers);\n for (const w of snapshot) {\n try {\n w({\n seq: -1,\n op: 'delete',\n ref: { org: '', type: 'view', name: '_close' } as MetaRef,\n hash: null,\n parentHash: null,\n actor: 'system',\n ts: new Date().toISOString(),\n source: 'sys-metadata-repo-close',\n });\n } catch { /* noop */ }\n }\n this.watchers.clear();\n }\n\n // ── helpers ─────────────────────────────────────────────────────────\n\n private assertOpen(): void {\n if (this.closed) throw new Error('SysMetadataRepository is closed');\n }\n\n /**\n * Defense-in-depth authorization gate.\n *\n * `intent` defaults to `'override-artifact'` (the historical strict\n * behavior). The protocol layer passes `'runtime-only'` after it has\n * verified — via the schema registry — that no artifact item exists\n * at `(type, name)`. In that case we accept types with\n * `allowRuntimeCreate: true`, even when `allowOrgOverride` is false.\n *\n * The env-var escape hatch (`OS_METADATA_WRITABLE`) still\n * applies to BOTH intents, so operators can opt into artifact\n * overrides at runtime for emergency fixes.\n */\n private assertAllowed(type: string, intent: MetadataWriteIntent = 'override-artifact'): void {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n const allowedByRegistry = OVERLAY_ALLOWED_TYPES.has(singular) || OVERLAY_ALLOWED_TYPES.has(type);\n if (allowedByRegistry) return;\n\n // Two-tier extension: runtime-only writes target a brand-new\n // (artifact-free) item, so they only need `allowRuntimeCreate`.\n // Two cases qualify:\n // 1. Type is statically registered with `allowRuntimeCreate: true`.\n // 2. Type has NO static registry entry — it was added at runtime\n // by a plugin (e.g. `theme`, `api`, `connector`). The listing\n // endpoint synthesises `allowRuntimeCreate: true` for these,\n // so the write gate must accept them too. Otherwise the UI\n // would advertise a writable type that 403s on save.\n if (intent === 'runtime-only') {\n if (RUNTIME_CREATE_ALLOWED_TYPES.has(singular) || RUNTIME_CREATE_ALLOWED_TYPES.has(type)) {\n return;\n }\n if (!STATIC_REGISTRY_TYPES.has(singular) && !STATIC_REGISTRY_TYPES.has(type)) {\n return;\n }\n }\n\n // Phase 3a-env-writable: env-var escape hatch.\n const env = envWritableMetadataTypes();\n if (env.has(singular) || env.has(type)) return;\n\n const allowed = [\n ...OVERLAY_ALLOWED_TYPES,\n ...envWritableMetadataTypes(),\n ];\n const code = intent === 'runtime-only' ? 'not_creatable' : 'not_overridable';\n const detail = intent === 'runtime-only'\n ? `'${type}' has neither allowOrgOverride nor allowRuntimeCreate in the registry. `\n : `'${type}' is not allowOrgOverride in the registry. `;\n const err: any = new Error(\n `[${code}] ${detail}` +\n `Overlay-allowed: ${Array.from(new Set(allowed)).join(', ') || '(none)'}. ` +\n `Set OS_METADATA_WRITABLE to enable additional types at runtime.`,\n );\n err.code = code;\n err.status = 403;\n throw err;\n }\n\n private whereFor(\n ref: Pick<MetaRef, 'type' | 'name'>,\n state: OverlayState = 'active',\n ): Record<string, unknown> {\n return {\n type: ref.type,\n name: ref.name,\n organization_id: this.organizationId,\n state,\n };\n }\n\n private fullRef(ref: Pick<MetaRef, 'type' | 'name'>): MetaRef {\n return {\n org: this.orgLabel,\n type: ref.type,\n name: ref.name,\n };\n }\n\n private rowToItem(ref: Pick<MetaRef, 'type' | 'name'>, row: any): MetadataItem {\n const body: Record<string, unknown> =\n typeof row.metadata === 'string' ? JSON.parse(row.metadata) : (row.metadata ?? {});\n const hash: string = row.checksum ?? hashSpec(body);\n return {\n ref: this.fullRef(ref),\n body,\n hash,\n parentHash: null,\n authoredBy: row.updated_by ?? row.created_by ?? 'unknown',\n authoredAt: row.updated_at ?? row.created_at ?? new Date().toISOString(),\n message: undefined,\n seq: this.seqCounter,\n };\n }\n\n private broadcast(evt: MetadataEvent): void {\n for (const w of Array.from(this.watchers)) {\n try { w(evt); } catch { /* listener errors don't break the repo */ }\n }\n }\n\n private matchesFilter(evt: MetadataEvent, filter: WatchFilter): boolean {\n if (filter.type && evt.ref.type !== filter.type) return false;\n if (filter.name && evt.ref.name !== filter.name) return false;\n if (filter.org && evt.ref.org !== filter.org) return false;\n return true;\n }\n\n /**\n * Per-org monotonic event sequence. Reads `MAX(event_seq) + 1` from\n * `sys_metadata_history` scoped by `organization_id`. MUST be called\n * inside a transaction (the only caller is the put/delete txn body) —\n * concurrent writers in the same org race otherwise.\n */\n private async nextEventSeq(ctx: any): Promise<number> {\n try {\n const rows = await this.engine.find(this.historyTable, {\n where: { organization_id: this.organizationId },\n context: ctx,\n });\n let max = 0;\n for (const row of rows as Array<{ event_seq?: number | null }>) {\n const v = typeof row.event_seq === 'number' ? row.event_seq : 0;\n if (v > max) max = v;\n }\n return max + 1;\n } catch {\n // Table not provisioned yet (fresh DB) — start at 1.\n return 1;\n }\n }\n\n /**\n * Per-(org,type,name) lineage counter. Reads from history (not from\n * `sys_metadata.version`) so delete + recreate continues incrementing\n * instead of restarting at 1.\n */\n private async nextItemVersion(\n ref: Pick<MetaRef, 'type' | 'name'>,\n ctx: any,\n ): Promise<number> {\n try {\n const rows = await this.engine.find(this.historyTable, {\n where: {\n organization_id: this.organizationId,\n type: ref.type,\n name: ref.name,\n },\n context: ctx,\n });\n let max = 0;\n for (const row of rows as Array<{ version?: number | null }>) {\n const v = typeof row.version === 'number' ? row.version : 0;\n if (v > max) max = v;\n }\n return max + 1;\n } catch {\n return 1;\n }\n }\n\n /** Lightweight UUID-ish id for history rows; sufficient for an audit log. */\n private uuid(): string {\n if (typeof globalThis.crypto?.randomUUID === 'function') {\n return globalThis.crypto.randomUUID();\n }\n return `evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Load-time metadata diagnostics.\n *\n * Decorates metadata documents read from `getMetaItems()` /\n * `getMetaItem()` with a `_diagnostics` envelope so Studio (and any\n * other consumer) can render validity badges, inline field errors, and\n * governance dashboards without having to re-implement spec validation\n * on the client.\n *\n * Single source of truth: the same {@link getMetadataTypeSchema} that\n * the save path (`protocol.saveMetaItem` →\n * `resolveOverlaySchema().safeParse()`) and the JSON-Schema emitter\n * (`getMetaTypes() → entries[].schema`) already consult. Adding a new\n * metadata type's Zod schema in one place automatically wires it up\n * for read-time diagnostics, write-time validation, **and** Studio's\n * form renderer.\n *\n * Wire shape (`_diagnostics`) intentionally mirrors the existing\n * {@link MetadataValidationResult} type from\n * `@objectstack/spec/kernel` so consumers can share one type alias\n * across the validate / write / read surfaces.\n */\n\nimport type { z } from 'zod';\nimport { getMetadataTypeSchema } from '@objectstack/spec/kernel';\nimport type { MetadataValidationResult } from '@objectstack/spec/kernel';\nimport { PLURAL_TO_SINGULAR } from '@objectstack/spec/shared';\n\n/**\n * Re-export the canonical validation-result type so callers in this\n * package don't need to dual-import from `@objectstack/spec/kernel`.\n */\nexport type MetadataDiagnostics = MetadataValidationResult;\n\n/**\n * Compute spec diagnostics for a single metadata document.\n *\n * Returns `undefined` when the type has no registered Zod schema\n * (`function` / `service` / `router`, or any plugin type that has not\n * called `registerMetadataTypeSchema()`). Callers MUST treat that as\n * \"no opinion\" — not as \"valid\" — and either skip decoration entirely\n * or surface a `validatable: false` flag if their UI cares.\n */\nexport function computeMetadataDiagnostics(\n type: string,\n item: unknown,\n): MetadataDiagnostics | undefined {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n const schema = getMetadataTypeSchema(singular);\n if (!schema) return undefined;\n\n if (item === null || item === undefined || typeof item !== 'object') {\n return {\n valid: false,\n errors: [{\n path: '',\n message: 'Metadata document must be a non-null object',\n code: 'invalid_type',\n }],\n };\n }\n\n // Strip our own decoration before re-validating so it never becomes\n // a false-positive \"unrecognized_keys\" failure on schemas that grow\n // a `.strict()` mode in the future.\n const candidate = '_diagnostics' in (item as Record<string, unknown>)\n ? stripDiagnostics(item as Record<string, unknown>)\n : item;\n\n const parsed = (schema as z.ZodTypeAny).safeParse(candidate);\n if (parsed.success) {\n return { valid: true };\n }\n\n const errors = parsed.error.issues.map((issue) => ({\n path: issue.path.map(String).join('.'),\n message: issue.message,\n code: issue.code as string,\n }));\n\n return { valid: false, errors };\n}\n\nfunction stripDiagnostics(item: Record<string, unknown>): Record<string, unknown> {\n const { _diagnostics: _drop, ...rest } = item;\n void _drop;\n return rest;\n}\n\n/**\n * Attach `_diagnostics` to a single metadata item. Returns the item\n * unchanged when no diagnostics could be computed (unknown type) or\n * when the input is not an object.\n *\n * The returned reference is always a shallow copy when decoration\n * occurs — callers must not assume identity equality with the input.\n */\nexport function decorateMetadataItem<T>(type: string, item: T): T {\n if (!item || typeof item !== 'object') return item;\n const diagnostics = computeMetadataDiagnostics(type, item);\n if (!diagnostics) return item;\n return { ...(item as Record<string, unknown>), _diagnostics: diagnostics } as T;\n}\n\n/**\n * Decorate an array of metadata items. Non-array inputs and non-object\n * elements are returned unchanged, preserving the upstream defensive\n * \"items may be a wrapped or naked array\" contract documented in\n * `rest-server.ts`.\n */\nexport function decorateMetadataItems<T>(type: string, items: T[]): T[] {\n if (!Array.isArray(items)) return items;\n return items.map((item) => decorateMetadataItem(type, item));\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { QueryAST, HookContext, ServiceObject } from '@objectstack/spec/data';\nimport {\n EngineQueryOptions,\n DataEngineInsertOptions,\n EngineUpdateOptions,\n EngineDeleteOptions,\n EngineAggregateOptions,\n EngineCountOptions\n} from '@objectstack/spec/data';\nimport { ExecutionContext, ExecutionContextSchema } from '@objectstack/spec/kernel';\nimport { DriverInterface, IDataEngine, Logger, createLogger } from '@objectstack/core';\nimport { CoreServiceName, StorageNameMapping } from '@objectstack/spec/system';\nimport { IRealtimeService, RealtimeEventPayload } from '@objectstack/spec/contracts';\nimport type { ICryptoProvider, CryptoHandle } from '@objectstack/spec/contracts';\nimport {\n collectSecretFields,\n makeSecretRef,\n parseSecretRef,\n isSecretRef,\n SECRET_MASK,\n} from './secret-fields.js';\nimport { pluralToSingular, ExternalWriteForbiddenError } from '@objectstack/spec/shared';\nimport { SchemaRegistry, computeFQN } from './registry.js';\nimport { ExpressionEngine } from '@objectstack/formula';\nimport type { Expression } from '@objectstack/spec';\nimport { isAggregatedViewContainer, expandViewContainer } from '@objectstack/spec';\nimport { bindHooksToEngine } from './hook-binder.js';\nimport { validateRecord } from './validation/record-validator.js';\nimport { evaluateValidationRules, needsPriorRecord, stripReadonlyWhenFields } from './validation/rule-validator.js';\nimport { applyInMemoryAggregation } from './in-memory-aggregation.js';\n\ninterface FormulaPlanEntry { name: string; expression: Expression; }\n\nfunction planFormulaProjection(\n schema: any,\n requestedFields: string[] | undefined\n): { plan: FormulaPlanEntry[]; projected?: string[] } {\n if (!schema?.fields) return { plan: [] };\n const allFieldNames = Object.keys(schema.fields);\n // When no explicit projection, evaluate every formula field on the schema —\n // matches REST default of \"return everything\". Explicit projection still\n // honours the caller's selection.\n const targets = (Array.isArray(requestedFields) && requestedFields.length > 0)\n ? requestedFields\n : allFieldNames;\n const plan: FormulaPlanEntry[] = [];\n const projected = new Set<string>();\n for (const f of targets) {\n const def = (schema.fields as any)[f];\n if (def?.type === 'formula' && def.expression) {\n // Normalize string-shorthand → Expression envelope (M9 transition).\n const expr: Expression = typeof def.expression === 'string'\n ? { dialect: 'cel', source: def.expression }\n : def.expression;\n plan.push({ name: f, expression: expr });\n // Pre-compile to surface syntax errors at planning stage rather than\n // per-row eval. Dependency discovery (which fields the formula reads)\n // is no longer used — CEL uses dynamic projection via `record.<field>`.\n ExpressionEngine.compile(expr);\n } else if (Array.isArray(requestedFields) && requestedFields.length > 0) {\n projected.add(f);\n }\n }\n if (plan.length === 0) return { plan: [] };\n // For formulas: project all schema fields so CEL `record.<field>` lookups\n // see complete data. Static dependency analysis on AST is M9.7 work.\n if (Array.isArray(requestedFields) && requestedFields.length > 0) {\n if (!projected.has('id')) projected.add('id');\n for (const fname of allFieldNames) {\n // Skip formula fields themselves — they are virtual and not\n // projectable by the underlying driver. Without this guard the\n // SQL driver emits `SELECT response_rate ...` which fails as\n // \"no such column\" and the driver returns [] (silently).\n const fdef = (schema.fields as any)[fname];\n if (fdef?.type === 'formula') continue;\n projected.add(fname);\n }\n return { plan, projected: Array.from(projected) };\n }\n // Implicit/full projection — leave projected undefined so the driver\n // returns its default columns (typically *).\n return { plan };\n}\n\nfunction applyFormulaPlan(plan: FormulaPlanEntry[], records: any[]): void {\n if (!plan.length) return;\n for (const rec of records) {\n if (rec == null) continue;\n for (const fp of plan) {\n const r = ExpressionEngine.evaluate(fp.expression, { record: rec });\n rec[fp.name] = r.ok ? r.value : null;\n }\n }\n}\n\nexport type HookHandler = (context: HookContext) => Promise<void> | void;\n\n/**\n * Per-object hook entry with priority support\n */\nexport interface HookEntry {\n handler: HookHandler;\n object?: string | string[]; // undefined = global hook\n priority: number;\n packageId?: string;\n /**\n * Original metadata-form `Hook` definition this entry was bound from\n * (when registered via `bindHooksToEngine`). Pure code-paths that call\n * `engine.registerHook` directly leave this undefined.\n */\n meta?: any;\n /** Hook `name` from metadata; used for diagnostics & deduplication. */\n hookName?: string;\n}\n\n/** Function registry entry — see `registerFunction`. */\ninterface FunctionEntry {\n handler: HookHandler;\n packageId?: string;\n}\n\n/**\n * Operation Context for Middleware Chain\n */\nexport interface OperationContext {\n object: string;\n operation: 'find' | 'findOne' | 'insert' | 'update' | 'delete' | 'count' | 'aggregate';\n ast?: QueryAST;\n data?: any;\n options?: any;\n context?: ExecutionContext;\n result?: any;\n}\n\n/**\n * Engine Middleware (Onion model)\n */\nexport type EngineMiddleware = (\n ctx: OperationContext,\n next: () => Promise<void>\n) => Promise<void>;\n\n/**\n * Host Context provided to plugins (Internal ObjectQL Plugin System)\n */\nexport interface ObjectQLHostContext {\n ql: ObjectQL;\n logger: Logger;\n // Extensible map for host-specific globals (like HTTP Router, etc.)\n [key: string]: any;\n}\n\n/**\n * Derive the registry key for a metadata item.\n *\n * Most metadata items expose a top-level `name` (or `id`). The `View`\n * container defined by `@objectstack/spec/ui` is special: it aggregates\n * `list / form / listViews / formViews` for a single object and is\n * keyed implicitly by its target object name (see `data.object`).\n *\n * Per spec, `ViewSchema` does NOT have a top-level `name` field\n * (view.zod.ts), so we resolve it from the inner data source. This\n * matches the server-side metadata API contract (`/api/v1/meta/views/:object`).\n */\nfunction resolveMetadataItemName(key: string, item: any): string | undefined {\n if (!item) return undefined;\n if (item.name) return item.name;\n if (item.id) return item.id;\n if (key === 'views') {\n // Independent ViewItems (\"Object has-many View\") carry a top-level `name`\n // (handled above) and bind to their object via `object`. The aggregated\n // container has no top-level name/object, so fall back to its inner data\n // source — matching the loader's expansion key.\n return (\n item?.object ||\n item?.list?.data?.object ||\n item?.form?.data?.object ||\n undefined\n );\n }\n return undefined;\n}\n\n/**\n * ObjectQL Engine\n * \n * Implements the IDataEngine interface for data persistence.\n * Acts as the reference implementation for:\n * - CoreServiceName.data (CRUD)\n * - CoreServiceName.metadata (Schema Registry)\n */\n/** A roll-up `summary` field on a parent object that aggregates a child. */\ninterface SummaryDescriptor {\n parentObject: string;\n summaryField: string;\n /** FK field on the child pointing back to the parent. */\n fkField: string;\n fn: 'count' | 'sum' | 'min' | 'max' | 'avg';\n /** Child field aggregated (unused for count). */\n sourceField: string;\n}\n\nexport class ObjectQL implements IDataEngine {\n /**\n * Ambient transaction store (ADR-0034). While a `transaction()` callback\n * runs, the active transaction handle lives here so that EVERY data\n * operation — including internal reads done during a write (reference\n * checks, hooks, expand) — automatically binds to the same connection\n * instead of asking the pool for another one and deadlocking on the\n * single-connection SQLite pool.\n */\n private readonly txStore = new AsyncLocalStorage<{ transaction: unknown }>();\n\n private drivers = new Map<string, DriverInterface>();\n private defaultDriver: string | null = null;\n private logger: Logger;\n\n // Datasource mapping rules (imported from defineStack)\n private datasourceMapping: Array<{\n namespace?: string;\n package?: string;\n objectPattern?: string;\n default?: boolean;\n datasource: string;\n priority?: number;\n }> = [];\n\n // Package manifests registry (for defaultDatasource lookup)\n private manifests = new Map<string, any>();\n\n // Datasource definitions by name (ADR-0015): carries schemaMode +\n // external.allowWrites so the write gate (Gate 3) can enforce federation\n // ownership. Populated from manifests in registerApp and via\n // registerDatasourceDef. Absent entry ⇒ treated as managed (default DB).\n private datasourceDefs = new Map<string, { schemaMode?: string; external?: { allowWrites?: boolean } }>();\n\n // Per-object hooks with priority support\n private hooks: Map<string, HookEntry[]> = new Map([\n ['beforeFind', []], ['afterFind', []],\n ['beforeInsert', []], ['afterInsert', []],\n ['beforeUpdate', []], ['afterUpdate', []],\n ['beforeDelete', []], ['afterDelete', []],\n ]);\n\n // Middleware chain (onion model)\n private middlewares: Array<{\n fn: EngineMiddleware;\n object?: string;\n }> = [];\n\n // Action registry: key = \"objectName:actionName\"\n private actions = new Map<string, { handler: (ctx: any) => Promise<any> | any; package?: string }>();\n\n // Function registry: name → handler. Used by `bindHooksToEngine` to\n // resolve string-named hook handlers (the JSON-safe form). Populated by\n // `defineStack({ functions })` via `AppPlugin`, or directly via\n // `engine.registerFunction(...)`.\n private functions = new Map<string, FunctionEntry>();\n\n // Host provided context additions (e.g. Server router)\n private hostContext: Record<string, any> = {};\n\n // Realtime service for event publishing\n private realtimeService?: IRealtimeService;\n\n // Crypto provider backing `secret`-typed fields. Optional: when absent,\n // writing an object that declares a secret field fails closed (never\n // persists cleartext). Injected by the host via setCryptoProvider().\n private cryptoProvider?: ICryptoProvider;\n\n // Per-engine SchemaRegistry instance.\n //\n // Historically SchemaRegistry was a process-wide singleton of static state,\n // which broke multi-environment servers: a project kernel would inherit every\n // object registered by the control plane (e.g. sys_metadata), and\n // getDriver()'s owner lookup would route CRUD to the wrong database. Each\n // engine now owns its registry so kernels are fully isolated.\n private _registry: SchemaRegistry = new SchemaRegistry();\n\n constructor(hostContext: Record<string, any> = {}) {\n this.hostContext = hostContext;\n // Use provided logger or create a new one\n this.logger = hostContext.logger || createLogger({ level: 'info', format: 'pretty' });\n // Pick up production hardening switches from env so deployers can\n // enforce strict-body without code changes:\n // OBJECTQL_STRICT_HOOKS=1 → unresolved hooks throw at bind time\n // OBJECTQL_WARN_LEGACY_HANDLER=1 → log a deprecation per legacy bind\n if (process?.env?.OBJECTQL_STRICT_HOOKS === '1') {\n (this as any)._strictHookBinding = true;\n }\n if (process?.env?.OBJECTQL_WARN_LEGACY_HANDLER === '1') {\n (this as any)._warnLegacyHandler = true;\n }\n this.logger.info('ObjectQL Engine Instance Created');\n }\n\n /**\n * Service Status Report\n * Used by Kernel to verify health and capabilities.\n */\n getStatus() {\n return {\n name: CoreServiceName.enum.data,\n status: 'running',\n version: '0.9.0',\n features: ['crud', 'query', 'aggregate', 'transactions', 'metadata']\n };\n }\n\n /**\n * Expose the SchemaRegistry for plugins to register metadata.\n *\n * Returns the per-engine instance, NOT the class. Each ObjectQL engine\n * owns its registry so multi-environment kernels remain isolated.\n */\n get registry(): SchemaRegistry {\n return this._registry;\n }\n\n /**\n * Load and Register a Plugin\n */\n async use(manifestPart: any, runtimePart?: any) {\n this.logger.debug('Loading plugin', { \n hasManifest: !!manifestPart, \n hasRuntime: !!runtimePart \n });\n\n // 1. Validate / Register Manifest\n if (manifestPart) {\n this.registerApp(manifestPart);\n }\n\n // 2. Execute Runtime\n if (runtimePart) {\n const pluginDef = (runtimePart as any).default || runtimePart;\n if (pluginDef.onEnable) {\n this.logger.debug('Executing plugin runtime onEnable');\n \n const context: ObjectQLHostContext = {\n ql: this,\n logger: this.logger,\n // Expose the driver registry helper explicitly if needed\n drivers: {\n register: (driver: DriverInterface) => this.registerDriver(driver)\n },\n ...this.hostContext\n };\n \n await pluginDef.onEnable(context);\n this.logger.debug('Plugin runtime onEnable completed');\n }\n }\n }\n\n /**\n * Register a hook\n * @param event The event name (e.g. 'beforeFind', 'afterInsert')\n * @param handler The handler function\n * @param options Optional: target object(s) and priority\n */\n registerHook(event: string, handler: HookHandler, options?: {\n object?: string | string[];\n priority?: number;\n packageId?: string;\n /** Original metadata Hook definition (set by `bindHooksToEngine`). */\n meta?: any;\n /** Stable name from metadata (set by `bindHooksToEngine`). */\n hookName?: string;\n }) {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n const entries = this.hooks.get(event)!;\n entries.push({\n handler,\n object: options?.object,\n priority: options?.priority ?? 100,\n packageId: options?.packageId,\n meta: options?.meta,\n hookName: options?.hookName,\n });\n // Sort by priority (lower runs first)\n entries.sort((a, b) => a.priority - b.priority);\n this.logger.debug('Registered hook', { event, object: options?.object, priority: options?.priority ?? 100, totalHandlers: entries.length });\n }\n\n /**\n * Remove all hooks registered under a given `packageId`. Used by\n * `bindHooksToEngine` to make re-binding (hot reload, app reinstall)\n * idempotent, and by app uninstall flows.\n */\n unregisterHooksByPackage(packageId: string): number {\n if (!packageId) return 0;\n let removed = 0;\n for (const [event, entries] of this.hooks.entries()) {\n const before = entries.length;\n const kept = entries.filter((e) => e.packageId !== packageId);\n if (kept.length !== before) {\n this.hooks.set(event, kept);\n removed += before - kept.length;\n }\n }\n if (removed > 0) {\n this.logger.debug('Unregistered hooks by package', { packageId, removed });\n }\n return removed;\n }\n\n /**\n * Register a named function handler that can later be referenced by\n * string from a `Hook.handler` field. This is the JSON-safe form of\n * handler binding — declarative metadata persisted to disk or shipped\n * over the wire only carries the name.\n */\n registerFunction(name: string, handler: HookHandler, packageId?: string): void {\n if (!name || typeof handler !== 'function') return;\n this.functions.set(name, { handler, packageId });\n this.logger.debug('Registered function', { name, packageId });\n }\n\n /** Look up a registered function by name. */\n resolveFunction(name: string): HookHandler | undefined {\n return this.functions.get(name)?.handler;\n }\n\n /** Remove all functions registered under a given `packageId`. */\n unregisterFunctionsByPackage(packageId: string): number {\n if (!packageId) return 0;\n let removed = 0;\n for (const [name, entry] of this.functions.entries()) {\n if (entry.packageId === packageId) {\n this.functions.delete(name);\n removed += 1;\n }\n }\n if (removed > 0) {\n this.logger.debug('Unregistered functions by package', { packageId, removed });\n }\n return removed;\n }\n\n /**\n * Bind a list of declarative `Hook` metadata definitions to this engine.\n *\n * Convenience proxy to the canonical `bindHooksToEngine` so callers do\n * not need a separate import. Use `import { bindHooksToEngine } from\n * '@objectstack/objectql'` directly when you want the result object.\n */\n bindHooks(hooks: any[] | undefined, opts?: {\n packageId?: string;\n functions?: Record<string, HookHandler>;\n bodyRunner?: any;\n strict?: boolean;\n warnLegacyHandler?: boolean;\n metrics?: any;\n }): void {\n const merged = { ...(opts ?? {}), logger: this.logger } as any;\n if (!merged.bodyRunner && (this as any)._defaultBodyRunner) {\n merged.bodyRunner = (this as any)._defaultBodyRunner;\n }\n if (merged.strict === undefined && (this as any)._strictHookBinding) {\n merged.strict = true;\n }\n if (merged.warnLegacyHandler === undefined && (this as any)._warnLegacyHandler) {\n merged.warnLegacyHandler = true;\n }\n if (!merged.metrics && (this as any)._hookMetricsRecorder) {\n merged.metrics = (this as any)._hookMetricsRecorder;\n }\n bindHooksToEngine(this, hooks, merged);\n }\n\n /**\n * Install a default body-runner used when `bindHooks` is called without\n * an explicit one. The runtime layer sets this once on each per-project\n * engine so every binding path (template seed, metadata sync, AppPlugin)\n * can execute hook `body.source` consistently.\n */\n setDefaultBodyRunner(runner: any): void {\n (this as any)._defaultBodyRunner = runner;\n }\n\n /**\n * Toggle strict hook-binding mode for this engine. When enabled, every\n * subsequent `bindHooks` call rejects on the first unresolved hook\n * instead of silently warning. Production runtimes should enable this.\n */\n setStrictHookBinding(strict: boolean): void {\n (this as any)._strictHookBinding = strict;\n }\n\n /** Toggle deprecation warnings for hooks still using legacy `handler` ref. */\n setWarnLegacyHandler(warn: boolean): void {\n (this as any)._warnLegacyHandler = warn;\n }\n\n /**\n * Install a metrics recorder used by every subsequent `bindHooks` call.\n * The recorder's methods are invoked per-execution to count outcomes\n * (success / error / timeout / capability_rejected), skips, and retries.\n * Defaults to no-op so the engine pays zero cost when nobody is observing.\n */\n setHookMetricsRecorder(recorder: any): void {\n (this as any)._hookMetricsRecorder = recorder;\n }\n\n /** Read the engine's installed metrics recorder, if any. */\n getHookMetricsRecorder(): any {\n return (this as any)._hookMetricsRecorder;\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const entries = this.hooks.get(event) || [];\n \n if (entries.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: entries.length });\n \n for (const entry of entries) {\n // Per-object matching\n if (entry.object) {\n const targets = Array.isArray(entry.object) ? entry.object : [entry.object];\n if (!targets.includes('*') && !targets.includes(context.object)) {\n continue; // Skip non-matching hooks\n }\n }\n await entry.handler(context);\n }\n }\n\n // ========================================\n // Action System\n // ========================================\n\n /**\n * Register a named action on an object.\n * Actions are custom business logic callable via `repo.execute(actionName, params)`.\n *\n * @param objectName Target object\n * @param actionName Unique action name within the object\n * @param handler Handler function\n * @param packageName Optional package owner (for cleanup)\n */\n registerAction(objectName: string, actionName: string, handler: (ctx: any) => Promise<any> | any, packageName?: string): void {\n const key = `${objectName}:${actionName}`;\n this.actions.set(key, { handler, package: packageName });\n this.logger.debug('Registered action', { objectName, actionName, package: packageName });\n }\n\n /**\n * Execute a named action on an object.\n */\n async executeAction(objectName: string, actionName: string, ctx: any): Promise<any> {\n const entry = this.actions.get(`${objectName}:${actionName}`);\n if (!entry) {\n throw new Error(`Action '${actionName}' on object '${objectName}' not found`);\n }\n return entry.handler(ctx);\n }\n\n /**\n * Remove all actions registered by a specific package.\n */\n removeActionsByPackage(packageName: string): void {\n for (const [key, entry] of this.actions.entries()) {\n if (entry.package === packageName) {\n this.actions.delete(key);\n }\n }\n }\n\n /**\n * Register a middleware function\n * Middlewares execute in onion model around every data operation.\n * @param fn The middleware function\n * @param options Optional: target object filter\n */\n registerMiddleware(fn: EngineMiddleware, options?: { object?: string }): void {\n this.middlewares.push({ fn, object: options?.object });\n this.logger.debug('Registered middleware', { object: options?.object, total: this.middlewares.length });\n }\n\n /**\n * Execute an operation through the middleware chain\n */\n private async executeWithMiddleware(ctx: OperationContext, executor: () => Promise<any>): Promise<any> {\n const applicable = this.middlewares.filter(m =>\n !m.object || m.object === '*' || m.object === ctx.object\n );\n\n let index = 0;\n const next = async (): Promise<void> => {\n if (index < applicable.length) {\n const mw = applicable[index++];\n await mw.fn(ctx, next);\n } else {\n ctx.result = await executor();\n }\n };\n\n await next();\n return ctx.result;\n }\n\n /**\n * Build a HookContext.session from ExecutionContext\n */\n private buildSession(execCtx?: ExecutionContext): HookContext['session'] {\n if (!execCtx) return undefined;\n return {\n userId: execCtx.userId,\n tenantId: execCtx.tenantId,\n roles: execCtx.roles,\n accessToken: execCtx.accessToken,\n // Propagate system-elevated flag so hooks can distinguish engine\n // self-writes (e.g. approval status mirror) from genuine user writes.\n ...((execCtx as any).isSystem ? { isSystem: true } : {}),\n } as HookContext['session'];\n }\n\n /**\n * Build the DriverOptions blob passed to every IDataDriver call.\n *\n * Always carries `tenantId` from the active ExecutionContext so the\n * driver can enforce per-tenant isolation (SQL driver auto-scopes reads\n * and auto-injects the tenant column on writes). Existing user-supplied\n * shapes (transactions, AST extras) are preserved by spreading them\n * first.\n *\n * System / isSystem callers may still cross tenants by clearing\n * `tenantId` themselves on the resulting object; this helper does not\n * mask the system path.\n */\n private buildDriverOptions(execCtx?: ExecutionContext, base?: any): any {\n // The open transaction may arrive explicitly via the context, or ambiently\n // via txStore when an internal query runs during a transactional write\n // (ADR-0034). Explicit wins; ambient is the safety net.\n const tx = execCtx?.transaction !== undefined\n ? execCtx.transaction\n : this.txStore.getStore()?.transaction;\n const hasTx = tx !== undefined;\n const hasTenant = execCtx?.tenantId !== undefined;\n const isSystem = execCtx?.isSystem === true;\n if (!hasTx && !hasTenant && !isSystem) return base;\n const opts: any = base && typeof base === 'object' ? { ...base } : {};\n if (hasTx && opts.transaction === undefined) {\n opts.transaction = tx;\n }\n if (hasTenant && opts.tenantId === undefined) {\n opts.tenantId = execCtx!.tenantId;\n }\n if (isSystem && opts.bypassTenantAudit === undefined) {\n // System-elevated writes (boot-time seeds, internal mirrors, scheduled\n // hooks) are unscoped by design — silence the audit warn for them but\n // still flag genuine user-path bugs.\n opts.bypassTenantAudit = true;\n }\n return opts;\n }\n\n /**\n * Build a HookContext.api: a ScopedContext that hooks can use to\n * read/write other objects within the same execution context.\n * Falls back to a system-elevated empty context when no execCtx\n * is supplied (e.g. system-triggered hooks).\n */\n private buildHookApi(execCtx?: ExecutionContext): ScopedContext {\n const safeCtx: ExecutionContext = execCtx ?? ({ isSystem: true } as any);\n return new ScopedContext(safeCtx, this as unknown as IDataEngine);\n }\n\n /**\n * Apply field defaults to an incoming insert payload. Defaults that are\n * Expression envelopes (e.g. `{ dialect: 'cel', source: 'today()' }`,\n * `{ dialect: 'cel', source: 'os.user.id' }`) are evaluated via\n * `ExpressionEngine` against the calling user/org/now snapshot. Static\n * defaults are applied verbatim. Records that already supplied a value for a\n * field are left untouched.\n *\n * Implements ROADMAP §M9.9b — `defaultValue` accepts Expression so authors\n * can replace \"write a hook to default to today/current-user\" with a\n * declarative `defaultValue: cel\\`today()\\``.\n */\n private applyFieldDefaults(\n object: string,\n record: Record<string, unknown>,\n execCtx?: ExecutionContext,\n nowSnapshot?: Date,\n ): Record<string, unknown> {\n const schema = this.getSchema(object);\n const fieldsRaw = (schema as any)?.fields;\n if (!fieldsRaw || typeof fieldsRaw !== 'object') return record;\n // `fields` may be a Record<string, Field> (canonical) or an array (legacy).\n const fieldEntries: Array<{ name: string; defaultValue?: unknown }> = Array.isArray(fieldsRaw)\n ? fieldsRaw\n : Object.entries(fieldsRaw).map(([name, def]) => ({ name, ...(def as object) }));\n const out = { ...record };\n const now = nowSnapshot ?? new Date();\n for (const f of fieldEntries) {\n if (out[f.name] !== undefined) continue;\n if (f.defaultValue == null) continue;\n const dv = f.defaultValue;\n if (typeof dv === 'object' && dv !== null && (dv as any).dialect && typeof (dv as any).source === 'string') {\n const result = ExpressionEngine.evaluate(dv as any, {\n now,\n user: execCtx?.userId ? { id: String(execCtx.userId), role: execCtx?.roles?.[0] } : undefined,\n org: execCtx?.tenantId ? { id: String(execCtx.tenantId) } : undefined,\n record: out,\n extra: { object },\n });\n if (result.ok) {\n out[f.name] = result.value as unknown;\n } else {\n this.logger.warn('Failed to evaluate default expression', {\n object, field: f.name, error: result.error,\n });\n }\n } else {\n out[f.name] = dv;\n }\n }\n return out;\n }\n\n /**\n * Generate values for empty `autonumber` fields on insert — ONLY for drivers\n * that do not generate them natively (memory, mongodb). For SQL-backed objects\n * the driver owns a persistent, atomic `_objectstack_sequences` table and\n * advertises `supports.autonumber === true`; the engine then defers entirely\n * and never pre-fills (so the persistent sequence is the single source of\n * truth — see #1603). Required-validation exempts `autonumber` either way, so\n * a `required` record number is never rejected for \"missing\" — the runtime\n * owns the value, not the client.\n *\n * In the fallback path the next value is `max(existing) + 1`, seeded once per\n * `object.field` from the store then incremented in memory (monotonic within\n * the process, resilient to deletions). `autonumberFormat` is honored, e.g.\n * `CASE-{0000}` → `CASE-0042`. NOTE: this in-memory seeding is single-instance.\n */\n private async applyAutonumbers(\n object: string,\n record: Record<string, unknown>,\n execCtx?: ExecutionContext,\n driverOwnsAutonumber?: boolean,\n ): Promise<void> {\n if (driverOwnsAutonumber) return; // driver generates persistently in create()\n const fields = (this.getSchema(object) as any)?.fields;\n if (!fields || typeof fields !== 'object' || Array.isArray(fields)) return;\n for (const [name, def] of Object.entries(fields)) {\n if ((def as any)?.type !== 'autonumber') continue;\n const current = record[name];\n if (current != null && current !== '') continue; // respect explicit value\n const key = `${object}.${name}`;\n let next = this.autonumberCounters.get(key);\n if (next == null) next = await this.seedAutonumber(object, name, execCtx);\n next += 1;\n this.autonumberCounters.set(key, next);\n // Honor either the spec-canonical `autonumberFormat` or the shorthand\n // `format` (both appear in metadata; the driver reads both too) — #1603.\n const fmt = (def as any).autonumberFormat ?? (def as any).format;\n record[name] = this.formatAutonumber(fmt, next);\n }\n }\n\n /** Seed the autonumber counter from the current max numeric value in store. */\n private async seedAutonumber(\n object: string,\n field: string,\n execCtx?: ExecutionContext,\n ): Promise<number> {\n try {\n const rows = await this.find(object, {\n select: ['id', field],\n limit: 5000,\n context: execCtx,\n } as any);\n let max = 0;\n for (const r of rows || []) {\n const v = r?.[field];\n if (v == null) continue;\n const m = String(v).match(/(\\d+)(?!.*\\d)/); // last run of digits\n if (m) max = Math.max(max, parseInt(m[1], 10) || 0);\n }\n return max;\n } catch {\n return 0;\n }\n }\n\n /** Apply an autonumber format like `CASE-{0000}`; default to the bare number. */\n private formatAutonumber(format: string | undefined, value: number): string {\n if (!format) return String(value);\n const m = format.match(/\\{(0+)\\}/);\n if (!m) return format.includes('{0}') ? format.replace('{0}', String(value)) : `${format}${value}`;\n const padded = String(value).padStart(m[1].length, '0');\n return format.replace(m[0], padded);\n }\n\n /**\n * Register contribution (Manifest)\n * \n * Installs the manifest as a Package (the unit of installation),\n * then decomposes it into individual metadata items (objects, apps, actions, etc.)\n * and registers each into the SchemaRegistry.\n * \n * Key: Package ≠ App. The manifest is the package. The apps[] array inside\n * the manifest contains UI navigation definitions (AppSchema).\n */\n registerApp(manifest: any) {\n const id = manifest.id || manifest.name;\n const namespace = manifest.namespace as string | undefined;\n this.invalidateSummaryIndex(); // new objects may add/change summary fields\n this.logger.debug('Registering package manifest', { id, namespace });\n console.warn(`[ObjectQL:registerApp] id=${id} flows=${Array.isArray(manifest.flows) ? manifest.flows.length : typeof manifest.flows} keys=${Object.keys(manifest).join(',')}`);\n\n // Store manifest for defaultDatasource lookup\n if (id) {\n this.manifests.set(id, manifest);\n }\n\n // Index datasource definitions (ADR-0015) so the write gate can read\n // schemaMode + external.allowWrites. Manifests may carry `datasources`\n // as an array or a name-keyed map.\n if (manifest.datasources) {\n const dsList = Array.isArray(manifest.datasources)\n ? manifest.datasources\n : Object.entries(manifest.datasources).map(([name, def]) => ({ name, ...(def as any) }));\n for (const ds of dsList) {\n if (ds?.name) this.registerDatasourceDef(ds);\n }\n }\n\n // 1. Register the Package (manifest + lifecycle state)\n this._registry.installPackage(manifest);\n this.logger.debug('Installed Package', { id: manifest.id, name: manifest.name, namespace });\n\n // 2. Register owned objects\n if (manifest.objects) {\n if (Array.isArray(manifest.objects)) {\n this.logger.debug('Registering objects from manifest (Array)', { id, objectCount: manifest.objects.length });\n for (const objDef of manifest.objects) {\n const fqn = this._registry.registerObject(objDef, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n } else {\n this.logger.debug('Registering objects from manifest (Map)', { id, objectCount: Object.keys(manifest.objects).length });\n for (const [name, objDef] of Object.entries(manifest.objects)) {\n // Ensure name in definition matches key\n (objDef as any).name = name;\n const fqn = this._registry.registerObject(objDef as any, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n }\n }\n\n // 2b. Register object extensions (fields added to objects owned by other packages)\n if (Array.isArray(manifest.objectExtensions) && manifest.objectExtensions.length > 0) {\n this.logger.debug('Registering object extensions', { id, count: manifest.objectExtensions.length });\n for (const ext of manifest.objectExtensions) {\n const targetFqn = ext.extend;\n const priority = ext.priority ?? 200;\n // Create a partial object definition for the extension\n const extDef = {\n name: targetFqn, // Use the target FQN as name\n fields: ext.fields,\n label: ext.label,\n pluralLabel: ext.pluralLabel,\n description: ext.description,\n validations: ext.validations,\n indexes: ext.indexes,\n };\n // Register as extension (namespace is undefined since we're targeting by FQN)\n this._registry.registerObject(extDef as any, id, undefined, 'extend', priority);\n this.logger.debug('Registered Object Extension', { target: targetFqn, priority, from: id });\n }\n }\n\n // 3. Register apps (UI navigation definitions) as their own metadata type\n // Resolve short objectName references in navigation to FQN so the\n // Console UI can match them against the object registry.\n if (Array.isArray(manifest.apps) && manifest.apps.length > 0) {\n this.logger.debug('Registering apps from manifest', { id, count: manifest.apps.length });\n for (const app of manifest.apps) {\n const appName = app.name || app.id;\n if (appName) {\n const resolved = namespace ? this.resolveNavObjectNames(app, namespace) : app;\n this._registry.registerApp(resolved, id);\n this.logger.debug('Registered App', { app: appName, from: id });\n }\n }\n }\n\n // 4. If manifest itself looks like an App (has navigation), also register as app\n // This handles the case where the manifest IS the app definition (legacy/simple packages)\n if (manifest.name && manifest.navigation && !manifest.apps?.length) {\n const resolved = namespace ? this.resolveNavObjectNames(manifest, namespace) : manifest;\n this._registry.registerApp(resolved, id);\n this.logger.debug('Registered manifest-as-app', { app: manifest.name, from: id });\n }\n\n // 4b. Register navigation contributions (ADR-0029 D7) — nav items this\n // package injects into apps owned by other packages (e.g. a\n // capability plugin adding its menu into the `setup` app). Merged\n // into the target app's navigation on read by group id + priority.\n if (Array.isArray((manifest as any).navigationContributions) && (manifest as any).navigationContributions.length > 0) {\n for (const contribution of (manifest as any).navigationContributions) {\n this._registry.registerAppNavContribution(contribution, id);\n }\n this.logger.debug('Registered navigation contributions', {\n from: id,\n count: (manifest as any).navigationContributions.length,\n });\n }\n\n // 5. Register all other metadata types generically\n const metadataArrayKeys = [\n // UI Protocol\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'datasets', 'themes',\n // Automation Protocol\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'jobs',\n // Security Protocol\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n // AI Protocol\n 'agents', 'tools', 'skills', 'ragPipelines',\n // API Protocol\n 'apis',\n // Data Extensions\n 'hooks', 'mappings', 'analyticsCubes',\n // Integration Protocol\n 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (manifest as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n this.logger.debug(`Registering ${key} from manifest`, { id, count: items.length });\n for (const item of items) {\n const itemName = resolveMetadataItemName(key, item);\n if (itemName) {\n const toRegister = item.name === itemName ? item : { ...item, name: itemName };\n this._registry.registerItem(pluralToSingular(key), toRegister, 'name' as any, id);\n // \"Object has-many View\" (ADR-0017): a `defineView` document\n // aggregates an object's views. Register the container under\n // the bare <object> key (above, back-compat) AND expand it\n // into independent ViewItems registered under <object>.<key>,\n // so `getViewsByObject()` / `GET /meta/view?object=` surface\n // the per-view `package` layer the switcher + Studio consume.\n if (key === 'views' && isAggregatedViewContainer(toRegister)) {\n for (const vi of expandViewContainer(itemName, toRegister)) {\n this._registry.registerItem('view', vi, 'name' as any, id);\n }\n }\n } else {\n this.logger.warn(`Skipping ${pluralToSingular(key)} without a derivable name`, { id });\n }\n }\n }\n }\n\n // 6. Register seed data as metadata (keyed by target object name)\n const seedData = (manifest as any).data;\n if (Array.isArray(seedData) && seedData.length > 0) {\n this.logger.debug('Registering seed data datasets', { id, count: seedData.length });\n for (const dataset of seedData) {\n if (dataset.object) {\n this._registry.registerItem('data', dataset, 'object' as any, id);\n }\n }\n }\n\n // 6. Register contributions\n if (manifest.contributes?.kinds) {\n this.logger.debug('Registering kinds from manifest', { id, kindCount: manifest.contributes.kinds.length });\n for (const kind of manifest.contributes.kinds) {\n this._registry.registerKind(kind);\n this.logger.debug('Registered Kind', { kind: kind.name || kind.type, from: id });\n }\n }\n\n // 7. Recursively register nested plugins\n if (Array.isArray(manifest.plugins) && manifest.plugins.length > 0) {\n this.logger.debug('Processing nested plugins', { id, count: manifest.plugins.length });\n for (const plugin of manifest.plugins) {\n if (plugin && typeof plugin === 'object') {\n const pluginName = plugin.name || plugin.id || 'unnamed-plugin';\n this.logger.debug('Registering nested plugin', { pluginName, parentId: id });\n this.registerPlugin(plugin, id, namespace);\n }\n }\n }\n }\n\n /**\n * Deep-clone an app definition, resolving objectName references in navigation\n * items via the registry. Object names are canonical identifiers — no FQN\n * expansion is applied.\n */\n private resolveNavObjectNames(app: any, namespace: string): any {\n if (!app.navigation) return app;\n\n const resolveItems = (items: any[]): any[] =>\n items.map((item: any) => {\n const resolved = { ...item };\n if (resolved.objectName && !resolved.objectName.includes('__')) {\n resolved.objectName = computeFQN(namespace, resolved.objectName);\n }\n if (Array.isArray(resolved.children)) {\n resolved.children = resolveItems(resolved.children);\n }\n return resolved;\n });\n\n return { ...app, navigation: resolveItems(app.navigation) };\n }\n\n /**\n * Register a nested plugin's metadata (objects, actions, views, etc.)\n *\n * Unlike registerApp(), this does NOT call SchemaRegistry.installPackage()\n * because plugins are not formal manifests — they are lightweight config\n * bundles with objects, actions, triggers, and navigation.\n *\n * @param plugin - The plugin config object\n * @param parentId - The parent package ID (for ownership tracking)\n * @param parentNamespace - The parent package's namespace (for FQN resolution)\n */\n private registerPlugin(plugin: any, parentId: string, parentNamespace?: string) {\n const pluginName = plugin.name || plugin.id || 'unnamed';\n const pluginNamespace = plugin.namespace || parentNamespace;\n\n // Use parentId as the owning package for namespace consistency.\n // The parent package already claimed the namespace — nested plugins\n // contribute objects UNDER the parent's ownership.\n const ownerId = parentId;\n\n // Register objects (supports both Array and Map formats)\n if (plugin.objects) {\n try {\n if (Array.isArray(plugin.objects)) {\n this.logger.debug('Registering plugin objects (Array)', { pluginName, count: plugin.objects.length });\n for (const objDef of plugin.objects) {\n const fqn = this._registry.registerObject(objDef, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n } else {\n const entries = Object.entries(plugin.objects);\n this.logger.debug('Registering plugin objects (Map)', { pluginName, count: entries.length });\n for (const [name, objDef] of entries) {\n (objDef as any).name = name;\n const fqn = this._registry.registerObject(objDef as any, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n }\n } catch (err: any) {\n this.logger.warn('Failed to register plugin objects', { pluginName, error: err.message });\n }\n }\n\n // Register plugin as app if it has navigation (for sidebar display)\n if (plugin.name && plugin.navigation) {\n try {\n const resolved = pluginNamespace ? this.resolveNavObjectNames(plugin, pluginNamespace) : plugin;\n this._registry.registerApp(resolved, ownerId);\n this.logger.debug('Registered plugin-as-app', { app: plugin.name, from: pluginName });\n } catch (err: any) {\n this.logger.warn('Failed to register plugin as app', { pluginName, error: err.message });\n }\n }\n\n // Register metadata arrays (actions, views, triggers, etc.)\n const metadataArrayKeys = [\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'datasets', 'themes',\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n 'agents', 'ragPipelines', 'apis',\n 'hooks', 'mappings', 'analyticsCubes', 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (plugin as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n for (const item of items) {\n const itemName = resolveMetadataItemName(key, item);\n if (itemName) {\n const toRegister = item.name === itemName ? item : { ...item, name: itemName };\n this._registry.registerItem(pluralToSingular(key), toRegister, 'name' as any, ownerId);\n }\n }\n }\n }\n }\n\n /**\n * Register a new storage driver\n */\n registerDriver(driver: DriverInterface, isDefault: boolean = false) {\n if (this.drivers.has(driver.name)) {\n this.logger.warn('Driver already registered, skipping', { driverName: driver.name });\n return;\n }\n\n this.drivers.set(driver.name, driver);\n this.logger.info('Registered driver', {\n driverName: driver.name,\n version: driver.version\n });\n\n if (isDefault || this.drivers.size === 1) {\n this.defaultDriver = driver.name;\n this.logger.info('Set default driver', { driverName: driver.name });\n }\n }\n\n /**\n * Register a Datasource *definition* (ADR-0015).\n *\n * Distinct from {@link registerDriver}, which registers a live connection.\n * This captures the declarative `schemaMode` + `external.allowWrites` so the\n * write gate ({@link assertWriteAllowed}) can enforce external-datasource\n * ownership. Safe to call repeatedly; last write wins.\n */\n registerDatasourceDef(def: { name: string; schemaMode?: string; external?: { allowWrites?: boolean } }): void {\n if (!def?.name) return;\n this.datasourceDefs.set(def.name, { schemaMode: def.schemaMode, external: def.external });\n }\n\n /**\n * Write gate — Gate 3 of ADR-0015 §5.3.\n *\n * Blocks insert/update/delete against a federated datasource\n * (`schemaMode !== 'managed'`) unless BOTH the datasource opts in\n * (`external.allowWrites`) AND the object opts in (`external.writable`).\n * Managed datasources (the common case, including the absence of any\n * definition) are unaffected.\n */\n private assertWriteAllowed(objectName: string, operation: 'insert' | 'update' | 'delete'): void {\n const object = this._registry.getObject(objectName) as any;\n const dsName = object?.datasource;\n if (!dsName || dsName === 'default') return;\n\n const ds = this.datasourceDefs.get(dsName);\n // No recorded definition, or an explicitly managed one ⇒ allow.\n if (!ds || !ds.schemaMode || ds.schemaMode === 'managed') return;\n\n const dsAllows = ds.external?.allowWrites ?? false;\n const objAllows = object?.external?.writable ?? false;\n if (!(dsAllows && objAllows)) {\n throw new ExternalWriteForbiddenError(\n `Write '${operation}' blocked on object '${objectName}': datasource '${dsName}' is external ` +\n `(schemaMode=${ds.schemaMode}). Requires datasource.external.allowWrites=true (got ${dsAllows}) ` +\n `AND object.external.writable=true (got ${objAllows}).`,\n );\n }\n }\n\n /**\n * Set the realtime service for publishing data change events.\n * Should be called after kernel resolves the realtime service.\n *\n * @param service - An IRealtimeService instance for event publishing\n */\n setRealtimeService(service: IRealtimeService): void {\n this.realtimeService = service;\n this.logger.info('RealtimeService configured for data events');\n }\n\n /**\n * Register the crypto provider that backs `secret`-typed fields.\n *\n * When set, the engine encrypts secret fields on write (storing ciphertext in\n * `sys_secret` and only an opaque ref on the business row) and masks them on\n * read. When NOT set, writing to an object that declares a secret field is\n * **fail-closed** — the write throws rather than persist cleartext.\n *\n * Mirrors the Settings subsystem's ICryptoProvider wiring; the host (e.g.\n * `serve`) injects `LocalCryptoProvider` in dev and a KMS/Vault-backed\n * provider in production.\n */\n setCryptoProvider(provider: ICryptoProvider): void {\n this.cryptoProvider = provider;\n this.logger.info('CryptoProvider configured for secret fields');\n }\n\n /**\n * Encrypt any `secret`-typed fields on `row` in place before it reaches the\n * driver. Each plaintext is wrapped by the ICryptoProvider, persisted as a\n * `sys_secret` row, and replaced on `row` by an opaque ref. Cleartext never\n * reaches the business table.\n *\n * Rules:\n * - No secret fields on the object ⇒ no-op (fast path, no crypto cost).\n * - `null`/`undefined` value ⇒ left as-is (clears the secret).\n * - Value already a ref (re-save of an unchanged ref) ⇒ left as-is.\n * - Value equal to the read mask ⇒ dropped, so a form round-trip that\n * echoes the mask does not overwrite the stored secret.\n * - **Fail-closed:** any other value with no CryptoProvider registered, or\n * no reachable `sys_secret` store, THROWS — never persists cleartext.\n */\n private async encryptSecretFields(\n object: string,\n row: Record<string, unknown>,\n context: ExecutionContext | undefined,\n driverOptions: unknown,\n ): Promise<void> {\n if (!row || typeof row !== 'object') return;\n const schema = this._registry.getObject(object);\n const secretFields = collectSecretFields(schema);\n if (secretFields.length === 0) return;\n\n for (const field of secretFields) {\n if (!(field in row)) continue;\n const value = row[field];\n\n if (value === null || typeof value === 'undefined') continue; // clear\n if (isSecretRef(value)) continue; // already encrypted ref\n if (value === SECRET_MASK) {\n // The read path masks secrets to SECRET_MASK; a form that echoes it\n // back means \"unchanged\". Drop the key so the stored secret survives.\n delete row[field];\n continue;\n }\n\n if (!this.cryptoProvider) {\n throw new Error(\n `Cannot persist secret field \"${object}.${field}\": no CryptoProvider is registered. `\n + 'Wire one via engine.setCryptoProvider(...) (e.g. LocalCryptoProvider in dev, '\n + 'a KMS/Vault provider in production). Refusing to store cleartext (fail-closed).',\n );\n }\n\n const plain = typeof value === 'string' ? value : JSON.stringify(value);\n const handle: CryptoHandle = await this.cryptoProvider.encrypt(plain, {\n namespace: object,\n key: field,\n tenantId: context?.tenantId,\n });\n\n let secretDriver;\n try {\n secretDriver = this.getDriver('sys_secret');\n } catch {\n throw new Error(\n `Cannot persist secret field \"${object}.${field}\": the sys_secret store is not available. `\n + 'Ensure the platform-objects (sys_secret) are registered before writing secret fields (fail-closed).',\n );\n }\n\n await secretDriver.create(\n 'sys_secret',\n {\n id: handle.id,\n namespace: object,\n key: field,\n kms_key_id: handle.kmsKeyId,\n alg: handle.alg,\n version: handle.version,\n ciphertext: handle.ciphertext,\n created_at: new Date().toISOString(),\n },\n driverOptions as any,\n );\n\n row[field] = makeSecretRef(handle.id);\n }\n }\n\n /**\n * Mask `secret`-typed fields on read so plaintext never leaves the engine\n * through the normal query path. A set secret becomes {@link SECRET_MASK};\n * an unset one stays `null`. Privileged callers that genuinely need the\n * plaintext use {@link resolveSecret} against the stored ref.\n */\n private maskSecretFields(object: string, rows: any): void {\n if (!rows) return;\n const schema = this._registry.getObject(object);\n const secretFields = collectSecretFields(schema);\n if (secretFields.length === 0) return;\n const list = Array.isArray(rows) ? rows : [rows];\n for (const row of list) {\n if (!row || typeof row !== 'object') continue;\n for (const field of secretFields) {\n if (!(field in row)) continue;\n row[field] = row[field] == null ? null : SECRET_MASK;\n }\n }\n }\n\n /**\n * Dereference a stored secret ref back to its plaintext. Intended for\n * privileged, server-side consumers (e.g. a datasource connection-pool\n * binder) — NOT exposed through the generic read path, which only ever\n * returns the mask.\n *\n * Fail-closed: throws when no CryptoProvider is registered or the\n * `sys_secret` row is missing. Returns `null` when `ref` is not a secret ref.\n */\n async resolveSecret(ref: unknown, opts?: { tenantId?: string }): Promise<string | null> {\n const id = parseSecretRef(ref);\n if (!id) return null;\n if (!this.cryptoProvider) {\n throw new Error('Cannot resolve secret: no CryptoProvider is registered (fail-closed).');\n }\n const secretDriver = this.getDriver('sys_secret');\n const found = await secretDriver.find('sys_secret', { object: 'sys_secret', where: { id } } as QueryAST);\n const secret: any = Array.isArray(found) ? found[0] : found;\n if (!secret) {\n throw new Error(`Cannot resolve secret: sys_secret row \"${id}\" not found (fail-closed).`);\n }\n const handle: CryptoHandle = {\n id: secret.id,\n kmsKeyId: secret.kms_key_id,\n alg: secret.alg,\n version: secret.version,\n ciphertext: secret.ciphertext,\n };\n return this.cryptoProvider.decrypt(handle, {\n namespace: secret.namespace,\n key: secret.key,\n tenantId: opts?.tenantId,\n });\n }\n\n /**\n * Helper to get object definition\n */\n getSchema(objectName: string): ServiceObject | undefined {\n return this._registry.getObject(objectName);\n }\n\n /**\n * Resolve any object identifier to the physical storage name used by drivers.\n *\n * Accepts the canonical short name (e.g., 'account') or, for explicit\n * cross-package disambiguation, the canonical object name (e.g., 'account'). The result is\n * the physical table name derived via `StorageNameMapping.resolveTableName`.\n */\n private resolveObjectName(name: string): string {\n const schema = this._registry.getObject(name);\n if (schema) {\n return StorageNameMapping.resolveTableName(schema);\n }\n // Return name as-is (canonical name = table name; no FQN prefix to strip)\n return StorageNameMapping.resolveTableName({ name });\n }\n\n /**\n * Helper to get the target driver\n *\n * Resolution priority (first match wins):\n * 1. Object's explicit `datasource` field (if not 'default')\n * 2. DatasourceMapping rules (namespace/package/pattern matching)\n * 3. Package's `defaultDatasource` from manifest\n * 4. Global default driver\n */\n private getDriver(objectName: string): DriverInterface {\n const object = this._registry.getObject(objectName);\n\n // 1. Object's explicit datasource field (highest priority)\n if (object?.datasource && object.datasource !== 'default') {\n if (this.drivers.has(object.datasource)) {\n return this.drivers.get(object.datasource)!;\n }\n throw new Error(`[ObjectQL] Datasource '${object.datasource}' configured for object '${objectName}' is not registered.`);\n }\n\n // 2. Check datasourceMapping rules\n const mappedDatasource = this.resolveDatasourceFromMapping(objectName, object);\n if (mappedDatasource && this.drivers.has(mappedDatasource)) {\n this.logger.debug('Resolved datasource from mapping', {\n object: objectName,\n datasource: mappedDatasource\n });\n return this.drivers.get(mappedDatasource)!;\n }\n\n // 3. Check package's defaultDatasource\n // Use the object's FQN name (from getObject) for ownership lookup\n const fqn = object?.name || objectName;\n const owner = this._registry.getObjectOwner(fqn);\n if (owner?.packageId) {\n const manifest = this.manifests.get(owner.packageId);\n if (manifest?.defaultDatasource && manifest.defaultDatasource !== 'default') {\n if (this.drivers.has(manifest.defaultDatasource)) {\n this.logger.debug('Resolved datasource from package manifest', {\n object: objectName,\n package: owner.packageId,\n datasource: manifest.defaultDatasource\n });\n return this.drivers.get(manifest.defaultDatasource)!;\n }\n }\n }\n\n // 4. Fallback to global default driver\n if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n return this.drivers.get(this.defaultDriver)!;\n }\n\n throw new Error(`[ObjectQL] No driver available for object '${objectName}'`);\n }\n\n /**\n * Resolve datasource from mapping rules\n *\n * Rules are evaluated in order (or by priority if specified).\n * First matching rule wins.\n */\n private resolveDatasourceFromMapping(\n objectName: string,\n object?: any\n ): string | null {\n if (!this.datasourceMapping || this.datasourceMapping.length === 0) {\n return null;\n }\n\n // Sort rules by priority if any have priority set\n const sortedRules = [...this.datasourceMapping].sort((a, b) => {\n const aPriority = a.priority ?? 1000;\n const bPriority = b.priority ?? 1000;\n return aPriority - bPriority;\n });\n\n for (const rule of sortedRules) {\n // 1. Match by namespace\n if (rule.namespace && object?.namespace === rule.namespace) {\n return rule.datasource;\n }\n\n // 2. Match by package ID\n if (rule.package && object?.packageId === rule.package) {\n return rule.datasource;\n }\n\n // 3. Match by object name pattern (glob-style)\n if (rule.objectPattern && this.matchPattern(objectName, rule.objectPattern)) {\n return rule.datasource;\n }\n\n // 4. Default fallback rule\n if (rule.default) {\n return rule.datasource;\n }\n }\n\n return null;\n }\n\n /**\n * Simple glob pattern matching\n * Supports * (any chars) and ? (single char)\n */\n private matchPattern(objectName: string, pattern: string): boolean {\n const regexPattern = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex special chars\n .replace(/\\*/g, '.*') // * → .*\n .replace(/\\?/g, '.'); // ? → .\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(objectName);\n }\n\n /**\n * Set datasource mapping rules\n * Called by ObjectQLPlugin during bootstrap\n */\n setDatasourceMapping(rules: Array<{\n namespace?: string;\n package?: string;\n objectPattern?: string;\n default?: boolean;\n datasource: string;\n priority?: number;\n }>) {\n this.datasourceMapping = rules;\n this.logger.info('Datasource mapping rules configured', {\n ruleCount: rules.length\n });\n }\n\n /**\n * Initialize the engine and all registered drivers\n */\n async init() {\n this.logger.info('Initializing ObjectQL engine', { \n driverCount: this.drivers.size,\n drivers: Array.from(this.drivers.keys())\n });\n \n const failedDrivers: string[] = [];\n for (const [name, driver] of this.drivers) {\n try {\n await driver.connect();\n this.logger.info('Driver connected successfully', { driverName: name });\n } catch (e) {\n failedDrivers.push(name);\n this.logger.error('Failed to connect driver', e as Error, { driverName: name });\n }\n }\n\n if (failedDrivers.length > 0) {\n this.logger.warn(\n `${failedDrivers.length} of ${this.drivers.size} driver(s) failed initial connect. ` +\n `Operations may recover via lazy reconnection or fail at query time.`,\n { failedDrivers }\n );\n }\n \n this.logger.info('ObjectQL engine initialization complete');\n }\n\n async destroy() {\n this.logger.info('Destroying ObjectQL engine', { driverCount: this.drivers.size });\n \n for (const [name, driver] of this.drivers.entries()) {\n try {\n await driver.disconnect();\n } catch (e) {\n this.logger.error('Error disconnecting driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine destroyed');\n }\n\n // ============================================\n // Helper: Expand Related Records\n // ============================================\n\n /** Maximum depth for recursive expand to prevent infinite loops */\n private static readonly MAX_EXPAND_DEPTH = 3;\n private static readonly MAX_CASCADE_DEPTH = 10;\n /** In-memory next-value cache per `object.field` for autonumber generation,\n * lazily seeded from the current max in the store. */\n private readonly autonumberCounters = new Map<string, number>();\n\n /** Lazily-built index: child object name → roll-up summary descriptors on\n * parent objects that aggregate it. Invalidated when packages register. */\n private summaryIndex: Map<string, SummaryDescriptor[]> | null = null;\n\n /** Invalidate the cached roll-up summary index (call when metadata changes). */\n private invalidateSummaryIndex(): void {\n this.summaryIndex = null;\n }\n\n /** Scan all registered objects for `summary` fields and index them by the\n * child object they aggregate, resolving the child→parent FK field. */\n private buildSummaryIndex(): Map<string, SummaryDescriptor[]> {\n const index = new Map<string, SummaryDescriptor[]>();\n let objects: any[] = [];\n try { objects = (this._registry as any).getAllObjects?.() ?? []; } catch { objects = []; }\n for (const parent of objects) {\n const fields = parent?.fields;\n if (!fields || typeof fields !== 'object' || Array.isArray(fields)) continue;\n for (const [summaryField, def] of Object.entries(fields)) {\n const d: any = def;\n if (d?.type !== 'summary' || !d.summaryOperations) continue;\n const so = d.summaryOperations;\n const childObject = so.object;\n const fn = so.function;\n if (!childObject || !fn) continue;\n // Resolve the FK on the child pointing back to this parent.\n let fkField: string | undefined = so.relationshipField;\n if (!fkField) {\n const child = this._registry.getObject(childObject) as any;\n const cfields = child?.fields || {};\n for (const [cfName, cdef] of Object.entries(cfields)) {\n const cd: any = cdef;\n if ((cd?.type === 'master_detail' || cd?.type === 'lookup') && cd?.reference === parent.name) {\n fkField = cfName;\n break;\n }\n }\n }\n if (!fkField) continue; // can't resolve the relationship — skip\n const list = index.get(childObject) ?? [];\n list.push({ parentObject: parent.name, summaryField, fkField, fn, sourceField: so.field });\n index.set(childObject, list);\n }\n }\n return index;\n }\n\n private getSummaryDescriptors(childObject: string): SummaryDescriptor[] {\n if (!this.summaryIndex) this.summaryIndex = this.buildSummaryIndex();\n return this.summaryIndex.get(childObject) ?? [];\n }\n\n /**\n * Recompute roll-up `summary` fields on parent records after a child write.\n * For each affected parent (the FK value on the changed/old child record), it\n * aggregates the child collection and writes the result onto the parent's\n * summary field. Runs in the caller's execution context so it joins the same\n * transaction (e.g. the cross-object batch) when one is open.\n */\n private async recomputeSummaries(\n childObject: string,\n records: any,\n previous: any,\n execCtx?: ExecutionContext,\n ): Promise<void> {\n const descriptors = this.getSummaryDescriptors(childObject);\n if (descriptors.length === 0) return;\n const recs = Array.isArray(records) ? records : records ? [records] : [];\n const prevs = Array.isArray(previous) ? previous : previous ? [previous] : [];\n for (const desc of descriptors) {\n const ids = new Set<string>();\n for (const r of recs) { const v = r?.[desc.fkField]; if (v != null && v !== '') ids.add(String(v)); }\n for (const p of prevs) { const v = p?.[desc.fkField]; if (v != null && v !== '') ids.add(String(v)); }\n for (const parentId of ids) {\n try {\n const rows = await this.aggregate(childObject, {\n where: { [desc.fkField]: parentId },\n aggregations: [{\n function: desc.fn,\n ...(desc.fn === 'count' ? {} : { field: desc.sourceField }),\n alias: 'value',\n }],\n context: execCtx,\n } as any);\n let value = rows?.[0]?.value;\n if (value == null) value = (desc.fn === 'count' || desc.fn === 'sum') ? 0 : null;\n await this.update(desc.parentObject, { id: parentId, [desc.summaryField]: value }, { context: execCtx } as any);\n } catch (err) {\n this.logger.warn('Roll-up summary recompute failed', {\n childObject, parentObject: desc.parentObject, parentId, field: desc.summaryField,\n error: (err as any)?.message,\n });\n }\n }\n }\n }\n\n /**\n * Post-process expand: resolve lookup/master_detail fields by batch-loading related records.\n * \n * This is a driver-agnostic implementation that uses secondary queries ($in batches)\n * to load related records, then injects them into the result set.\n * \n * @param objectName - The source object name\n * @param records - The records returned by the driver\n * @param expand - The expand map from QueryAST (field name → nested QueryAST)\n * @param depth - Current recursion depth (0-based)\n * @returns Records with expanded lookup fields (IDs replaced by full objects)\n */\n private async expandRelatedRecords(\n objectName: string,\n records: any[],\n expand: Record<string, QueryAST>,\n depth: number = 0,\n execCtx?: ExecutionContext,\n ): Promise<any[]> {\n if (!records || records.length === 0) return records;\n if (depth >= ObjectQL.MAX_EXPAND_DEPTH) return records;\n\n const objectSchema = this._registry.getObject(objectName);\n // If no schema registered, skip expand — return raw data\n if (!objectSchema || !objectSchema.fields) return records;\n\n for (const [fieldName, nestedAST] of Object.entries(expand)) {\n const fieldDef = objectSchema.fields[fieldName];\n\n // Skip if field not found or not a relationship type\n if (!fieldDef || !fieldDef.reference) continue;\n if (fieldDef.type !== 'lookup' && fieldDef.type !== 'master_detail') continue;\n\n const referenceObject = fieldDef.reference;\n\n // Collect all foreign key IDs from records (handle both single and multiple values)\n const allIds: any[] = [];\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n if (Array.isArray(val)) {\n allIds.push(...val.filter((id: any) => id != null));\n } else if (typeof val === 'object') {\n // Already expanded — skip\n continue;\n } else {\n allIds.push(val);\n }\n }\n\n // De-duplicate IDs\n const uniqueIds = [...new Set(allIds)];\n if (uniqueIds.length === 0) continue;\n\n // Batch-load related records using $in query\n try {\n const relatedQuery: QueryAST = {\n object: referenceObject,\n where: { id: { $in: uniqueIds } },\n ...(nestedAST.fields ? { fields: nestedAST.fields } : {}),\n ...(nestedAST.orderBy ? { orderBy: nestedAST.orderBy } : {}),\n };\n\n const driver = this.getDriver(referenceObject);\n // Propagate tenantId so cross-object expansion respects isolation —\n // e.g. a contact expansion only resolves IDs visible to the caller's\n // tenant. Without this the driver returns the raw FK target which\n // would let a maliciously crafted FK reach across tenants.\n const expandOpts = this.buildDriverOptions(execCtx);\n const relatedRecords = await driver.find(referenceObject, relatedQuery, expandOpts) ?? [];\n\n // Build a lookup map: id → record\n const recordMap = new Map<string, any>();\n for (const rec of relatedRecords) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n\n // Recursively expand nested relations if present\n if (nestedAST.expand && Object.keys(nestedAST.expand).length > 0) {\n const expandedRelated = await this.expandRelatedRecords(\n referenceObject,\n relatedRecords,\n nestedAST.expand,\n depth + 1,\n execCtx,\n );\n // Rebuild map with expanded records\n recordMap.clear();\n for (const rec of expandedRelated) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n }\n\n // Inject expanded records back into the original result set\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n\n if (Array.isArray(val)) {\n record[fieldName] = val.map((id: any) => recordMap.get(String(id)) ?? id);\n } else if (typeof val !== 'object') {\n record[fieldName] = recordMap.get(String(val)) ?? val;\n }\n // If val is already an object, leave it as-is\n }\n } catch (e) {\n // Graceful degradation: if expand fails, keep original IDs\n this.logger.warn('Failed to expand relationship field; retaining foreign key IDs', {\n object: objectName,\n field: fieldName,\n reference: referenceObject,\n error: (e as Error).message,\n });\n }\n }\n\n return records;\n }\n\n // ============================================\n // Data Access Methods (IDataEngine Interface)\n // ============================================\n\n async find(object: string, query?: EngineQueryOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n this.logger.debug('Find operation starting', { object, query });\n const driver = this.getDriver(object);\n const ast: QueryAST = { object, ...query };\n // Remove context from the AST — it's not a driver concern\n delete (ast as any).context;\n // Normalize OData `top` alias → standard `limit`\n if ((ast as any).top != null && ast.limit == null) {\n ast.limit = (ast as any).top;\n }\n delete (ast as any).top;\n\n // Plan formula projection: rewrite ast.fields to drop virtual formula\n // names and inject their dependencies, so the driver returns the raw\n // fields needed to compute the formulas after fetch.\n const _findSchema = this._registry.getObject(object);\n const _findFormula = planFormulaProjection(_findSchema, ast.fields as string[] | undefined);\n if (_findFormula.projected) ast.fields = _findFormula.projected;\n\n // Drop any requested field that doesn't exist on the schema. Without\n // this, drivers (notably SqlDriver) emit `SELECT unknown_col FROM ...`\n // which the DB rejects (\"no such column\") — and SqlDriver swallows\n // that error and returns `[]`, making a frontend bug (e.g. a generic\n // view requesting `name`/`due_date` on every object) look like \"no\n // records exist\". Silently filtering matches the existing OData\n // tolerance and Salesforce/Postgres behavior of `SELECT *` semantics.\n if (_findSchema?.fields && Array.isArray(ast.fields) && ast.fields.length > 0) {\n const known = new Set(Object.keys(_findSchema.fields));\n // Always allow the primary key + audit columns even if not present in\n // schema.fields. Without this, callers requesting `select=id,name`\n // silently get the `id` projected away, breaking record navigation.\n known.add('id');\n known.add('created_at');\n known.add('updated_at');\n const filtered = (ast.fields as string[]).filter(f => {\n // Keep relationship paths like `owner.name` — the engine will\n // resolve those via populate; only validate top-level segment.\n const head = String(f).split('.')[0];\n return known.has(head);\n });\n // Guard against an empty projection — fall back to `*` so the\n // request still returns rows. An empty SELECT list would either\n // 400 in Postgres or silently project nothing.\n ast.fields = filtered.length > 0 ? filtered : undefined;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'find',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast: opCtx.ast, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result = await driver.find(object, hookContext.input.ast as QueryAST, hookContext.input.options as any);\n\n // Post-process: evaluate formula virtual fields against the raw rows\n if (Array.isArray(result)) applyFormulaPlan(_findFormula.plan, result);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && Array.isArray(result)) {\n result = await this.expandRelatedRecords(object, result, ast.expand, 0, opCtx.context);\n }\n \n hookContext.event = 'afterFind';\n hookContext.result = result;\n await this.triggerHooks('afterFind', hookContext);\n\n // Never let secret-field plaintext (or its ref) leave through the\n // generic read path — mask after hooks run. Privileged consumers use\n // resolveSecret() against the stored ref instead.\n this.maskSecretFields(object, hookContext.result);\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Find operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result as any[];\n }\n\n async findOne(objectName: string, query?: EngineQueryOptions): Promise<any> {\n objectName = this.resolveObjectName(objectName);\n this.logger.debug('FindOne operation', { objectName });\n const driver = this.getDriver(objectName);\n const ast: QueryAST = { object: objectName, ...query, limit: 1 };\n // Remove context and top alias from the AST\n delete (ast as any).context;\n delete (ast as any).top;\n\n // Plan formula projection (same as find): rewrite ast.fields so the driver\n // returns the raw dependency fields, then evaluate formulas after fetch.\n const _findOneSchema = this._registry.getObject(objectName);\n const _findOneFormula = planFormulaProjection(_findOneSchema, ast.fields as string[] | undefined);\n if (_findOneFormula.projected) ast.fields = _findOneFormula.projected;\n\n // Drop unknown fields — see equivalent block in `find()` for rationale.\n if (_findOneSchema?.fields && Array.isArray(ast.fields) && ast.fields.length > 0) {\n const known = new Set(Object.keys(_findOneSchema.fields));\n // Always allow the primary key + audit columns even if not present\n // in schema.fields (matches `find()` behavior).\n known.add('id');\n known.add('created_at');\n known.add('updated_at');\n const filtered = (ast.fields as string[]).filter(f => known.has(String(f).split('.')[0]));\n ast.fields = filtered.length > 0 ? filtered : undefined;\n }\n\n const opCtx: OperationContext = {\n object: objectName,\n operation: 'findOne',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const findOneOpts = this.buildDriverOptions(opCtx.context);\n let result = await driver.findOne(objectName, opCtx.ast as QueryAST, findOneOpts);\n\n // Post-process: evaluate formula virtual fields against the raw row\n if (result != null) applyFormulaPlan(_findOneFormula.plan, [result]);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && result != null) {\n const expanded = await this.expandRelatedRecords(objectName, [result], ast.expand, 0, opCtx.context);\n result = expanded[0];\n }\n\n // Mask secret fields — plaintext never leaves through the read path.\n this.maskSecretFields(objectName, result);\n\n return result;\n });\n\n return opCtx.result;\n }\n\n async insert(object: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Insert operation starting', { object, isBatch: Array.isArray(data) });\n this.assertWriteAllowed(object, 'insert');\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'insert',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeInsert', hookContext);\n // Thread the open transaction (if any) into the driver-facing\n // options so that knex's `.transacting(trx)` is honoured. Without\n // this, calls inside a `engine.transaction(...)` block would deadlock\n // on SQLite's single-connection pool. Also propagates tenantId so\n // the driver can enforce per-tenant isolation.\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result;\n const nowSnap = new Date();\n const schemaForValidation = this._registry.getObject(object);\n // When the driver generates autonumbers natively (persistent SQL\n // sequence), the engine defers to it — see #1603.\n const driverOwnsAutonumber = (driver as any)?.supports?.autonumber === true;\n if (Array.isArray(hookContext.input.data)) {\n // Bulk Create — apply defaults per row\n const rows = (hookContext.input.data as any[]).map((row) =>\n this.applyFieldDefaults(object, row as Record<string, unknown>, opCtx.context, nowSnap),\n );\n for (const r of rows) {\n await this.applyAutonumbers(object, r as Record<string, unknown>, opCtx.context, driverOwnsAutonumber);\n }\n for (const r of rows) {\n await this.encryptSecretFields(object, r, opCtx.context, hookContext.input.options);\n }\n for (const r of rows) {\n validateRecord(schemaForValidation, r, 'insert');\n evaluateValidationRules(schemaForValidation as any, r, 'insert', { logger: this.logger });\n }\n if (driver.bulkCreate) {\n result = await driver.bulkCreate(object, rows, hookContext.input.options as any);\n } else {\n // Fallback loop\n result = await Promise.all(rows.map((item) => driver.create(object, item, hookContext.input.options as any)));\n }\n } else {\n const row = this.applyFieldDefaults(\n object,\n hookContext.input.data as Record<string, unknown>,\n opCtx.context,\n nowSnap,\n );\n await this.applyAutonumbers(object, row, opCtx.context, driverOwnsAutonumber);\n await this.encryptSecretFields(object, row, opCtx.context, hookContext.input.options);\n validateRecord(schemaForValidation, row, 'insert');\n evaluateValidationRules(schemaForValidation as any, row, 'insert', { logger: this.logger });\n result = await driver.create(object, row, hookContext.input.options as any);\n }\n\n hookContext.event = 'afterInsert';\n hookContext.result = result;\n await this.triggerHooks('afterInsert', hookContext);\n\n // Roll-up: recompute parent summary fields that aggregate this object.\n await this.recomputeSummaries(object, result, null, opCtx.context);\n\n // Publish data.record.created event to realtime service\n if (this.realtimeService) {\n try {\n if (Array.isArray(result)) {\n // Bulk insert - publish event for each record\n for (const record of result) {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: record.id,\n after: record,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n }\n this.logger.debug(`Published ${result.length} data.record.created events`, { object });\n } else {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: result.id,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.created event', { object, recordId: result.id });\n }\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Insert operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async update(object: string, data: any, options?: EngineUpdateOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Update operation starting', { object });\n this.assertWriteAllowed(object, 'update');\n const driver = this.getDriver(object);\n \n // 1. Extract ID from data or where if it's a single update by ID.\n // Only a SCALAR `where.id` means \"update one row by primary key\". An\n // operator object ({ $in: [...] }, { $ne: ... }, …) is a multi-row\n // predicate — treating it as an id would bind the object literally\n // (e.g. `WHERE id = {\"$in\":[...]}`, which SQLite rejects). Leave `id`\n // undefined in that case so the call routes to updateMany (requires\n // options.multi=true), where applyFilters compiles the operator.\n let id = data.id;\n if (!id && options?.where && typeof options.where === 'object' && 'id' in options.where) {\n const whereId = (options.where as Record<string, unknown>).id;\n const t = typeof whereId;\n if (whereId !== null && (t === 'string' || t === 'number' || t === 'bigint')) {\n id = whereId;\n }\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'update',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result;\n // Pre-update snapshot. Exposed to after-hooks via `hookContext.previous`\n // (the HookContext contract documents `previous` for update/delete) and\n // reused for object-level validation rules. Fetched once, only for\n // single-id updates, when either a rule needs it (ADR-0020:\n // state_machine / cross_field / script — a PATCH carries only changed\n // fields) OR an afterUpdate hook is registered. The latter is what makes\n // record-change flow triggers work: their start-condition gate reads\n // `previous.*` (e.g. `status == \"done\" && previous.status != \"done\"`),\n // which silently fails when `previous` is absent.\n let priorRecord: Record<string, unknown> | null = null;\n const updateSchema = this._registry.getObject(object);\n if (hookContext.input.id) {\n await this.encryptSecretFields(object, hookContext.input.data as Record<string, unknown>, opCtx.context, hookContext.input.options);\n validateRecord(updateSchema, hookContext.input.data as Record<string, unknown>, 'update');\n if (needsPriorRecord(updateSchema as any) || (this.hooks.get('afterUpdate')?.length ?? 0) > 0) {\n const priorAst: QueryAST = { object, where: { id: hookContext.input.id }, limit: 1 };\n priorRecord = await driver.findOne(object, priorAst, hookContext.input.options as any);\n }\n // B2: drop writes to fields locked by a TRUE `readonlyWhen` — the\n // field is read-only for this record's state, so the incoming\n // change is ignored (the persisted value is kept).\n hookContext.input.data = stripReadonlyWhenFields(updateSchema as any, hookContext.input.data as Record<string, unknown>, priorRecord, this.logger) as any;\n evaluateValidationRules(updateSchema as any, hookContext.input.data as Record<string, unknown>, 'update', { previous: priorRecord, logger: this.logger });\n result = await driver.update(object, hookContext.input.id as string, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else if (options?.multi && driver.updateMany) {\n await this.encryptSecretFields(object, hookContext.input.data as Record<string, unknown>, opCtx.context, hookContext.input.options);\n validateRecord(updateSchema, hookContext.input.data as Record<string, unknown>, 'update');\n // Multi-row update: per-row prior state is not fetched (one query\n // per matched row would be unbounded). state_machine /\n // cross_field rules are skipped here; warn so the gap is visible.\n if (needsPriorRecord(updateSchema as any)) {\n this.logger.warn('Object-level validation rules (state_machine/cross_field/script) are not enforced on multi-row updates', { object });\n }\n const ast: QueryAST = { object, where: options.where };\n result = await driver.updateMany(object, ast, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else {\n throw new Error('Update requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterUpdate';\n hookContext.result = result;\n if (priorRecord) hookContext.previous = priorRecord;\n await this.triggerHooks('afterUpdate', hookContext);\n\n // Roll-up: recompute parent summaries; pass priorRecord too so a child\n // that moved to a different parent updates BOTH old and new parent.\n await this.recomputeSummaries(object, result, priorRecord, opCtx.context);\n\n // Publish data.record.updated event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.updated',\n object,\n payload: {\n recordId,\n changes: hookContext.input.data,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.updated event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Update operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n /**\n * Apply referential delete behavior for relations pointing AT this record,\n * before it is removed. For every registered object with a `master_detail`\n * or `lookup` field referencing `object`, honor the field's `deleteBehavior`:\n * - `cascade` → delete the dependent rows (recursively, so grandchildren\n * are handled by each child's own delete),\n * - `set_null` → clear the foreign key,\n * - `restrict` → refuse the delete when dependents exist.\n * `master_detail` defaults to `cascade` (the parent owns the child\n * lifecycle); `lookup` defaults to `set_null`. Only runs for single-id\n * deletes — multi/predicate deletes skip cascade (logged).\n */\n private async cascadeDeleteRelations(\n object: string,\n id: string | number,\n context?: ExecutionContext,\n depth = 0,\n ): Promise<void> {\n if (id == null || depth >= ObjectQL.MAX_CASCADE_DEPTH) return;\n let objects: ServiceObject[];\n try {\n objects = this._registry.getAllObjects();\n } catch {\n return;\n }\n for (const child of objects) {\n const childName = (child as any)?.name as string | undefined;\n const fields = (child as any)?.fields as Record<string, any> | undefined;\n if (!childName || !fields) continue;\n for (const [fieldName, fdef] of Object.entries(fields)) {\n if (!fdef || (fdef.type !== 'master_detail' && fdef.type !== 'lookup')) continue;\n const ref = fdef.reference;\n if (!ref) continue;\n // Match the target object by raw or resolved name.\n let resolvedRef: string | undefined;\n try { resolvedRef = this.resolveObjectName(ref); } catch { resolvedRef = undefined; }\n if (ref !== object && resolvedRef !== object) continue;\n\n // A master-detail parent owns its children: cascade by default (the\n // child FK is typically required, so set_null would be invalid). Only\n // an explicit `restrict` deviates. A plain lookup honors its\n // configured deleteBehavior (default set_null).\n const behavior: string =\n fdef.type === 'master_detail'\n ? (fdef.deleteBehavior === 'restrict' ? 'restrict' : 'cascade')\n : (fdef.deleteBehavior || 'set_null');\n\n let dependents: any[];\n try {\n dependents = await this.find(childName, { where: { [fieldName]: id }, context } as any);\n } catch {\n continue;\n }\n if (!dependents || dependents.length === 0) continue;\n\n if (behavior === 'restrict') {\n throw new Error(\n `Cannot delete ${object} (${id}): ${dependents.length} dependent ${childName} record(s) via ${fieldName}`,\n );\n }\n\n for (const dep of dependents) {\n const depId = dep?.id;\n if (depId == null) continue;\n if (behavior === 'cascade') {\n // Recurse via the public delete so the child's own cascade,\n // hooks and events fire.\n await this.delete(childName, { where: { id: depId }, context } as any);\n } else {\n await this.update(childName, { id: depId, [fieldName]: null }, { context } as any);\n }\n }\n }\n }\n }\n\n async delete(object: string, options?: EngineDeleteOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Delete operation starting', { object });\n this.assertWriteAllowed(object, 'delete');\n const driver = this.getDriver(object);\n\n // Extract ID logic similar to update\n let id: any = undefined;\n if (options?.where && typeof options.where === 'object' && 'id' in options.where) {\n id = (options.where as Record<string, unknown>).id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'delete',\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeDelete', hookContext);\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result;\n // Capture the row's FK values BEFORE deletion so roll-up summaries can\n // recompute the (now-orphaned) parent. Only when a summary aggregates\n // this object — avoids an extra read on every delete.\n let summaryPrev: any = null;\n if (hookContext.input.id && this.getSummaryDescriptors(object).length > 0) {\n try {\n summaryPrev = await this.findOne(object, { where: { id: hookContext.input.id }, context: opCtx.context } as any);\n } catch { /* best-effort */ }\n }\n if (hookContext.input.id) {\n // Honor referential delete behavior (cascade/set_null/restrict)\n // for relations pointing at this record before removing it.\n await this.cascadeDeleteRelations(object, hookContext.input.id as string | number, opCtx.context);\n result = await driver.delete(object, hookContext.input.id as string, hookContext.input.options as any);\n } else if (options?.multi && driver.deleteMany) {\n const ast: QueryAST = { object, where: options.where };\n result = await driver.deleteMany(object, ast, hookContext.input.options as any);\n } else {\n throw new Error('Delete requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterDelete';\n hookContext.result = result;\n await this.triggerHooks('afterDelete', hookContext);\n\n // Roll-up: recompute the parent summary now that the child is gone.\n if (summaryPrev) await this.recomputeSummaries(object, null, summaryPrev, opCtx.context);\n\n // Publish data.record.deleted event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.deleted',\n object,\n payload: {\n recordId,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.deleted event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Delete operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async count(object: string, query?: EngineCountOptions): Promise<number> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'count',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const countOpts = this.buildDriverOptions(opCtx.context);\n if (driver.count) {\n const ast: QueryAST = { object, where: query?.where };\n return driver.count(object, ast, countOpts);\n }\n // Fallback to find().length\n const res = await this.find(object, { where: query?.where, fields: ['id'], context: opCtx.context });\n return res.length;\n });\n\n return opCtx.result as number;\n }\n\n async aggregate(object: string, query: EngineAggregateOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'aggregate',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const ast: QueryAST = {\n object,\n where: query.where,\n groupBy: query.groupBy as any,\n aggregations: query.aggregations,\n };\n\n // Prefer driver.aggregate() when available — driver.find() in many\n // drivers (e.g. driver-sql) does not honor `groupBy` / `aggregations`\n // and would silently return ungrouped raw rows. Fall back to find()\n // for drivers that handle aggregations through their query AST.\n const drv = driver as any;\n // Structured groupBy items ({field, dateGranularity}) require the\n // driver to advertise per-granularity native bucket support via\n // `supports.queryDateGranularity[g]`. If every structured item is\n // supported we can push the aggregate down to the driver; otherwise\n // we fall back to driver.find() + in-memory bucketing so the result\n // remains correct on partial-support dialects (e.g. SQLite + week).\n const groupByItems = Array.isArray(query.groupBy) ? (query.groupBy as any[]) : [];\n const granularityCaps: Record<string, boolean> | undefined =\n drv?.supports?.queryDateGranularity;\n const structuredItems = groupByItems.filter((g) => typeof g !== 'string');\n const allStructuredSupported = structuredItems.every((g: any) => {\n if (!g?.dateGranularity) return true; // plain {field} object is fine\n return granularityCaps?.[g.dateGranularity] === true;\n });\n if (typeof drv.aggregate === 'function' && allStructuredSupported) {\n return drv.aggregate(object, ast, this.buildDriverOptions(opCtx.context));\n }\n // In-memory fallback path: ask the driver for raw rows, then bucket +\n // aggregate here. This guarantees `groupBy` (incl. structured items\n // carrying `dateGranularity`) and `aggregations` always work even on\n // drivers that have no native aggregation support (driver-rest,\n // driver-memory, partial SQL drivers).\n const raw = await driver.find(object, ast, this.buildDriverOptions(opCtx.context));\n return applyInMemoryAggregation(raw, ast);\n });\n\n return opCtx.result as any[];\n }\n \n /**\n * Run raw driver-specific commands (SQL for SqlDriver, REST for RestDriver, …).\n *\n * ⚠️ **Tenant isolation bypass.** Raw `execute()` does NOT thread the\n * caller's `ExecutionContext.tenantId` into a `WHERE organization_id`\n * predicate — drivers see the command verbatim. Callers MUST inline the\n * tenant filter themselves, or restrict raw execution to genuinely global\n * statements (schema migrations, sys_* / control-plane tables).\n *\n * Prefer the typed entry points (`find`, `update`, `delete`, `count`, …)\n * whenever feasible — they auto-apply tenancy + soft-delete + audit warnings.\n */\n async execute(command: any, options?: Record<string, any>): Promise<any> {\n // Driver selection priority:\n // 1. options.object → route via getDriver(objectName)\n // 2. options.datasource → explicit driver name\n // 3. default driver (set via datasourceMapping or defaultDriver)\n // This lets system services (e.g. PackageService, AuditService) issue raw\n // SQL against the control-plane / default DB without having to know the\n // object name behind every CREATE TABLE / SELECT statement.\n let driver: DriverInterface | undefined;\n if (options?.object) {\n driver = this.getDriver(options.object);\n } else if (options?.datasource && this.drivers.has(options.datasource)) {\n driver = this.drivers.get(options.datasource);\n } else if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n driver = this.drivers.get(this.defaultDriver);\n } else if (this.drivers.size === 1) {\n // Single registered driver — unambiguously the right one.\n driver = this.drivers.values().next().value;\n }\n\n if (!driver) {\n throw new Error(\n 'Execute requires options.object to select a driver, or a default driver to be configured. ' +\n 'Configure datasourceMapping with `default: true` or pass `{ object }` / `{ datasource }` in options.',\n );\n }\n if (!driver.execute) {\n throw new Error('Selected driver does not implement execute()');\n }\n\n // Support both call shapes:\n // execute('SELECT ...', { args: [...] })\n // execute({ sql: 'SELECT ...', args: [...] })\n let rawCommand: any = command;\n let params: any[] | undefined = options?.args ?? options?.params;\n if (command && typeof command === 'object' && !Array.isArray(command) && 'sql' in command) {\n rawCommand = command.sql;\n if (params === undefined) {\n params = command.args ?? command.params;\n }\n }\n\n return driver.execute(rawCommand, params, options);\n }\n\n /**\n * Execute a callback inside a database transaction.\n *\n * The callback receives a context object that should be passed to all\n * downstream `engine.insert/update/delete/find/findOne` calls (as\n * `{ context: trxCtx }`). The transaction handle threads through\n * `OperationContext.context.transaction` and the SQL driver's per-builder\n * `.transacting(trx)` call.\n *\n * - If the default driver does not support `beginTransaction`, the callback\n * runs directly with the supplied base context (no rollback). This keeps\n * the API safe to call on drivers without ACID support (e.g. the\n * in-memory driver in tests).\n * - On callback success the transaction is committed; on any thrown error\n * it is rolled back and the original error is re-thrown.\n *\n * Use case: multi-step operations that must be atomic (e.g. CRM\n * `convertLead`, which creates an account + contact + opportunity + flips\n * the lead in a single unit of work).\n */\n async transaction<T>(\n callback: (trxCtx: any) => Promise<T>,\n baseContext?: any,\n ): Promise<T> {\n const driver = this.defaultDriver ? this.drivers.get(this.defaultDriver) : undefined;\n const drv = driver as any;\n if (!drv?.beginTransaction) {\n return callback(baseContext);\n }\n const trx = await drv.beginTransaction();\n const trxCtx = { ...(baseContext ?? {}), transaction: trx };\n try {\n // Run the callback inside the ambient transaction store so internal\n // queries during writes reuse this transaction's connection (ADR-0034).\n const result = await this.txStore.run({ transaction: trx }, () => callback(trxCtx));\n if (drv.commit) await drv.commit(trx);\n else if (drv.commitTransaction) await drv.commitTransaction(trx);\n return result;\n } catch (err) {\n try {\n if (drv.rollback) await drv.rollback(trx);\n else if (drv.rollbackTransaction) await drv.rollbackTransaction(trx);\n } catch {\n // swallow rollback failures so the original error surfaces\n }\n throw err;\n }\n }\n\n // ============================================\n // Compatibility / Convenience API\n // ============================================\n // These methods provide a higher-level API matching the @objectql/core\n // ObjectQL interface, enabling painless migration from the legacy layer.\n\n /**\n * Register a single object definition.\n * \n * Proxies to SchemaRegistry.registerObject() with sensible defaults.\n * Fields without a `name` property are auto-assigned from their key.\n */\n registerObject(\n schema: ServiceObject,\n packageId: string = '__runtime__',\n namespace?: string\n ): string {\n // Auto-assign field names from keys\n if (schema.fields) {\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field && typeof field === 'object' && !('name' in field)) {\n (field as any).name = key;\n }\n }\n }\n return this._registry.registerObject(schema, packageId, namespace);\n }\n\n /**\n * Unregister a single object by name.\n */\n unregisterObject(name: string, packageId?: string): void {\n if (packageId) {\n this._registry.unregisterObjectsByPackage(packageId);\n } else {\n // Remove from generic metadata as fallback\n this._registry.unregisterItem('object', name);\n }\n }\n\n /**\n * Get an object definition by name.\n * Alias for getSchema() — matches @objectql/core API.\n */\n getObject(name: string): ServiceObject | undefined {\n return this.getSchema(name);\n }\n\n /**\n * Get all registered object configs as a name→config map.\n * Matches @objectql/core getConfigs() API.\n */\n getConfigs(): Record<string, ServiceObject> {\n const result: Record<string, ServiceObject> = {};\n const objects = this._registry.getAllObjects();\n for (const obj of objects) {\n if (obj.name) {\n result[obj.name] = obj;\n }\n }\n return result;\n }\n\n /**\n * Get a registered driver by datasource name.\n * \n * Unlike the private getDriver() (which resolves by object name),\n * this method directly looks up a driver by its registered name.\n */\n getDriverByName(name: string): DriverInterface | undefined {\n return this.drivers.get(name);\n }\n\n /**\n * Introspect a datasource's live remote schema (ADR-0015).\n *\n * Resolves the driver registered under `datasource` and delegates to its\n * `introspectSchema()` capability. Used by the external-datasource service\n * (and CLI/REST) to list remote tables and validate federated objects.\n *\n * @throws if the datasource has no registered driver, or the driver does\n * not support introspection.\n */\n async introspectDatasource(datasource: string): Promise<unknown> {\n const driver = this.drivers.get(datasource) as any;\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${datasource}' has no registered driver to introspect.`);\n }\n if (typeof driver.introspectSchema !== 'function') {\n throw new Error(`[ObjectQL] Driver for datasource '${datasource}' does not support introspectSchema().`);\n }\n return driver.introspectSchema();\n }\n\n /**\n * Get the driver responsible for the given object.\n *\n * Resolves datasource binding from the object's schema definition,\n * falling back to the default driver. This is a public version of\n * the internal getDriver() used by CRUD operations.\n *\n * @param objectName - FQN or short name of the registered object.\n * @returns The resolved DriverInterface, or undefined if no driver is available.\n */\n getDriverForObject(objectName: string): DriverInterface | undefined {\n try {\n return this.getDriver(objectName);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Sync all registered object schemas to their respective drivers.\n * Call this after dynamically registering new objects at runtime\n * (e.g. after template seeding) to ensure tables/collections exist\n * before inserting seed data.\n */\n async syncSchemas(): Promise<void> {\n const allObjects = this._registry.getAllObjects();\n for (const obj of allObjects) {\n const driver = this.getDriverForObject(obj.name);\n if (!driver) continue;\n const tableName = StorageNameMapping.resolveTableName(obj);\n if (typeof (driver as any).syncSchemasBatch === 'function' && (driver as any).supports?.batchSchemaSync) {\n // Already handled per-driver below; skip individual call\n }\n if (typeof (driver as any).syncSchema === 'function') {\n try {\n await (driver as any).syncSchema(tableName, obj);\n } catch {\n // best effort — log suppressed to avoid noise on already-synced tables\n }\n }\n }\n }\n\n /**\n * Sync a SINGLE object's physical storage (create/alter its table) on\n * demand. Boot-time {@link syncSchemas} runs once at startup, so an object\n * that becomes live at runtime (e.g. publishing a drafted object) has a\n * registry entry but no table — data CRUD then fails with \"no such table\"\n * until the next restart. Calling this right after the object is registered\n * makes it immediately usable. Idempotent: the SQL driver only creates the\n * table when absent (and alters to add new columns).\n */\n async syncObjectSchema(objectName: string): Promise<void> {\n const obj = this._registry.getObject(objectName) as any;\n if (!obj) return;\n const driver = this.getDriverForObject(objectName);\n if (!driver || typeof (driver as any).syncSchema !== 'function') return;\n const tableName = StorageNameMapping.resolveTableName(obj);\n await (driver as any).syncSchema(tableName, obj);\n }\n\n /**\n * Drop the physical storage (table/collection) backing an object — the\n * inverse of {@link syncObjectSchema}. DESTRUCTIVE: deletes all rows in the\n * table. Used by the protocol delete path when the caller explicitly opts\n * into storage teardown (e.g. discarding an object that was published only\n * to preview it). No-op when the object's driver does not expose `dropTable`.\n * Resolves the physical table name from the registered definition, falling\n * back to the bare name if the def was already removed.\n */\n async dropObjectSchema(objectName: string): Promise<void> {\n const obj = this._registry.getObject(objectName) as any;\n const driver = this.getDriverForObject(objectName);\n if (!driver || typeof (driver as any).dropTable !== 'function') return;\n const tableName = StorageNameMapping.resolveTableName(obj ?? ({ name: objectName } as any));\n await (driver as any).dropTable(tableName);\n }\n\n /**\n * Get a registered driver by datasource name.\n * Alias matching @objectql/core datasource() API.\n *\n * @throws Error if the datasource is not found\n */\n datasource(name: string): DriverInterface {\n const driver = this.drivers.get(name);\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${name}' not found`);\n }\n return driver;\n }\n\n /**\n * Register a hook handler.\n * Convenience alias for registerHook() matching @objectql/core on() API.\n * \n * Usage:\n * ql.on('beforeInsert', 'user', async (ctx) => { ... });\n */\n on(\n event: string,\n objectName: string,\n handler: (ctx: HookContext) => Promise<void> | void,\n packageId?: string\n ): void {\n this.registerHook(event, handler, { object: objectName, packageId });\n }\n\n /**\n * Remove all hooks, actions, and objects contributed by a package.\n */\n removePackage(packageId: string): void {\n // Remove hooks\n for (const [key, handlers] of this.hooks.entries()) {\n const filtered = handlers.filter(h => h.packageId !== packageId);\n if (filtered.length !== handlers.length) {\n this.hooks.set(key, filtered);\n }\n }\n // Remove actions\n this.removeActionsByPackage(packageId);\n // Remove objects\n this._registry.unregisterObjectsByPackage(packageId, true);\n }\n\n /**\n * Gracefully shut down the engine, disconnecting all drivers.\n * Alias for destroy() — matches @objectql/core close() API.\n */\n async close(): Promise<void> {\n return this.destroy();\n }\n\n /**\n * Create a scoped execution context bound to this engine.\n * \n * Usage:\n * const ctx = engine.createContext({ userId: '...', tenantId: '...' });\n * const users = ctx.object('user');\n * await users.find({ filter: { status: 'active' } });\n */\n createContext(ctx: Partial<ExecutionContext>): ScopedContext {\n return new ScopedContext(\n ExecutionContextSchema.parse(ctx),\n this\n );\n }\n\n /**\n * Static factory: create a fully configured ObjectQL instance.\n * \n * Matches @objectql/core's `new ObjectQL(config)` pattern but also\n * registers drivers and objects, then calls init().\n * \n * Usage:\n * const ql = await ObjectQL.create({\n * datasources: { default: myDriver },\n * objects: { user: { name: 'user', fields: { ... } } }\n * });\n */\n static async create(config: {\n datasources?: Record<string, DriverInterface>;\n objects?: Record<string, ServiceObject>;\n hooks?: Array<{ event: string; object: string; handler: (ctx: HookContext) => Promise<void> | void }>;\n }): Promise<ObjectQL> {\n const ql = new ObjectQL();\n\n // Register drivers\n if (config.datasources) {\n for (const [name, driver] of Object.entries(config.datasources)) {\n // Set driver name if not already set\n if (!driver.name) {\n (driver as any).name = name;\n }\n ql.registerDriver(driver, name === 'default');\n }\n }\n\n // Register objects\n if (config.objects) {\n for (const [_key, schema] of Object.entries(config.objects)) {\n ql.registerObject(schema);\n }\n }\n\n // Register hooks\n if (config.hooks) {\n for (const hook of config.hooks) {\n ql.on(hook.event, hook.object, hook.handler);\n }\n }\n\n // Initialize (connect drivers)\n await ql.init();\n\n return ql;\n }\n}\n\n/**\n * Repository scoped to a single object, bound to an execution context.\n *\n * Provides both IDataEngine-style methods (find, insert, update, delete)\n * and convenience aliases (create, updateById, deleteById) matching\n * the @objectql/core ObjectRepository API.\n */\nexport class ObjectRepository {\n constructor(\n private objectName: string,\n private context: ExecutionContext,\n private engine: IDataEngine & { executeAction?: (o: string, a: string, c: any) => Promise<any> }\n ) {}\n\n async find(query: any = {}): Promise<any[]> {\n return this.engine.find(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async findOne(query: any = {}): Promise<any> {\n return this.engine.findOne(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async insert(data: any): Promise<any> {\n return this.engine.insert(this.objectName, data, {\n context: this.context,\n });\n }\n\n /** Alias for insert() — matches @objectql/core convention */\n async create(data: any): Promise<any> {\n return this.insert(data);\n }\n\n async update(data: any, options: any = {}): Promise<any> {\n return this.engine.update(this.objectName, data, {\n ...options,\n context: this.context,\n });\n }\n\n /** Update a single record by ID */\n async updateById(id: string | number, data: any): Promise<any> {\n return this.engine.update(this.objectName, { ...data, id: id }, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async delete(options: any = {}): Promise<any> {\n return this.engine.delete(this.objectName, {\n ...options,\n context: this.context,\n });\n }\n\n /** Delete a single record by ID */\n async deleteById(id: string | number): Promise<any> {\n return this.engine.delete(this.objectName, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async count(query: any = {}): Promise<number> {\n return this.engine.count(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Aggregate query */\n async aggregate(query: any = {}): Promise<any[]> {\n return this.engine.aggregate(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Execute a named action registered on this object */\n async execute(actionName: string, params?: any): Promise<any> {\n if (this.engine.executeAction) {\n return this.engine.executeAction(this.objectName, actionName, {\n ...params,\n userId: this.context.userId,\n tenantId: this.context.tenantId,\n roles: this.context.roles,\n });\n }\n throw new Error(`Actions not supported by engine`);\n }\n}\n\n/**\n * Scoped execution context with object() accessor.\n * \n * Provides identity (userId, tenantId/spaceId, roles),\n * repository access via object(), privilege escalation via sudo(),\n * and transactional execution via transaction().\n */\nexport class ScopedContext {\n constructor(\n private executionContext: ExecutionContext,\n private engine: IDataEngine\n ) {}\n\n /** Get a repository scoped to this context */\n object(name: string): ObjectRepository {\n return new ObjectRepository(name, this.executionContext, this.engine as any);\n }\n\n /** Create an elevated (system) context */\n sudo(): ScopedContext {\n return new ScopedContext(\n { ...this.executionContext, isSystem: true },\n this.engine\n );\n }\n\n /**\n * Execute a callback within a database transaction.\n *\n * The callback receives a new ScopedContext whose operations\n * share the same transaction handle. If the callback throws,\n * the transaction is rolled back; otherwise it is committed.\n *\n * Falls back to non-transactional execution if the driver\n * does not support transactions.\n */\n async transaction(callback: (trxCtx: ScopedContext) => Promise<any>): Promise<any> {\n const engine = this.engine as any;\n\n // Find the default driver for transaction support\n const driver = engine.defaultDriver\n ? engine.drivers?.get(engine.defaultDriver)\n : undefined;\n\n if (!driver?.beginTransaction) {\n // No transaction support — execute directly\n return callback(this);\n }\n\n const trx = await driver.beginTransaction();\n const trxCtx = new ScopedContext(\n { ...this.executionContext, transaction: trx },\n this.engine\n );\n // Share the engine's ambient transaction store so internal queries during\n // writes reuse this transaction's connection (ADR-0034).\n const txStore = (this.engine as any)?.txStore as\n | { run<R>(s: { transaction: unknown }, fn: () => R): R }\n | undefined;\n const runIn = <R>(fn: () => Promise<R>): Promise<R> =>\n txStore ? txStore.run({ transaction: trx }, fn) : fn();\n\n try {\n const result = await runIn(() => callback(trxCtx));\n if (driver.commit) await driver.commit(trx);\n else if (driver.commitTransaction) await driver.commitTransaction(trx);\n return result;\n } catch (error) {\n if (driver.rollback) await driver.rollback(trx);\n else if (driver.rollbackTransaction) await driver.rollbackTransaction(trx);\n throw error;\n }\n }\n\n get userId() { return this.executionContext.userId; }\n get tenantId() { return this.executionContext.tenantId; }\n /** Alias for tenantId — matches ObjectQLContext.spaceId convention */\n get spaceId() { return this.executionContext.tenantId; }\n get roles() { return this.executionContext.roles; }\n get isSystem() { return this.executionContext.isSystem; }\n\n /** Internal: expose the transaction handle for driver-level access */\n get transactionHandle() { return this.executionContext.transaction; }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Secret-field channel — helpers for the `secret` FieldType.\n *\n * A `secret` field (DB password, API key, token) is **reversible**: the engine\n * encrypts it on write via the registered `ICryptoProvider`, persists the\n * ciphertext as a `sys_secret` row, and stores only an opaque *ref* on the\n * business row. On read the ref is masked, never the plaintext. This mirrors\n * the Settings subsystem (`sys_setting.value_enc → sys_secret.id`), generalized\n * to object fields.\n *\n * Contrast with `password` — a one-way hash owned by the auth subsystem, never\n * decrypted. The two never share a code path.\n */\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n/**\n * Prefix marking a persisted field value as a `sys_secret` handle ref rather\n * than cleartext. Chosen to be unambiguous and human-greppable in a DB dump,\n * while making it obvious that the column holds no plaintext.\n */\nexport const SECRET_REF_PREFIX = 'secret:';\n\n/**\n * Value returned in place of a secret field on a normal read. Indicates\n * \"a secret is set\" without leaking the handle id or the plaintext. A field\n * with no stored secret resolves to `null` instead.\n */\nexport const SECRET_MASK = '••••••••';\n\n/** Wrap a `sys_secret` handle id as the opaque ref persisted on the row. */\nexport function makeSecretRef(handleId: string): string {\n return `${SECRET_REF_PREFIX}${handleId}`;\n}\n\n/** True when `value` is a secret ref previously produced by {@link makeSecretRef}. */\nexport function isSecretRef(value: unknown): value is string {\n return typeof value === 'string' && value.startsWith(SECRET_REF_PREFIX);\n}\n\n/** Extract the `sys_secret` handle id from a ref, or `null` when not a ref. */\nexport function parseSecretRef(value: unknown): string | null {\n return isSecretRef(value) ? (value as string).slice(SECRET_REF_PREFIX.length) : null;\n}\n\n/**\n * Collect the names of `secret`-typed fields declared on an object schema.\n * Returns an empty array when the schema has no fields or no secret fields —\n * callers can fast-path on `length === 0` to skip all crypto work.\n */\nexport function collectSecretFields(schema: ServiceObject | undefined | null): string[] {\n const fields = (schema as any)?.fields as Record<string, { type?: string }> | undefined;\n if (!fields) return [];\n const out: string[] = [];\n for (const [name, def] of Object.entries(fields)) {\n if (def && def.type === 'secret') out.push(name);\n }\n return out;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Declarative Hook Wrappers\n *\n * Turns a raw `HookHandler` into one that honours the declarative metadata\n * fields defined on `HookSchema` (`condition`, `async`, `retryPolicy`,\n * `timeout`, `onError`). This lives outside the engine's `triggerHooks`\n * loop so the engine stays minimal and the semantics are unit-testable in\n * isolation.\n *\n * The resulting wrapped handler keeps the original `(ctx) => Promise<void>`\n * signature, so `engine.registerHook` does not need to know anything about\n * the metadata-driven behaviours.\n */\nimport type { Hook, HookContext } from '@objectstack/spec/data';\nimport type { Expression } from '@objectstack/spec';\nimport type { HookHandler } from './engine.js';\nimport { ExpressionEngine } from '@objectstack/formula';\nimport { noopHookMetricsRecorder, type HookMetricsRecorder, type HookMetricOutcome } from './hook-metrics.js';\n\nexport interface WrapDeclarativeOptions {\n /** Logger for declarative-layer diagnostics (timeouts, retries, swallowed errors). */\n logger?: {\n debug: (msg: string, meta?: any) => void;\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n error: (msg: string, meta?: any) => void;\n };\n /** Optional per-execution metrics sink. Defaults to no-op. */\n metrics?: HookMetricsRecorder;\n}\n\nconst noopLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/**\n * Wrap a hook handler so it honours the declarative fields defined on\n * `HookSchema`. The wrapping order, from outermost to innermost, is:\n *\n * 1. condition → skip when formula evaluates falsy\n * 2. async → fire-and-forget (after* events only)\n * 3. retry → repeat on throw with backoff\n * 4. timeout → abort if handler runs too long\n * 5. onError → swallow when set to 'log'\n *\n * The condition formula is evaluated against the most useful record-shaped\n * payload available on the context (write payloads first, then `previous`,\n * then a flat merge of input). Read events typically have no record yet,\n * so a condition on a `beforeFind` will simply skip when no data is\n * present.\n */\nexport function wrapDeclarativeHook(\n meta: Hook,\n handler: HookHandler,\n opts: WrapDeclarativeOptions = {},\n): HookHandler {\n const logger = opts.logger ?? noopLogger;\n const metrics = opts.metrics ?? noopHookMetricsRecorder;\n const isAfterEvent = meta.events?.some((e) => typeof e === 'string' && e.startsWith('after')) ?? false;\n const hasBody = Boolean((meta as any).body);\n const labelFor = (ctx: HookContext) => ({\n hook: meta.name,\n object: ctx.object ?? (typeof (meta as any).object === 'string' ? (meta as any).object : undefined),\n event: ctx.event,\n body: hasBody,\n });\n\n // Pre-compile condition once so each invocation is cheap.\n let conditionFn: ((record: any) => boolean) | undefined;\n if (meta.condition) {\n // Accept either string shorthand or full Expression envelope.\n const expr: Expression = typeof meta.condition === 'string'\n ? { dialect: 'cel', source: meta.condition }\n : (meta.condition as Expression);\n if (expr.source && expr.source.trim()) {\n const check = ExpressionEngine.compile(expr);\n if (check.ok) {\n conditionFn = (record: any) => {\n const r = ExpressionEngine.evaluate<boolean>(expr, { record: record ?? {} });\n if (!r.ok) {\n logger.warn('[hook] condition evaluation failed; treating as false', {\n hook: meta.name,\n condition: expr.source,\n error: r.error.message,\n });\n return false;\n }\n return Boolean(r.value);\n };\n } else {\n logger.warn('[hook] condition formula failed to compile; condition ignored', {\n hook: meta.name,\n condition: expr.source,\n error: check.error.message,\n });\n }\n }\n }\n\n const retryMax = Math.max(0, Number(meta.retryPolicy?.maxRetries ?? 0));\n const retryBackoffMs = Math.max(0, Number(meta.retryPolicy?.backoffMs ?? 0));\n const timeoutMs = typeof meta.timeout === 'number' && meta.timeout > 0 ? meta.timeout : undefined;\n const onError = meta.onError ?? 'abort';\n // `async` is only meaningful for after* events; ignore on before* (we must\n // wait for the handler to potentially mutate ctx.input).\n const fireAndForget = Boolean(meta.async) && isAfterEvent;\n\n const runWithTimeout = async (ctx: HookContext): Promise<void> => {\n if (!timeoutMs) {\n await handler(ctx);\n return;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n Promise.resolve().then(() => handler(ctx)),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(`Hook '${meta.name}' timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n };\n\n const runWithRetry = async (ctx: HookContext): Promise<void> => {\n let attempt = 0;\n let lastErr: unknown;\n // attempts = 1 + retryMax\n while (attempt <= retryMax) {\n try {\n await runWithTimeout(ctx);\n return;\n } catch (err) {\n lastErr = err;\n attempt += 1;\n if (attempt > retryMax) break;\n if (retryBackoffMs > 0) {\n await new Promise((r) => setTimeout(r, retryBackoffMs * attempt));\n }\n try { metrics.recordRetry(labelFor(ctx), attempt); } catch { /* noop */ }\n logger.warn('[hook] retrying after failure', {\n hook: meta.name,\n attempt,\n maxRetries: retryMax,\n error: (err as any)?.message,\n });\n }\n }\n throw lastErr;\n };\n\n const runWithErrorPolicy = async (ctx: HookContext): Promise<void> => {\n try {\n await runWithRetry(ctx);\n } catch (err) {\n if (onError === 'log') {\n logger.error('[hook] handler failed (onError=log; suppressing)', {\n hook: meta.name,\n object: ctx.object,\n event: ctx.event,\n error: (err as any)?.message,\n });\n return;\n }\n throw err;\n }\n };\n\n return async (ctx: HookContext): Promise<void> => {\n // 1. Condition gate\n if (conditionFn) {\n const record = pickRecordPayload(ctx);\n if (!conditionFn(record)) {\n logger.debug('[hook] skipped by condition', {\n hook: meta.name,\n object: ctx.object,\n event: ctx.event,\n });\n try { metrics.recordSkip(labelFor(ctx), 'condition'); } catch { /* noop */ }\n return;\n }\n }\n\n const restore = installFlatInput(ctx);\n const startedAt = Date.now();\n\n const recordOutcome = (err?: any) => {\n const elapsed = Date.now() - startedAt;\n let outcome: HookMetricOutcome = 'success';\n if (err) {\n const msg = String(err?.message ?? err ?? '');\n if (/timed out after/i.test(msg)) outcome = 'timeout';\n else if (/capability|cap-rejection|capability_rejected/i.test(msg)) outcome = 'capability_rejected';\n else outcome = 'error';\n }\n try { metrics.recordExecution(labelFor(ctx), outcome, elapsed); } catch { /* noop */ }\n };\n\n try {\n // 2. Fire-and-forget for declarative async after* hooks\n if (fireAndForget) {\n try { metrics.recordSkip(labelFor(ctx), 'fire_and_forget'); } catch { /* noop */ }\n // For fire-and-forget we can't keep ctx.input swapped while the\n // engine moves on — copy what we need, restore, and run async.\n void runWithErrorPolicy(ctx)\n .then(() => recordOutcome())\n .catch((err) => {\n recordOutcome(err);\n logger.error('[hook] async handler error (fire-and-forget)', {\n hook: meta.name,\n error: (err as any)?.message,\n });\n });\n return;\n }\n\n try {\n await runWithErrorPolicy(ctx);\n recordOutcome();\n } catch (err) {\n recordOutcome(err);\n throw err;\n }\n } finally {\n restore();\n }\n };\n}\n\n/**\n * Swap `ctx.input` in place for a Proxy that exposes a flat record view\n * over the engine's `{ data, options, id? }` wrapper. Returns a function\n * that restores the original `ctx.input` reference. Reads of\n * `id` / `options` / `ast` / `data` fall through to the wrapper; reads\n * of any other key fall through to `data`. Writes always go to `data`\n * (creating it if missing) so the engine's downstream `input.data`\n * read picks up mutations made by user code as `input.field = value`.\n */\nfunction installFlatInput(ctx: HookContext): () => void {\n const raw: any = ctx.input ?? {};\n const looksWrapped =\n raw && typeof raw === 'object' &&\n ('data' in raw || 'options' in raw || 'id' in raw || 'ast' in raw);\n if (!looksWrapped) return () => {};\n\n const ensureData = (): Record<string, unknown> => {\n if (!raw.data || typeof raw.data !== 'object') {\n raw.data = {};\n }\n return raw.data as Record<string, unknown>;\n };\n\n const proxy = new Proxy(raw, {\n get(target, prop, receiver) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n return Reflect.get(target, prop, receiver);\n }\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) {\n return (data as any)[prop];\n }\n return Reflect.get(target, prop, receiver);\n },\n set(target, prop, value) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n (target as any)[prop] = value;\n return true;\n }\n ensureData()[prop as string] = value;\n return true;\n },\n has(target, prop) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n return prop in target;\n }\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) return true;\n return prop in target;\n },\n ownKeys(target) {\n // Only enumerate the flat record fields. Wrapper keys\n // (id/options/ast/data) remain accessible via dot/bracket notation\n // but are hidden from Object.keys/for-in so user code that does\n // `Object.keys(input).filter(k => input[k] !== previous[k])` only\n // sees actual record fields.\n const dataKeys = target.data && typeof target.data === 'object'\n ? Object.keys(target.data)\n : [];\n return Array.from(new Set(dataKeys));\n },\n getOwnPropertyDescriptor(target, prop) {\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) {\n return { configurable: true, enumerable: true, writable: true, value: (data as any)[prop] };\n }\n // Wrapper keys: still descriptors so `prop in input` works, but\n // marked non-enumerable so they don't appear in Object.keys().\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n const desc = Object.getOwnPropertyDescriptor(target, prop);\n return desc ? { ...desc, enumerable: false } : undefined;\n }\n return Object.getOwnPropertyDescriptor(target, prop);\n },\n });\n\n (ctx as any).input = proxy;\n return () => {\n (ctx as any).input = raw;\n };\n}\n\n/**\n * Choose the record-shaped object the condition formula should evaluate\n * against. Order:\n * 1. ctx.input.data — write operations carry the new record here\n * 2. ctx.previous — update/delete carry pre-image here\n * 3. ctx.input — fall back to flat input bag (read ops, custom shapes)\n */\nfunction pickRecordPayload(ctx: HookContext): any {\n const input: any = ctx.input ?? {};\n if (input && typeof input === 'object' && input.data && typeof input.data === 'object') {\n return input.data;\n }\n if (ctx.previous && typeof ctx.previous === 'object') {\n return ctx.previous;\n }\n return input;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Hook Execution Metrics\n *\n * Lightweight, transport-agnostic recorder interface for per-hook execution\n * counters and latencies. The default implementation is a no-op so the\n * engine pays zero cost when nobody is observing.\n *\n * Wire a real recorder by calling `engine.setHookMetricsRecorder(recorder)`.\n * The runtime / kernel can adapt this to Otel, Prometheus, StatsD, or\n * whatever telemetry pipeline ships with the deployment.\n *\n * Recorded events:\n * - `recordExecution(label, outcome, durationMs)`\n * outcome ∈ 'success' | 'error' | 'timeout' | 'capability_rejected'\n * - `recordSkip(label, reason)`\n * reason ∈ 'condition' | 'fire_and_forget'\n * - `recordRetry(label, attempt)`\n */\n\nexport type HookMetricOutcome =\n | 'success'\n | 'error'\n | 'timeout'\n | 'capability_rejected';\n\nexport type HookSkipReason = 'condition' | 'fire_and_forget';\n\nexport interface HookMetricLabel {\n /** Hook name (stable id from metadata). */\n hook: string;\n /** Object name the hook is bound to. May be undefined for global hooks. */\n object?: string;\n /** Lifecycle event (`beforeInsert`, `afterUpdate`, etc.). */\n event?: string;\n /** True when the handler comes from a metadata `body` (sandboxed JS). */\n body?: boolean;\n}\n\nexport interface HookMetricsRecorder {\n recordExecution(label: HookMetricLabel, outcome: HookMetricOutcome, durationMs: number): void;\n recordSkip(label: HookMetricLabel, reason: HookSkipReason): void;\n recordRetry(label: HookMetricLabel, attempt: number): void;\n}\n\nexport const noopHookMetricsRecorder: HookMetricsRecorder = {\n recordExecution: () => {},\n recordSkip: () => {},\n recordRetry: () => {},\n};\n\n/**\n * In-memory recorder useful for tests, dev-mode dashboards, and as a\n * starting point for adapter implementations. Aggregates counts + a\n * rolling sum of latency per (hook, outcome).\n */\nexport class InMemoryHookMetricsRecorder implements HookMetricsRecorder {\n private executions = new Map<string, { count: number; totalMs: number }>();\n private skips = new Map<string, number>();\n private retries = new Map<string, number>();\n\n recordExecution(label: HookMetricLabel, outcome: HookMetricOutcome, durationMs: number): void {\n const key = `${label.hook}|${outcome}`;\n const cur = this.executions.get(key) ?? { count: 0, totalMs: 0 };\n cur.count += 1;\n cur.totalMs += Math.max(0, durationMs);\n this.executions.set(key, cur);\n }\n\n recordSkip(label: HookMetricLabel, reason: HookSkipReason): void {\n const key = `${label.hook}|${reason}`;\n this.skips.set(key, (this.skips.get(key) ?? 0) + 1);\n }\n\n recordRetry(label: HookMetricLabel, _attempt: number): void {\n this.retries.set(label.hook, (this.retries.get(label.hook) ?? 0) + 1);\n }\n\n snapshot(): {\n executions: Array<{ hook: string; outcome: HookMetricOutcome; count: number; totalMs: number }>;\n skips: Array<{ hook: string; reason: HookSkipReason; count: number }>;\n retries: Array<{ hook: string; count: number }>;\n } {\n return {\n executions: Array.from(this.executions, ([key, v]) => {\n const [hook, outcome] = key.split('|');\n return { hook, outcome: outcome as HookMetricOutcome, count: v.count, totalMs: v.totalMs };\n }),\n skips: Array.from(this.skips, ([key, count]) => {\n const [hook, reason] = key.split('|');\n return { hook, reason: reason as HookSkipReason, count };\n }),\n retries: Array.from(this.retries, ([hook, count]) => ({ hook, count })),\n };\n }\n\n reset(): void {\n this.executions.clear();\n this.skips.clear();\n this.retries.clear();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Hook Binder\n *\n * Single, canonical entry point that turns declarative `Hook` metadata into\n * runtime registrations on the `ObjectQL` engine. Every metadata source —\n * `defineStack({ hooks })` (consumed by `AppPlugin`), the per-project\n * template seeder (`MultiProjectPlugin`), and the metadata service\n * (`ObjectQLPlugin.loadMetadataFromService`) — funnels through here so\n * that:\n *\n * - Inline function handlers and string-named handlers share one resolver.\n * - Declarative fields (`condition`, `async`, `retryPolicy`, `timeout`,\n * `onError`) are honoured uniformly via `wrapDeclarativeHook`.\n * - Hooks can be unregistered as a unit via `packageId`, enabling clean\n * hot-reload and app uninstall.\n *\n * The ObjectQL engine itself stays simple — it knows how to store and\n * trigger handlers, but knows nothing about declarative semantics. All\n * metadata-aware behaviour lives in this binder + the wrapper module.\n */\n\nimport type { Hook } from '@objectstack/spec/data';\nimport type { ObjectQL, HookHandler } from './engine.js';\nimport { wrapDeclarativeHook } from './hook-wrappers.js';\nimport type { HookMetricsRecorder } from './hook-metrics.js';\n\nexport interface BindHooksOptions {\n /** Owning package / app id — used for `unregisterHooksByPackage`. */\n packageId?: string;\n\n /**\n * Optional name → function map for resolving string `handler` references.\n * Typically supplied by `defineStack({ functions })` and merged with any\n * functions previously registered on the engine.\n */\n functions?: Record<string, HookHandler>;\n\n /**\n * Optional factory that converts a metadata-only `Hook.body` (L1 expression\n * or L2 sandboxed JS source) into an executable `HookHandler`. The runtime\n * package wires this up using `QuickJSScriptRunner`; objectql itself stays\n * sandbox-free so it can run in lightweight environments.\n *\n * If `hook.body` is set and this factory is missing, the hook is skipped\n * with a clear error.\n */\n bodyRunner?: (hook: Hook) => HookHandler | undefined;\n\n /**\n * When true, treat unresolved hooks (body present but no runner, or handler\n * string with no implementation) as fatal errors instead of warnings. Used\n * by production runtimes to fail fast on misconfiguration. Defaults false.\n */\n strict?: boolean;\n\n /**\n * When true, emit a deprecation warning for every hook that still relies\n * on a `handler` ref string instead of the metadata-only `body`. Used by\n * the CLI (compile time) and runtime (boot time) to nudge users away from\n * the legacy `.mjs` runtime bundle path. Defaults false.\n */\n warnLegacyHandler?: boolean;\n\n /** Per-hook execution metrics sink. Defaults to no-op. */\n metrics?: HookMetricsRecorder;\n\n /** Logger; defaults to a silent no-op. */\n logger?: {\n debug: (msg: string, meta?: any) => void;\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n error: (msg: string, meta?: any) => void;\n };\n}\n\nconst noopLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/** Counter for stats. */\nexport interface BindHooksResult {\n registered: number;\n skipped: number;\n errors: Array<{ hook: string; reason: string }>;\n}\n\n/**\n * Bind a list of declarative `Hook` definitions to a running ObjectQL engine.\n *\n * Idempotent on `(packageId, hook.name, event, object)`: re-binding the\n * same set after a hot reload first calls `unregisterHooksByPackage`\n * (when `packageId` is provided).\n */\nexport function bindHooksToEngine(\n engine: ObjectQL,\n hooks: Hook[] | undefined,\n opts: BindHooksOptions = {},\n): BindHooksResult {\n const logger = opts.logger ?? noopLogger;\n const result: BindHooksResult = { registered: 0, skipped: 0, errors: [] };\n\n if (!Array.isArray(hooks) || hooks.length === 0) {\n return result;\n }\n\n // Hot-reload friendly: drop anything we previously bound under this\n // packageId so the new set fully replaces the old.\n if (opts.packageId && typeof (engine as any).unregisterHooksByPackage === 'function') {\n try {\n (engine as any).unregisterHooksByPackage(opts.packageId);\n } catch (err: any) {\n logger.warn('[hook-binder] unregister-by-package failed; continuing', {\n packageId: opts.packageId,\n error: err?.message,\n });\n }\n }\n\n // Pre-load any inline functions supplied via `bundle.functions` so\n // string-handler resolution works.\n if (opts.functions && typeof (engine as any).registerFunction === 'function') {\n for (const [name, fn] of Object.entries(opts.functions)) {\n try {\n (engine as any).registerFunction(name, fn, opts.packageId);\n } catch (err: any) {\n logger.warn('[hook-binder] failed to register function', {\n name,\n error: err?.message,\n });\n }\n }\n }\n\n for (const hook of hooks) {\n try {\n const resolved = resolveHandler(engine, hook, opts);\n if (!resolved) {\n result.skipped += 1;\n const reason = (hook as any).body\n ? `hook body present but no bodyRunner supplied to bindHooksToEngine (runtime must wire QuickJSScriptRunner)`\n : typeof hook.handler === 'string'\n ? `unknown function '${hook.handler}'`\n : 'no handler';\n result.errors.push({ hook: hook.name, reason });\n if (opts.strict) {\n throw new Error(`[hook-binder] strict: cannot bind hook '${hook.name}': ${reason}`);\n }\n logger.warn('[hook-binder] skipping hook with unresolved handler', {\n hook: hook.name,\n handler: hook.handler,\n hasBody: Boolean((hook as any).body),\n });\n continue;\n }\n\n if (opts.warnLegacyHandler && !(hook as any).body && typeof hook.handler === 'string') {\n logger.warn('[hook-binder] DEPRECATED: hook uses legacy handler ref without body', {\n hook: hook.name,\n handler: hook.handler,\n hint: 'Move the handler source into Hook.body so the artifact stays metadata-only and the .mjs runtime bundle can be dropped.',\n });\n }\n\n const wrapped = wrapDeclarativeHook(hook, resolved, { logger, metrics: opts.metrics });\n const objects = normalizeObjects(hook.object);\n const events = Array.isArray(hook.events) ? hook.events : [];\n\n for (const event of events) {\n for (const object of objects) {\n engine.registerHook(event, wrapped, {\n object,\n priority: typeof hook.priority === 'number' ? hook.priority : 100,\n packageId: opts.packageId,\n // Reflect metadata so future tooling can introspect / unregister\n // and so we can detect duplicate name collisions.\n // The engine ignores unknown options today; this is forward-only.\n ...({ meta: hook, hookName: hook.name } as any),\n } as any);\n result.registered += 1;\n }\n }\n } catch (err: any) {\n result.errors.push({ hook: hook.name, reason: err?.message ?? String(err) });\n logger.error('[hook-binder] failed to bind hook', {\n hook: hook.name,\n error: err?.message,\n });\n }\n }\n\n if (result.registered > 0) {\n logger.debug('[hook-binder] hooks bound', {\n packageId: opts.packageId,\n registered: result.registered,\n skipped: result.skipped,\n });\n }\n\n return result;\n}\n\nfunction normalizeObjects(target: Hook['object']): string[] {\n if (Array.isArray(target)) return target.length > 0 ? target : ['*'];\n if (typeof target === 'string' && target.length > 0) return [target];\n return ['*'];\n}\n\nfunction resolveHandler(\n engine: ObjectQL,\n hook: Hook,\n opts: BindHooksOptions,\n): HookHandler | undefined {\n // Metadata-only body (L1 expression or L2 sandboxed JS) takes precedence\n // over the legacy `handler` field. This is the cloud-deployable path —\n // the body string ships inside the artifact JSON and runs under a\n // capability-gated sandbox supplied by the runtime.\n const body = (hook as any).body;\n if (body && typeof body === 'object') {\n let runner = opts.bodyRunner;\n if (typeof runner !== 'function') {\n const fallback = (engine as any)?._defaultBodyRunner;\n if (typeof fallback === 'function') runner = fallback;\n }\n if (typeof runner !== 'function') {\n return undefined;\n }\n const fn = runner(hook);\n if (typeof fn === 'function') return fn;\n return undefined;\n }\n\n const h = hook.handler;\n if (typeof h === 'function') return h as HookHandler;\n if (typeof h === 'string' && h.length > 0) {\n // Try the per-bundle map first (hot path during initial bind),\n // then fall back to whatever the engine already knows.\n const fromBundle = opts.functions?.[h];\n if (typeof fromBundle === 'function') return fromBundle;\n if (typeof (engine as any).resolveFunction === 'function') {\n const fn = (engine as any).resolveFunction(h);\n if (typeof fn === 'function') return fn as HookHandler;\n }\n }\n return undefined;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Record Validator\n *\n * Validates an incoming insert/update payload against the canonical\n * `Field` metadata of an `ObjectSchema`. Implements ROADMAP §M10.4 —\n * \"Zod-at-rest\" — but does not require constructing a Zod schema:\n * we walk the field map directly, which is both faster and lets us\n * produce per-field error envelopes shaped for REST consumption.\n *\n * Rules applied (in order, stop at first error per field):\n *\n * - `required` missing/null/empty-string is rejected (insert only;\n * PATCH validates only fields actually supplied)\n * - `maxLength` / `minLength` (text/textarea/email/url/phone/password)\n * - `min` / `max` (number/currency/percent/rating/slider)\n * - format email / url / phone (lightweight RFC-aware regex)\n * - select / multiselect: value must appear in `options`\n * - boolean / toggle: must coerce to boolean\n * - date / datetime: must be ISO-parsable\n *\n * System-injected fields (`id`, `created_at`, `created_by`,\n * `updated_at`, `updated_by`, `organization_id`) are never validated\n * here — the engine and the audit plugin manage them.\n *\n * On failure, a `ValidationError` is thrown with `.fields[]` holding\n * one entry per offending field. REST translates this into a\n * `400 { code: 'VALIDATION_FAILED', message, fields }` envelope so\n * the UI can highlight the specific input.\n */\n\nconst SKIP_FIELDS = new Set<string>([\n 'id', 'created_at', 'created_by', 'updated_at', 'updated_by',\n 'organization_id', 'tenant_id',\n]);\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n// Permissive URL pattern: accept any scheme:// + non-empty body so that\n// non-HTTP URIs used by drivers (libsql://, postgres://, mysql://, file://, s3://, …)\n// pass field-level validation. Stricter per-field checks can be enforced\n// via custom validators where needed.\nconst URL_RE = /^[a-z][a-z0-9+.\\-]*:\\/\\/[^\\s]+$/i;\nconst PHONE_RE = /^[+()\\-\\s\\d.]{5,}$/;\n\nexport interface FieldValidationError {\n field: string;\n code:\n | 'required'\n | 'min_length'\n | 'max_length'\n | 'min_value'\n | 'max_value'\n | 'invalid_email'\n | 'invalid_url'\n | 'invalid_phone'\n | 'invalid_number'\n | 'invalid_boolean'\n | 'invalid_date'\n | 'invalid_option'\n // Object-level validation rules (ADR-0020, see rule-validator.ts)\n | 'invalid_transition'\n | 'rule_violation'\n | 'invalid_format'\n | 'invalid_json'\n | 'json_schema_violation';\n message: string;\n /** Allowed values for select/multiselect, when applicable. */\n options?: string[];\n}\n\nexport class ValidationError extends Error {\n readonly code = 'VALIDATION_FAILED';\n readonly fields: FieldValidationError[];\n constructor(fields: FieldValidationError[]) {\n super(\n `Validation failed for ${fields.length} field(s): ` +\n fields.map((f) => `${f.field} (${f.code})`).join(', '),\n );\n this.name = 'ValidationError';\n this.fields = fields;\n }\n}\n\ntype Mode = 'insert' | 'update';\n\ninterface FieldDef {\n name?: string;\n type: string;\n required?: boolean;\n readonly?: boolean;\n system?: boolean;\n multiple?: boolean;\n maxLength?: number;\n minLength?: number;\n min?: number;\n max?: number;\n options?: Array<{ value: string | number; label?: string } | string | number>;\n}\n\nfunction isMissing(v: unknown): boolean {\n return v === undefined || v === null || (typeof v === 'string' && v.trim() === '');\n}\n\nfunction optionValues(options: FieldDef['options']): string[] {\n if (!Array.isArray(options)) return [];\n return options.map((o) =>\n typeof o === 'object' && o !== null ? String((o as any).value) : String(o),\n );\n}\n\nfunction validateOne(name: string, def: FieldDef, value: unknown): FieldValidationError | null {\n // ── required ────────────────────────────────────────────────────\n // `autonumber` is runtime-owned: the value is generated by the engine /\n // driver (the SQL driver assigns it from a persistent sequence AFTER this\n // validation runs), so a missing value is never a client error — see #1603.\n if (def.required && isMissing(value) && def.type !== 'autonumber') {\n return { field: name, code: 'required', message: `${name} is required` };\n }\n if (isMissing(value)) return null; // nothing else to check\n\n const t = def.type;\n\n // ── string types ────────────────────────────────────────────────\n if (t === 'text' || t === 'textarea' || t === 'email' || t === 'url' || t === 'phone' || t === 'password' || t === 'markdown' || t === 'html' || t === 'richtext' || t === 'code') {\n const s = typeof value === 'string' ? value : String(value);\n if (def.maxLength !== undefined && s.length > def.maxLength) {\n return { field: name, code: 'max_length', message: `${name} must be ≤ ${def.maxLength} characters (got ${s.length})` };\n }\n if (def.minLength !== undefined && s.length < def.minLength) {\n return { field: name, code: 'min_length', message: `${name} must be ≥ ${def.minLength} characters (got ${s.length})` };\n }\n if (t === 'email' && !EMAIL_RE.test(s)) {\n return { field: name, code: 'invalid_email', message: `${name} must be a valid email address` };\n }\n if (t === 'url' && !URL_RE.test(s)) {\n return { field: name, code: 'invalid_url', message: `${name} must be a valid URL (scheme://...)` };\n }\n if (t === 'phone' && !PHONE_RE.test(s)) {\n return { field: name, code: 'invalid_phone', message: `${name} must be a valid phone number` };\n }\n return null;\n }\n\n // ── number types ────────────────────────────────────────────────\n if (t === 'number' || t === 'currency' || t === 'percent' || t === 'rating' || t === 'slider') {\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) {\n return { field: name, code: 'invalid_number', message: `${name} must be a number` };\n }\n if (def.min !== undefined && n < def.min) {\n return { field: name, code: 'min_value', message: `${name} must be ≥ ${def.min}` };\n }\n if (def.max !== undefined && n > def.max) {\n return { field: name, code: 'max_value', message: `${name} must be ≤ ${def.max}` };\n }\n return null;\n }\n\n // ── boolean ────────────────────────────────────────────────────\n if (t === 'boolean' || t === 'toggle') {\n if (typeof value === 'boolean') return null;\n if (value === 0 || value === 1 || value === '0' || value === '1' || value === 'true' || value === 'false') return null;\n return { field: name, code: 'invalid_boolean', message: `${name} must be true or false` };\n }\n\n // ── date/datetime ───────────────────────────────────────────────\n if (t === 'date' || t === 'datetime' || t === 'time') {\n if (value instanceof Date) return null;\n if (typeof value === 'string' && !Number.isNaN(Date.parse(value))) return null;\n return { field: name, code: 'invalid_date', message: `${name} must be a valid ${t} (ISO-8601)` };\n }\n\n // ── select / multiselect / radio ────────────────────────────────\n if (t === 'select' || t === 'radio') {\n const allowed = optionValues(def.options);\n if (allowed.length > 0 && !allowed.includes(String(value))) {\n return { field: name, code: 'invalid_option', message: `${name} must be one of: ${allowed.join(', ')}`, options: allowed };\n }\n return null;\n }\n if (t === 'multiselect' || t === 'checkboxes' || t === 'tags') {\n const allowed = optionValues(def.options);\n if (allowed.length === 0) return null;\n const arr = Array.isArray(value) ? value : [value];\n for (const v of arr) {\n if (!allowed.includes(String(v))) {\n return { field: name, code: 'invalid_option', message: `${name}: \"${v}\" is not one of: ${allowed.join(', ')}`, options: allowed };\n }\n }\n return null;\n }\n\n // Other types (lookup, file, formula, json, location, etc.) — no\n // strict shape check at this layer; reference integrity is handled\n // elsewhere (lookup) and the rest are opaque payloads.\n return null;\n}\n\n/**\n * Validate a payload against a list of declared fields. `objectSchema`\n * comes from `ObjectQL.getRegistry().getObject(name)` and exposes a\n * `fields` map of `{ [fieldName]: FieldDef }`.\n *\n * Returns void on success; throws `ValidationError` on failure.\n */\nexport function validateRecord(\n objectSchema: { fields?: Record<string, FieldDef> } | undefined | null,\n data: Record<string, unknown> | undefined | null,\n mode: Mode,\n): void {\n if (!objectSchema?.fields || !data) return;\n\n const errors: FieldValidationError[] = [];\n const fields = objectSchema.fields;\n\n if (mode === 'insert') {\n // Walk all declared fields — required check applies even when\n // the caller didn't supply the field at all.\n for (const [name, def] of Object.entries(fields)) {\n if (SKIP_FIELDS.has(name)) continue;\n if (def.system || def.readonly) continue;\n const err = validateOne(name, def, data[name]);\n if (err) errors.push(err);\n }\n } else {\n // Update — validate only supplied fields, skip required check.\n for (const [name, value] of Object.entries(data)) {\n if (SKIP_FIELDS.has(name)) continue;\n const def = fields[name];\n if (!def) continue;\n if (def.system || def.readonly) continue;\n // Clone def with required=false so PATCH-omitted-fields don't 400.\n const err = validateOne(name, { ...def, required: false }, value);\n if (err) errors.push(err);\n }\n }\n\n if (errors.length > 0) throw new ValidationError(errors);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Validation-Rule Evaluator (ADR-0020)\n *\n * Where `record-validator.ts` checks field *shape* (types, lengths, option\n * membership), this module enforces the object-level **business rules**\n * declared in `ObjectSchema.validations` — the discriminated union of\n * `state_machine`, `cross_field`, `script`, … rules.\n *\n * Until ADR-0020 these rules were pure declaration: nothing on the write\n * path ever read `objectSchema.validations`, so a `state_machine` rule that\n * said \"an account can't jump from churned straight back to prospect\"\n * silently allowed exactly that. This evaluator closes that gap.\n *\n * ## What runs here\n *\n * - `state_machine` — the headline guardrail. On update, if the state field\n * changed and the new value is not in `transitions[oldValue]`, the write\n * is rejected. Needs the **prior** record (see plumbing note below).\n * - `script` / `cross_field` — CEL predicates. If the predicate evaluates\n * TRUE the rule is violated. These share the prior-record gap with\n * `state_machine` (a PATCH carries only changed fields), so they are\n * evaluated against the *merged* record `{ ...previous, ...patch }`.\n * - `format` — a single field's value against a regex and/or a named format\n * (`email` / `url` / `phone` / `json`). Only runs when the write touches\n * the field and the value is non-empty (emptiness is the field-shape\n * validator's job, not the format rule's).\n * - `json_schema` — a JSON field validated against a JSON Schema via ajv.\n * - `conditional` — evaluates the `when` CEL predicate and then recurses into\n * `then` (true) or `otherwise` (false). The nested rule's violation message\n * is surfaced; the *outer* conditional's `severity` decides whether it\n * blocks (so `when`-gated guards can be advisory as a unit).\n *\n * Every variant declared by `ValidationRuleSchema` is enforced here — the\n * schema deliberately excludes anything that would need I/O or a handler model\n * (uniqueness → DB index, async → form layer, custom → lifecycle hook), so\n * there are no silent no-ops.\n *\n * ## Execution-control semantics (from `BaseValidationSchema`)\n *\n * - `active: false` → rule skipped entirely.\n * - `events` → rule only runs for the matching write context\n * (`insert` / `update`). `delete` is not a write\n * payload context here.\n * - `priority` → rules evaluated low-number-first (stable).\n * - `severity` → only `error` blocks the write. `warning` / `info`\n * are logged (best-effort) and never throw.\n *\n * ## Fail-open for *broken* rules, fail-closed for *violated* rules\n *\n * A CEL predicate that cannot be evaluated (parse error, references an\n * unbound variable, …) is a broken rule, not a violated one — it is logged\n * and skipped rather than bricking every write to the object. A predicate\n * that evaluates cleanly to \"violated\", or a transition that is definitively\n * illegal, is fail-closed (the write is rejected).\n *\n * ## Prior-record plumbing\n *\n * `state_machine` and the field-spanning predicates are meaningful only with\n * the record's prior state. The engine fetches it once (see\n * `engine.update`) and threads it in via `opts.previous`. On `insert` there\n * is no prior state, so `state_machine` is a no-op (the field-level select\n * check already constrains the initial value to a declared option).\n */\n\nimport { ExpressionEngine } from '@objectstack/formula';\nimport type { Expression } from '@objectstack/spec';\nimport Ajv, { type ValidateFunction } from 'ajv';\nimport { ValidationError, type FieldValidationError } from './record-validator.js';\n\ntype Mode = 'insert' | 'update';\n\ninterface BaseRule {\n type: string;\n name: string;\n message: string;\n active?: boolean;\n events?: Array<'insert' | 'update' | 'delete'>;\n priority?: number;\n severity?: 'error' | 'warning' | 'info';\n}\n\ninterface StateMachineRule extends BaseRule {\n type: 'state_machine';\n field: string;\n transitions: Record<string, string[]>;\n}\n\ninterface PredicateRule extends BaseRule {\n type: 'script' | 'cross_field';\n condition: string | Expression;\n fields?: string[];\n}\n\ninterface FormatRule extends BaseRule {\n type: 'format';\n field: string;\n regex?: string;\n format?: 'email' | 'url' | 'phone' | 'json';\n}\n\ninterface JsonSchemaRule extends BaseRule {\n type: 'json_schema';\n field: string;\n schema: Record<string, unknown>;\n}\n\ninterface ConditionalRule extends BaseRule {\n type: 'conditional';\n when: string | Expression;\n then: BaseRule;\n otherwise?: BaseRule;\n}\n\n/**\n * Context threaded through every rule evaluation. `data` is the raw incoming\n * write (a PATCH on update); `merged` overlays it on the prior record so a\n * predicate referencing an unchanged field still sees its persisted value.\n * Field-scoped rules (`state_machine`, `format`, `json_schema`) key off `data`\n * to decide whether the write actually touched their field.\n */\ninterface RuleContext {\n data: Record<string, unknown>;\n merged: Record<string, unknown>;\n previous: Record<string, unknown> | undefined;\n mode: Mode;\n logger: EvaluateRulesOptions['logger'];\n}\n\n/**\n * Shared ajv instance. `strict: false` tolerates author-written JSON Schemas\n * that use vendor keywords; `compile` results are memoised per schema object\n * (see `jsonSchemaCache`) so we don't recompile on every write.\n */\nconst ajv = new Ajv({ allErrors: true, strict: false });\nconst jsonSchemaCache = new WeakMap<object, ValidateFunction>();\n\nexport interface EvaluateRulesOptions {\n /** Prior persisted record (update only). Absent on insert. */\n previous?: Record<string, unknown> | null;\n /** Optional logger for non-blocking diagnostics (broken rules, warnings). */\n logger?: { warn?: (msg: string, meta?: any) => void };\n}\n\n/**\n * Returns true when the object declares at least one validation rule whose\n * correct evaluation needs the prior record (so the engine knows whether the\n * extra fetch on the update path is worth it).\n */\nexport function needsPriorRecord(\n objectSchema: { validations?: unknown[]; fields?: Record<string, ConditionalFieldDef> } | undefined | null,\n): boolean {\n const rules = objectSchema?.validations;\n const ruleNeeds = Array.isArray(rules) && rules.some((r) => ruleNeedsPrior(r));\n return !!(ruleNeeds || fieldsNeedPrior(objectSchema?.fields));\n}\n\n/**\n * Strip fields whose `readonlyWhen` CEL predicate is TRUE for the (merged)\n * record from an UPDATE payload — the field is locked, so an incoming change is\n * ignored (the persisted value is kept) rather than rejected. Returns the same\n * object when nothing is locked, else a shallow copy with the locked keys\n * removed. A broken predicate is fail-open (the change is allowed through).\n */\nexport function stripReadonlyWhenFields(\n objectSchema: { fields?: Record<string, ConditionalFieldDef> } | undefined | null,\n data: Record<string, unknown> | undefined | null,\n previous: Record<string, unknown> | undefined | null,\n logger?: EvaluateRulesOptions['logger'],\n): Record<string, unknown> | undefined | null {\n const fields = objectSchema?.fields;\n if (!fields || !data) return data;\n const merged = { ...(previous ?? {}), ...data };\n let result = data;\n for (const [name, def] of Object.entries(fields)) {\n if (!def?.readonlyWhen || !(name in data)) continue;\n const res = ExpressionEngine.evaluate<boolean>(toExpression(def.readonlyWhen), {\n record: merged,\n previous: previous ?? undefined,\n });\n if (!res.ok) {\n logger?.warn?.(`readonlyWhen for '${name}' failed to evaluate — change allowed through`);\n continue;\n }\n if (res.value === true) {\n if (result === data) result = { ...data };\n delete (result as Record<string, unknown>)[name];\n logger?.warn?.(`Field '${name}' is read-only (readonlyWhen) — ignoring incoming change`);\n }\n }\n return result;\n}\n\n/**\n * A rule needs the prior record if it reasons about the transition or compares\n * against unchanged fields (`state_machine` / `cross_field` / `script`), or if\n * it is a `conditional` whose branches (or `when`) recursively do. `format` and\n * `json_schema` only inspect the incoming value, so they never need it.\n */\nfunction ruleNeedsPrior(r: unknown): boolean {\n if (r == null || typeof r !== 'object') return false;\n const type = (r as BaseRule).type;\n if (type === 'state_machine' || type === 'cross_field' || type === 'script') {\n return true;\n }\n if (type === 'conditional') {\n const c = r as ConditionalRule;\n // `when` is evaluated against the merged record; the branches may need prior\n // state. Be conservative and fetch if either branch does.\n return ruleNeedsPrior(c.then) || ruleNeedsPrior(c.otherwise);\n }\n return false;\n}\n\n/** Field-level conditional rules (B2): a field is required / read-only when its\n * CEL predicate is TRUE over the record. */\ninterface ConditionalFieldDef {\n requiredWhen?: string | Expression;\n conditionalRequired?: string | Expression; // back-compat alias of requiredWhen\n readonlyWhen?: string | Expression;\n}\n\nfunction isMissing(v: unknown): boolean {\n return v === undefined || v === null || (typeof v === 'string' && v.trim() === '');\n}\n\n/** True when any field declares a conditional rule that needs the merged/prior\n * record to evaluate (so the engine fetches `previous` on update). */\nfunction fieldsNeedPrior(fields: Record<string, ConditionalFieldDef> | undefined): boolean {\n if (!fields) return false;\n return Object.values(fields).some(\n (f) => f && (f.requiredWhen || f.conditionalRequired || f.readonlyWhen),\n );\n}\n\n/** Normalize an author-time ExpressionInput into the canonical envelope. */\nfunction toExpression(cond: string | Expression): Expression {\n return typeof cond === 'string' ? { dialect: 'cel', source: cond } : cond;\n}\n\n/**\n * Evaluate an object's declared validation rules against an incoming write.\n *\n * Throws `ValidationError` (the same envelope `validateRecord` uses, so REST\n * surfaces a single `400 VALIDATION_FAILED`) when one or more `error`-severity\n * rules are violated. Returns void otherwise.\n */\nexport function evaluateValidationRules(\n objectSchema: { validations?: unknown[]; fields?: Record<string, ConditionalFieldDef> } | undefined | null,\n data: Record<string, unknown> | undefined | null,\n mode: Mode,\n opts: EvaluateRulesOptions = {},\n): void {\n if (!data) return;\n const rules = objectSchema?.validations;\n const hasRules = Array.isArray(rules) && rules.length > 0;\n const fields = objectSchema?.fields;\n const hasFieldRules = fieldsNeedPrior(fields);\n if (!hasRules && !hasFieldRules) return;\n\n const previous = opts.previous ?? undefined;\n // Merged view used by predicate rules: prior state overlaid with the PATCH,\n // so a rule referencing an unchanged field still sees its persisted value.\n const merged: Record<string, unknown> = { ...(previous ?? {}), ...data };\n const ctx: RuleContext = { data, merged, previous, mode, logger: opts.logger };\n\n const errors: FieldValidationError[] = [];\n\n // Field-level conditional rules (B2): a field whose `requiredWhen`\n // (or its `conditionalRequired` alias) predicate is TRUE over the merged\n // record must have a value — enforced server-side so the rule can't be\n // bypassed. (`readonlyWhen` is handled by stripReadonlyWhenFields on the\n // write path, not here.) A broken predicate is fail-open (logged, skipped).\n if (hasFieldRules && fields) {\n for (const [name, def] of Object.entries(fields)) {\n const pred = def?.requiredWhen ?? def?.conditionalRequired;\n if (!pred) continue;\n const res = ExpressionEngine.evaluate<boolean>(toExpression(pred), { record: merged, previous });\n if (!res.ok) {\n opts.logger?.warn?.(`requiredWhen for '${name}' failed to evaluate — skipped`);\n continue;\n }\n if (res.value === true && isMissing(merged[name])) {\n errors.push({ field: name, code: 'required', message: `${name} is required` });\n }\n }\n }\n\n const ordered = (hasRules ? rules! : [])\n .filter((r): r is BaseRule => r != null && typeof r === 'object')\n .filter((r) => r.active !== false)\n .filter((r) => {\n const events = r.events ?? ['insert', 'update'];\n return events.includes(mode);\n })\n .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));\n\n for (const rule of ordered) {\n let violation: FieldValidationError | null = null;\n try {\n violation = evaluateRule(rule, ctx);\n } catch (err) {\n // Defensive: a broken rule must never brick a write.\n opts.logger?.warn?.(`Validation rule '${rule.name}' threw — skipped`, err);\n continue;\n }\n\n if (!violation) continue;\n\n const severity = rule.severity ?? 'error';\n if (severity === 'error') {\n errors.push(violation);\n } else {\n opts.logger?.warn?.(\n `Validation rule '${rule.name}' (${severity}): ${violation.message}`,\n );\n }\n }\n\n if (errors.length > 0) throw new ValidationError(errors);\n}\n\n/**\n * Dispatch a single rule to its checker, returning the violation (or null).\n * Shared by the top-level loop and by `checkConditional`, which recurses into\n * its `then` / `otherwise` branch. Unknown types return null — but the schema\n * (`ValidationRuleSchema`) only admits the types handled below, so in practice\n * every declared rule is covered.\n */\nfunction evaluateRule(rule: BaseRule, ctx: RuleContext): FieldValidationError | null {\n switch (rule.type) {\n case 'state_machine':\n return checkStateMachine(rule as StateMachineRule, ctx.mode, ctx.data, ctx.previous);\n case 'script':\n case 'cross_field':\n return checkPredicate(rule as PredicateRule, ctx.merged, ctx.previous, ctx.logger);\n case 'format':\n return checkFormat(rule as FormatRule, ctx.data, ctx.logger);\n case 'json_schema':\n return checkJsonSchema(rule as JsonSchemaRule, ctx.data, ctx.logger);\n case 'conditional':\n return checkConditional(rule as ConditionalRule, ctx);\n default:\n return null;\n }\n}\n\n/**\n * State-machine transition check.\n *\n * Only meaningful on update with a prior record: if the state field changed,\n * the new value must appear in `transitions[oldValue]`. Lenient where it\n * cannot reason (no prior record, unchanged value, or a prior state with no\n * declared transitions) so it never blocks legitimate or legacy data.\n */\nfunction checkStateMachine(\n rule: StateMachineRule,\n mode: Mode,\n data: Record<string, unknown>,\n previous: Record<string, unknown> | undefined,\n): FieldValidationError | null {\n // Insert has no prior state — the field-level select check already\n // constrains the initial value to a declared option.\n if (mode === 'insert' || !previous) return null;\n // The PATCH didn't touch the state field → no transition to validate.\n if (!(rule.field in data)) return null;\n\n const from = previous[rule.field];\n const to = data[rule.field];\n // No change, or clearing the value → nothing to enforce.\n if (from === to || to === undefined || to === null) return null;\n\n const fromKey = String(from);\n const allowed = rule.transitions[fromKey];\n // Prior state not described by the FSM (legacy / external write) — cannot\n // reason about its legal targets, so don't block.\n if (!Array.isArray(allowed)) return null;\n\n if (!allowed.includes(String(to))) {\n return {\n field: rule.field,\n code: 'invalid_transition',\n message:\n rule.message ||\n `Invalid transition for ${rule.field}: ${fromKey} → ${String(to)}`,\n };\n }\n return null;\n}\n\n/**\n * CEL predicate check (`script` / `cross_field`). The predicate expresses the\n * *failure* condition: if it evaluates TRUE the rule is violated. An\n * un-evaluable predicate is treated as a broken rule (logged, skipped).\n */\nfunction checkPredicate(\n rule: PredicateRule,\n record: Record<string, unknown>,\n previous: Record<string, unknown> | undefined,\n logger: EvaluateRulesOptions['logger'],\n): FieldValidationError | null {\n const expr = toExpression(rule.condition);\n const result = ExpressionEngine.evaluate<boolean>(expr, {\n record,\n previous: previous ?? undefined,\n });\n\n if (!result.ok) {\n logger?.warn?.(\n `Validation rule '${rule.name}' predicate failed to evaluate (${result.error.kind}: ${result.error.message}) — skipped`,\n );\n return null;\n }\n\n if (result.value === true) {\n return {\n field: rule.fields?.[0] ?? '_record',\n code: 'rule_violation',\n message: rule.message,\n };\n }\n return null;\n}\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n// Lenient phone matcher: optional leading +, then 7–20 digits with spaces,\n// dashes, dots and parens allowed as separators. Intentionally permissive —\n// strict national formats belong in a `regex`.\nconst PHONE_RE = /^\\+?[\\d\\s().-]{7,20}$/;\n\n/**\n * Format check (`format`). Validates a single field's value against an optional\n * `regex` and/or a named `format`. Only runs when the write touches the field\n * (mirrors `state_machine`) and the value is non-empty — requiredness and\n * type-shape are the field-level validator's job, so an absent/blank value is\n * not a *format* violation. A malformed `regex` is a broken rule (logged,\n * fail-open), not a violation.\n */\nfunction checkFormat(\n rule: FormatRule,\n data: Record<string, unknown>,\n logger: EvaluateRulesOptions['logger'],\n): FieldValidationError | null {\n if (!(rule.field in data)) return null;\n const value = data[rule.field];\n if (value === null || value === undefined || value === '') return null;\n const str = String(value);\n\n if (rule.regex) {\n let re: RegExp;\n try {\n re = new RegExp(rule.regex);\n } catch {\n logger?.warn?.(`Validation rule '${rule.name}' has an invalid regex — skipped`);\n return null;\n }\n if (!re.test(str)) return formatViolation(rule);\n }\n\n if (rule.format && !matchesNamedFormat(rule.format, str)) {\n return formatViolation(rule);\n }\n return null;\n}\n\nfunction matchesNamedFormat(format: FormatRule['format'], str: string): boolean {\n switch (format) {\n case 'email':\n return EMAIL_RE.test(str);\n case 'phone':\n return PHONE_RE.test(str);\n case 'url':\n try {\n // eslint-disable-next-line no-new\n new URL(str);\n return true;\n } catch {\n return false;\n }\n case 'json':\n try {\n JSON.parse(str);\n return true;\n } catch {\n return false;\n }\n default:\n return true;\n }\n}\n\nfunction formatViolation(rule: FormatRule): FieldValidationError {\n return { field: rule.field, code: 'invalid_format', message: rule.message };\n}\n\n/**\n * JSON Schema check (`json_schema`). Validates a JSON field against the rule's\n * schema via ajv. The field value may be a parsed object or a JSON string (a\n * string that fails to parse is itself a violation). Only runs when the write\n * touches the field and the value is non-null. A schema ajv cannot compile is a\n * broken rule (logged, fail-open).\n */\nfunction checkJsonSchema(\n rule: JsonSchemaRule,\n data: Record<string, unknown>,\n logger: EvaluateRulesOptions['logger'],\n): FieldValidationError | null {\n if (!(rule.field in data)) return null;\n let value = data[rule.field];\n if (value === null || value === undefined) return null;\n\n if (typeof value === 'string') {\n try {\n value = JSON.parse(value);\n } catch {\n return { field: rule.field, code: 'invalid_json', message: rule.message };\n }\n }\n\n let validate = jsonSchemaCache.get(rule.schema);\n if (!validate) {\n try {\n validate = ajv.compile(rule.schema);\n } catch (err) {\n logger?.warn?.(\n `Validation rule '${rule.name}' has an uncompilable JSON Schema — skipped`,\n err,\n );\n return null;\n }\n jsonSchemaCache.set(rule.schema, validate);\n }\n\n if (!validate(value)) {\n return { field: rule.field, code: 'json_schema_violation', message: rule.message };\n }\n return null;\n}\n\n/**\n * Conditional check (`conditional`). Evaluates the `when` predicate against the\n * merged record, then recurses into `then` (true) or `otherwise` (false) via\n * `evaluateRule`. An un-evaluable `when` is a broken rule (logged, fail-open).\n * The nested rule supplies the violation (field/code/message); the *outer*\n * conditional's `severity` governs whether it blocks (handled by the caller).\n */\nfunction checkConditional(\n rule: ConditionalRule,\n ctx: RuleContext,\n): FieldValidationError | null {\n const result = ExpressionEngine.evaluate<boolean>(toExpression(rule.when), {\n record: ctx.merged,\n previous: ctx.previous ?? undefined,\n });\n\n if (!result.ok) {\n ctx.logger?.warn?.(\n `Validation rule '${rule.name}' when-predicate failed to evaluate (${result.error.kind}: ${result.error.message}) — skipped`,\n );\n return null;\n }\n\n const branch = result.value === true ? rule.then : rule.otherwise;\n if (!branch || branch.active === false) return null;\n return evaluateRule(branch, ctx);\n}\n\n/**\n * Introspection helper (ADR-0020 D3.3): given an object's schema, a state\n * field, and a current state, return the legal next states declared by the\n * matching `state_machine` rule. Returns `null` when no such rule exists (so\n * callers can distinguish \"no FSM governs this field\" from \"a dead-end state\n * with zero outgoing transitions\", which returns `[]`).\n */\nexport function legalNextStates(\n objectSchema: { validations?: unknown[] } | undefined | null,\n field: string,\n currentState: string,\n): string[] | null {\n const rules = objectSchema?.validations;\n if (!Array.isArray(rules)) return null;\n const rule = rules.find(\n (r): r is StateMachineRule =>\n r != null &&\n typeof r === 'object' &&\n (r as BaseRule).type === 'state_machine' &&\n (r as StateMachineRule).field === field,\n );\n if (!rule) return null;\n return rule.transitions[currentState] ?? [];\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n//\n// In-memory implementation of the QueryAST aggregation contract.\n//\n// This module is the engine's last-resort path: when the underlying driver\n// returned raw rows but the caller asked for `groupBy` / `aggregations`, the\n// engine pipes the rows through here so the abstract contract is always\n// honoured even on drivers without native aggregation (driver-rest, partial\n// SQL drivers, mock drivers in tests).\n//\n// Capabilities:\n// * Flat groupBy strings: `['region']`\n// * Structured groupBy with date bucketing: `[{ field: 'closed_at',\n// dateGranularity: 'quarter' }]`\n// * Aggregation functions: count, count_distinct, sum, avg, min, max,\n// array_agg, string_agg\n// * `distinct: true` on aggregations (collapse duplicates before applying\n// the function)\n// * `filter: FilterCondition` on aggregations is **not** evaluated here —\n// the engine routes filtered aggregations through the driver where\n// possible; the in-memory fallback ignores the per-aggregation filter and\n// logs a warning if one is present.\n//\n// Date bucketing uses ISO-8601 conventions (weeks start Monday). Null /\n// invalid values bucket as the literal string `'(null)'` to remain\n// consistent with the client `useReportData` hook.\n\nimport type { QueryAST, GroupByNode, AggregationNode, DateGranularityValue } from '@objectstack/spec/data';\n\n/**\n * Group + aggregate raw rows according to the AST's `groupBy` /\n * `aggregations`. When neither is present, returns the rows unchanged.\n */\nexport function applyInMemoryAggregation(\n rows: any[],\n ast: Pick<QueryAST, 'groupBy' | 'aggregations'>,\n): any[] {\n const groupBy = (ast.groupBy ?? []) as GroupByNode[];\n const aggregations = (ast.aggregations ?? []) as AggregationNode[];\n if (groupBy.length === 0 && aggregations.length === 0) return rows;\n\n if (groupBy.length === 0) {\n // Pure aggregation — single result row.\n return [aggregateBucket(rows, aggregations)];\n }\n\n const buckets = new Map<string, { key: Record<string, any>; rows: any[] }>();\n for (const row of rows) {\n const key: Record<string, any> = {};\n const parts: string[] = [];\n for (const g of groupBy) {\n const fieldName = typeof g === 'string' ? g : (g.alias ?? g.field);\n const value = projectGroupValue(row, g);\n key[fieldName] = value;\n parts.push(`${fieldName}=${value}`);\n }\n const id = parts.join('\\u0001');\n let bucket = buckets.get(id);\n if (!bucket) {\n bucket = { key, rows: [] };\n buckets.set(id, bucket);\n }\n bucket.rows.push(row);\n }\n\n const out: any[] = [];\n for (const { key, rows: bucketRows } of buckets.values()) {\n const aggValues = aggregateBucket(bucketRows, aggregations);\n out.push({ ...key, ...aggValues });\n }\n return out;\n}\n\nfunction projectGroupValue(row: any, g: GroupByNode): string {\n const field = typeof g === 'string' ? g : g.field;\n const v = row?.[field];\n if (typeof g !== 'string' && g.dateGranularity) {\n return bucketDateValue(v, g.dateGranularity);\n }\n return v == null ? '(null)' : String(v);\n}\n\nfunction aggregateBucket(rows: any[], aggregations: AggregationNode[]): Record<string, any> {\n const out: Record<string, any> = {};\n for (const agg of aggregations) {\n const alias = agg.alias;\n const fn = agg.function;\n if (fn === 'count') {\n if (!agg.field) {\n out[alias] = rows.length;\n } else {\n out[alias] = rows.reduce(\n (acc, r) => (r[agg.field as string] != null ? acc + 1 : acc),\n 0,\n );\n }\n continue;\n }\n const field = agg.field;\n if (!field) {\n out[alias] = null;\n continue;\n }\n const values = collectValues(rows, field, !!agg.distinct);\n\n switch (fn) {\n case 'count_distinct':\n out[alias] = new Set(values.filter((v) => v != null)).size;\n break;\n case 'sum':\n out[alias] = values.reduce((a, b) => a + toNumber(b), 0);\n break;\n case 'avg': {\n const nums = values.filter((v) => v != null).map(toNumber);\n out[alias] = nums.length === 0 ? null : nums.reduce((a, b) => a + b, 0) / nums.length;\n break;\n }\n case 'min': {\n const defined = values.filter((v) => v != null);\n out[alias] = defined.length === 0 ? null : defined.reduce((a, b) => (a < b ? a : b));\n break;\n }\n case 'max': {\n const defined = values.filter((v) => v != null);\n out[alias] = defined.length === 0 ? null : defined.reduce((a, b) => (a > b ? a : b));\n break;\n }\n case 'array_agg':\n out[alias] = values.slice();\n break;\n case 'string_agg':\n out[alias] = values.filter((v) => v != null).map(String).join(',');\n break;\n default:\n out[alias] = null;\n }\n }\n return out;\n}\n\nfunction collectValues(rows: any[], field: string, distinct: boolean): any[] {\n if (!distinct) return rows.map((r) => r?.[field]);\n const seen = new Set<unknown>();\n const out: any[] = [];\n for (const r of rows) {\n const v = r?.[field];\n if (seen.has(v)) continue;\n seen.add(v);\n out.push(v);\n }\n return out;\n}\n\nfunction toNumber(v: any): number {\n if (typeof v === 'number') return v;\n if (v == null) return 0;\n const n = Number(v);\n return Number.isFinite(n) ? n : 0;\n}\n\n/**\n * Bucket a date-like value into an ISO-formatted period label. Weeks start\n * Monday and use ISO week numbering.\n */\nexport function bucketDateValue(value: unknown, granularity: DateGranularityValue): string {\n if (value == null) return '(null)';\n const d = value instanceof Date ? value : new Date(String(value));\n if (Number.isNaN(d.getTime())) return '(null)';\n const y = d.getUTCFullYear();\n const m = d.getUTCMonth() + 1;\n switch (granularity) {\n case 'year':\n return String(y);\n case 'quarter':\n return `${y}-Q${Math.floor((m - 1) / 3) + 1}`;\n case 'month':\n return `${y}-${String(m).padStart(2, '0')}`;\n case 'day':\n return `${y}-${String(m).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;\n case 'week': {\n // ISO-8601 week date: week 1 contains the first Thursday of the year.\n const target = new Date(Date.UTC(y, d.getUTCMonth(), d.getUTCDate()));\n const dayNum = (target.getUTCDay() + 6) % 7; // Mon=0..Sun=6\n target.setUTCDate(target.getUTCDate() - dayNum + 3);\n const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4));\n const weekNo = 1 + Math.round(\n ((target.getTime() - firstThursday.getTime()) / 86400000 - 3 + ((firstThursday.getUTCDay() + 6) % 7)) / 7,\n );\n return `${target.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;\n }\n default:\n return String(value);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * MetadataFacade\n *\n * Provides a clean, injectable interface over SchemaRegistry.\n * Registered as the 'metadata' kernel service to eliminate\n * downstream packages needing to manually wrap SchemaRegistry.\n *\n * Implements the async IMetadataService interface.\n * Internally delegates to SchemaRegistry (in-memory) with Promise wrappers.\n *\n * Each facade is bound to a specific SchemaRegistry instance — passed in the\n * constructor — so that multi-kernel servers can give every kernel its own\n * metadata surface without leaking state across tenants.\n */\nexport class MetadataFacade {\n constructor(private registry: SchemaRegistry) {}\n\n /**\n * Register a metadata item\n */\n async register(type: string, name: string, data: any): Promise<void> {\n const definition = typeof data === 'object' && data !== null\n ? { ...data, name: data.name ?? name }\n : data;\n if (type === 'object') {\n this.registry.registerItem(type, definition, 'name' as any);\n } else {\n this.registry.registerItem(type, definition, definition.id ? 'id' as any : 'name' as any);\n }\n }\n\n /**\n * Get a metadata item by type and name\n */\n async get(type: string, name: string): Promise<any> {\n const item = this.registry.getItem(type, name) as any;\n return item?.content ?? item;\n }\n\n /**\n * Get the raw entry (with metadata wrapper)\n */\n getEntry(type: string, name: string): any {\n return this.registry.getItem(type, name);\n }\n\n /**\n * List all items of a type\n */\n async list(type: string): Promise<any[]> {\n const items = this.registry.listItems(type);\n return items.map((item: any) => item?.content ?? item);\n }\n\n /**\n * Unregister a metadata item\n */\n async unregister(type: string, name: string): Promise<void> {\n this.registry.unregisterItem(type, name);\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n const item = this.registry.getItem(type, name);\n return item !== undefined && item !== null;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const items = this.registry.listItems(type);\n return items.map((item: any) => item?.name ?? item?.content?.name ?? '').filter(Boolean);\n }\n\n /**\n * Unregister all metadata from a package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n this.registry.unregisterObjectsByPackage(packageName);\n }\n\n /**\n * Convenience: get object definition\n */\n async getObject(name: string): Promise<any> {\n return this.registry.getObject(name);\n }\n\n /**\n * Convenience: list all objects\n */\n async listObjects(): Promise<any[]> {\n return this.registry.getAllObjects();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectQL } from './engine.js';\nimport { ObjectStackProtocolImplementation } from './protocol.js';\nimport { Plugin, PluginContext } from '@objectstack/core';\nimport { StorageNameMapping } from '@objectstack/spec/system';\nimport {\n SysMetadataObject,\n SysMetadataHistoryObject,\n SysMetadataAuditObject,\n SysViewDefinitionObject,\n} from '@objectstack/metadata-core';\n\nexport type { Plugin, PluginContext };\n\n/**\n * Protocol extension for DB-based metadata hydration.\n * `loadMetaFromDb` is implemented by ObjectStackProtocolImplementation but\n * is NOT (yet) part of the canonical ObjectStackProtocol wire-contract in\n * `@objectstack/spec`, since it is a server-side bootstrap concern only.\n */\ninterface ProtocolWithDbRestore {\n loadMetaFromDb(): Promise<{ loaded: number; errors: number }>;\n}\n\n/** Type guard — checks whether the service exposes `loadMetaFromDb`. */\nfunction hasLoadMetaFromDb(service: unknown): service is ProtocolWithDbRestore {\n return (\n typeof service === 'object' &&\n service !== null &&\n typeof (service as Record<string, unknown>)['loadMetaFromDb'] === 'function'\n );\n}\n\n/**\n * Options for ObjectQLPlugin.\n *\n * `environmentId` scopes all metadata writes + reads to a specific project.\n * When set, `protocol.saveMetaItem` stamps `environment_id = <environmentId>` on\n * new sys_metadata rows, and `protocol.loadMetaFromDb` filters by the same\n * column. Leave undefined in single-kernel / self-hosted mode — rows land\n * in the platform-global scope (environment_id IS NULL).\n */\nexport interface ObjectQLPluginOptions {\n /** Optional pre-built engine. When absent, one is lazily created in init. */\n ql?: ObjectQL;\n /** Passed to `new ObjectQL(...)` when `ql` is not supplied. */\n hostContext?: Record<string, any>;\n /** Scope sys_metadata reads/writes to this project. */\n environmentId?: string;\n /**\n * Override the kernel's default plugin-start timeout for this plugin.\n * Defaults to 120000 (120s). Schema sync to a remote SQL backend\n * (Neon/Postgres/Turso) is latency-bound — the SQL driver currently\n * does NOT support `batchSchemaSync`, so it issues one round-trip per\n * registered object × twice (Phase 1 + Phase 3 in `start()`). On a\n * cold remote DB with N tables this can blow past the kernel's\n * default 30s easily, even though everything is healthy.\n */\n startupTimeout?: number;\n /**\n * Skip both `syncRegisteredSchemas()` calls inside `start()` and\n * assume DDL is managed out-of-band (e.g. an `apps/cloud/scripts/migrate.ts`\n * run before deploy that connects directly to the database and creates\n * all `sys_*` + custom tables once).\n *\n * Use this on cold-start-sensitive runtimes (Cloudflare Containers,\n * Lambda) where the platform's inbound-request budget is shorter than\n * a fresh remote-DB schema sync. The plugin still hydrates the\n * SchemaRegistry from `sys_metadata` (Phase 2), so custom user\n * objects come up — they just aren't re-DDL'd on every cold boot.\n *\n * Falls back to `process.env.OS_SKIP_SCHEMA_SYNC === '1'` when the\n * option is unset, so containers can flip it via their env without a\n * code change.\n */\n skipSchemaSync?: boolean;\n}\n\nexport class ObjectQLPlugin implements Plugin {\n name = 'com.objectstack.engine.objectql';\n type = 'objectql';\n version = '1.0.0';\n /**\n * Schema sync to remote SQL DBs is latency-bound (one round-trip per\n * table × 2 phases). Default to 120s instead of the kernel's 30s so\n * cold Neon/Turso starts don't get killed mid-sync.\n */\n startupTimeout = 120_000;\n\n private ql: ObjectQL | undefined;\n private hostContext?: Record<string, any>;\n private environmentId?: string;\n private skipSchemaSync = false;\n /** Unsubscribe handles for metadata-event subscriptions (ADR-0008 PR-7). */\n private metadataUnsubscribes: Array<() => void> = [];\n\n constructor(qlOrOptions?: ObjectQL | ObjectQLPluginOptions, hostContext?: Record<string, any>) {\n // Back-compat: legacy callers passed `(ObjectQL, hostContext)` positionally.\n if (qlOrOptions instanceof ObjectQL) {\n this.ql = qlOrOptions;\n this.hostContext = hostContext;\n return;\n }\n // New signature: options bag.\n const opts = (qlOrOptions as ObjectQLPluginOptions | undefined) ?? {};\n if (opts.ql) {\n this.ql = opts.ql;\n }\n this.hostContext = opts.hostContext ?? hostContext;\n this.environmentId = opts.environmentId;\n if (typeof opts.startupTimeout === 'number' && opts.startupTimeout > 0) {\n this.startupTimeout = opts.startupTimeout;\n }\n this.skipSchemaSync =\n typeof opts.skipSchemaSync === 'boolean'\n ? opts.skipSchemaSync\n : process.env.OS_SKIP_SCHEMA_SYNC === '1';\n }\n\n init = async (ctx: PluginContext) => {\n if (!this.ql) {\n // Pass kernel logger to engine to avoid creating a separate logger instance\n const hostCtx = { ...this.hostContext, logger: ctx.logger };\n this.ql = new ObjectQL(hostCtx);\n }\n \n // Register as provider for Core Kernel Services\n ctx.registerService('objectql', this.ql);\n\n ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n\n // Register manifest service for direct app/package registration.\n // Plugins call ctx.getService('manifest').register(manifestData)\n // instead of the legacy ctx.registerService('app.<id>', manifestData) convention.\n const ql = this.ql;\n ctx.registerService('manifest', {\n register: (manifest: any) => {\n ql.registerApp(manifest);\n ctx.logger.debug('Manifest registered via manifest service', {\n id: manifest.id || manifest.name\n });\n }\n });\n\n ctx.logger.info('ObjectQL engine registered', {\n services: ['objectql', 'data', 'manifest'],\n });\n\n // Register the metadata-storage objects this engine's own protocol reads\n // and writes — `sys_metadata` (loadMetaFromDb / getMetaItems / saveMetaItem),\n // its history/audit siblings, and `sys_view_definition`. Doing it here\n // guarantees their tables get schema-synced in start() even when no\n // MetadataPlugin is present (e.g. standalone \"host config\" apps, where the\n // CLI auto-registers a bare ObjectQLPlugin and nothing else owns these\n // tables → \"no such table: sys_metadata\" on every read).\n //\n // Gated on `environmentId === undefined` — the SAME condition that gates\n // `restoreMetadataFromDb` below: platform / standalone kernels own their\n // local sys_metadata, whereas per-project (cloud) kernels source metadata\n // from the control plane and must NOT provision these tables locally.\n // Definitions live in @objectstack/metadata-core (shared by this protocol\n // and the metadata layer's DatabaseLoader). registerApp is idempotent, so\n // a MetadataPlugin that also registers them is harmless.\n if (this.environmentId === undefined) {\n this.ql.registerApp({\n id: 'com.objectstack.metadata-objects',\n name: 'Metadata Platform Objects',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n objects: [\n SysMetadataObject,\n SysMetadataHistoryObject,\n SysMetadataAuditObject,\n SysViewDefinitionObject,\n ],\n });\n }\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(\n this.ql,\n () => ctx.getServices ? ctx.getServices() : new Map(),\n undefined,\n this.environmentId,\n );\n\n ctx.registerService('protocol', protocolShim);\n ctx.logger.info('Protocol service registered');\n\n // Register an `analytics` service adapter that maps the dispatcher's\n // expected interface (query / getMeta / generateSql) onto the\n // protocol shim's `analyticsQuery`. Without this, HttpDispatcher's\n // `handleAnalytics` cannot resolve a service and `/api/v1/analytics/*`\n // returns ROUTE_NOT_FOUND, even though discovery advertises the route\n // (objectql's getDiscovery hardcodes `analytics: enabled:true`). The\n // adapter delegates `query` to the cube → engine.aggregate translator\n // already implemented in protocol.ts; getMeta/generateSql return a\n // structured \"not implemented\" payload so callers see something\n // useful instead of a 500.\n ctx.registerService('analytics', {\n // HttpDispatcher passes the raw POST body (AnalyticsQuery shape:\n // `{ cube, measures, dimensions, where?, filters?, ... }`). The\n // protocol shim's `analyticsQuery` expects the wrapped envelope\n // `{ cube, query }` and destructures `request.query` for dims /\n // measures. Reshape here so the destructure resolves to the\n // analytics query instead of `undefined` (which caused\n // \"Cannot read properties of undefined (reading 'dimensions')\").\n //\n // `analyticsQuery` also returns its own `{ success, data: { rows,\n // fields } }` envelope. HttpDispatcher wraps service responses\n // again with `success(result)`, so without unwrapping here the\n // client sees `{success, data:{success, data:{rows, fields}}}` —\n // KPI widgets read `data.rows` and silently get nothing. Unwrap\n // to the inner `{ rows, fields }` payload so a single wrap from\n // the dispatcher yields the canonical shape.\n query: async (body: any) => {\n const envelope = body && typeof body === 'object' && 'query' in body && 'cube' in body\n ? body\n : { cube: body?.cube, query: body };\n const result = await protocolShim.analyticsQuery(envelope);\n // Unwrap an inner `{ success, data }` envelope (one level only).\n if (result && typeof result === 'object' && 'success' in result && 'data' in result) {\n return (result as any).data;\n }\n return result;\n },\n getMeta: async () => ({\n cubes: [],\n message: 'Analytics meta endpoint not implemented by ObjectQL adapter',\n }),\n generateSql: async (_body: any) => ({\n sql: null,\n message: 'Analytics SQL generation not implemented by ObjectQL adapter',\n }),\n });\n }\n\n start = async (ctx: PluginContext) => {\n ctx.logger.info('ObjectQL engine starting...');\n\n // Sync from external metadata service (e.g. MetadataPlugin) if available\n try {\n const metadataService = ctx.getService('metadata') as any;\n if (metadataService && typeof metadataService.loadMany === 'function' && this.ql) {\n await this.loadMetadataFromService(metadataService, ctx);\n }\n // ── ADR-0008 PR-7: subscribe to object metadata events so the\n // SchemaRegistry cache is invalidated on edits (Studio HMR).\n // The metadata service bubbles repo events through its own\n // `subscribe(type, cb)` API (PR-6 bridge), so we don't talk\n // to the repo directly here — this keeps ObjectQL decoupled\n // from the storage backend.\n if (metadataService && typeof metadataService.subscribe === 'function' && this.ql) {\n this.subscribeToMetadataEvents(metadataService, ctx);\n }\n } catch (e: any) {\n ctx.logger.debug('No external metadata service to sync from');\n }\n \n // Discover features from Kernel Services\n if (ctx.getServices && this.ql) {\n const services = ctx.getServices();\n for (const [name, service] of services.entries()) {\n if (name.startsWith('driver.')) {\n // Register Driver\n this.ql.registerDriver(service);\n ctx.logger.debug('Discovered and registered driver service', { serviceName: name });\n }\n if (name.startsWith('app.')) {\n // Legacy fallback: discover app.* services (DEPRECATED)\n ctx.logger.warn(\n `[DEPRECATED] Service \"${name}\" uses legacy app.* convention. ` +\n `Migrate to ctx.getService('manifest').register(data).`\n );\n this.ql.registerApp(service); // service is Manifest\n ctx.logger.debug('Discovered and registered app service (legacy)', { serviceName: name });\n }\n }\n\n // Bridge realtime service from kernel service registry to ObjectQL.\n // RealtimeServicePlugin registers as 'realtime' service during init().\n // This enables ObjectQL to publish data change events.\n try {\n const realtimeService = ctx.getService('realtime');\n if (realtimeService && typeof realtimeService === 'object' && 'publish' in realtimeService) {\n ctx.logger.info('[ObjectQLPlugin] Bridging realtime service to ObjectQL for event publishing');\n this.ql.setRealtimeService(realtimeService as any);\n }\n } catch (e: any) {\n ctx.logger.debug('[ObjectQLPlugin] No realtime service found — data events will not be published', {\n error: e.message,\n });\n }\n }\n\n // Initialize drivers (calls driver.connect() which sets up persistence)\n await this.ql?.init();\n\n // Phase 1: Sync built-in schemas so sys_metadata table exists before reading it.\n //\n // Cold-start-sensitive runtimes (Cloudflare Containers, Lambda) can\n // opt out via `skipSchemaSync` / `OS_SKIP_SCHEMA_SYNC=1`. In that\n // mode an out-of-band migration must have already created every\n // table; we only assume the DDL is in place and skip straight to\n // hydration. This avoids one round-trip per table × N objects on\n // every cold boot.\n if (this.skipSchemaSync) {\n ctx.logger.info('Skipping schema sync (OS_SKIP_SCHEMA_SYNC=1) — assuming DDL is managed out-of-band');\n } else {\n await this.syncRegisteredSchemas(ctx);\n }\n\n // Phase 2: Hydrate SchemaRegistry from sys_metadata (loads custom/template objects).\n // Project kernels (environmentId set) never persist sys_metadata locally —\n // metadata is sourced from the artifact (MetadataPlugin) or routed to the\n // control plane via ControlPlaneProxyDriver. Skip to avoid querying a table\n // that does not exist on local project DBs.\n if (this.environmentId === undefined) {\n await this.restoreMetadataFromDb(ctx);\n } else {\n ctx.logger.info('Project kernel — skipping sys_metadata hydration (metadata sourced from artifact)');\n }\n\n // Phase 3: Sync any new schemas that were just hydrated from the DB\n // (e.g. CRM objects seeded via template — they must have tables before use).\n if (!this.skipSchemaSync) {\n await this.syncRegisteredSchemas(ctx);\n }\n\n // Bridge all SchemaRegistry objects to metadata service.\n //\n // `SchemaRegistry` is a process-wide singleton, so project kernels in a\n // multi-environment server would otherwise inherit every object ever\n // registered by any sibling project. When this plugin was constructed\n // with a `environmentId`, the kernel is project-scoped — its\n // metadata comes from the artifact (MetadataPlugin) or the\n // control-plane proxy, not from local sys_metadata. The bridge would\n // only pollute its metadata service with cross-project leakage, so\n // skip it in that case.\n if (this.environmentId === undefined) {\n await this.bridgeObjectsToMetadataService(ctx);\n }\n\n // Register built-in audit hooks\n this.registerAuditHooks(ctx);\n\n // Tenant isolation is now handled by `@objectstack/plugin-security`\n // via the `member_default` permission set's RLS rule\n // (`organization_id = current_user.organization_id`, with\n // field-existence guards). The legacy hard-coded `tenant_id` filter\n // middleware was removed because it (a) collided with the\n // SecurityPlugin RLS pipeline and (b) blindly filtered tables that\n // don't have a `tenant_id` column (e.g. `sys_organization`),\n // returning 0 rows instead of all rows.\n\n ctx.logger.info('ObjectQL engine started', {\n driversRegistered: this.ql?.['drivers']?.size || 0,\n objectsRegistered: this.ql?.registry?.getAllObjects?.()?.length || 0\n });\n }\n\n stop = async (ctx: PluginContext) => {\n // ADR-0008 PR-7: tear down metadata subscriptions on plugin stop so\n // tests don't leak watchers and reloaded plugins don't double-subscribe.\n for (const unsub of this.metadataUnsubscribes) {\n try { unsub(); } catch (e: any) {\n ctx.logger.debug('[ObjectQLPlugin] metadata-event unsubscribe failed', { error: e?.message });\n }\n }\n this.metadataUnsubscribes = [];\n }\n\n /**\n * Subscribe to `object` metadata events from the metadata service and\n * invalidate the SchemaRegistry merge cache on each event (ADR-0008\n * PR-7). For create/update we also re-load the affected object from\n * the metadata service so subsequent reads see the new definition;\n * for delete we unregister it from every contributing package.\n *\n * Events are filtered to the canonical `object` type — view/dashboard\n * /flow edits go through their own consumers (Studio SSE, REST cache).\n *\n * Stored unsubscribe handle is invoked from {@link stop}.\n */\n private subscribeToMetadataEvents(metadataService: any, ctx: PluginContext) {\n const handler = async (evt: any) => {\n if (!this.ql) return;\n const name: string = evt?.name ?? '';\n if (!name) return;\n const eventType: 'added' | 'changed' | 'deleted' =\n evt?.type === 'added' || evt?.type === 'changed' || evt?.type === 'deleted'\n ? evt.type\n : 'changed';\n\n try {\n // Drop the merged-schema cache entry first so any in-flight\n // resolveObject() races recompute against the new state.\n this.ql.registry.invalidate(name);\n\n if (eventType === 'deleted') {\n ctx.logger.info('[ObjectQLPlugin] object metadata deleted — registry invalidated', { name });\n return;\n }\n\n // Re-fetch the canonical definition from the metadata service.\n // The metadata service goes through its loader chain (FS, DB,\n // attached repository), so this picks up edits from any source.\n const fresh = typeof metadataService.get === 'function'\n ? await metadataService.get('object', name)\n : undefined;\n if (fresh && typeof fresh === 'object') {\n // Re-register with the original contributor metadata. We use\n // 'metadata-service' as packageId to match how the initial\n // load enrolls these objects (see `loadMetadataFromService`).\n const packageId = (fresh as any)._packageId ?? 'metadata-service';\n const namespace = (fresh as any).namespace;\n this.ql.registry.registerObject(\n fresh as any,\n packageId,\n namespace,\n 'own',\n );\n ctx.logger.info('[ObjectQLPlugin] object metadata updated — registry refreshed', {\n name,\n packageId,\n });\n } else {\n ctx.logger.debug('[ObjectQLPlugin] object event received but metadata service has no fresh body', { name });\n }\n } catch (e: any) {\n ctx.logger.warn('[ObjectQLPlugin] metadata event handler failed', {\n name,\n error: e?.message,\n });\n }\n };\n\n const unsub = metadataService.subscribe('object', handler);\n if (typeof unsub === 'function') {\n this.metadataUnsubscribes.push(unsub);\n } else if (unsub && typeof unsub.unsubscribe === 'function') {\n // Support `MetadataWatchHandle` style return shape.\n this.metadataUnsubscribes.push(() => unsub.unsubscribe());\n }\n ctx.logger.info('[ObjectQLPlugin] subscribed to object metadata events (ADR-0008 PR-7)');\n }\n\n /**\n * Register built-in audit hooks for auto-stamping created_by/updated_by\n * and fetching previousData for update/delete operations. These are\n * declared as canonical `Hook` metadata and bound through the same\n * `bindHooksToEngine` path used by `defineStack({ hooks })`, so the\n * engine's built-ins flow through the same rails as user code\n * (dogfooding the protocol).\n */\n private registerAuditHooks(ctx: PluginContext) {\n if (!this.ql) return;\n\n const stamp = () => new Date().toISOString();\n\n /**\n * Returns true when the resolved object schema declares a field with the\n * given name. Audit fields (`created_by`, `updated_by`, `tenant_id`) are\n * NOT auto-injected by the SQL driver, so we must only stamp values for\n * fields the user has explicitly declared on the object — otherwise the\n * driver will issue an INSERT against a column that does not exist in\n * the physical table (e.g. `table lead has no column named created_by`).\n *\n * `created_at`/`updated_at` are unconditional because driver-sql creates\n * them as built-in columns on every table.\n */\n const hasField = (objectName: string, field: string): boolean => {\n try {\n const schema: any = this.ql?.getSchema?.(objectName);\n if (!schema || typeof schema !== 'object') return false;\n const fields = schema.fields;\n if (!fields || typeof fields !== 'object') return false;\n return Object.prototype.hasOwnProperty.call(fields, field);\n } catch {\n return false;\n }\n };\n\n const applyToRecord = (\n record: Record<string, any>,\n objectName: string,\n session: any,\n isInsert: boolean,\n ) => {\n const now = stamp();\n if (isInsert) {\n record.created_at = record.created_at ?? now;\n }\n record.updated_at = now;\n if (session?.userId) {\n if (isInsert && hasField(objectName, 'created_by')) {\n record.created_by = record.created_by ?? session.userId;\n }\n if (hasField(objectName, 'updated_by')) {\n record.updated_by = session.userId;\n }\n }\n if (isInsert && session?.tenantId && hasField(objectName, 'tenant_id')) {\n record.tenant_id = record.tenant_id ?? session.tenantId;\n }\n };\n\n const stampData = (\n data: unknown,\n objectName: string,\n session: any,\n isInsert: boolean,\n ) => {\n if (Array.isArray(data)) {\n for (const row of data) {\n if (row && typeof row === 'object') {\n applyToRecord(row as Record<string, any>, objectName, session, isInsert);\n }\n }\n } else if (data && typeof data === 'object') {\n applyToRecord(data as Record<string, any>, objectName, session, isInsert);\n }\n };\n\n const builtinHooks: any[] = [\n {\n name: 'sys_stamp_audit_insert',\n object: '*',\n events: ['beforeInsert'],\n priority: 10,\n description: 'Auto-stamp created_by / updated_by / created_at / updated_at / tenant_id on insert (only when the field exists on the object schema)',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.data) {\n stampData(hookCtx.input.data, hookCtx.object, hookCtx.session, true);\n }\n },\n },\n {\n name: 'sys_stamp_audit_update',\n object: '*',\n events: ['beforeUpdate'],\n priority: 10,\n description: 'Auto-stamp updated_by / updated_at on update (only when the field exists on the object schema)',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.data) {\n stampData(hookCtx.input.data, hookCtx.object, hookCtx.session, false);\n }\n },\n },\n {\n name: 'sys_fetch_previous_update',\n object: '*',\n events: ['beforeUpdate'],\n priority: 5,\n description: 'Auto-fetch the previous record for update hooks',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id },\n context: {\n roles: [],\n permissions: [],\n isSystem: true,\n ...(hookCtx.transaction ? { transaction: hookCtx.transaction } : {}),\n } as any,\n });\n if (existing) hookCtx.previous = existing;\n } catch (_e) {\n // Non-fatal: some objects may not support findOne\n }\n }\n },\n },\n {\n name: 'sys_fetch_previous_delete',\n object: '*',\n events: ['beforeDelete'],\n priority: 5,\n description: 'Auto-fetch the previous record for delete hooks',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id },\n context: {\n roles: [],\n permissions: [],\n isSystem: true,\n ...(hookCtx.transaction ? { transaction: hookCtx.transaction } : {}),\n } as any,\n });\n if (existing) hookCtx.previous = existing;\n } catch (_e) {\n // Non-fatal\n }\n }\n },\n },\n ];\n\n if (typeof (this.ql as any).bindHooks === 'function') {\n (this.ql as any).bindHooks(builtinHooks, { packageId: 'sys:audit' });\n } else {\n // Defensive fallback if binder isn't available (older builds).\n for (const h of builtinHooks) {\n for (const event of h.events) {\n this.ql.registerHook(event, h.handler, {\n object: h.object,\n priority: h.priority,\n packageId: 'sys:audit',\n });\n }\n }\n }\n\n ctx.logger.debug('Audit hooks registered via binder (created_by/updated_by, previousData)');\n }\n\n /**\n * Tenant isolation moved to `@objectstack/plugin-security`'s\n * `member_default` permission set RLS\n * (`organization_id = current_user.organization_id`, with\n * field-existence guards). The legacy `registerTenantMiddleware`\n * method was removed because it (a) collided with SecurityPlugin's\n * RLS pipeline and (b) blindly filtered tables that don't have a\n * `tenant_id` column (e.g. `sys_organization`), returning 0 rows\n * instead of all rows.\n */\n\n /**\n * Synchronize all registered object schemas to the database.\n *\n * Groups objects by their responsible driver, then:\n * - If the driver advertises `supports.batchSchemaSync` and implements\n * `syncSchemasBatch()`, submits all schemas in a single call (reducing\n * network round-trips for remote drivers like Turso).\n * - Otherwise falls back to sequential `syncSchema()` per object.\n *\n * This is idempotent — drivers must tolerate repeated calls without\n * duplicating tables or erroring out.\n *\n * Drivers that do not implement `syncSchema` are silently skipped.\n */\n private async syncRegisteredSchemas(ctx: PluginContext) {\n if (!this.ql) return;\n\n const allObjects = this.ql.registry?.getAllObjects?.() ?? [];\n if (allObjects.length === 0) return;\n\n let synced = 0;\n let skipped = 0;\n\n // Group objects by driver for potential batch optimization\n const driverGroups = new Map<any, Array<{ obj: any; tableName: string }>>();\n\n for (const obj of allObjects) {\n const driver = this.ql.getDriverForObject(obj.name);\n if (!driver) {\n ctx.logger.debug('No driver available for object, skipping schema sync', {\n object: obj.name,\n });\n skipped++;\n continue;\n }\n\n if (typeof driver.syncSchema !== 'function') {\n ctx.logger.debug('Driver does not support syncSchema, skipping', {\n object: obj.name,\n driver: driver.name,\n });\n skipped++;\n continue;\n }\n\n const tableName = StorageNameMapping.resolveTableName(obj);\n\n let group = driverGroups.get(driver);\n if (!group) {\n group = [];\n driverGroups.set(driver, group);\n }\n group.push({ obj, tableName });\n }\n\n // Process each driver group\n for (const [driver, entries] of driverGroups) {\n // Batch path: driver supports batch schema sync\n if (\n driver.supports?.batchSchemaSync &&\n typeof driver.syncSchemasBatch === 'function'\n ) {\n const batchPayload = entries.map((e) => ({\n object: e.tableName,\n schema: e.obj,\n }));\n try {\n await driver.syncSchemasBatch(batchPayload);\n synced += entries.length;\n ctx.logger.debug('Batch schema sync succeeded', {\n driver: driver.name,\n count: entries.length,\n });\n } catch (e: unknown) {\n ctx.logger.warn('Batch schema sync failed, falling back to sequential', {\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n // Fallback: sequential sync for this driver's objects\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (seqErr: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: seqErr instanceof Error ? seqErr.message : String(seqErr),\n });\n }\n }\n }\n } else {\n // Sequential path: no batch support\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (e: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n }\n }\n\n if (synced > 0 || skipped > 0) {\n ctx.logger.info('Schema sync complete', { synced, skipped, total: allObjects.length });\n }\n }\n\n /**\n * Restore persisted metadata from the database (sys_metadata) on startup.\n *\n * Calls `protocol.loadMetaFromDb()` to bulk-load all active metadata\n * records (objects, views, apps, etc.) into the in-memory SchemaRegistry.\n * This closes the persistence loop so that user-created schemas survive\n * kernel cold starts and redeployments.\n *\n * Gracefully degrades when:\n * - The protocol service is unavailable (e.g., in-memory-only mode).\n * - `loadMetaFromDb` is not implemented by the protocol shim.\n * - The underlying driver/table does not exist yet (first-run scenario).\n */\n private async restoreMetadataFromDb(ctx: PluginContext): Promise<void> {\n // Phase 1: Resolve protocol service (separate from DB I/O for clearer diagnostics)\n let protocol: ProtocolWithDbRestore;\n try {\n const service = ctx.getService('protocol');\n if (!service || !hasLoadMetaFromDb(service)) {\n ctx.logger.debug('Protocol service does not support loadMetaFromDb, skipping DB restore');\n return;\n }\n protocol = service;\n } catch (e: unknown) {\n ctx.logger.debug('Protocol service unavailable, skipping DB restore', {\n error: e instanceof Error ? e.message : String(e),\n });\n return;\n }\n\n // Phase 2: DB hydration (loads into SchemaRegistry)\n try {\n const { loaded, errors } = await protocol.loadMetaFromDb();\n\n if (loaded > 0 || errors > 0) {\n ctx.logger.info('Metadata restored from database to SchemaRegistry', { loaded, errors });\n } else {\n ctx.logger.debug('No persisted metadata found in database');\n }\n } catch (e: unknown) {\n // Non-fatal: first-run or in-memory driver may not have sys_metadata yet\n ctx.logger.debug('DB metadata restore failed (non-fatal)', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Bridge all SchemaRegistry objects to the metadata service.\n *\n * This ensures objects registered by plugins and loaded from sys_metadata\n * are visible to AI tools and other consumers that query IMetadataService.\n *\n * Runs after both restoreMetadataFromDb() and syncRegisteredSchemas() to\n * catch all objects in the SchemaRegistry regardless of their source.\n */\n private async bridgeObjectsToMetadataService(ctx: PluginContext): Promise<void> {\n try {\n const metadataService = ctx.getService<any>('metadata');\n if (!metadataService || typeof metadataService.register !== 'function') {\n ctx.logger.debug('Metadata service unavailable for bridging, skipping');\n return;\n }\n\n if (!this.ql?.registry) {\n ctx.logger.debug('SchemaRegistry unavailable for bridging, skipping');\n return;\n }\n\n const objects = this.ql.registry.getAllObjects();\n let bridged = 0;\n\n for (const obj of objects) {\n try {\n // Check if object is already in metadata service to avoid duplicates\n const existing = await metadataService.getObject(obj.name);\n if (!existing) {\n // Register object that exists in SchemaRegistry but not in metadata service\n await metadataService.register('object', obj.name, obj);\n bridged++;\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge object to metadata service', {\n object: obj.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n if (bridged > 0) {\n ctx.logger.info('Bridged objects from SchemaRegistry to metadata service', {\n count: bridged,\n total: objects.length\n });\n } else {\n ctx.logger.debug('No objects needed bridging (all already in metadata service)');\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge objects to metadata service', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Load metadata from external metadata service into ObjectQL registry\n * This enables ObjectQL to use file-based or remote metadata\n */\n private async loadMetadataFromService(metadataService: any, ctx: PluginContext) {\n ctx.logger.info('Syncing metadata from external service into ObjectQL registry...');\n \n // Metadata types to sync (ADR-0020: no `workflow` type — record state\n // machines are a `state_machine` validation rule on the object)\n const metadataTypes = ['object', 'view', 'app', 'flow', 'function', 'hook'];\n let totalLoaded = 0;\n \n for (const type of metadataTypes) {\n try {\n // Check if service has loadMany method\n if (typeof metadataService.loadMany === 'function') {\n const items = await metadataService.loadMany(type);\n\n if (items && items.length > 0) {\n // Functions arrive as JSON-safe records ({name, handler})\n // where `handler` is a function reference or compiled code\n // already attached by the metadata pipeline. Register them\n // BEFORE binding hooks so string-named hook handlers can\n // resolve.\n if (type === 'function' && this.ql && typeof (this.ql as any).registerFunction === 'function') {\n for (const item of items) {\n if (item?.name && typeof item.handler === 'function') {\n (this.ql as any).registerFunction(item.name, item.handler, 'metadata-service');\n }\n }\n }\n\n items.forEach((item: any) => {\n // Determine key field (usually 'name' or 'id')\n const keyField = item.id ? 'id' : 'name';\n \n // For objects, use the ownership-aware registration\n if (type === 'object' && this.ql) {\n // Objects are registered differently (ownership model)\n // Skip for now - handled by app registration\n return;\n }\n \n // Register other types in the registry\n if (this.ql?.registry?.registerItem) {\n this.ql.registry.registerItem(type, item, keyField);\n }\n });\n\n // Hooks need to be wired into the execution pipeline,\n // not just stored in the registry. Funnel through the\n // canonical binder so declarative semantics (condition,\n // retry, timeout, async, onError, priority, packageId)\n // are honoured uniformly with the AppPlugin path.\n if (type === 'hook' && this.ql && typeof (this.ql as any).bindHooks === 'function') {\n (this.ql as any).bindHooks(items, {\n packageId: 'metadata-service',\n });\n }\n\n totalLoaded += items.length;\n ctx.logger.info(`Synced ${items.length} ${type}(s) from metadata service`);\n }\n }\n } catch (e: any) {\n // Type might not exist in metadata service - that's ok\n ctx.logger.debug(`No ${type} metadata found or error loading`, { \n error: e.message \n });\n }\n }\n \n if (totalLoaded > 0) {\n ctx.logger.info(`Metadata sync complete: ${totalLoaded} items loaded into ObjectQL registry`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectKernel } from '@objectstack/core';\nimport { ObjectQLPlugin } from './plugin.js';\nimport type { Plugin } from '@objectstack/core';\n\n/**\n * Options for creating an ObjectQL Kernel.\n */\nexport interface ObjectQLKernelOptions {\n /**\n * Additional plugins to register with the kernel.\n */\n plugins?: Plugin[];\n}\n\n/**\n * Convenience factory for creating an ObjectQL-ready kernel.\n *\n * Creates an ObjectKernel pre-configured with the ObjectQLPlugin\n * (data engine, schema registry, protocol implementation) plus any\n * additional plugins provided.\n *\n * @example\n * ```typescript\n * import { createObjectQLKernel } from '@objectstack/objectql';\n *\n * const kernel = createObjectQLKernel({\n * plugins: [myDriverPlugin, myAuthPlugin],\n * });\n * await kernel.bootstrap();\n * ```\n */\nexport async function createObjectQLKernel(options: ObjectQLKernelOptions = {}): Promise<ObjectKernel> {\n const kernel = new ObjectKernel();\n\n // Register the core ObjectQLPlugin first\n await kernel.use(new ObjectQLPlugin());\n\n // Register any additional plugins\n if (options.plugins) {\n for (const plugin of options.plugins) {\n await kernel.use(plugin);\n }\n }\n\n return kernel;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n// ── Introspection Types ──────────────────────────────────────────────────────\n\n/**\n * Column metadata from database introspection.\n */\nexport interface IntrospectedColumn {\n /** Column name */\n name: string;\n /** Native database type (e.g., 'varchar', 'integer', 'timestamp') */\n type: string;\n /** Whether the column is nullable */\n nullable: boolean;\n /** Default value if any */\n defaultValue?: unknown;\n /** Whether this is a primary key */\n isPrimary?: boolean;\n /** Whether this column has a unique constraint */\n isUnique?: boolean;\n /** Maximum length for string types */\n maxLength?: number;\n}\n\n/**\n * Foreign key relationship metadata.\n */\nexport interface IntrospectedForeignKey {\n /** Column name in the source table */\n columnName: string;\n /** Referenced table name */\n referencedTable: string;\n /** Referenced column name */\n referencedColumn: string;\n /** Constraint name */\n constraintName?: string;\n}\n\n/**\n * Table metadata from database introspection.\n */\nexport interface IntrospectedTable {\n /** Table name */\n name: string;\n /** List of columns */\n columns: IntrospectedColumn[];\n /** List of foreign key relationships */\n foreignKeys: IntrospectedForeignKey[];\n /** Primary key columns */\n primaryKeys: string[];\n}\n\n/**\n * Complete database schema introspection result.\n */\nexport interface IntrospectedSchema {\n /** Map of table name to table metadata */\n tables: Record<string, IntrospectedTable>;\n}\n\n// ── Utility Functions ────────────────────────────────────────────────────────\n\n/**\n * Convert a snake_case or plain string to Title Case.\n *\n * @example\n * toTitleCase('first_name') // => 'First Name'\n * toTitleCase('project_task') // => 'Project Task'\n */\nexport function toTitleCase(str: string): string {\n return str\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Map a native database column type to an ObjectStack FieldType.\n */\nfunction mapDatabaseTypeToFieldType(\n dbType: string\n): 'text' | 'textarea' | 'number' | 'boolean' | 'datetime' | 'date' | 'time' | 'json' {\n const type = dbType.toLowerCase();\n\n // Text types\n if (type.includes('char') || type.includes('varchar') || type.includes('text')) {\n if (type.includes('text')) return 'textarea';\n return 'text';\n }\n\n // Numeric types\n if (\n type.includes('int') || type === 'integer' || type === 'bigint' || type === 'smallint'\n ) {\n return 'number';\n }\n if (\n type.includes('float') || type.includes('double') || type.includes('decimal') ||\n type.includes('numeric') || type === 'real'\n ) {\n return 'number';\n }\n\n // Boolean\n if (type.includes('bool')) {\n return 'boolean';\n }\n\n // Date / Time types\n if (type.includes('timestamp') || type === 'datetime') {\n return 'datetime';\n }\n if (type === 'date') {\n return 'date';\n }\n if (type === 'time') {\n return 'time';\n }\n\n // JSON types\n if (type === 'json' || type === 'jsonb') {\n return 'json';\n }\n\n // Default to text\n return 'text';\n}\n\n/**\n * Convert an introspected database schema to ObjectStack object definitions.\n *\n * This allows using existing database tables without manually defining metadata.\n *\n * @param introspectedSchema - The schema returned from driver.introspectSchema()\n * @param options - Optional filtering / conversion settings\n * @returns Array of ServiceObject definitions that can be registered with ObjectQL\n *\n * @example\n * ```typescript\n * const schema = await driver.introspectSchema();\n * const objects = convertIntrospectedSchemaToObjects(schema);\n * for (const obj of objects) {\n * engine.registerObject(obj);\n * }\n * ```\n */\nexport function convertIntrospectedSchemaToObjects(\n introspectedSchema: IntrospectedSchema,\n options?: {\n /** Tables to exclude from conversion */\n excludeTables?: string[];\n /** Tables to include (if specified, only these will be converted) */\n includeTables?: string[];\n /** Whether to skip system columns like id, created_at, updated_at (default: true) */\n skipSystemColumns?: boolean;\n }\n): ServiceObject[] {\n const objects: ServiceObject[] = [];\n const excludeTables = options?.excludeTables || [];\n const includeTables = options?.includeTables;\n const skipSystemColumns = options?.skipSystemColumns !== false;\n\n for (const [tableName, table] of Object.entries(introspectedSchema.tables)) {\n if (excludeTables.includes(tableName)) continue;\n if (includeTables && !includeTables.includes(tableName)) continue;\n\n const fields: Record<string, any> = {};\n\n for (const column of table.columns) {\n // Skip system columns if requested\n if (skipSystemColumns && ['id', 'created_at', 'updated_at'].includes(column.name)) {\n continue;\n }\n\n // Check for foreign key → lookup field\n const foreignKey = table.foreignKeys.find((fk) => fk.columnName === column.name);\n\n if (foreignKey) {\n fields[column.name] = {\n name: column.name,\n type: 'lookup' as const,\n reference: foreignKey.referencedTable,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n } else {\n const fieldType = mapDatabaseTypeToFieldType(column.type);\n\n const field: Record<string, any> = {\n name: column.name,\n type: fieldType,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n\n if (column.isUnique) {\n field.unique = true;\n }\n if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {\n field.maxLength = column.maxLength;\n }\n if (column.defaultValue != null) {\n field.defaultValue = column.defaultValue;\n }\n\n fields[column.name] = field;\n }\n }\n\n objects.push({\n name: tableName,\n label: toTitleCase(tableName),\n fields,\n } as ServiceObject);\n }\n\n return objects;\n}\n"],"mappings":"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","names":["import_data","import_types","import_types","import_kernel","import_shared","item","import_metadata_core","import_data","import_shared","import_ui","import_kernel","import_kernel","import_shared","records","SeedLoaderService","runBuildProbes","import_kernel","import_system","import_shared","import_formula","import_formula","noopLogger","import_formula","Ajv","isMissing","EMAIL_RE","PHONE_RE","import_system","import_metadata_core","import_core"]}
1
+ {"version":3,"sources":["../src/seed-loader.ts","../src/build-probes.ts","../src/index.ts","../src/registry.ts","../src/protocol.ts","../src/sys-metadata-repository.ts","../src/metadata-diagnostics.ts","../src/engine.ts","../src/secret-fields.ts","../src/hook-wrappers.ts","../src/hook-metrics.ts","../src/hook-binder.ts","../src/validation/record-validator.ts","../src/validation/rule-validator.ts","../src/in-memory-aggregation.ts","../src/metadata-facade.ts","../src/plugin.ts","../src/kernel-factory.ts","../src/util.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { IDataEngine, IMetadataService, ISeedLoaderService } from '@objectstack/spec/contracts';\nimport type {\n SeedLoaderRequest,\n SeedLoaderResult,\n SeedLoaderConfig,\n SeedLoaderConfigInput,\n ObjectDependencyGraph,\n ObjectDependencyNode,\n ReferenceResolution,\n ReferenceResolutionError,\n SeedLoadResult,\n Seed,\n} from '@objectstack/spec/data';\nimport { SeedLoaderConfigSchema } from '@objectstack/spec/data';\nimport { resolveSeedRecord } from '@objectstack/formula';\n\ninterface Logger {\n info(message: string, meta?: Record<string, any>): void;\n warn(message: string, meta?: Record<string, any>): void;\n error(message: string, error?: Error, meta?: Record<string, any>): void;\n debug(message: string, meta?: Record<string, any>): void;\n}\n\n/** Default field used for externalId matching on target objects */\nconst DEFAULT_EXTERNAL_ID_FIELD = 'name';\n\n/**\n * SeedLoaderService — Runtime implementation of ISeedLoaderService\n *\n * Provides metadata-driven seed data loading with:\n * - Automatic lookup/master_detail reference resolution via externalId\n * - Topological dependency ordering (parents before children)\n * - Multi-pass loading for circular references\n * - Dry-run validation mode\n * - Upsert support honoring SeedSchema mode\n * - Actionable error reporting\n */\nexport class SeedLoaderService implements ISeedLoaderService {\n private engine: IDataEngine;\n private metadata: IMetadataService;\n private logger: Logger;\n\n constructor(engine: IDataEngine, metadata: IMetadataService, logger: Logger) {\n this.engine = engine;\n this.metadata = metadata;\n this.logger = logger;\n }\n\n // ==========================================================================\n // Public API\n // ==========================================================================\n\n async load(request: SeedLoaderRequest): Promise<SeedLoaderResult> {\n const startTime = Date.now();\n const config = request.config;\n const allErrors: ReferenceResolutionError[] = [];\n const allResults: SeedLoadResult[] = [];\n\n // 1. Filter datasets by environment\n const datasets = this.filterByEnv(request.seeds, config.env);\n\n if (datasets.length === 0) {\n return this.buildEmptyResult(config, Date.now() - startTime);\n }\n\n // 2. Build dependency graph\n const objectNames = datasets.map(d => d.object);\n const graph = await this.buildDependencyGraph(objectNames);\n\n this.logger.info('[SeedLoader] Dependency graph built', {\n objects: objectNames.length,\n insertOrder: graph.insertOrder,\n circularDeps: graph.circularDependencies.length,\n });\n\n // 3. Order datasets by topological insert order\n const orderedDatasets = this.orderDatasets(datasets, graph.insertOrder);\n\n // 4. Build reference lookup map from metadata (field → target object)\n const refMap = this.buildReferenceMap(graph);\n\n // 5. Pass 1: Insert/upsert records, resolving references\n const insertedRecords = new Map<string, Map<string, string>>(); // object → externalIdValue → internalId\n const deferredUpdates: DeferredUpdate[] = [];\n\n for (const dataset of orderedDatasets) {\n const result = await this.loadDataset(\n dataset, config, refMap, insertedRecords, deferredUpdates, allErrors\n );\n allResults.push(result);\n\n if (config.haltOnError && result.errored > 0) {\n this.logger.warn('[SeedLoader] Halting on first error', { object: dataset.object });\n break;\n }\n }\n\n // 6. Pass 2: Resolve deferred references (circular dependencies)\n if (config.multiPass && deferredUpdates.length > 0 && !config.dryRun) {\n this.logger.info('[SeedLoader] Pass 2: resolving deferred references', {\n count: deferredUpdates.length,\n });\n await this.resolveDeferredUpdates(deferredUpdates, insertedRecords, allResults, allErrors, config.organizationId);\n }\n\n // 7. Build final result\n const durationMs = Date.now() - startTime;\n return this.buildResult(config, graph, allResults, allErrors, durationMs);\n }\n\n async buildDependencyGraph(objectNames: string[]): Promise<ObjectDependencyGraph> {\n const nodes: ObjectDependencyNode[] = [];\n const objectSet = new Set(objectNames);\n\n for (const objectName of objectNames) {\n const objDef = await this.metadata.getObject(objectName) as any;\n const dependsOn: string[] = [];\n const references: ReferenceResolution[] = [];\n\n if (objDef && objDef.fields) {\n const fields = objDef.fields as Record<string, any>;\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n if (\n (fieldDef.type === 'lookup' || fieldDef.type === 'master_detail') &&\n fieldDef.reference\n ) {\n const targetObject = fieldDef.reference as string;\n\n // Track dependency ordering only for objects within the graph\n if (objectSet.has(targetObject) && !dependsOn.includes(targetObject)) {\n dependsOn.push(targetObject);\n }\n\n // Track ALL references for resolution (target may exist in database)\n references.push({\n field: fieldName,\n targetObject,\n targetField: DEFAULT_EXTERNAL_ID_FIELD,\n fieldType: fieldDef.type as 'lookup' | 'master_detail',\n });\n }\n }\n }\n\n nodes.push({ object: objectName, dependsOn, references });\n }\n\n // Topological sort\n const { insertOrder, circularDependencies } = this.topologicalSort(nodes);\n\n return { nodes, insertOrder, circularDependencies };\n }\n\n async validate(datasets: Seed[], config?: SeedLoaderConfigInput): Promise<SeedLoaderResult> {\n const parsedConfig = SeedLoaderConfigSchema.parse({ ...config, dryRun: true });\n return this.load({ seeds: datasets, config: parsedConfig });\n }\n\n // ==========================================================================\n // Internal: Seed Loading\n // ==========================================================================\n\n private async loadDataset(\n dataset: Seed,\n config: SeedLoaderConfig,\n refMap: Map<string, ReferenceResolution[]>,\n insertedRecords: Map<string, Map<string, string>>,\n deferredUpdates: DeferredUpdate[],\n allErrors: ReferenceResolutionError[],\n ): Promise<SeedLoadResult> {\n const objectName = dataset.object;\n const mode = dataset.mode || config.defaultMode;\n const externalId = dataset.externalId || 'name';\n\n let inserted = 0;\n let updated = 0;\n let skipped = 0;\n let errored = 0;\n let referencesResolved = 0;\n let referencesDeferred = 0;\n const errors: ReferenceResolutionError[] = [];\n\n // Ensure the object's record map exists\n if (!insertedRecords.has(objectName)) {\n insertedRecords.set(objectName, new Map());\n }\n\n // Pre-load existing records for upsert matching. When a target\n // organization is set, scope the lookup so each tenant gets its\n // own copy (otherwise upsert would clobber other tenants' rows\n // that share the same natural key — e.g. `name: 'Acme Corp'`).\n let existingRecords: Map<string, any> | undefined;\n if ((mode === 'upsert' || mode === 'update' || mode === 'ignore') && !config.dryRun) {\n existingRecords = await this.loadExistingRecords(\n objectName,\n externalId,\n config.organizationId,\n );\n }\n\n // Get reference resolutions for this object\n const objectRefs = refMap.get(objectName) || [];\n\n // Pin a single `now()` snapshot for the entire dataset so multi-pass\n // loads see one logical clock — the M9 determinism guarantee for seeds.\n const seedNow = new Date();\n\n // Identity/context bound to seed CEL expressions. `os.user` / `os.org`\n // resolve from here, so `owner_id: cel\\`os.user.id\\`` works. When no\n // identity is supplied, `os.user` / `os.org` are simply unbound and any\n // record that references them fails loudly below (rather than silently\n // writing a raw Expression envelope into the column).\n const seedIdentity = config.identity;\n const baseEvalCtx = {\n now: seedNow,\n user: seedIdentity?.user,\n // Fall back to the per-tenant organizationId so `os.org.id` resolves\n // during per-org replay even without an explicit identity.org.\n org: seedIdentity?.org ?? (config.organizationId ? { id: config.organizationId } : undefined),\n env: config.env,\n };\n\n for (let i = 0; i < dataset.records.length; i++) {\n // Resolve any embedded Expression envelopes (e.g. `cel\\`daysFromNow(30)\\``,\n // `cel\\`os.user.id\\``) BEFORE reference resolution so downstream lookups\n // see resolved values.\n const seedResult = resolveSeedRecord(\n dataset.records[i] as Record<string, never>,\n baseEvalCtx,\n );\n if (!seedResult.ok) {\n // LOUD FAILURE: a record whose dynamic values cannot be resolved is\n // dropped — but never silently. Record an actionable error (so it\n // surfaces in result.errors and flips success=false) instead of\n // writing the unresolved Expression envelope into the database.\n errored++;\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: '(expression)',\n targetObject: objectName,\n targetField: '(expression)',\n attemptedValue: dataset.records[i],\n recordIndex: i,\n message:\n `Cannot resolve dynamic seed values for ${objectName} record #${i}: ${seedResult.error.message}. ` +\n 'Records using cel`os.user.id` / cel`os.org.id` require a seed identity — ' +\n 'ensure a system/admin user exists before seeding (see SeedLoaderConfig.identity).',\n };\n errors.push(error);\n allErrors.push(error);\n this.logger.warn(`[SeedLoader] ${error.message}`);\n continue;\n }\n const record = { ...(seedResult.value as Record<string, unknown>) };\n\n // Per-tenant tagging: when a target org is set, stamp every\n // seeded row with it (unless the record itself already supplies\n // an explicit organization_id — respect dataset author overrides).\n // Skipped objects that don't declare `organization_id` will have\n // the extra key silently ignored by the engine.\n if (config.organizationId && record['organization_id'] == null) {\n record['organization_id'] = config.organizationId;\n }\n\n // Resolve references\n for (const ref of objectRefs) {\n const fieldValue = record[ref.field];\n if (fieldValue === undefined || fieldValue === null) continue;\n\n // LOUD FAILURE: a reference must be a natural-key string (or an\n // internal id). An object value — e.g. the wrapper `{ externalId: 'X' }`\n // — never resolves: it would otherwise fall through unresolved and reach\n // the driver as a non-bindable value (\"SQLite3 can only bind ...\"). This\n // used to be silently skipped (and only crashed on a persistent DB's\n // update path), so catch it here and report the actionable fix instead.\n if (typeof fieldValue === 'object') {\n const wrapped = (fieldValue as Record<string, unknown>).externalId;\n const hint =\n wrapped !== undefined\n ? ` Pass the natural key directly: ${ref.field}: ${JSON.stringify(wrapped)}.`\n : ` Pass the target's ${ref.targetField} value as a plain string.`;\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n message:\n `Invalid reference for ${objectName}.${ref.field}: expected a ` +\n `${ref.targetObject}.${ref.targetField} natural-key string but got an object.${hint}`,\n };\n errors.push(error);\n allErrors.push(error);\n this.logger.warn(`[SeedLoader] ${error.message}`, { recordIndex: i });\n // Drop the unresolvable value so it never reaches the driver.\n record[ref.field] = null;\n continue;\n }\n\n // Skip if value looks like an internal ID (not a natural key)\n if (typeof fieldValue !== 'string' || this.looksLikeInternalId(fieldValue)) continue;\n\n // Try to resolve via already-inserted records\n const targetMap = insertedRecords.get(ref.targetObject);\n const resolvedId = targetMap?.get(String(fieldValue));\n\n if (resolvedId) {\n record[ref.field] = resolvedId;\n referencesResolved++;\n } else if (!config.dryRun) {\n // Try to resolve from existing data in the database\n const dbId = await this.resolveFromDatabase(ref.targetObject, ref.targetField, fieldValue, config.organizationId);\n if (dbId) {\n record[ref.field] = dbId;\n referencesResolved++;\n } else if (config.multiPass) {\n // Defer to pass 2\n record[ref.field] = null;\n deferredUpdates.push({\n objectName,\n recordExternalId: String(record[externalId] ?? ''),\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n });\n referencesDeferred++;\n } else {\n // Cannot resolve - record error\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n message: `Cannot resolve reference: ${objectName}.${ref.field} = '${fieldValue}' → ${ref.targetObject}.${ref.targetField} not found`,\n };\n errors.push(error);\n allErrors.push(error);\n }\n } else {\n // Dry-run: attempt resolution, report error if not found\n const targetMap2 = insertedRecords.get(ref.targetObject);\n if (!targetMap2?.has(String(fieldValue))) {\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: ref.field,\n targetObject: ref.targetObject,\n targetField: ref.targetField,\n attemptedValue: fieldValue,\n recordIndex: i,\n message: `[dry-run] Reference may not resolve: ${objectName}.${ref.field} = '${fieldValue}' → ${ref.targetObject}.${ref.targetField}`,\n };\n errors.push(error);\n allErrors.push(error);\n }\n }\n }\n\n // Insert/upsert the record\n if (!config.dryRun) {\n try {\n const result = await this.writeRecord(\n objectName, record, mode, externalId, existingRecords\n );\n\n if (result.action === 'inserted') inserted++;\n else if (result.action === 'updated') updated++;\n else if (result.action === 'skipped') skipped++;\n\n // Track the inserted/updated record's ID for reference resolution\n const externalIdValue = String(record[externalId] ?? '');\n const internalId = result.id;\n if (externalIdValue && internalId) {\n insertedRecords.get(objectName)!.set(externalIdValue, String(internalId));\n }\n } catch (err: any) {\n // LOUD FAILURE: write errors were previously only counted +\n // warn-logged, so dropped rows were invisible in result.errors and\n // the boot summary. Surface them as actionable errors too, so the\n // overall load is marked unsuccessful and the reason is reported.\n errored++;\n const error: ReferenceResolutionError = {\n sourceObject: objectName,\n field: '(write)',\n targetObject: objectName,\n targetField: externalId,\n attemptedValue: record[externalId] ?? null,\n recordIndex: i,\n message: `Failed to write ${objectName} record #${i} (${externalId}=${String(record[externalId] ?? '')}): ${err.message}`,\n };\n errors.push(error);\n allErrors.push(error);\n this.logger.warn(`[SeedLoader] ${error.message}`, { recordIndex: i });\n }\n } else {\n // Dry-run: simulate insert tracking\n const externalIdValue = String(record[externalId] ?? '');\n if (externalIdValue) {\n insertedRecords.get(objectName)!.set(externalIdValue, `dry-run-id-${i}`);\n }\n inserted++; // Count as \"would be inserted\"\n }\n }\n\n return {\n object: objectName,\n mode,\n inserted,\n updated,\n skipped,\n errored,\n total: dataset.records.length,\n referencesResolved,\n referencesDeferred,\n errors,\n };\n }\n\n // ==========================================================================\n // Internal: Reference Resolution\n // ==========================================================================\n\n private async resolveFromDatabase(\n targetObject: string,\n targetField: string,\n value: unknown,\n organizationId?: string,\n ): Promise<string | null> {\n try {\n const where: Record<string, unknown> = { [targetField]: value };\n // Per-tenant replay: when scoping is requested, only consider\n // rows that belong to the target tenant so cross-tenant rows\n // never get borrowed as a \"resolved\" reference (would silently\n // create a cross-org FK).\n if (organizationId) where.organization_id = organizationId;\n const records = await this.engine.find(targetObject, {\n where,\n fields: ['id'],\n limit: 1,\n context: { isSystem: true },\n } as any);\n if (records && records.length > 0) {\n return String(records[0].id || records[0]._id);\n }\n } catch {\n // Target object may not exist yet\n }\n return null;\n }\n\n private async resolveDeferredUpdates(\n deferredUpdates: DeferredUpdate[],\n insertedRecords: Map<string, Map<string, string>>,\n allResults: SeedLoadResult[],\n allErrors: ReferenceResolutionError[],\n organizationId?: string,\n ): Promise<void> {\n for (const deferred of deferredUpdates) {\n // Try to resolve from inserted records\n const targetMap = insertedRecords.get(deferred.targetObject);\n let resolvedId = targetMap?.get(String(deferred.attemptedValue));\n\n // Try database fallback\n if (!resolvedId) {\n resolvedId = (await this.resolveFromDatabase(\n deferred.targetObject, deferred.targetField, deferred.attemptedValue, organizationId\n )) ?? undefined;\n }\n\n if (resolvedId) {\n // Find the record and update the reference\n const objectRecordMap = insertedRecords.get(deferred.objectName);\n const recordId = objectRecordMap?.get(deferred.recordExternalId);\n\n if (recordId) {\n try {\n await this.engine.update(deferred.objectName, {\n id: recordId,\n [deferred.field]: resolvedId,\n }, { context: { isSystem: true } } as any);\n\n // Update result stats\n const resultEntry = allResults.find(r => r.object === deferred.objectName);\n if (resultEntry) {\n resultEntry.referencesResolved++;\n resultEntry.referencesDeferred--;\n }\n } catch (err: any) {\n this.logger.warn('[SeedLoader] Failed to resolve deferred reference', {\n object: deferred.objectName,\n field: deferred.field,\n error: err.message,\n });\n }\n }\n } else {\n // Still unresolved after pass 2\n const error: ReferenceResolutionError = {\n sourceObject: deferred.objectName,\n field: deferred.field,\n targetObject: deferred.targetObject,\n targetField: deferred.targetField,\n attemptedValue: deferred.attemptedValue,\n recordIndex: deferred.recordIndex,\n message: `Deferred reference unresolved after pass 2: ${deferred.objectName}.${deferred.field} = '${deferred.attemptedValue}' → ${deferred.targetObject}.${deferred.targetField} not found`,\n };\n\n const resultEntry = allResults.find(r => r.object === deferred.objectName);\n if (resultEntry) {\n resultEntry.errors.push(error);\n }\n allErrors.push(error);\n }\n }\n }\n\n // ==========================================================================\n // Internal: Write Operations\n // ==========================================================================\n\n /**\n * Seed writes always run as a privileged system context. This bypasses\n * RBAC checks (so seeds can target system tables like `sys_*`) and\n * disables the SecurityPlugin's auto-injection of `organization_id` /\n * `owner_id` — seeds either declare those fields explicitly per\n * record, or are intentionally cross-tenant / global.\n */\n private static readonly SEED_OPTIONS = { context: { isSystem: true } } as const;\n\n private async writeRecord(\n objectName: string,\n record: Record<string, unknown>,\n mode: string,\n externalId: string,\n existingRecords?: Map<string, any>,\n ): Promise<{ action: 'inserted' | 'updated' | 'skipped'; id?: string }> {\n const externalIdValue = record[externalId];\n const existing = existingRecords?.get(String(externalIdValue ?? ''));\n const opts = SeedLoaderService.SEED_OPTIONS as any;\n\n switch (mode) {\n case 'insert': {\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n\n case 'update': {\n if (!existing) {\n return { action: 'skipped' };\n }\n const id = this.extractId(existing);\n await this.engine.update(objectName, { ...record, id }, opts);\n return { action: 'updated', id };\n }\n\n case 'upsert': {\n if (existing) {\n const id = this.extractId(existing);\n await this.engine.update(objectName, { ...record, id }, opts);\n return { action: 'updated', id };\n } else {\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n }\n\n case 'ignore': {\n if (existing) {\n return { action: 'skipped', id: this.extractId(existing) };\n }\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n\n case 'replace': {\n // Replace mode: just insert (caller should have cleared the table)\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n\n default: {\n const result = await this.engine.insert(objectName, record, opts);\n return { action: 'inserted', id: this.extractId(result) };\n }\n }\n }\n\n // ==========================================================================\n // Internal: Dependency Graph\n // ==========================================================================\n\n /**\n * Kahn's algorithm for topological sort with cycle detection.\n */\n private topologicalSort(\n nodes: ObjectDependencyNode[],\n ): { insertOrder: string[]; circularDependencies: string[][] } {\n const inDegree = new Map<string, number>();\n const adjacency = new Map<string, string[]>();\n const objectSet = new Set(nodes.map(n => n.object));\n\n // Initialize\n for (const node of nodes) {\n inDegree.set(node.object, 0);\n adjacency.set(node.object, []);\n }\n\n // Build adjacency list and in-degree counts\n for (const node of nodes) {\n for (const dep of node.dependsOn) {\n // Exclude self-references from ordering (e.g., employee.manager_id → employee).\n // Self-referencing fields are still tracked in node.references for resolution.\n if (objectSet.has(dep) && dep !== node.object) {\n adjacency.get(dep)!.push(node.object);\n inDegree.set(node.object, (inDegree.get(node.object) || 0) + 1);\n }\n }\n }\n\n // Kahn's algorithm\n const queue: string[] = [];\n for (const [obj, degree] of inDegree) {\n if (degree === 0) queue.push(obj);\n }\n\n const insertOrder: string[] = [];\n while (queue.length > 0) {\n const current = queue.shift()!;\n insertOrder.push(current);\n\n for (const neighbor of (adjacency.get(current) || [])) {\n const newDegree = (inDegree.get(neighbor) || 0) - 1;\n inDegree.set(neighbor, newDegree);\n if (newDegree === 0) {\n queue.push(neighbor);\n }\n }\n }\n\n // Detect circular dependencies\n const circularDependencies: string[][] = [];\n const remaining = nodes.filter(n => !insertOrder.includes(n.object));\n\n if (remaining.length > 0) {\n // Find cycles using DFS\n const cycles = this.findCycles(remaining);\n circularDependencies.push(...cycles);\n\n // Add remaining objects to insertOrder (they'll need multi-pass)\n for (const node of remaining) {\n if (!insertOrder.includes(node.object)) {\n insertOrder.push(node.object);\n }\n }\n }\n\n return { insertOrder, circularDependencies };\n }\n\n private findCycles(nodes: ObjectDependencyNode[]): string[][] {\n const cycles: string[][] = [];\n const nodeMap = new Map(nodes.map(n => [n.object, n]));\n const visited = new Set<string>();\n const inStack = new Set<string>();\n\n const dfs = (current: string, path: string[]) => {\n if (inStack.has(current)) {\n // Found a cycle\n const cycleStart = path.indexOf(current);\n if (cycleStart !== -1) {\n cycles.push([...path.slice(cycleStart), current]);\n }\n return;\n }\n if (visited.has(current)) return;\n\n visited.add(current);\n inStack.add(current);\n path.push(current);\n\n const node = nodeMap.get(current);\n if (node) {\n for (const dep of node.dependsOn) {\n if (nodeMap.has(dep)) {\n dfs(dep, [...path]);\n }\n }\n }\n\n inStack.delete(current);\n };\n\n for (const node of nodes) {\n if (!visited.has(node.object)) {\n dfs(node.object, []);\n }\n }\n\n return cycles;\n }\n\n // ==========================================================================\n // Internal: Helpers\n // ==========================================================================\n\n private filterByEnv(datasets: Seed[], env?: string): Seed[] {\n if (!env) return datasets;\n return datasets.filter(d => (d.env as string[]).includes(env));\n }\n\n private orderDatasets(datasets: Seed[], insertOrder: string[]): Seed[] {\n const orderMap = new Map(insertOrder.map((name, i) => [name, i]));\n return [...datasets].sort((a, b) => {\n const orderA = orderMap.get(a.object) ?? Number.MAX_SAFE_INTEGER;\n const orderB = orderMap.get(b.object) ?? Number.MAX_SAFE_INTEGER;\n return orderA - orderB;\n });\n }\n\n private buildReferenceMap(graph: ObjectDependencyGraph): Map<string, ReferenceResolution[]> {\n const map = new Map<string, ReferenceResolution[]>();\n for (const node of graph.nodes) {\n if (node.references.length > 0) {\n map.set(node.object, node.references);\n }\n }\n return map;\n }\n\n private async loadExistingRecords(\n objectName: string,\n externalId: string,\n organizationId?: string,\n ): Promise<Map<string, any>> {\n const map = new Map<string, any>();\n try {\n const findArgs: Record<string, unknown> = {\n fields: ['id', externalId],\n context: { isSystem: true },\n };\n // Per-tenant replay: restrict to the target tenant's own rows\n // so upsert key matching never returns another tenant's record\n // (would silently steal/overwrite rows across orgs).\n if (organizationId) findArgs.where = { organization_id: organizationId };\n const records = await this.engine.find(objectName, findArgs as any);\n for (const record of records || []) {\n const key = String(record[externalId] ?? '');\n if (key) {\n map.set(key, record);\n }\n }\n } catch {\n // Object may not have records yet\n }\n return map;\n }\n\n private looksLikeInternalId(value: string): boolean {\n // UUID v4 pattern\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {\n return true;\n }\n // MongoDB ObjectId pattern (24 hex chars)\n if (/^[0-9a-f]{24}$/i.test(value)) {\n return true;\n }\n return false;\n }\n\n private extractId(record: any): string | undefined {\n if (!record) return undefined;\n return String(record.id || record._id || '');\n }\n\n private buildEmptyResult(config: SeedLoaderConfig, durationMs: number): SeedLoaderResult {\n return {\n success: true,\n dryRun: config.dryRun,\n dependencyGraph: { nodes: [], insertOrder: [], circularDependencies: [] },\n results: [],\n errors: [],\n summary: {\n objectsProcessed: 0,\n totalRecords: 0,\n totalInserted: 0,\n totalUpdated: 0,\n totalSkipped: 0,\n totalErrored: 0,\n totalReferencesResolved: 0,\n totalReferencesDeferred: 0,\n circularDependencyCount: 0,\n durationMs,\n },\n };\n }\n\n private buildResult(\n config: SeedLoaderConfig,\n graph: ObjectDependencyGraph,\n results: SeedLoadResult[],\n errors: ReferenceResolutionError[],\n durationMs: number,\n ): SeedLoaderResult {\n const summary = {\n objectsProcessed: results.length,\n totalRecords: results.reduce((sum, r) => sum + r.total, 0),\n totalInserted: results.reduce((sum, r) => sum + r.inserted, 0),\n totalUpdated: results.reduce((sum, r) => sum + r.updated, 0),\n totalSkipped: results.reduce((sum, r) => sum + r.skipped, 0),\n totalErrored: results.reduce((sum, r) => sum + r.errored, 0),\n totalReferencesResolved: results.reduce((sum, r) => sum + r.referencesResolved, 0),\n totalReferencesDeferred: results.reduce((sum, r) => sum + r.referencesDeferred, 0),\n circularDependencyCount: graph.circularDependencies.length,\n durationMs,\n };\n\n const hasErrors = errors.length > 0 || summary.totalErrored > 0;\n\n return {\n success: !hasErrors,\n dryRun: config.dryRun,\n dependencyGraph: graph,\n results,\n errors,\n summary,\n };\n }\n}\n\n// ==========================================================================\n// Internal Types\n// ==========================================================================\n\ninterface DeferredUpdate {\n objectName: string;\n recordExternalId: string;\n field: string;\n targetObject: string;\n targetField: string;\n attemptedValue: unknown;\n recordIndex: number;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n//\n// ADR-0038 L3 — runtime probes: after a publish, exercise the published app\n// the way a user would (one real read per artifact) and report what is\n// actually broken AT RUNTIME. Schema-valid ≠ renders ≠ returns data: the\n// 2026-06-10/11 incident set shipped seeds that never materialized, dataset\n// queries that returned 0 on populated objects, and \"Published!\" states the\n// runtime couldn't read back — all invisible until something actually\n// queried. These probes are that something, run by the build pipeline (not\n// the user), generalizing the `seedApplied` pattern to the whole artifact\n// graph.\n//\n// Every finding is a BuildIssue (the ADR-0038 verification contract — same\n// shape the cloud L1 graph lint emits) with `layer: 'runtime'`, so agents,\n// chat surfaces, and eval harnesses consume one stream regardless of which\n// verification plane found the problem.\n\n/** One runtime-verification finding (ADR-0038 BuildIssue, layer 'runtime'). */\nexport interface RuntimeBuildIssue {\n layer: 'runtime';\n severity: 'error' | 'warning';\n /** The artifact whose runtime behaviour is broken. */\n artifact: { type: string; name: string };\n /** What it exercised, when narrower than the artifact (e.g. a widget). */\n ref?: { type: string; name: string; member?: string };\n /** 'seed_not_applied' | 'view_read_failed' | 'empty_query' | 'widget_query_failed' | 'probes_unavailable' */\n code: string;\n message: string;\n fix?: string;\n}\n\n/** Aggregate result of one post-publish probe pass. */\nexport interface BuildProbeReport {\n /** Findings, empty when every probe passed. */\n issues: RuntimeBuildIssue[];\n /** How many probes actually ran, per plane (0s mean nothing to probe). */\n checked: { seeds: number; views: number; widgets: number };\n}\n\n/** The single read the probes need from the data engine. */\nexport interface ProbeEngine {\n find(objectName: string, query: unknown): Promise<Array<Record<string, unknown>>>;\n}\n\n/** Optional analytics surface — when absent, widget probes degrade to a warning. */\nexport interface ProbeAnalytics {\n queryDataset(dataset: unknown, selection: unknown, context?: unknown): Promise<unknown>;\n}\n\nexport interface RunBuildProbesOptions {\n engine: ProbeEngine;\n /** Read an ACTIVE (published) item body by type+name; undefined when absent. */\n getItem: (type: string, name: string) => Promise<unknown | undefined>;\n /** The just-published artifact set (publishPackageDrafts' `published`). */\n published: Array<{ type: string; name: string }>;\n /**\n * The kernel's analytics service, when one is mounted. Widget probes run\n * the SAME `queryDataset` path the dashboard renderer hits — absent\n * service means widgets can't be probed (one aggregate warning, not\n * per-widget noise).\n */\n analytics?: ProbeAnalytics;\n /** Threaded into engine/analytics reads (tenant scoping). */\n organizationId?: string | null;\n}\n\ntype Rec = Record<string, unknown>;\n\nfunction asRec(v: unknown): Rec | undefined {\n return v && typeof v === 'object' && !Array.isArray(v) ? (v as Rec) : undefined;\n}\n\nfunction asArr(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\n\n/** Result rows of a queryDataset call, tolerant of {rows}/{data}/array shapes. */\nfunction resultRows(result: unknown): unknown[] {\n if (Array.isArray(result)) return result;\n const r = asRec(result);\n if (!r) return [];\n if (Array.isArray(r.rows)) return r.rows;\n if (Array.isArray(r.data)) return r.data;\n return [];\n}\n\n/** True when the object has at least one row (probe read, isSystem). */\nasync function hasRows(\n engine: ProbeEngine,\n objectName: string,\n organizationId?: string | null,\n): Promise<boolean> {\n const rows = await engine.find(objectName, {\n fields: ['id'],\n limit: 1,\n ...(organizationId ? { where: { organization_id: organizationId } } : {}),\n context: { isSystem: true },\n });\n return Array.isArray(rows) && rows.length > 0;\n}\n\n/**\n * Run the L3 runtime probes over a just-published artifact set:\n *\n * • per published `seed` — its target object must have rows now\n * (`seed_not_applied`: the rows were promised but never materialized);\n * • per published `view` — a limit-1 read through the same engine the\n * renderer uses must not throw (`view_read_failed`);\n * • per published `dashboard` widget — its real dataset selection must\n * execute (`widget_query_failed`) and must not return empty on an object\n * that HAS rows (`empty_query` — the four-layer staging incident class).\n *\n * All probes are reads (limit-1 / single aggregate); a probe crash is\n * reported, never thrown — verification must not break the publish it\n * verifies.\n */\nexport async function runBuildProbes(opts: RunBuildProbesOptions): Promise<BuildProbeReport> {\n const issues: RuntimeBuildIssue[] = [];\n const checked = { seeds: 0, views: 0, widgets: 0 };\n const { engine, getItem, published, analytics, organizationId } = opts;\n\n // Memoized active-item reads (a dashboard and its widgets share datasets).\n const itemCache = new Map<string, unknown | undefined>();\n const readItem = async (type: string, name: string): Promise<unknown | undefined> => {\n const key = `${type} ${name}`;\n if (itemCache.has(key)) return itemCache.get(key);\n let item: unknown | undefined;\n try {\n item = await getItem(type, name);\n } catch {\n item = undefined;\n }\n itemCache.set(key, item);\n return item;\n };\n\n // ── Seeds: rows must exist after publish ────────────────────────────────\n for (const p of published.filter((x) => x.type === 'seed')) {\n const body = asRec(await readItem('seed', p.name));\n const objectName = typeof body?.object === 'string' ? body.object : undefined;\n if (!objectName) continue;\n checked.seeds += 1;\n try {\n if (!(await hasRows(engine, objectName, organizationId))) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'seed', name: p.name },\n ref: { type: 'object', name: objectName },\n code: 'seed_not_applied',\n message: `Seed \"${p.name}\" was published but object \"${objectName}\" has no rows — the sample data never materialized.`,\n fix: `Check the publish response's seedApplied for the load error, fix the seed rows (field names/types), and republish the seed.`,\n });\n }\n } catch (e) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'seed', name: p.name },\n ref: { type: 'object', name: objectName },\n code: 'seed_not_applied',\n message: `Seed \"${p.name}\" probe could not read object \"${objectName}\": ${String((e as Error)?.message ?? e)}`,\n });\n }\n }\n\n // ── Views: the renderer's read path must not throw ──────────────────────\n for (const p of published.filter((x) => x.type === 'view')) {\n const body = asRec(await readItem('view', p.name));\n const config = asRec(body?.config);\n const dataObj = asRec(config?.data)?.object;\n const objectName =\n typeof body?.object === 'string' ? body.object\n : typeof dataObj === 'string' ? dataObj\n : undefined;\n if (!objectName) continue;\n checked.views += 1;\n try {\n await engine.find(objectName, {\n fields: ['id'],\n limit: 1,\n ...(organizationId ? { where: { organization_id: organizationId } } : {}),\n context: { isSystem: true },\n });\n } catch (e) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'view', name: p.name },\n ref: { type: 'object', name: objectName },\n code: 'view_read_failed',\n message: `View \"${p.name}\" cannot read object \"${objectName}\": ${String((e as Error)?.message ?? e)} — it will render as an error for every user.`,\n fix: `Verify object \"${objectName}\" published successfully (its table must exist) and that the view's binding is correct.`,\n });\n }\n }\n\n // ── Dashboard widgets: the real dataset selection must return data ──────\n const dashboards = published.filter((x) => x.type === 'dashboard');\n let widgetsToProbe = 0;\n for (const p of dashboards) {\n const body = asRec(await readItem('dashboard', p.name));\n const widgets = asArr(body?.widgets).map(asRec).filter((w): w is Rec => !!w);\n const datasetBound = widgets.filter((w) => typeof w.dataset === 'string' && w.dataset);\n widgetsToProbe += datasetBound.length;\n if (!analytics || typeof analytics.queryDataset !== 'function') continue;\n\n for (const w of datasetBound) {\n const widgetId = String(w.id ?? w.title ?? '?');\n const dsName = w.dataset as string;\n const dataset = asRec(await readItem('dataset', dsName));\n if (!dataset) continue; // dangling dataset is an L1 (graph) finding, not a runtime one\n checked.widgets += 1;\n\n // The widget's own selection when present, else the dataset's\n // first measure — the same default the renderer falls back to.\n const measures = asArr(w.values).filter((v): v is string => typeof v === 'string' && v.length > 0);\n const firstMeasure = asRec(asArr(dataset.measures)[0])?.name;\n const selection = {\n measures: measures.length ? measures : typeof firstMeasure === 'string' ? [firstMeasure] : [],\n dimensions: [],\n limit: 1,\n };\n if (selection.measures.length === 0) continue; // nothing selectable — schema/graph problem\n\n const objectName = typeof dataset.object === 'string' ? dataset.object : undefined;\n try {\n const result = await analytics.queryDataset(dataset, selection, undefined);\n const rows = resultRows(result);\n if (rows.length === 0 && objectName && (await hasRows(engine, objectName, organizationId))) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'dashboard', name: p.name },\n ref: { type: 'dataset', name: dsName, member: widgetId },\n code: 'empty_query',\n message: `Dashboard \"${p.name}\" widget \"${widgetId}\" returns NO data from dataset \"${dsName}\" although object \"${objectName}\" has rows — the widget will render empty for every user.`,\n fix: `Run the dataset query directly to see the compiled strategy/SQL; check the dataset's measure/dimension field bindings against object \"${objectName}\".`,\n });\n }\n } catch (e) {\n issues.push({\n layer: 'runtime',\n severity: 'error',\n artifact: { type: 'dashboard', name: p.name },\n ref: { type: 'dataset', name: dsName, member: widgetId },\n code: 'widget_query_failed',\n message: `Dashboard \"${p.name}\" widget \"${widgetId}\" query against dataset \"${dsName}\" failed: ${String((e as Error)?.message ?? e)}`,\n fix: `Fix the dataset definition (or the widget's values/dimensions) so the query compiles, then republish.`,\n });\n }\n }\n }\n\n // Widgets existed but no analytics service was mounted — say so ONCE\n // (silence would read as \"probed and passed\", which it was not).\n if (widgetsToProbe > 0 && (!analytics || typeof analytics.queryDataset !== 'function')) {\n issues.push({\n layer: 'runtime',\n severity: 'warning',\n artifact: { type: 'dashboard', name: dashboards.map((d) => d.name).join(', ') },\n code: 'probes_unavailable',\n message: `${widgetsToProbe} dashboard widget(s) could not be probed: no analytics service is mounted on this kernel.`,\n });\n }\n\n return { issues, checked };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n// Export Registry\nexport { \n SchemaRegistry,\n applySystemFields,\n computeFQN,\n parseFQN,\n RESERVED_NAMESPACES,\n DEFAULT_OWNER_PRIORITY,\n DEFAULT_EXTENDER_PRIORITY,\n} from './registry.js';\nexport type { ObjectContributor, SchemaRegistryOptions } from './registry.js';\n\n// Export Protocol Implementation\nexport { ObjectStackProtocolImplementation } from './protocol.js';\n\n// ADR-0008 PR-10b: MetadataRepository wrapper over the existing sys_metadata table.\nexport { SysMetadataRepository } from './sys-metadata-repository.js';\nexport type { SysMetadataEngine, SysMetadataRepositoryOptions } from './sys-metadata-repository.js';\n\n// Export Engine\nexport { ObjectQL, ObjectRepository, ScopedContext } from './engine.js';\nexport type { ObjectQLHostContext, HookHandler, HookEntry, OperationContext, EngineMiddleware } from './engine.js';\n\n// Export in-memory aggregation fallback (used by engine.aggregate when the\n// driver lacks native groupBy/aggregations support; also useful for tests).\nexport { applyInMemoryAggregation, bucketDateValue } from './in-memory-aggregation.js';\n\n// Export Hook Binder & Wrappers (declarative-metadata → engine glue)\nexport { bindHooksToEngine } from './hook-binder.js';\nexport type { BindHooksOptions, BindHooksResult } from './hook-binder.js';\nexport { wrapDeclarativeHook } from './hook-wrappers.js';\nexport type { WrapDeclarativeOptions } from './hook-wrappers.js';\n\n// Export Validation\nexport { ValidationError, validateRecord } from './validation/record-validator.js';\nexport type { FieldValidationError } from './validation/record-validator.js';\nexport { evaluateValidationRules, needsPriorRecord, legalNextStates } from './validation/rule-validator.js';\nexport type { EvaluateRulesOptions } from './validation/rule-validator.js';\nexport {\n InMemoryHookMetricsRecorder,\n noopHookMetricsRecorder,\n} from './hook-metrics.js';\nexport type {\n HookMetricsRecorder,\n HookMetricLabel,\n HookMetricOutcome,\n HookSkipReason,\n} from './hook-metrics.js';\n\n// Export MetadataFacade\nexport { MetadataFacade } from './metadata-facade.js';\n\n// Export Plugin Shim\nexport { ObjectQLPlugin } from './plugin.js';\n\n// Export Kernel Factory\nexport { createObjectQLKernel } from './kernel-factory.js';\nexport type { ObjectQLKernelOptions } from './kernel-factory.js';\n\n// Export secret-field channel helpers (for hosts / privileged consumers)\nexport {\n SECRET_REF_PREFIX,\n SECRET_MASK,\n makeSecretRef,\n isSecretRef,\n parseSecretRef,\n collectSecretFields,\n} from './secret-fields.js';\n\n// Export Utilities\nexport {\n toTitleCase,\n convertIntrospectedSchemaToObjects,\n} from './util.js';\nexport type {\n IntrospectedColumn,\n IntrospectedForeignKey,\n IntrospectedTable,\n IntrospectedSchema,\n} from './util.js';\n\n// Seed loader — materializes `seed` metadata into rows (used by publishMetaItem\n// and the runtime dispatcher/app plugins).\nexport { SeedLoaderService } from './seed-loader.js';\n\n// ADR-0038 L3 — post-publish runtime probes (one real read per published\n// artifact); findings are BuildIssue-shaped with layer 'runtime'.\nexport { runBuildProbes } from './build-probes.js';\nexport type { RuntimeBuildIssue, BuildProbeReport, RunBuildProbesOptions } from './build-probes.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ServiceObject, ObjectSchema, ObjectOwnership } from '@objectstack/spec/data';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport { ObjectStackManifest, ManifestSchema, InstalledPackage, InstalledPackageSchema } from '@objectstack/spec/kernel';\nimport { AppSchema } from '@objectstack/spec/ui';\nimport { applyProtection } from '@objectstack/spec/shared';\n\n/**\n * Reserved namespaces that do not get FQN prefix applied.\n * Objects in these namespaces keep their short names (e.g., \"user\" — short name IS the canonical key).\n */\nexport const RESERVED_NAMESPACES = new Set(['base', 'system']);\n\n/**\n * Default priorities for ownership types.\n */\nexport const DEFAULT_OWNER_PRIORITY = 100;\nexport const DEFAULT_EXTENDER_PRIORITY = 200;\n\n/**\n * Contributor Record\n * Tracks how a package contributes to an object (own or extend).\n */\nexport interface ObjectContributor {\n packageId: string;\n namespace: string;\n ownership: ObjectOwnership;\n priority: number;\n definition: ServiceObject;\n}\n\n/**\n * Compute canonical registry key for an object.\n *\n * Under the current naming convention, object names are canonical identifiers\n * and are used as-is (no namespace__ prefix). The namespace parameter is\n * retained for backward compatibility but no longer affects the returned key.\n *\n * @param namespace - The package namespace (unused, kept for API compatibility)\n * @param shortName - The object's name (already the canonical identifier)\n * @returns The object name unchanged\n *\n * @example\n * computeFQN('crm', 'account') // => 'account'\n * computeFQN(undefined, 'task') // => 'task'\n */\nexport function computeFQN(_namespace: string | undefined, shortName: string): string {\n return shortName;\n}\n\n/**\n * Parse FQN back to namespace and short name.\n * \n * @param fqn - Object name (e.g., \"account\" or legacy \"crm__account\" for backward compat)\n * @returns { namespace, shortName } - namespace is undefined for unprefixed names\n */\nexport function parseFQN(fqn: string): { namespace: string | undefined; shortName: string } {\n const idx = fqn.indexOf('__');\n if (idx === -1) {\n return { namespace: undefined, shortName: fqn };\n }\n return {\n namespace: fqn.slice(0, idx),\n shortName: fqn.slice(idx + 2),\n };\n}\n\n/**\n * Deep merge two ServiceObject definitions.\n * Fields are merged additively. Other props: later value wins.\n */\nfunction mergeObjectDefinitions(base: ServiceObject, extension: Partial<ServiceObject>): ServiceObject {\n const merged = { ...base };\n\n // Merge fields additively\n if (extension.fields) {\n merged.fields = { ...base.fields, ...extension.fields };\n }\n\n // Merge validations additively\n if (extension.validations) {\n merged.validations = [...(base.validations || []), ...extension.validations];\n }\n\n // Merge indexes additively\n if (extension.indexes) {\n merged.indexes = [...(base.indexes || []), ...extension.indexes];\n }\n\n // Override scalar props (last writer wins)\n if (extension.label !== undefined) merged.label = extension.label;\n if (extension.pluralLabel !== undefined) merged.pluralLabel = extension.pluralLabel;\n if (extension.description !== undefined) merged.description = extension.description;\n\n return merged;\n}\n\n/**\n * Global Schema Registry\n * Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)\n * \n * ## Namespace & Ownership Model\n * \n * Objects use a namespace-based FQN system:\n * - `namespace`: Short identifier from package manifest (e.g., \"crm\", \"todo\")\n * - `name`: canonical object name (e.g., \"account\", \"sys_user\")\n * - Reserved namespaces (`base`, `system`) don't get prefixed\n * \n * Ownership modes:\n * - `own`: One package owns the object (creates the table, defines base schema)\n * - `extend`: Multiple packages can extend an object (add fields, merge by priority)\n * \n * ## Package vs App Distinction\n * - **Package**: The unit of installation, stored under type 'package'.\n * Each InstalledPackage wraps a ManifestSchema with lifecycle state.\n * - **App**: A UI navigation shell (AppSchema), registered under type 'apps'.\n * Apps are extracted from packages during registration.\n * - A package may contain 0, 1, or many apps.\n */\nexport type RegistryLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\n/**\n * Construction options for {@link SchemaRegistry}.\n */\nexport interface SchemaRegistryOptions {\n /**\n * Whether the host kernel runs in multi-tenant mode. The `organization_id`\n * column itself is auto-injected regardless of this flag (lookup →\n * sys_organization, on every registered object that doesn't already declare\n * it, isn't `managedBy` an external subsystem, and hasn't opted out via\n * `systemFields`/`tenancy.enabled:false`). When `true` the injected column\n * is additionally INDEXED — single-tenant stacks skip the index since\n * nothing ever filters by organization.\n *\n * Sourced from the `OS_MULTI_TENANT` env var when not explicitly set —\n * matches how the SecurityPlugin and CLI startup banner pick the mode.\n * Default is `false` (single-tenant) so local `dev`/`start` runs seed\n * demo data inline at boot; set `OS_MULTI_TENANT=true` for cloud /\n * production multi-org deployments. Pass an explicit boolean to override\n * (useful in tests).\n */\n multiTenant?: boolean;\n\n /**\n * Policy for cross-package base-layer metadata collisions (ADR-0048) — two\n * different code packages registering a bare-named generic item under the\n * same `(type, name)`.\n *\n * - `'error'` (default): throw {@link MetadataCollisionError} at registration\n * time, naming both packages and the type/name. Makes the otherwise-silent\n * last-write-wins shadowing a loud, actionable failure.\n * - `'warn'`: log a warning and let the registration proceed. For deliberate\n * migrations where a collision is temporarily expected.\n *\n * Sourced from `OS_METADATA_COLLISION` (`warn` to downgrade) when not set\n * explicitly. Legitimate runtime/DB overlays and same-package reloads are\n * never treated as collisions regardless of this setting.\n */\n collisionPolicy?: 'error' | 'warn';\n}\n\n/**\n * Augment a registered object with implicit system fields.\n *\n * Returns a *new* schema object when fields are added; returns the input\n * unchanged when nothing applies (the cheap path for system tables).\n *\n * Author-declared fields always win — we splice the system fields at the\n * front of the field map, so any same-named author field overwrites them\n * via the natural `{ ...sys, ...authored }` merge.\n *\n * Currently injects:\n * - `organization_id` — always provisioned (unless the object opts out via\n * `systemFields`/`tenancy.enabled:false` or is `better-auth` managed) so\n * the column never depends on the global multi-tenant flag. Required-false;\n * org-scoping populates it on insert in multi-tenant mode, and it stays\n * NULL on single-tenant stacks. Only the column's INDEX is gated on\n * `multiTenant` (no per-tenant filtering exists single-tenant).\n * - `created_at` / `created_by` / `updated_at` / `updated_by` — audit\n * fields. Marked `system: true, readonly: true` so detail views can\n * surface them in a dedicated \"System Information\" section while\n * edit forms / drawers filter them out. The driver populates the\n * timestamps; the `*_by` lookups are filled by the runtime when an\n * authenticated session is present (NULL otherwise — e.g. seeded\n * rows).\n */\nexport function applySystemFields(\n schema: ServiceObject,\n opts: { multiTenant: boolean }\n): ServiceObject {\n // 1. Hard opt-out at object level (e.g. seed/migration tables).\n if ((schema as any).systemFields === false) return schema;\n\n // 2. Skip only `better-auth` managed tables. Their column layout is\n // driven by better-auth's own migrations (sys_user, sys_session,\n // sys_organization, …) and injecting extra columns here would\n // collide with what better-auth expects. Other `managedBy` buckets\n // (`platform`, `config`, `system`, `append-only`) all need the\n // tenant + audit columns for multi-tenant isolation and time-travel\n // history — withholding them silently broke RLS reads on\n // sys_audit_log / sys_activity (the SecurityPlugin's\n // field-existence safety net dropped `organization_id =\n // current_user.organization_id` as \"field missing\", producing\n // RLS_DENY_FILTER → 0 rows for every non-admin caller).\n if (schema.managedBy === 'better-auth') return schema;\n\n const sf =\n typeof (schema as any).systemFields === 'object' && (schema as any).systemFields !== null\n ? ((schema as any).systemFields as { tenant?: boolean; audit?: boolean })\n : undefined;\n\n // Honor explicit opt-out via either `systemFields.tenant === false`\n // OR `tenancy.enabled === false`. The latter is the schema-level\n // declaration that the table is a shared/global catalog (e.g.\n // sys_package — the Marketplace registry). Without this, the\n // registry would still inject `organization_id`, and the\n // SecurityPlugin's RLS layer would filter every cross-org read down\n // to 0 rows even though the schema explicitly disabled multi-tenancy.\n const tenancyDisabled = (schema as any).tenancy?.enabled === false;\n // The `organization_id` COLUMN is provisioned unconditionally (subject only\n // to the explicit opt-outs above) — its existence no longer depends on the\n // global multi-tenant flag. Decoupling \"does the column exist\" from \"is\n // tenancy enabled\" is what stops sudo writers (audit / messaging / inbox /\n // outbox …) from failing with \"no column named organization_id\" on\n // single-tenant stacks: they can always stamp the column, it just stays NULL\n // when no tenant context exists. The multi-tenant flag now governs only\n // whether the column is INDEXED — on a single-tenant DB nothing ever filters\n // by organization, so the index would be dead weight.\n const wantTenant = sf?.tenant !== false && !tenancyDisabled;\n const wantAudit = sf?.audit !== false;\n\n const additions: Record<string, any> = {};\n\n if (wantTenant && !schema.fields?.organization_id) {\n additions.organization_id = {\n type: 'lookup',\n reference: 'sys_organization',\n label: 'Organization',\n required: false,\n indexed: opts.multiTenant,\n hidden: true,\n readonly: true,\n system: true,\n description:\n 'Tenant scope (auto-populated by org-scoping on insert; NULL on single-tenant stacks).',\n };\n }\n\n if (wantAudit) {\n if (!schema.fields?.created_at) {\n additions.created_at = {\n type: 'datetime',\n label: 'Created At',\n required: false,\n readonly: true,\n system: true,\n description: 'Timestamp when the record was created (auto-populated by the driver).',\n };\n }\n if (!schema.fields?.created_by) {\n additions.created_by = {\n type: 'lookup',\n reference: 'sys_user',\n label: 'Created By',\n required: false,\n readonly: true,\n system: true,\n description: 'User who created the record (populated when an authenticated session is present).',\n };\n }\n if (!schema.fields?.updated_at) {\n additions.updated_at = {\n type: 'datetime',\n label: 'Last Modified At',\n required: false,\n readonly: true,\n system: true,\n description: 'Timestamp of the most recent modification (auto-populated by the driver).',\n };\n }\n if (!schema.fields?.updated_by) {\n additions.updated_by = {\n type: 'lookup',\n reference: 'sys_user',\n label: 'Last Modified By',\n required: false,\n readonly: true,\n system: true,\n description: 'User who last modified the record (populated when an authenticated session is present).',\n };\n }\n }\n\n if (Object.keys(additions).length === 0) return schema;\n\n return {\n ...schema,\n fields: { ...additions, ...(schema.fields ?? {}) },\n };\n}\n\n/**\n * The rehydration sentinel stamped on items loaded back from `sys_metadata`\n * (runtime/DB overlay rows). It is NOT a real owning code package, so it must\n * never participate in cross-package collision detection (ADR-0048).\n */\nconst SYS_METADATA_OWNER = 'sys_metadata';\n\n/**\n * True when `pkg` identifies a genuine code package (an artifact owner), as\n * opposed to absent provenance or the `sys_metadata` runtime-overlay sentinel.\n * Cross-package collision detection (ADR-0048) only compares real owners so\n * that legitimate runtime/DB overlays never look like a base-layer collision.\n */\nfunction isRealPackage(pkg: unknown): pkg is string {\n return typeof pkg === 'string' && pkg.length > 0 && pkg !== SYS_METADATA_OWNER;\n}\n\n/**\n * Raised when two **different** code packages register a generic (non-object)\n * metadata item under the same `(type, name)` in the code-defined base layer\n * (ADR-0048).\n *\n * The registry key for bare-named UI/automation metadata (`page`, `dashboard`,\n * `flow`, `app`, `action`, `doc`, …) carries no package coordinate — those\n * names are only snake_case-validated, never namespace-prefix-validated the way\n * object names are. So two installed packages that each define e.g. a `page`\n * named `home` collide on the same logical key, and bare-name read resolution\n * (`getItem`) would silently return whichever the registry iterates first,\n * leaving the other package's item unreachable. This error makes that hazard\n * loud at registration/install time instead of silent at read time.\n */\nexport class MetadataCollisionError extends Error {\n readonly type: string;\n readonly name_: string;\n readonly existingPackageId: string;\n readonly incomingPackageId: string;\n\n constructor(type: string, name: string, existingPackageId: string, incomingPackageId: string) {\n super(\n `Cross-package metadata collision: ${type}/${name} is registered by ` +\n `package \"${existingPackageId}\" and package \"${incomingPackageId}\". ` +\n `Bare-named ${type} metadata has no package coordinate in the registry, ` +\n `so the second registration would silently shadow the first ` +\n `(last-write-wins at read time). Rename one of them (a namespace prefix ` +\n `such as \"<namespace>_${name}\" is recommended), or, if this is a ` +\n `deliberate migration, set OS_METADATA_COLLISION=warn to downgrade to a ` +\n `warning. See ADR-0048.`,\n );\n this.name = 'MetadataCollisionError';\n this.type = type;\n // `name` is the Error message-class name; store the metadata name separately.\n this.name_ = name;\n this.existingPackageId = existingPackageId;\n this.incomingPackageId = incomingPackageId;\n }\n}\n\nexport class SchemaRegistry {\n // ==========================================\n // Logging control\n // ==========================================\n\n /** Controls verbosity of registry console messages. Default: 'info'. */\n private _logLevel: RegistryLogLevel = 'info';\n\n /** Whether to auto-inject multi-tenant system fields. */\n private readonly multiTenant: boolean;\n\n /** Cross-package base-layer collision policy (ADR-0048). */\n private readonly collisionPolicy: 'error' | 'warn';\n\n constructor(options: SchemaRegistryOptions = {}) {\n if (options.multiTenant !== undefined) {\n this.multiTenant = options.multiTenant;\n } else {\n // Mirror the SecurityPlugin / CLI banner default (env-driven, off by default).\n this.multiTenant =\n String(readEnvWithDeprecation('OS_MULTI_ORG_ENABLED', 'OS_MULTI_TENANT') ?? 'false').toLowerCase() !== 'false';\n }\n\n // ADR-0048 — default to a loud error on cross-package collision; allow an\n // env opt-out for deliberate migrations.\n this.collisionPolicy =\n options.collisionPolicy ??\n ((process.env.OS_METADATA_COLLISION ?? '').toLowerCase() === 'warn' ? 'warn' : 'error');\n }\n\n get logLevel(): RegistryLogLevel { return this._logLevel; }\n set logLevel(level: RegistryLogLevel) { this._logLevel = level; }\n\n private log(msg: string): void {\n if (this._logLevel === 'silent' || this._logLevel === 'error' || this._logLevel === 'warn') return;\n console.log(msg);\n }\n\n // ==========================================\n // Object-specific storage (Ownership Model)\n // ==========================================\n\n /** FQN → Contributor[] (all packages that own/extend this object) */\n private objectContributors = new Map<string, ObjectContributor[]>();\n\n /** FQN → Merged ServiceObject (cached, invalidated on changes) */\n private mergedObjectCache = new Map<string, ServiceObject>();\n\n /** Namespace → Set<PackageId> (multiple packages can share a namespace) */\n private namespaceRegistry = new Map<string, Set<string>>();\n\n // ==========================================\n // Generic metadata storage (non-object types)\n // ==========================================\n\n /** Type → Name/ID → MetadataItem */\n private metadata = new Map<string, Map<string, any>>();\n\n /**\n * App name → navigation contributions (ADR-0029 D7).\n *\n * Lets packages inject nav items into apps they do not own (the UI analog\n * of object extenders). Merged into the owning app's `navigation` tree on\n * read in {@link getApp} / {@link getAllApps} by group id + priority.\n */\n private appNavContributions = new Map<string, Array<{ packageId?: string; group?: string; priority: number; items: any[] }>>();\n\n /**\n * Package ids that must be installed in a DISABLED state. Seeded once at\n * boot (from persisted state) BEFORE any package registration so that every\n * registration path — boot artifact, marketplace rehydrate, local import —\n * honors persisted disable state uniformly without a fragile post-boot\n * re-application hook. See {@link setInitialDisabledPackageIds} and\n * {@link installPackage}.\n */\n private initialDisabledPackageIds = new Set<string>();\n\n /**\n * Seed the set of package ids that should be installed disabled. Call this\n * before package registration begins; later `installPackage` calls for these\n * ids land in the `disabled` state. Replaces any previously seeded set.\n */\n setInitialDisabledPackageIds(ids: Iterable<string>): void {\n this.initialDisabledPackageIds = new Set(ids);\n }\n\n // ==========================================\n // Namespace Management\n // ==========================================\n\n /**\n * Register a namespace for a package.\n * Multiple packages can share the same namespace (e.g. 'sys').\n */\n registerNamespace(namespace: string, packageId: string): void {\n if (!namespace) return;\n\n let owners = this.namespaceRegistry.get(namespace);\n if (!owners) {\n owners = new Set();\n this.namespaceRegistry.set(namespace, owners);\n }\n owners.add(packageId);\n this.log(`[Registry] Registered namespace: ${namespace} → ${packageId}`);\n }\n\n /**\n * Unregister a namespace when a package is uninstalled.\n */\n unregisterNamespace(namespace: string, packageId: string): void {\n const owners = this.namespaceRegistry.get(namespace);\n if (owners) {\n owners.delete(packageId);\n if (owners.size === 0) {\n this.namespaceRegistry.delete(namespace);\n }\n this.log(`[Registry] Unregistered namespace: ${namespace} ← ${packageId}`);\n }\n }\n\n /**\n * Get the packages that use a namespace.\n */\n getNamespaceOwner(namespace: string): string | undefined {\n const owners = this.namespaceRegistry.get(namespace);\n if (!owners || owners.size === 0) return undefined;\n // Return the first registered package for backwards compatibility\n return owners.values().next().value;\n }\n\n /**\n * Get all packages that share a namespace.\n */\n getNamespaceOwners(namespace: string): string[] {\n const owners = this.namespaceRegistry.get(namespace);\n return owners ? Array.from(owners) : [];\n }\n\n // ==========================================\n // Object Registration (Ownership Model)\n // ==========================================\n\n /**\n * Register an object with ownership semantics.\n * \n * @param schema - The object definition\n * @param packageId - The owning package ID\n * @param namespace - The package namespace (for FQN computation)\n * @param ownership - 'own' (single owner) or 'extend' (additive merge)\n * @param priority - Merge priority (lower applied first, higher wins on conflict)\n * \n * @throws Error if trying to 'own' an object that already has an owner\n */\n registerObject(\n schema: ServiceObject,\n packageId: string,\n namespace?: string,\n ownership: ObjectOwnership = 'own',\n priority: number = ownership === 'own' ? DEFAULT_OWNER_PRIORITY : DEFAULT_EXTENDER_PRIORITY\n ): string {\n // Apply system-field injection (multi-tenant org_id, future owner/audit)\n // BEFORE FQN computation and contributor storage so every consumer of\n // the registered schema (driver syncSchema, REST projector, hooks)\n // sees the same canonical shape. Author-declared fields win — see\n // applySystemFields().\n schema = applySystemFields(schema, { multiTenant: this.multiTenant });\n\n const shortName = schema.name;\n const fqn = computeFQN(namespace, shortName);\n\n // Ensure namespace is registered\n if (namespace) {\n this.registerNamespace(namespace, packageId);\n }\n\n // Get or create contributor list\n let contributors = this.objectContributors.get(fqn);\n if (!contributors) {\n contributors = [];\n this.objectContributors.set(fqn, contributors);\n }\n\n // Validate ownership rules\n if (ownership === 'own') {\n const existingOwner = contributors.find(c => c.ownership === 'own');\n if (existingOwner && existingOwner.packageId !== packageId) {\n throw new Error(\n `Object \"${fqn}\" is already owned by package \"${existingOwner.packageId}\". ` +\n `Package \"${packageId}\" cannot claim ownership. Use 'extend' to add fields.`\n );\n }\n // Remove existing owner contribution from same package (re-registration)\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'own');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n console.warn(`[Registry] Re-registering owned object: ${fqn} from ${packageId}`);\n }\n } else {\n // extend mode: remove existing extension from same package\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'extend');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n }\n }\n\n // ADR-0010 §3.7 — translate the author-facing `protection` block\n // into the private `_lock` envelope and stamp package provenance\n // on the schema before it lands in the contributor list. Mirrors\n // registerItem() so object schemas surface lock fields on GET.\n applyProtection(schema as any, { packageId });\n\n // Add new contributor\n const contributor: ObjectContributor = {\n packageId,\n namespace: namespace || '',\n ownership,\n priority,\n definition: { ...schema, name: fqn }, // Store with FQN as name\n };\n contributors.push(contributor);\n\n // Sort by priority (ascending: lower priority applied first)\n contributors.sort((a, b) => a.priority - b.priority);\n\n // Invalidate merge cache\n this.mergedObjectCache.delete(fqn);\n\n this.log(`[Registry] Registered object: ${fqn} (${ownership}, priority=${priority}) from ${packageId}`);\n return fqn;\n }\n\n /**\n * Resolve an object by FQN, merging all contributions.\n * Returns the merged object or undefined if not found.\n */\n resolveObject(fqn: string): ServiceObject | undefined {\n // Check cache first\n const cached = this.mergedObjectCache.get(fqn);\n if (cached) return cached;\n\n const contributors = this.objectContributors.get(fqn);\n if (!contributors || contributors.length === 0) {\n return undefined;\n }\n\n // Find owner (must exist for a valid object)\n const ownerContrib = contributors.find(c => c.ownership === 'own');\n if (!ownerContrib) {\n console.warn(`[Registry] Object \"${fqn}\" has extenders but no owner. Skipping.`);\n return undefined;\n }\n\n // Start with owner's definition\n let merged = { ...ownerContrib.definition };\n\n // Apply extensions in priority order (already sorted)\n for (const contrib of contributors) {\n if (contrib.ownership === 'extend') {\n merged = mergeObjectDefinitions(merged, contrib.definition);\n }\n }\n\n // Cache the result\n this.mergedObjectCache.set(fqn, merged);\n return merged;\n }\n\n /**\n * Get object by name (short name canonical, FQN supported for disambiguation).\n *\n * Short names are canonical for user code, AI generation, and most lookups.\n * FQN is accepted as an explicit fallback for cross-package disambiguation\n * when two packages contribute objects with the same short name.\n *\n * Resolution order:\n * 1. Exact name match — the name IS the canonical key.\n * If multiple packages contribute the same short name, a warning is logged\n * and the first match wins — disambiguate by passing the FQN explicitly.\n * 2. Legacy FQN match (e.g., 'crm__account') — backward compat.\n */\n getObject(name: string): ServiceObject | undefined {\n // Canonical: short name lookup\n const matches: string[] = [];\n for (const fqn of this.objectContributors.keys()) {\n const { shortName } = parseFQN(fqn);\n if (shortName === name) {\n matches.push(fqn);\n }\n }\n if (matches.length > 0) {\n if (matches.length > 1) {\n console.warn(\n `[SchemaRegistry] Ambiguous short name \"${name}\" matches: ${matches.join(', ')}. ` +\n `Returning first match. Use FQN to disambiguate.`\n );\n }\n return this.resolveObject(matches[0]);\n }\n\n // Fallback: explicit FQN\n return this.resolveObject(name);\n }\n\n /**\n * Get all registered objects (merged).\n * \n * @param packageId - Optional filter: only objects contributed by this package\n */\n getAllObjects(packageId?: string): ServiceObject[] {\n const results: ServiceObject[] = [];\n\n for (const fqn of this.objectContributors.keys()) {\n // If filtering by package, check if this package contributes\n if (packageId) {\n const contributors = this.objectContributors.get(fqn);\n const hasContribution = contributors?.some(c => c.packageId === packageId);\n if (!hasContribution) continue;\n }\n\n const merged = this.resolveObject(fqn);\n if (merged) {\n // Tag with contributor info for UI\n (merged as any)._packageId = this.getObjectOwner(fqn)?.packageId;\n results.push(merged);\n }\n }\n\n return results;\n }\n\n /**\n * Get all contributors for an object.\n */\n getObjectContributors(fqn: string): ObjectContributor[] {\n return this.objectContributors.get(fqn) || [];\n }\n\n /**\n * Get the owner contributor for an object.\n */\n getObjectOwner(fqn: string): ObjectContributor | undefined {\n const contributors = this.objectContributors.get(fqn);\n return contributors?.find(c => c.ownership === 'own');\n }\n\n /**\n * ADR-0029 K0 — assert every registered object resolves to exactly one\n * owner.\n *\n * A second `own` from a different package is already rejected eagerly in\n * {@link registerObject} (it throws). This is the install-time backstop\n * called once all packages are registered (kernel bootstrap complete),\n * and it additionally catches the case `registerObject` cannot: an object\n * that has only `extend` contributions and **no owner** — which would\n * otherwise resolve to nothing. Surfacing it here turns a silent\n * \"extend a non-existent object\" into a clear bootstrap error.\n *\n * This is the invariant the kernel-decomposition (ADR-0029) relies on:\n * the `sys` namespace is shared across many first-party plugins, but each\n * object name has exactly one owner.\n *\n * @throws Error listing every object whose owner count is not exactly 1.\n */\n assertSingleOwnerPerObject(): void {\n const violations: string[] = [];\n for (const [fqn, contributors] of this.objectContributors.entries()) {\n const owners = contributors.filter(c => c.ownership === 'own');\n if (owners.length === 0) {\n const extenders = contributors.map(c => c.packageId).join(', ') || '(none)';\n violations.push(\n `Object \"${fqn}\" has no owner — only extend contributions from [${extenders}]. ` +\n `Exactly one package must register it with ownership 'own'.`\n );\n } else if (owners.length > 1) {\n const names = owners.map(c => c.packageId).join(', ');\n violations.push(\n `Object \"${fqn}\" has ${owners.length} owners [${names}] — exactly one is allowed.`\n );\n }\n }\n if (violations.length > 0) {\n throw new Error(\n `[Registry] single-owner-per-object check failed (ADR-0029):\\n ` +\n violations.join('\\n ')\n );\n }\n }\n\n /**\n * Unregister all objects contributed by a package.\n * \n * @throws Error if trying to uninstall an owner that has extenders\n */\n unregisterObjectsByPackage(packageId: string, force: boolean = false): void {\n for (const [fqn, contributors] of this.objectContributors.entries()) {\n // Find this package's contributions\n const packageContribs = contributors.filter(c => c.packageId === packageId);\n \n for (const contrib of packageContribs) {\n if (contrib.ownership === 'own' && !force) {\n // Check if there are extenders from other packages\n const otherExtenders = contributors.filter(\n c => c.packageId !== packageId && c.ownership === 'extend'\n );\n if (otherExtenders.length > 0) {\n throw new Error(\n `Cannot uninstall package \"${packageId}\": object \"${fqn}\" is extended by ` +\n `${otherExtenders.map(c => c.packageId).join(', ')}. Uninstall extenders first.`\n );\n }\n }\n\n // Remove contribution\n const idx = contributors.indexOf(contrib);\n if (idx !== -1) {\n contributors.splice(idx, 1);\n this.log(`[Registry] Removed ${contrib.ownership} contribution to ${fqn} from ${packageId}`);\n }\n }\n\n // Clean up empty contributor lists\n if (contributors.length === 0) {\n this.objectContributors.delete(fqn);\n }\n\n // Invalidate cache\n this.mergedObjectCache.delete(fqn);\n }\n }\n\n // ==========================================\n // Generic Metadata (Non-Object Types)\n // ==========================================\n\n /**\n * Universal Register Method for non-object metadata.\n */\n registerItem<T>(type: string, item: T, keyField: keyof T = 'name' as keyof T, packageId?: string) {\n if (!this.metadata.has(type)) {\n this.metadata.set(type, new Map());\n }\n const collection = this.metadata.get(type)!;\n const baseName = String(item[keyField]);\n\n // ADR-0010 §3.7 — translate the author-facing `protection` block\n // into the private `_lock` envelope and stamp package provenance.\n // Centralised with the artifact loader path in metadata/plugin.ts\n // so both load paths produce identical lock state.\n applyProtection(item as any, { packageId });\n\n // Validation Hook\n try {\n this.validate(type, item);\n } catch (e: any) {\n console.error(`[Registry] Validation failed for ${type} ${baseName}: ${e.message}`);\n }\n\n // Use composite key (packageId:name) when packageId is provided\n const storageKey = packageId ? `${packageId}:${baseName}` : baseName;\n\n if (collection.has(storageKey)) {\n this.log(`[Registry] Overwriting ${type}: ${storageKey}`);\n }\n\n // ADR-0048 — cross-package base-layer collision. When a code package\n // registers a bare-named generic item, refuse it loudly if a DIFFERENT\n // code package already owns the same (type, name). Without this guard the\n // two items live under distinct composite keys but bare-name resolution\n // (`getItem`) returns whichever the Map iterates first, silently shadowing\n // the loser — last-write-wins with no diagnostic.\n //\n // What is deliberately NOT a collision (these must pass through):\n // - Same package re-registering the same name (idempotent reload):\n // `conflictOwner` excludes `packageId` itself.\n // - Runtime/DB overlay rows registered under the bare key with no real\n // package provenance (or the `sys_metadata` sentinel): that is the\n // legitimate ADR-0005 overlay path, already surfaced by the\n // artifact-vs-DB warning below.\n if (isRealPackage(packageId)) {\n const conflictOwner = this.findOtherPackageOwner(collection, baseName, packageId);\n if (conflictOwner) {\n const err = new MetadataCollisionError(type, baseName, conflictOwner, packageId);\n if (this.collisionPolicy === 'warn') {\n console.warn(`[Registry] ${err.message}`);\n } else {\n throw err;\n }\n }\n }\n\n // Artifact-vs-DB collision warning. When a code package ships an item\n // whose name already exists as a DB-only entry (registered earlier\n // without a packageId — typically rehydrated from sys_metadata by\n // loadMetaFromDb / getMetaItems), the runtime overlay layer makes\n // the DB row silently shadow the new artifact value. That is correct\n // ADR-0005 behavior, but the silent shadowing can surprise package\n // authors and operators. Log a single warning so the situation is\n // discoverable in startup logs.\n if (packageId && collection.has(baseName)) {\n const dbOnly = collection.get(baseName) as any;\n if (dbOnly && !dbOnly._packageId) {\n console.warn(\n `[Registry] Collision: ${type}/${baseName} ships from package ` +\n `\"${packageId}\" but a runtime-authored row with the same name already ` +\n `exists in sys_metadata. The runtime row will shadow the package value ` +\n `(ADR-0005 overlay precedence). Rename one, or delete the sys_metadata ` +\n `row if the package value should win.`,\n );\n }\n }\n\n collection.set(storageKey, item);\n this.log(`[Registry] Registered ${type}: ${storageKey}`);\n }\n\n /**\n * Find a code package OTHER than `incoming` that already owns `baseName` in\n * `collection` (ADR-0048 cross-package collision detection). Scans the live\n * collection — like {@link getItem} / {@link unregisterItem} — so it always\n * reflects current state with no parallel index to drift across\n * reset/unregister. Returns the conflicting owner's package id, or undefined\n * when the name is free or only held by the same package / a runtime overlay.\n */\n private findOtherPackageOwner(\n collection: Map<string, any>,\n baseName: string,\n incoming: string,\n ): string | undefined {\n for (const [key, item] of collection) {\n // Same logical name only — the bare key or any `<pkg>:<baseName>` key.\n if (key !== baseName && !key.endsWith(`:${baseName}`)) continue;\n const owner = item?._packageId;\n if (isRealPackage(owner) && owner !== incoming) return owner;\n }\n return undefined;\n }\n\n /**\n * Validate Metadata against Spec Zod Schemas\n */\n validate(type: string, item: any): unknown {\n if (type === 'object') {\n return ObjectSchema.parse(item);\n }\n if (type === 'app') {\n return AppSchema.parse(item);\n }\n if (type === 'package') {\n return InstalledPackageSchema.parse(item);\n }\n if (type === 'plugin') {\n return ManifestSchema.parse(item);\n }\n return true;\n }\n\n /**\n * Universal Unregister Method\n */\n unregisterItem(type: string, name: string) {\n const collection = this.metadata.get(type);\n if (!collection) {\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n return;\n }\n if (collection.has(name)) {\n collection.delete(name);\n this.log(`[Registry] Unregistered ${type}: ${name}`);\n return;\n }\n // Scan composite keys\n for (const key of collection.keys()) {\n if (key.endsWith(`:${name}`)) {\n collection.delete(key);\n this.log(`[Registry] Unregistered ${type}: ${key}`);\n return;\n }\n }\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n }\n\n /**\n * Universal Get Method\n */\n getItem<T>(type: string, name: string): T | undefined {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getObject(name) as unknown as T | undefined;\n }\n \n const collection = this.metadata.get(type);\n if (!collection) return undefined;\n const direct = collection.get(name);\n if (direct) return direct as T;\n // Scan for composite keys\n for (const [key, item] of collection) {\n if (key.endsWith(`:${name}`)) {\n return item as T;\n }\n }\n return undefined;\n }\n\n /**\n * Artifact-only lookup (ADR-0010 §3.3). Unlike {@link getItem} — which\n * returns the plain-key entry first, so a runtime/DB-rehydrated row\n * registered under the bare name SHADOWS the packaged artifact — this\n * scans the composite (`<packageId>:<name>`) entries first and only\n * returns an item whose `_packageId` marks a genuine code package\n * (truthy and not the `'sys_metadata'` rehydration sentinel).\n *\n * This is what the protocol's lock/provenance resolution must use:\n * the artifact's `_lock` envelope always wins over an overlay, and an\n * overlay row hydrated into the plain key must never be able to mask\n * it (that masking is exactly the \"registry pollution\" bug where a\n * locked app's `_lock` read back as undefined after a PUT+GET).\n */\n getArtifactItem<T>(type: string, name: string): T | undefined {\n if (type === 'object' || type === 'objects') {\n const obj = this.getObject(name) as any;\n return obj && obj._packageId && obj._packageId !== 'sys_metadata'\n ? (obj as T)\n : undefined;\n }\n const collection = this.metadata.get(type);\n if (!collection) return undefined;\n for (const [key, item] of collection) {\n if (key !== name && key.endsWith(`:${name}`)) {\n const it = item as any;\n if (it && it._packageId && it._packageId !== 'sys_metadata') return item as T;\n }\n }\n const direct = collection.get(name) as any;\n if (direct && direct._packageId && direct._packageId !== 'sys_metadata') {\n return direct as T;\n }\n return undefined;\n }\n\n /**\n * Remove a plain-key runtime shadow so the packaged artifact registered\n * under a composite key becomes the visible value again. Used by the\n * metadata reset path (`deleteMetaItem`): deleting the `sys_metadata`\n * overlay row must also heal the in-memory registry, otherwise the\n * stale overlay copy keeps shadowing the artifact until restart.\n *\n * Deliberately conservative: the plain-key entry is only deleted when a\n * packaged artifact still exists under a composite key, so the name\n * stays resolvable afterwards. A runtime-only item (no artifact\n * backing) is left untouched. Note the plain entry's own `_packageId`\n * is NOT consulted — the hydration path grafts the artifact envelope\n * onto the shadow (ADR-0010 §3.3), so a stamped `_packageId` does not\n * mean the plain entry IS the artifact registration; artifact loaders\n * always register under a composite key.\n */\n removeRuntimeShadow(type: string, name: string): boolean {\n const collection = this.metadata.get(type);\n if (!collection || !collection.has(name)) return false;\n for (const [key, item] of collection) {\n if (key !== name && key.endsWith(`:${name}`)) {\n const it = item as any;\n if (it && it._packageId && it._packageId !== 'sys_metadata') {\n collection.delete(name);\n this.log(`[Registry] Removed runtime shadow ${type}: ${name} (artifact ${it._packageId} restored)`);\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * Universal List Method\n */\n listItems<T>(type: string, packageId?: string): T[] {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getAllObjects(packageId) as unknown as T[];\n }\n\n const items = Array.from(this.metadata.get(type)?.values() || []) as T[];\n let result = items;\n if (packageId) {\n result = result.filter((item: any) => item._packageId === packageId);\n }\n // Hide metadata owned by a disabled package so the console (app switcher,\n // view lists, dashboards, …) stops surfacing it after a disable. The\n // `package` type itself is never filtered — the Packages page must still\n // list disabled packages so they can be re-enabled. Disable is reversible:\n // items remain registered and reappear on enable.\n if (type !== 'package') {\n result = result.filter((item: any) => !this.isPackageDisabled((item as any)?._packageId));\n }\n return result;\n }\n\n /**\n * Whether a package has been explicitly disabled. Unknown packages and\n * items with no owning package are treated as enabled.\n */\n isPackageDisabled(packageId?: string): boolean {\n if (!packageId) return false;\n const pkg = this.getPackage(packageId);\n return pkg?.enabled === false || pkg?.status === 'disabled';\n }\n\n /**\n * Get all registered metadata types (Kinds)\n */\n getRegisteredTypes(): string[] {\n const types = Array.from(this.metadata.keys());\n // Always include 'object' even if stored separately\n if (!types.includes('object') && this.objectContributors.size > 0) {\n types.push('object');\n }\n return types;\n }\n\n // ==========================================\n // Package Management\n // ==========================================\n\n installPackage(manifest: ObjectStackManifest, settings?: Record<string, any>): InstalledPackage {\n const now = new Date().toISOString();\n const disabled = this.initialDisabledPackageIds.has(manifest.id);\n const pkg: InstalledPackage = {\n manifest,\n status: disabled ? 'disabled' : 'installed',\n enabled: !disabled,\n installedAt: now,\n updatedAt: now,\n ...(disabled ? { statusChangedAt: now } : {}),\n settings,\n };\n \n // Register namespace if present\n if (manifest.namespace) {\n this.registerNamespace(manifest.namespace, manifest.id);\n }\n \n if (!this.metadata.has('package')) {\n this.metadata.set('package', new Map());\n }\n const collection = this.metadata.get('package')!;\n if (collection.has(manifest.id)) {\n console.warn(`[Registry] Overwriting package: ${manifest.id}`);\n }\n collection.set(manifest.id, pkg);\n this.log(`[Registry] Installed package: ${manifest.id} (${manifest.name})`);\n return pkg;\n }\n\n uninstallPackage(id: string): boolean {\n const pkg = this.getPackage(id);\n if (!pkg) {\n console.warn(`[Registry] Package not found for uninstall: ${id}`);\n return false;\n }\n\n // Unregister namespace\n if (pkg.manifest.namespace) {\n this.unregisterNamespace(pkg.manifest.namespace, id);\n }\n\n // Unregister objects (will throw if extenders exist)\n this.unregisterObjectsByPackage(id);\n\n // Remove package record\n const collection = this.metadata.get('package');\n if (collection) {\n collection.delete(id);\n this.log(`[Registry] Uninstalled package: ${id}`);\n return true;\n }\n return false;\n }\n\n getPackage(id: string): InstalledPackage | undefined {\n return this.metadata.get('package')?.get(id) as InstalledPackage | undefined;\n }\n\n getAllPackages(): InstalledPackage[] {\n return this.listItems<InstalledPackage>('package');\n }\n\n enablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = true;\n pkg.status = 'installed';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Enabled package: ${id}`);\n }\n return pkg;\n }\n\n disablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = false;\n pkg.status = 'disabled';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Disabled package: ${id}`);\n }\n return pkg;\n }\n\n // ==========================================\n // App Helpers\n // ==========================================\n\n registerApp(app: any, packageId?: string) {\n this.registerItem('app', app, 'name', packageId);\n }\n\n getApp(name: string): any {\n const app = this.getItem('app', name);\n if (!app) return app;\n return this.applyNavContributions(app);\n }\n\n getAllApps(): any[] {\n return this.listItems('app').map((app: any) => this.applyNavContributions(app));\n }\n\n // ==========================================\n // App navigation contributions (ADR-0029 D7)\n // ==========================================\n\n /**\n * Register a navigation contribution — a package injecting nav items into\n * an app it does not own (the UI-layer analog of object `extend`).\n *\n * Contributions are merged into the target app's `navigation` tree lazily\n * on read ({@link getApp} / {@link getAllApps}) by group id + priority, so\n * registration order does not matter and the owning app can be registered\n * before or after its contributors.\n */\n registerAppNavContribution(\n contribution: { app: string; group?: string; priority?: number; items?: any[] },\n packageId?: string,\n ): void {\n if (!contribution || !contribution.app) return;\n const list = this.appNavContributions.get(contribution.app) ?? [];\n list.push({\n packageId,\n group: contribution.group,\n priority: contribution.priority ?? 200,\n items: Array.isArray(contribution.items) ? contribution.items : [],\n });\n this.appNavContributions.set(contribution.app, list);\n this.log(\n `[Registry] Navigation contribution: ${packageId ?? '(unknown)'} -> ${contribution.app}` +\n (contribution.group ? `/${contribution.group}` : '') +\n ` (${list[list.length - 1].items.length} items)`,\n );\n }\n\n /** Contributions registered for an app (empty array when none). */\n getAppNavContributions(appName: string): Array<{ packageId?: string; group?: string; priority: number; items: any[] }> {\n return this.appNavContributions.get(appName) ?? [];\n }\n\n /**\n * Return a copy of `app` with all registered navigation contributions\n * merged into its `navigation` tree. The stored app is never mutated, so\n * repeated reads stay idempotent.\n *\n * Public so the protocol serving path (`getMetaItems` / `getMetaItem` for\n * `app`) can merge contributions the same way `getApp` / `getAllApps` do —\n * the REST app endpoints read through the protocol, not these helpers, so\n * the merge must be reachable from there too (ADR-0029 D7).\n */\n applyNavContributions(app: any): any {\n const contributions = this.appNavContributions.get(app?.name);\n if (!contributions || contributions.length === 0) return app;\n\n const cloned = structuredClone(app);\n const nav: any[] = Array.isArray(cloned.navigation) ? cloned.navigation : (cloned.navigation = []);\n\n // Lower priority applied first — mirrors object extender ordering.\n const sorted = [...contributions].sort((a, b) => a.priority - b.priority);\n for (const c of sorted) {\n if (!c.items.length) continue;\n if (c.group) {\n const group = this.findNavGroup(nav, c.group);\n if (group) {\n if (!Array.isArray(group.children)) group.children = [];\n group.children.push(...c.items);\n } else {\n this.log(\n `[Registry] Navigation contribution from \"${c.packageId ?? '(unknown)'}\" targets ` +\n `missing group \"${c.group}\" in app \"${app.name}\" — appending at top level.`,\n );\n nav.push(...c.items);\n }\n } else {\n nav.push(...c.items);\n }\n }\n return cloned;\n }\n\n /** Depth-first search for a `type: 'group'` nav item by id. */\n private findNavGroup(items: any[], groupId: string): any | undefined {\n for (const item of items) {\n if (item && item.id === groupId && item.type === 'group') return item;\n if (item && Array.isArray(item.children)) {\n const found = this.findNavGroup(item.children, groupId);\n if (found) return found;\n }\n }\n return undefined;\n }\n\n // ==========================================\n // Plugin Helpers\n // ==========================================\n\n registerPlugin(manifest: ObjectStackManifest) {\n this.registerItem('plugin', manifest, 'id');\n }\n\n getAllPlugins(): ObjectStackManifest[] {\n return this.listItems<ObjectStackManifest>('plugin');\n }\n\n // ==========================================\n // Kind Helpers\n // ==========================================\n\n registerKind(kind: { id: string, globs: string[] }) {\n this.registerItem('kind', kind, 'id');\n }\n \n getAllKinds(): { id: string, globs: string[] }[] {\n return this.listItems('kind');\n }\n\n // ==========================================\n // Reset (for testing)\n // ==========================================\n\n /**\n * Invalidate the merged-schema cache for a single FQN (or short name).\n *\n * Call this from event-driven consumers (ADR-0008 M0 PR-7) when an\n * upstream metadata change makes the cached merged definition stale.\n * The contributor list is preserved — only the cached merge result is\n * dropped, so the next `resolveObject(fqn)` recomputes from scratch.\n *\n * Accepts either an FQN (`acme__contact`) or a bare short name\n * (`contact`); for the latter, all entries whose suffix matches the\n * name are invalidated.\n */\n invalidate(fqnOrName: string): void {\n if (this.mergedObjectCache.has(fqnOrName)) {\n this.mergedObjectCache.delete(fqnOrName);\n return;\n }\n // Short-name path: drop any cached merge whose FQN ends with `__<name>` or equals `<name>`.\n const suffix = `__${fqnOrName}`;\n for (const fqn of Array.from(this.mergedObjectCache.keys())) {\n if (fqn === fqnOrName || fqn.endsWith(suffix)) {\n this.mergedObjectCache.delete(fqn);\n }\n }\n }\n\n /** Drop every entry from the merged-schema cache. */\n invalidateAll(): void {\n this.mergedObjectCache.clear();\n }\n\n /**\n * Clear all registry state. Use only for testing.\n */\n reset(): void {\n this.objectContributors.clear();\n this.mergedObjectCache.clear();\n this.namespaceRegistry.clear();\n this.metadata.clear();\n this.appNavContributions.clear();\n this.log('[Registry] Reset complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport type { ObjectQL } from './engine.js';\nimport { SysMetadataRepository, type SysMetadataEngine } from './sys-metadata-repository.js';\nimport { ConflictError } from '@objectstack/metadata-core';\nimport type {\n BatchUpdateRequest,\n BatchUpdateResponse,\n UpdateManyDataRequest,\n DeleteManyDataRequest,\n InstallPackageRequest,\n InstallPackageResponse\n} from '@objectstack/spec/api';\nimport type { MetadataCacheRequest, MetadataCacheResponse, ServiceInfo, ApiRoutes, WellKnownCapabilities } from '@objectstack/spec/api';\nimport type { IFeedService } from '@objectstack/spec/contracts';\nimport { parseFilterAST, isFilterAST } from '@objectstack/spec/data';\nimport { PLURAL_TO_SINGULAR, SINGULAR_TO_PLURAL } from '@objectstack/spec/shared';\nimport { type FormView, isAggregatedViewContainer } from '@objectstack/spec/ui';\nimport { METADATA_FORM_REGISTRY } from '@objectstack/spec/system';\nimport { DEFAULT_METADATA_TYPE_REGISTRY, getMetadataTypeSchema, getMetadataTypeActions } from '@objectstack/spec/kernel';\nimport {\n extractProtection,\n evaluateLockForWrite,\n evaluateLockForDelete,\n resolveLockState,\n type MetadataLock,\n type MetadataProvenance,\n} from '@objectstack/spec/kernel';\nimport { z } from 'zod';\nimport {\n computeMetadataDiagnostics,\n computeViewReferenceDiagnostics,\n decorateMetadataItem,\n decorateMetadataItems,\n type MetadataDiagnostics,\n} from './metadata-diagnostics.js';\n\n/**\n * Canonical Zod schema per metadata type lives in\n * `@objectstack/spec/kernel/metadata-type-schemas` and is exposed through\n * {@link getMetadataTypeSchema}. Both save-time validation\n * ({@link resolveOverlaySchema}) and the `/meta/types/:type` JSON Schema\n * emitter consult that single source of truth, so adding a new\n * metadata-type schema requires editing exactly one file (or calling\n * `registerMetadataTypeSchema()` from a plugin).\n */\n// (TYPE_TO_SCHEMA removed — use `getMetadataTypeSchema(type)` directly.)\n\n/**\n * Canonical {@link FormView} layout per metadata type. Sourced from the\n * shared {@link METADATA_FORM_REGISTRY} in `@objectstack/spec/system` so\n * the runtime form payload, the i18n extractor, and Studio all read from\n * a single source of truth.\n *\n * Types without an entry render with the auto-generated single-section\n * layout derived from their JSON Schema (acceptable for simple types).\n */\nconst TYPE_TO_FORM: Readonly<Record<string, FormView>> = METADATA_FORM_REGISTRY;\n\n/**\n * Convert a Zod schema to a JSON Schema, returning `undefined` if conversion\n * fails (e.g. unsupported constructs). Cached per schema reference.\n */\nconst _jsonSchemaCache = new WeakMap<z.ZodTypeAny, Record<string, unknown> | null>();\nfunction toJsonSchemaSafe(schema: z.ZodTypeAny): Record<string, unknown> | undefined {\n const cached = _jsonSchemaCache.get(schema);\n if (cached !== undefined) return cached ?? undefined;\n try {\n const result = z.toJSONSchema(schema, { unrepresentable: 'any' }) as Record<string, unknown>;\n _jsonSchemaCache.set(schema, result);\n return result;\n } catch {\n _jsonSchemaCache.set(schema, null);\n return undefined;\n }\n}\n\n/**\n * Hand-crafted fallback JSON Schemas for metadata types whose Zod schema\n * cannot be safely converted via `z.toJSONSchema()` (e.g. due to recursive\n * references or non-representable constructs like `z.lazy()` chains).\n *\n * These mirror the shape consumed by the corresponding `*.form.ts` layouts,\n * so the SchemaForm renderer can still produce a real form (instead of\n * falling back to the raw JSON editor). All fields use lenient types\n * (`string | object | array`) because the widget hint in the form layout\n * is what actually drives the UI control selection — the JSON Schema is\n * only used to (a) seed defaults and (b) report which property names exist.\n */\nconst HAND_CRAFTED_SCHEMAS: Record<string, Record<string, unknown>> = {\n object: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n pluralLabel: { type: 'string' },\n icon: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n active: { type: 'boolean', default: true },\n isSystem: { type: 'boolean', default: false },\n abstract: { type: 'boolean', default: false },\n datasource: { type: 'string' },\n fields: {\n // Canonical Object.fields is a name-keyed map\n // (Record<string, FieldDefinition>) — insertion order is\n // display order. The SchemaForm engine recognises\n // `additionalProperties` as a Record and dispatches to\n // the `record` form-field renderer (ADR-0007). The form\n // layout in `object.form.ts` declares `type: 'record'`\n // so the inner `additionalProperties` schema is used to\n // shape each value.\n type: 'object',\n default: {},\n additionalProperties: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n type: { type: 'string' },\n required: { type: 'boolean', default: false },\n unique: { type: 'boolean', default: false },\n defaultValue: {},\n description: { type: 'string' },\n },\n required: ['type'],\n },\n },\n capabilities: { type: 'object', additionalProperties: true },\n },\n required: ['name'],\n additionalProperties: true,\n },\n action: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n objectName: { type: 'string' },\n icon: { type: 'string' },\n type: { type: 'string', enum: ['url', 'flow', 'api', 'script'] },\n variant: { type: 'string', enum: ['primary', 'secondary', 'danger', 'ghost', 'outline'] },\n target: { type: 'string' },\n method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] },\n body: {\n type: 'array',\n default: [],\n items: {\n type: 'object',\n properties: {\n line: { type: 'string' },\n },\n },\n },\n params: {\n type: 'array',\n default: [],\n items: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n label: { type: 'string' },\n type: { type: 'string' },\n required: { type: 'boolean', default: false },\n },\n required: ['name'],\n },\n },\n confirmText: { type: 'string' },\n successMessage: { type: 'string' },\n refreshAfter: { type: 'boolean', default: true },\n locations: {\n type: 'array',\n default: [],\n items: {\n type: 'object',\n properties: {\n location: { type: 'string' },\n },\n },\n },\n component: { type: 'string' },\n visible: { type: 'string' },\n disabled: { type: 'string' },\n shortcut: { type: 'string' },\n bulkEnabled: { type: 'boolean', default: false },\n aiExposed: { type: 'boolean', default: false },\n recordIdParam: { type: 'string' },\n recordIdField: { type: 'string' },\n bodyShape: { type: 'string', enum: ['flat', 'nested'] },\n },\n required: ['name', 'label', 'type'],\n additionalProperties: true,\n },\n // Validation rules live inside `object.validations[]`. The canonical\n // ValidationRuleSchema is a discriminated union of 9 variants; the\n // generic SchemaForm renderer treats unions as opaque JSON, so we\n // ship a *flat* form-friendly schema covering the common base\n // properties plus every variant-specific field as optional. Save-time\n // validation is unaffected — the union schema is still authoritative\n // at write time.\n validation: {\n type: 'object',\n properties: {\n // --- Base fields (all variants) ---\n name: { type: 'string', description: 'Unique rule name (snake_case)' },\n label: { type: 'string' },\n description: { type: 'string' },\n type: {\n type: 'string',\n enum: [\n 'script',\n 'unique',\n 'state_machine',\n 'format',\n 'cross_field',\n 'json',\n 'async',\n 'custom',\n 'conditional',\n ],\n default: 'script',\n description: 'Validation variant',\n },\n active: { type: 'boolean', default: true },\n events: {\n type: 'array',\n items: { type: 'string', enum: ['insert', 'update', 'delete'] },\n default: ['insert', 'update'],\n },\n priority: { type: 'number', default: 100, minimum: 0, maximum: 9999 },\n severity: {\n type: 'string',\n enum: ['error', 'warning', 'info'],\n default: 'error',\n },\n message: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n // --- Variant-specific (all optional, gated by `type`) ---\n condition: {\n type: 'string',\n description: 'CEL predicate (type=script). True ⇒ validation fails.',\n },\n fields: {\n type: 'array',\n items: { type: 'string' },\n description: 'Fields (type=unique / cross_field).',\n },\n scope: { type: 'string', description: 'CEL scope predicate (type=unique).' },\n caseSensitive: { type: 'boolean', default: true },\n field: { type: 'string', description: 'Single field (type=state_machine / format).' },\n transitions: {\n type: 'object',\n additionalProperties: { type: 'array', items: { type: 'string' } },\n description: 'Map { OldState: [AllowedNewStates] } (type=state_machine).',\n },\n regex: { type: 'string', description: 'Regex (type=format).' },\n format: {\n type: 'string',\n enum: ['email', 'url', 'phone', 'json'],\n description: 'Built-in format (type=format).',\n },\n url: { type: 'string', description: 'Endpoint URL (type=async).' },\n handler: { type: 'string', description: 'Handler reference (type=custom).' },\n when: { type: 'string', description: 'Outer condition (type=conditional).' },\n },\n required: ['name', 'type', 'message'],\n additionalProperties: true,\n },\n};\n\n/**\n * Zod schemas used to validate overlay items before they are persisted into\n * `sys_metadata` by {@link ObjectStackProtocolImplementation.saveMetaItem}.\n *\n * Single source of truth: the spec-side {@link getMetadataTypeSchema}\n * registry (`@objectstack/spec/kernel/metadata-type-schemas`). Every\n * metadata type whose payload should round-trip through Studio's\n * generic editor maps to its canonical Zod schema there; this function\n * is a plural→singular adapter on top of it.\n *\n * Validation policy:\n * - `safeParse` is used so we can craft a 422 with structured `issues`.\n * - We do NOT replace the persisted document with `parsed.data`; the\n * original payload is stored verbatim so Studio-only auxiliary fields\n * (e.g. `isPinned`, `isDefault`, `sortOrder`) survive the round-trip.\n * - Types without a registered schema (the wiring-layer types\n * `function`/`service`/`router`, and any plugin types that have not\n * yet called `registerMetadataTypeSchema()`) fall through unvalidated.\n */\nfunction resolveOverlaySchema(type: string, _item: unknown): z.ZodTypeAny | null {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n return getMetadataTypeSchema(singular) ?? null;\n}\n\n/**\n * Guarantee a `view` body carries a top-level `name`.\n *\n * {@link ObjectStackProtocolImplementation.getMetaItems} only surfaces a\n * sys_metadata overlay row when its parsed body has a top-level `name` (objects\n * and dashboards include one; some view producers — notably loose `{ list }`\n * fragments — do not, so the view is silently dropped from the object's view\n * list and never appears as a tab). We stamp the save name here, at the single\n * write chokepoint, without otherwise reshaping the document.\n *\n * Deliberately does NOT convert shape: both the `defineView` container form\n * (`{ list, listViews, … }`) and the `{ name, object, viewKind, config }`\n * record form are valid and the console consumes both — reshaping a container\n * into a record risks producing an invalid record (e.g. a non-`<object>.<key>`\n * name). Structural validity is enforced separately by the view metadata schema\n * during the spec-validation step. No-op for non-view types and bodies that\n * already carry a `name`.\n */\nexport function normalizeViewMetadata(type: string, item: unknown, saveName: string): unknown {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (singular !== 'view') return item;\n if (!item || typeof item !== 'object' || Array.isArray(item)) return item;\n const it = item as Record<string, unknown>;\n return it.name ? it : { ...it, name: saveName };\n}\n\n/**\n * ADR-0010 §3.3 — Overlay the artifact's metadata-protection envelope\n * onto a returned item so artifact-level lock/packageId/provenance\n * always wins over whatever was persisted in the `sys_metadata` overlay\n * row. Returns `item` unchanged when no artifact baseline is available.\n *\n * The artifact's `_lock`, `_lockReason`, `_packageId`, `_packageVersion`,\n * and `_provenance` are the source of truth — an overlay copy may\n * pre-date the artifact's protection declaration and would otherwise\n * mask it.\n */\nfunction mergeArtifactProtection(item: unknown, artifactItem: unknown): unknown {\n if (item === undefined || item === null) return item;\n if (artifactItem === undefined || artifactItem === null) return item;\n const a = artifactItem as Record<string, unknown>;\n if (typeof a !== 'object') return item;\n const out: Record<string, unknown> = { ...(item as Record<string, unknown>) };\n if (a._lock !== undefined) out._lock = a._lock;\n if (a._lockReason !== undefined) out._lockReason = a._lockReason;\n if (a._lockDocsUrl !== undefined) out._lockDocsUrl = a._lockDocsUrl;\n if (a._lockSource !== undefined) out._lockSource = a._lockSource;\n if (a._packageId !== undefined) out._packageId = a._packageId;\n if (a._packageVersion !== undefined) out._packageVersion = a._packageVersion;\n if (a._provenance !== undefined) out._provenance = a._provenance;\n return out;\n}\n\n/**\n * Simple hash function for ETag generation (browser-compatible)\n * Uses a basic hash algorithm instead of crypto.createHash\n */\nfunction simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(16);\n}\n\n/**\n * Thrown by `updateData` / `deleteData` when the caller supplies an\n * `expectedVersion` that does not match the current record's `updated_at`.\n *\n * The HTTP layer maps this to `409 Conflict` with code `CONCURRENT_UPDATE`,\n * and includes both the current server-side version and the current record\n * payload so the client can render an informed conflict-resolution UI\n * (\"Reload latest\" vs. \"Overwrite anyway\").\n *\n * NOTE: This is an *application-level* compare-and-set — not an atomic\n * storage-layer CAS. There is a small TOCTOU window between the version\n * check and the subsequent write. For the conflict frequency this targets\n * (different users seconds-to-minutes apart in B2B record editing) this\n * is more than adequate; a future revision can push the check into the\n * driver's UPDATE statement (`WHERE id=? AND updated_at=?`) for true\n * atomicity.\n */\nexport class ConcurrentUpdateError extends Error {\n readonly code = 'CONCURRENT_UPDATE';\n readonly status = 409;\n readonly currentVersion: string | null;\n readonly currentRecord: unknown;\n constructor(opts: { currentVersion: string | null; currentRecord: unknown; message?: string }) {\n super(opts.message ?? 'Record was modified by another user');\n this.name = 'ConcurrentUpdateError';\n this.currentVersion = opts.currentVersion;\n this.currentRecord = opts.currentRecord;\n }\n}\n\n/**\n * Normalises a version token for comparison. Strips RFC-7232-style quotes\n * (`\"…\"`) that an HTTP `If-Match` header may carry, trims whitespace, and\n * returns null for empty / nullish input.\n */\nfunction normaliseVersionToken(v: unknown): string | null {\n if (v === null || v === undefined) return null;\n const s = String(v).trim();\n if (!s) return null;\n if (s.length >= 2 && s.startsWith('\"') && s.endsWith('\"')) {\n return s.slice(1, -1);\n }\n return s;\n}\n\n/**\n * Service Configuration for Discovery\n * Maps service names to their routes and plugin providers\n */\nconst SERVICE_CONFIG: Record<string, { route: string; plugin: string }> = {\n auth: { route: '/api/v1/auth', plugin: 'plugin-auth' },\n automation: { route: '/api/v1/automation', plugin: 'plugin-automation' },\n cache: { route: '/api/v1/cache', plugin: 'plugin-redis' },\n queue: { route: '/api/v1/queue', plugin: 'plugin-bullmq' },\n job: { route: '/api/v1/jobs', plugin: 'job-scheduler' },\n ui: { route: '/api/v1/ui', plugin: 'ui-plugin' },\n workflow: { route: '/api/v1/workflow', plugin: 'plugin-workflow' },\n realtime: { route: '/api/v1/realtime', plugin: 'plugin-realtime' },\n notification: { route: '/api/v1/notifications', plugin: 'plugin-notifications' },\n ai: { route: '/api/v1/ai', plugin: 'plugin-ai' },\n i18n: { route: '/api/v1/i18n', plugin: 'service-i18n' },\n graphql: { route: '/graphql', plugin: 'plugin-graphql' }, // GraphQL uses /graphql by convention (not versioned REST)\n 'file-storage': { route: '/api/v1/storage', plugin: 'plugin-storage' },\n search: { route: '/api/v1/search', plugin: 'plugin-search' },\n};\n\n/**\n * Phase 3a-references: hand-curated reference path registry.\n *\n * Maps a *target* metadata type to the list of *source* type+path tuples\n * that may point at it. Used by {@link findReferencesToMeta} to scan all\n * loaded metadata and surface \"what depends on this?\" before a user\n * deletes or renames an artifact.\n *\n * Path syntax:\n * - `'foo'` → item.foo\n * - `'foo.bar'` → item.foo.bar\n * - `'foo[]'` → each element of array item.foo\n * - `'foo[].bar'` → bar of each element of array item.foo\n * - `'foo{}'` → each value of Record item.foo\n * - `'foo{}.bar'` → bar of each value of Record item.foo\n *\n * Coverage is intentionally narrow — covers the highest-value references\n * for MVP. Add more entries as new editors are built.\n */\nconst REFERENCE_PATHS: Record<string, Array<{ fromType: string; paths: string[]; kind: string }>> = {\n object: [\n { fromType: 'view', paths: ['object', 'objectName'], kind: 'view' },\n { fromType: 'dashboard', paths: ['widgets[].object', 'widgets[].objectName'], kind: 'dashboard widget' },\n { fromType: 'flow', paths: ['object', 'context.object', 'trigger.object', 'targetObject'], kind: 'flow' },\n { fromType: 'workflow', paths: ['object', 'targetObject'], kind: 'workflow' },\n { fromType: 'permission', paths: ['objects[].name', 'objects[].object'], kind: 'permission' },\n { fromType: 'app', paths: ['navItems[].objectName', 'navItems[].object', 'tabs[].objectName', 'tabs[].object'], kind: 'app nav' },\n { fromType: 'page', paths: ['object', 'objectName'], kind: 'page' },\n { fromType: 'report', paths: ['object', 'objectName'], kind: 'report' },\n { fromType: 'action', paths: ['object', 'objectName'], kind: 'action' },\n { fromType: 'validation', paths: ['object', 'objectName'], kind: 'validation' },\n { fromType: 'hook', paths: ['object', 'objectName'], kind: 'hook' },\n { fromType: 'object', paths: ['fields[].referenceTo', 'fields{}.referenceTo', 'fields{}.reference'], kind: 'field reference' },\n ],\n view: [\n { fromType: 'dashboard', paths: ['widgets[].view', 'widgets[].viewName'], kind: 'dashboard widget' },\n { fromType: 'app', paths: ['navItems[].viewName', 'tabs[].viewName'], kind: 'app nav' },\n { fromType: 'page', paths: ['viewName'], kind: 'page' },\n ],\n tool: [\n { fromType: 'agent', paths: ['tools[]', 'tools[].name'], kind: 'agent tool' },\n ],\n skill: [\n { fromType: 'agent', paths: ['skills[]', 'skills[].name'], kind: 'agent skill' },\n ],\n flow: [\n { fromType: 'app', paths: ['navItems[].flowName', 'tabs[].flowName'], kind: 'app nav' },\n ],\n dashboard: [\n { fromType: 'app', paths: ['navItems[].dashboardName', 'tabs[].dashboardName'], kind: 'app nav' },\n ],\n page: [\n { fromType: 'app', paths: ['navItems[].pageName', 'tabs[].pageName'], kind: 'app nav' },\n ],\n};\n\n/**\n * Extract one or more string values from `item` at `path`. Supports\n * `'a.b'` (nested object access) and `'a[].b'` (array element access).\n * Returns an empty array if any segment is missing.\n */\nfunction extractPathValues(item: unknown, path: string): string[] {\n if (!item || typeof item !== 'object') return [];\n const segments = path.split('.');\n let current: unknown[] = [item];\n for (const rawSeg of segments) {\n let kind: 'value' | 'array' | 'record' = 'value';\n let seg = rawSeg;\n if (seg.endsWith('[]')) {\n kind = 'array';\n seg = seg.slice(0, -2);\n } else if (seg.endsWith('{}')) {\n kind = 'record';\n seg = seg.slice(0, -2);\n }\n const next: unknown[] = [];\n for (const node of current) {\n if (!node || typeof node !== 'object') continue;\n let value: unknown;\n if (seg === '') {\n value = node;\n } else {\n value = (node as Record<string, unknown>)[seg];\n }\n if (value === undefined || value === null) continue;\n if (kind === 'array') {\n if (Array.isArray(value)) {\n for (const v of value) next.push(v);\n }\n } else if (kind === 'record') {\n if (Array.isArray(value)) {\n for (const v of value) next.push(v);\n } else if (typeof value === 'object') {\n for (const v of Object.values(value as Record<string, unknown>)) next.push(v);\n }\n } else {\n next.push(value);\n }\n }\n current = next;\n if (current.length === 0) return [];\n }\n // Coerce final values to strings, dropping non-string non-object leaves.\n const out: string[] = [];\n for (const v of current) {\n if (typeof v === 'string' && v.length > 0) out.push(v);\n else if (v && typeof v === 'object' && 'name' in (v as any) && typeof (v as any).name === 'string') {\n out.push((v as any).name);\n }\n }\n return out;\n}\n\n/**\n * Phase 3a-destructive: detect changes between an existing object schema\n * and an incoming overlay that would break runtime data — removed fields,\n * field type narrowing, required toggled on without a default. Returned\n * issues are surfaced as HTTP 409 `destructive_change` unless the caller\n * sets `force: true`, letting the admin UI render a warning dialog before\n * proceeding.\n *\n * Scope is intentionally narrow for MVP: covers the most common\n * data-loss footguns for `object` and `field` types. Subsequent passes\n * can layer in relationship changes, enum-value removals, etc.\n */\n/**\n * Shallow JSON diff used by `diffMetaItem`. Compares the top-level\n * keys of `from` vs `to`; primitive value changes are reported as\n * `changed`, nested objects/arrays that differ structurally are also\n * reported as a single `changed` entry (deep structural diffs are out\n * of scope — Studio renders the full bodies for a side-by-side view).\n */\nfunction diffShallow(\n from: Record<string, unknown>,\n to: Record<string, unknown>,\n): {\n added: Array<{ path: string; value: unknown }>;\n removed: Array<{ path: string; value: unknown }>;\n changed: Array<{ path: string; from: unknown; to: unknown }>;\n} {\n const added: Array<{ path: string; value: unknown }> = [];\n const removed: Array<{ path: string; value: unknown }> = [];\n const changed: Array<{ path: string; from: unknown; to: unknown }> = [];\n const fromKeys = new Set(Object.keys(from ?? {}));\n const toKeys = new Set(Object.keys(to ?? {}));\n for (const k of toKeys) {\n if (!fromKeys.has(k)) {\n added.push({ path: k, value: (to as any)[k] });\n } else {\n const a = (from as any)[k];\n const b = (to as any)[k];\n const aStr = JSON.stringify(a);\n const bStr = JSON.stringify(b);\n if (aStr !== bStr) {\n changed.push({ path: k, from: a, to: b });\n }\n }\n }\n for (const k of fromKeys) {\n if (!toKeys.has(k)) {\n removed.push({ path: k, value: (from as any)[k] });\n }\n }\n return { added, removed, changed };\n}\n\nfunction detectDestructiveObjectChanges(prev: any, next: any): Array<{\n code: string;\n field?: string;\n message: string;\n}> {\n if (!prev || typeof prev !== 'object' || !next || typeof next !== 'object') return [];\n const prevFields = (prev.fields && typeof prev.fields === 'object') ? prev.fields as Record<string, any> : {};\n const nextFields = (next.fields && typeof next.fields === 'object') ? next.fields as Record<string, any> : {};\n\n const issues: Array<{ code: string; field?: string; message: string }> = [];\n\n // Removed fields — silently dropping a column is a data-loss event.\n for (const fname of Object.keys(prevFields)) {\n // Skip system fields — those are managed by applySystemFields and\n // re-injected on every registerObject call; they will look \"removed\"\n // in any user-supplied overlay.\n if (prevFields[fname]?.system) continue;\n if (!(fname in nextFields)) {\n issues.push({\n code: 'field_removed',\n field: fname,\n message: `Field '${fname}' removed — existing data in this column will become inaccessible.`,\n });\n }\n }\n\n // Field type changes — narrowing or incompatible conversions.\n const TYPE_COMPATIBILITY: Record<string, Set<string>> = {\n text: new Set(['textarea', 'markdown', 'html', 'code']),\n number: new Set([]),\n boolean: new Set([]),\n date: new Set(['datetime']),\n datetime: new Set(['date']),\n };\n for (const fname of Object.keys(nextFields)) {\n const prevField = prevFields[fname];\n const nextField = nextFields[fname];\n if (!prevField) continue; // brand-new field — non-destructive\n const prevType = prevField.type;\n const nextType = nextField.type;\n if (prevType && nextType && prevType !== nextType) {\n const compatible = TYPE_COMPATIBILITY[prevType]?.has(nextType);\n if (!compatible) {\n issues.push({\n code: 'field_type_change',\n field: fname,\n message: `Field '${fname}' type changed from '${prevType}' to '${nextType}' — existing values may not convert cleanly.`,\n });\n }\n }\n // required toggled on without a default — new inserts will start\n // to fail validation, and any null rows already in the table will\n // fail on next save.\n if (!prevField.required && nextField.required && nextField.defaultValue === undefined) {\n issues.push({\n code: 'field_required_no_default',\n field: fname,\n message: `Field '${fname}' is now required but has no default value — existing rows with null values may fail validation.`,\n });\n }\n }\n return issues;\n}\n\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: ObjectQL;\n private getServicesRegistry?: () => Map<string, any>;\n private getFeedService?: () => IFeedService | undefined;\n /**\n * Project scope applied to sys_metadata reads/writes. When undefined\n * (single-kernel deployments), rows land in / come from the\n * platform-global bucket (`environment_id IS NULL`). When set, every\n * saveMetaItem insert/update and loadMetaFromDb query is filtered by\n * `environment_id = environmentId`, so per-project kernels see only their own\n * metadata even if several projects share the same physical database.\n */\n private environmentId?: string;\n\n /**\n * Lazily-instantiated SysMetadataRepository per organization. Keyed by\n * `${organizationId ?? '__env__'}`. Repositories are stateful — they\n * carry the per-org `seqCounter` and watch subscribers — so we cache\n * them rather than constructing one per call.\n */\n private overlayRepos = new Map<string, SysMetadataRepository>();\n\n constructor(\n engine: IDataEngine,\n getServicesRegistry?: () => Map<string, any>,\n getFeedService?: () => IFeedService | undefined,\n environmentId?: string,\n ) {\n this.engine = engine as ObjectQL;\n this.getServicesRegistry = getServicesRegistry;\n this.getFeedService = getFeedService;\n this.environmentId = environmentId;\n }\n\n /**\n * Lazily obtain a SysMetadataRepository for the given organization.\n * Env-wide overlays (organizationId == null) share a singleton under\n * the `__env__` key.\n */\n private getOverlayRepo(organizationId: string | null): SysMetadataRepository {\n const key = organizationId ?? '__env__';\n let repo = this.overlayRepos.get(key);\n if (!repo) {\n repo = new SysMetadataRepository({\n engine: this.engine as unknown as SysMetadataEngine,\n organizationId,\n orgLabel: organizationId ?? 'env',\n });\n this.overlayRepos.set(key, repo);\n }\n return repo;\n }\n\n /**\n * One-time guard for ensuring the overlay-uniqueness UNIQUE INDEX exists\n * on `sys_metadata`. ADR-0005: scopes overlays by\n * `(type, name, organization_id, environment_id, scope)` for active rows only.\n * Idempotent SQL — safe to attempt on every protocol instance.\n *\n * Inlined here (rather than importing from @objectstack/metadata/migrations)\n * to avoid a circular dependency: metadata already depends on objectql.\n */\n private overlayIndexEnsured = false;\n private async ensureOverlayIndex(): Promise<void> {\n if (this.overlayIndexEnsured) return;\n this.overlayIndexEnsured = true;\n try {\n const engineAny = this.engine as any;\n let driver: any = engineAny?.driver ?? engineAny?.getDriver?.();\n if (!driver && engineAny?.drivers instanceof Map) {\n for (const candidate of engineAny.drivers.values()) {\n if (\n candidate &&\n (typeof (candidate as any).raw === 'function' ||\n typeof (candidate as any).execute === 'function')\n ) {\n driver = candidate;\n break;\n }\n }\n }\n if (!driver) return;\n const exec = async (sql: string): Promise<void> => {\n if (typeof (driver as any).raw === 'function') {\n await (driver as any).raw(sql);\n } else if (typeof (driver as any).execute === 'function') {\n await (driver as any).execute(sql);\n } else {\n throw new Error('driver has neither raw nor execute');\n }\n };\n // ADR-0005 (revised 2026-05): per-env DBs replace the old\n // \"per-project\" isolation, so `environment_id` is no longer a\n // discriminator. Overlay uniqueness is `(type, name,\n // organization_id)` filtered to active rows. Drop the legacy\n // composite index first so the new partial UNIQUE can claim\n // the same name — DROP INDEX IF EXISTS is idempotent.\n try { await exec(\"DROP INDEX IF EXISTS idx_sys_metadata_overlay_active\"); } catch { /* best-effort */ }\n const partialSql =\n \"CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active \" +\n \"ON sys_metadata (type, name, organization_id) \" +\n \"WHERE state = 'active'\";\n const fallbackSql =\n \"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active \" +\n \"ON sys_metadata (type, name, organization_id)\";\n try {\n await exec(partialSql);\n } catch (err: any) {\n const msg = err instanceof Error ? err.message : String(err);\n if (/partial|where clause|syntax/i.test(msg)) {\n try {\n await exec(fallbackSql);\n } catch {\n // ignore — non-essential optimization\n }\n }\n // \"already exists\" or anything else: best-effort\n }\n // Mirror the same partial-UNIQUE for draft rows so a second\n // simultaneous draft cannot be inserted for the same\n // (type,name,org). The unique-active index above already\n // guards published rows; the two never collide because the\n // `state` predicate disambiguates them.\n const draftPartialSql =\n \"CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft \" +\n \"ON sys_metadata (type, name, organization_id) \" +\n \"WHERE state = 'draft'\";\n try {\n await exec(draftPartialSql);\n } catch (err: any) {\n const msg = err instanceof Error ? err.message : String(err);\n if (/partial|where clause|syntax/i.test(msg)) {\n try {\n await exec(\n \"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft \" +\n \"ON sys_metadata (type, name, organization_id)\",\n );\n } catch {\n // ignore — best effort\n }\n }\n }\n } catch {\n // ignore — index is an optimization, not a correctness invariant\n }\n }\n\n /**\n * Exposes the project scope the protocol is bound to. Consumers like\n * the HTTP dispatcher use this to decide whether to trust the process-\n * wide SchemaRegistry or whether they must route a read through the\n * protocol's environment_id-filtered lookup.\n */\n getProjectId(): string | undefined {\n return this.environmentId;\n }\n\n private requireFeedService(): IFeedService {\n const svc = this.getFeedService?.();\n if (!svc) {\n throw new Error('Feed service not available. Install and register service-feed to enable feed operations.');\n }\n return svc;\n }\n\n async getDiscovery() {\n // Get registered services from kernel if available\n const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : new Map();\n \n // Build dynamic service info with proper typing\n const services: Record<string, ServiceInfo> = {\n // --- Kernel-provided (objectql is an example kernel implementation) ---\n metadata: { enabled: true, status: 'available' as const, route: '/api/v1/meta', provider: 'objectql' },\n data: { enabled: true, status: 'available' as const, route: '/api/v1/data', provider: 'objectql' },\n analytics: { enabled: true, status: 'available' as const, route: '/api/v1/analytics', provider: 'objectql' },\n };\n\n // Check which services are actually registered\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n // Service is registered and available\n services[serviceName] = {\n enabled: true,\n status: 'available' as const,\n route: config.route,\n provider: config.plugin,\n };\n } else {\n // Service is not registered\n services[serviceName] = {\n enabled: false,\n status: 'unavailable' as const,\n message: `Install ${config.plugin} to enable`,\n };\n }\n }\n\n // Build routes from services — a flat convenience map for client routing\n const serviceToRouteKey: Record<string, keyof ApiRoutes> = {\n auth: 'auth',\n automation: 'automation',\n ui: 'ui',\n workflow: 'workflow',\n realtime: 'realtime',\n notification: 'notifications',\n ai: 'ai',\n i18n: 'i18n',\n graphql: 'graphql',\n 'file-storage': 'storage',\n };\n\n const optionalRoutes: Partial<ApiRoutes> = {\n analytics: '/api/v1/analytics',\n };\n\n // Add routes for available plugin services\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n const routeKey = serviceToRouteKey[serviceName];\n if (routeKey) {\n optionalRoutes[routeKey] = config.route;\n }\n }\n }\n\n // Add feed service status\n if (registeredServices.has('feed')) {\n services['feed'] = {\n enabled: true,\n status: 'available' as const,\n route: '/api/v1/data',\n provider: 'service-feed',\n };\n } else {\n services['feed'] = {\n enabled: false,\n status: 'unavailable' as const,\n message: 'Install service-feed to enable',\n };\n }\n\n const routes: ApiRoutes = {\n data: '/api/v1/data',\n metadata: '/api/v1/meta',\n ...optionalRoutes,\n };\n\n // Build well-known capabilities from registered services.\n // DiscoverySchema defines capabilities as Record<string, { enabled, features?, description? }>\n // (hierarchical format). We also keep a flat WellKnownCapabilities for backward compat.\n const wellKnown: WellKnownCapabilities = {\n feed: registeredServices.has('feed'),\n comments: registeredServices.has('feed'),\n automation: registeredServices.has('automation'),\n cron: registeredServices.has('job'),\n search: registeredServices.has('search'),\n export: registeredServices.has('automation') || registeredServices.has('queue'),\n chunkedUpload: registeredServices.has('file-storage'),\n };\n\n // Convert flat booleans → hierarchical capability objects\n const capabilities: Record<string, { enabled: boolean; description?: string }> = {};\n for (const [key, enabled] of Object.entries(wellKnown)) {\n capabilities[key] = { enabled };\n }\n\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n routes,\n services,\n capabilities,\n };\n }\n\n async getMetaTypes() {\n const schemaTypes = this.engine.registry.getRegisteredTypes();\n\n // Also include types from MetadataService (runtime-registered: agent, tool, etc.)\n let runtimeTypes: string[] = [];\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.getRegisteredTypes === 'function') {\n runtimeTypes = await metadataService.getRegisteredTypes();\n }\n } catch {\n // MetadataService not available\n }\n\n const allTypes = Array.from(new Set([...schemaTypes, ...runtimeTypes]));\n\n // Phase 3a-1: enrich response with per-type registry metadata so admin\n // UI can render directory pages, filter by domain, decide which types\n // expose write actions, etc. Existing clients keep working — the\n // `types: string[]` field is preserved alongside the new `entries`.\n //\n // Phase 3a-env-writable: `OS_METADATA_WRITABLE` env var (comma\n // separated singular type names) flips `allowOrgOverride` on listed\n // types so admins can self-serve. The same env var is consulted by\n // `isOverlayAllowed()` at write time — they must stay in sync.\n const writableOverrides = ObjectStackProtocolImplementation.envWritableTypes();\n const registryByType = new Map(\n DEFAULT_METADATA_TYPE_REGISTRY.map((e) => [e.type, e] as const)\n );\n\n const entries = allTypes.map((type) => {\n const singular = (PLURAL_TO_SINGULAR[type] ?? type) as string;\n // Phase 3a-schema: emit a JSON Schema per type so the generic\n // metadata admin UI can render real forms (no more raw-JSON\n // textareas for new resources). The canonical schema for every\n // built-in (and plugin-registered) metadata type lives in the\n // central `getMetadataTypeSchema()` registry; we delegate so\n // Studio's editor and the runtime overlay validator stay in\n // lock-step (one source of truth).\n const zodSchema = getMetadataTypeSchema(singular);\n const schema = (zodSchema ? toJsonSchemaSafe(zodSchema) : undefined)\n ?? HAND_CRAFTED_SCHEMAS[singular];\n const form = TYPE_TO_FORM[singular];\n\n // Type-level actions: merge the registry's declarative actions\n // with any plugin-registered overlay (`registerMetadataTypeActions`).\n // This is the single accessor — a host plugin (e.g. the private\n // datasource-admin backend) contributes its `test_connection`\n // button here, co-located with the route handler it calls, so the\n // button only appears when the backend that serves it is installed.\n const typeActions = getMetadataTypeActions(singular);\n\n const base = registryByType.get(singular as any);\n if (base) {\n const isEnvOverridden = writableOverrides.has(singular);\n return {\n ...base,\n type: singular,\n schemaId: singular, // API client expects schemaId field\n allowOrgOverride: base.allowOrgOverride || isEnvOverridden,\n overrideSource: isEnvOverridden && !base.allowOrgOverride\n ? 'env' as const\n : 'registry' as const,\n schema,\n form,\n // Override the spread `base.actions` with the merged view\n // (declarative + plugin-registered). Omit when empty to\n // preserve the prior \"no actions key\" response shape.\n ...(typeActions.length ? { actions: typeActions } : {}),\n };\n }\n // Runtime-registered type with no registry entry — synthesise a\n // minimal descriptor so the UI can still surface it.\n return {\n type: singular,\n schemaId: singular, // API client expects schemaId field\n label: singular,\n description: undefined,\n filePatterns: [],\n supportsOverlay: false,\n allowOrgOverride: writableOverrides.has(singular),\n allowRuntimeCreate: true,\n supportsVersioning: false,\n executionPinned: false,\n loadOrder: 1000,\n domain: 'system' as const,\n overrideSource: writableOverrides.has(singular) ? 'env' as const : 'registry' as const,\n schema,\n form,\n // Plugin-registered actions on a type with no registry entry.\n ...(typeActions.length ? { actions: typeActions } : {}),\n };\n }).sort((a, b) => {\n if (a.domain !== b.domain) return a.domain.localeCompare(b.domain);\n return a.type.localeCompare(b.type);\n });\n\n return { types: allTypes, entries };\n }\n\n /**\n * Sweep all (or filtered) metadata types and report entries that\n * fail spec validation. Powers the Studio governance view\n * (`GET /api/v1/meta/diagnostics`) and `os doctor`-style CLI\n * checks.\n *\n * `severity` defaults to `'error'` — only entries with at least\n * one Zod error issue are returned. `'warning'` includes\n * everything we surface (warnings are reserved for a future lint\n * layer on top of spec validation).\n *\n * `type` may be either a singular (`'view'`) or plural (`'views'`)\n * identifier; the underlying `getMetaItems` already normalises.\n *\n * Implementation note: leverages the `_diagnostics` already\n * decorated onto items by `getMetaItems()` to avoid running\n * `safeParse()` twice. For types whose schema is unregistered we\n * skip silently (they cannot be validated and should not appear\n * as \"valid\" either — they are simply opaque to this report).\n */\n async getMetaDiagnostics(request: {\n type?: string;\n severity?: 'error' | 'warning';\n organizationId?: string;\n packageId?: string;\n } = {}): Promise<{\n entries: Array<{ type: string; name: string; diagnostics: MetadataDiagnostics }>;\n total: number;\n scannedTypes: number;\n scannedItems: number;\n /**\n * Per-type aggregate stats — count of items and the list of\n * packages contributing to each type. Computed in the same\n * sweep so the Studio directory page can render tile counts\n * and a package filter in one round-trip.\n */\n stats: Record<string, { count: number; locked: number; packages: string[] }>;\n }> {\n const includeWarnings = request.severity === 'warning';\n const targetTypes = request.type\n ? [request.type]\n : DEFAULT_METADATA_TYPE_REGISTRY\n .filter((e) => getMetadataTypeSchema(e.type))\n .map((e) => e.type);\n\n const entries: Array<{ type: string; name: string; diagnostics: MetadataDiagnostics }> = [];\n const stats: Record<string, { count: number; locked: number; packages: string[] }> = {};\n let scannedItems = 0;\n\n for (const t of targetTypes) {\n let listed: any;\n try {\n listed = await this.getMetaItems({\n type: t,\n organizationId: request.organizationId,\n packageId: request.packageId,\n } as any);\n } catch {\n // Type not listable in this kernel scope — skip.\n continue;\n }\n const items: any[] = Array.isArray(listed?.items)\n ? listed.items\n : Array.isArray(listed)\n ? listed\n : [];\n const pkgSet = new Set<string>();\n let lockedCount = 0;\n for (const item of items) {\n scannedItems += 1;\n const pkg = (item?._packageId ?? null) as string | null;\n if (pkg) pkgSet.add(pkg);\n const lock = item?._lock as string | undefined;\n if (lock && lock !== 'none') lockedCount += 1;\n const diag: MetadataDiagnostics | undefined =\n item?._diagnostics ?? computeMetadataDiagnostics(t, item);\n if (!diag) continue;\n if (diag.valid && !includeWarnings) continue;\n if (diag.valid && includeWarnings && !diag.warnings?.length) continue;\n entries.push({\n type: t,\n name: typeof item?.name === 'string' ? item.name : '<unknown>',\n diagnostics: diag,\n });\n }\n stats[t] = { count: items.length, locked: lockedCount, packages: [...pkgSet].sort() };\n }\n\n return {\n entries,\n total: entries.length,\n scannedTypes: targetTypes.length,\n scannedItems,\n stats,\n };\n }\n\n async getMetaItems(request: { type: string; packageId?: string; organizationId?: string; previewDrafts?: boolean }) {\n const { packageId } = request;\n let items: unknown[] = [];\n\n // Unscoped kernels (control plane): read everything from SchemaRegistry.\n // Scoped (project) kernels: skip user-project entries in SchemaRegistry to\n // prevent cross-project leakage, but DO include scope:'system' packages\n // (plugin-auth, plugin-security, plugin-audit, …) — those are globally\n // shared and must be visible at every project's meta endpoint.\n if (this.environmentId === undefined) {\n items = [...this.engine.registry.listItems(request.type, packageId)];\n // Normalize singular/plural using explicit mapping\n if (items.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) items = [...this.engine.registry.listItems(alt, packageId)];\n }\n } else {\n // For project kernels: the SchemaRegistry is owned by THIS\n // kernel's ObjectQL instance (not shared across projects in the\n // process), so we can safely include every package — system\n // plugins (auth/security/audit) and the project's own app\n // package alike. The `_packageId` tag added by `listItems`\n // (registry.ts) is preserved for the sidebar to compute the\n // correct navigation URL.\n items = [...this.engine.registry.listItems(request.type, packageId)];\n if (items.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) items = [...this.engine.registry.listItems(alt, packageId)];\n }\n }\n\n // Always consult the DB so metadata persisted by the seeder /\n // bulkRegister shows up even when the registry already has unrelated\n // entries (the previous fallback-only logic meant per-env metadata\n // was never surfaced whenever system-bridged items populated the\n // registry). Deduplicate against whatever the registry returned.\n //\n // ADR-0005 (revised 2026-05): isolation is now per-organization, since\n // each env has its own physical DB. We surface both org-scoped overlays\n // (when an active org is provided) and env-wide (organization_id IS NULL)\n // overlays; org-scoped rows win on name collision.\n try {\n const orgId = (request as any).organizationId as string | undefined;\n const queryByOrg = async (oid: string | null): Promise<any[]> => {\n const whereClause: Record<string, unknown> = {\n type: request.type,\n state: 'active',\n organization_id: oid,\n };\n if (packageId) whereClause.package_id = packageId;\n let rs = await this.engine.find('sys_metadata', { where: whereClause });\n if ((!rs || rs.length === 0)) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = { type: alt, state: 'active', organization_id: oid };\n if (packageId) altWhere.package_id = packageId;\n rs = await this.engine.find('sys_metadata', { where: altWhere });\n }\n }\n return rs ?? [];\n };\n const envWideRecords = await queryByOrg(null);\n const orgRecords = orgId ? await queryByOrg(orgId) : [];\n // org-specific rows override env-wide rows on name collision\n const mergedMap = new Map<string, any>();\n for (const r of envWideRecords) mergedMap.set(r.name, r);\n for (const r of orgRecords) mergedMap.set(r.name, r);\n const records = Array.from(mergedMap.values());\n if (records && records.length > 0) {\n const byName = new Map<string, any>();\n for (const existing of items) {\n const entry = existing as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n byName.set(entry.name, entry);\n }\n }\n for (const record of records) {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n if (data && typeof data === 'object' && 'name' in data) {\n // Surface the persisted software-package binding so the\n // sidebar package filter and provenance classification\n // see overlay rows the same way they see registry items.\n const recPkg = (record as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && (data as any)._packageId === undefined) {\n (data as any)._packageId = recPkg;\n }\n byName.set(data.name, data);\n }\n // Only hydrate the global registry for unscoped calls —\n // scoped project entries must not leak process-wide.\n // Graft the artifact's protection envelope onto the\n // overlay body BEFORE registering: the plain-key entry\n // written here shadows the packaged artifact on\n // `registry.getItem`, and a bare overlay body would\n // strip `_lock`/`_packageId`/`_provenance` from every\n // registry-direct reader (ADR-0010 §3.3 — an overlay\n // must never loosen a packaged lock).\n if (this.environmentId === undefined && data && typeof data === 'object') {\n const artifact = this.lookupArtifactItem(request.type, (data as any).name);\n this.engine.registry.registerItem(\n request.type,\n mergeArtifactProtection(data, artifact),\n 'name' as any,\n );\n }\n }\n items = Array.from(byName.values());\n }\n } catch {\n // DB not available — fall through with whatever we already have.\n }\n\n // ADR-0033 draft-overlay preview: when the caller opts in (admin-gated\n // upstream — see http-dispatcher), overlay `state='draft'` rows on top of\n // the active result so the rendered console can preview pending changes\n // BEFORE publish (instead of only reading them as a JSON diff). Draft rows\n // WIN over active on name collision, and draft-only items (e.g. a brand-new\n // AI-authored object) surface too. Each overlaid item is tagged `_draft:true`\n // so the UI can badge it and show the \"PREVIEW — drafts\" banner. We do NOT\n // hydrate the SchemaRegistry from drafts — drafts must never leak into the\n // process-wide registry or to non-preview reads.\n if (request.previewDrafts) {\n try {\n const orgId = (request as any).organizationId as string | undefined;\n const queryDrafts = async (oid: string | null): Promise<any[]> => {\n const whereClause: Record<string, unknown> = { type: request.type, state: 'draft', organization_id: oid };\n if (packageId) whereClause.package_id = packageId;\n let rs = await this.engine.find('sys_metadata', { where: whereClause });\n if (!rs || rs.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = { type: alt, state: 'draft', organization_id: oid };\n if (packageId) altWhere.package_id = packageId;\n rs = await this.engine.find('sys_metadata', { where: altWhere });\n }\n }\n return rs ?? [];\n };\n const draftRecords = [...(await queryDrafts(null)), ...(orgId ? await queryDrafts(orgId) : [])];\n if (draftRecords.length > 0) {\n const byName = new Map<string, any>();\n for (const existing of items) {\n const entry = existing as any;\n if (entry && typeof entry === 'object' && 'name' in entry) byName.set(entry.name, entry);\n }\n for (const record of draftRecords) {\n const data = typeof record.metadata === 'string' ? JSON.parse(record.metadata) : record.metadata;\n if (data && typeof data === 'object' && 'name' in data) {\n const recPkg = (record as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && (data as any)._packageId === undefined) (data as any)._packageId = recPkg;\n (data as any)._draft = true;\n byName.set(data.name, data);\n }\n }\n items = Array.from(byName.values());\n }\n } catch {\n // DB unavailable — serve the active result unchanged.\n }\n }\n\n // Merge with MetadataService (runtime-registered items: agents, tools, etc.)\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.list === 'function') {\n let runtimeItems = await metadataService.list(request.type);\n // When filtering by packageId, only include runtime items that\n // belong to the requested package. MetadataService.list() returns\n // items from ALL packages, so we must filter here to respect the\n // package scope requested by the caller (e.g., Studio sidebar).\n if (packageId && runtimeItems && runtimeItems.length > 0) {\n runtimeItems = runtimeItems.filter((item: any) => item?._packageId === packageId);\n }\n if (runtimeItems && runtimeItems.length > 0) {\n // Merge, avoiding duplicates by name\n const itemMap = new Map<string, any>();\n for (const item of items) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n itemMap.set(entry.name, entry);\n }\n }\n for (const item of runtimeItems) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n // Do not overwrite entries already present in the\n // map: those came from sys_metadata (customization\n // overlays) or the SchemaRegistry and must win\n // over the MetadataService's artifact baseline.\n // Without this guard, saved per-org dashboard /\n // view overlays disappear from list endpoints on\n // refresh (detail endpoint kept showing the\n // overlay because it uses a different code path).\n if (!itemMap.has(entry.name)) {\n itemMap.set(entry.name, entry);\n }\n }\n }\n items = Array.from(itemMap.values());\n }\n }\n } catch {\n // MetadataService not available or doesn't support this type\n }\n\n // Hide metadata owned by a disabled package. `listItems` already drops\n // disabled-package items from the SchemaRegistry, but the DB overlay and\n // MetadataService merges above can re-introduce them (e.g. an app/view\n // persisted in sys_metadata). Re-apply the filter on the final merged\n // set so a disabled package's metadata stops surfacing in the console.\n // Never filter `package` (the Packages page must list disabled packages\n // to re-enable them) nor `object`/`objects` (filtering objects would\n // break data queries that depend on their schema).\n if (\n request.type !== 'package' &&\n request.type !== 'object' &&\n request.type !== 'objects'\n ) {\n items = (items as any[]).filter(\n (it) => !this.engine.registry.isPackageDisabled((it as any)?._packageId),\n );\n }\n\n // Canonical-shape exposure (ADR-0017, \"Object has-many View\"): a\n // `defineView` document is kept in the registry under the bare\n // `<object>` key for defensive single-item reads, but it is NOT a\n // first-class, independently addressable view — the registrar expands\n // it into independent ViewItems (each carrying `viewKind` + `config`).\n // Never surface the aggregated `{ list, form, listViews }` container\n // through enumeration so every list consumer (Studio metadata list,\n // REST `GET /meta/view`, AI schema retriever) sees exactly one\n // canonical entry per named view and never the legacy wrapper shape.\n if (request.type === 'view' || request.type === 'views') {\n items = (items as any[]).filter((it) => !isAggregatedViewContainer(it));\n }\n\n // Merge registered navigation contributions into each served app\n // (ADR-0029 D7). The setup app is a shell of empty group anchors;\n // platform-objects and capability plugins inject their menu entries as\n // contributions, merged lazily on read. REST app endpoints read through\n // this path (not registry.getAllApps), so the merge must happen here too\n // or every contributed group renders empty.\n if (request.type === 'app' || request.type === 'apps') {\n items = (items as any[]).map((app) => this.engine.registry.applyNavContributions(app));\n }\n\n return {\n type: request.type,\n items: decorateMetadataItems(\n request.type,\n (items as any[]).map((it) => {\n const a = this.lookupArtifactItem(\n request.type,\n (it as any)?.name,\n );\n return mergeArtifactProtection(it, a) as any;\n }),\n ),\n };\n }\n\n async getMetaItem(request: { type: string, name: string, packageId?: string, organizationId?: string, state?: 'active' | 'draft', previewDrafts?: boolean }) {\n let item: unknown;\n const orgId = request.organizationId;\n // Studio's editor opens a draft buffer with `state: 'draft'`;\n // runtime loaders omit it and get the live published row.\n const readState: 'active' | 'draft' = request.state === 'draft' ? 'draft' : 'active';\n\n // ADR-0033 draft-overlay preview (non-strict): when the caller opts in\n // (admin-gated upstream), prefer a `state='draft'` row if one exists, else\n // fall back to the active read below. This differs from the strict\n // `state:'draft'` mode, which 404s (`no_draft`) when no draft exists — the\n // render path must degrade to the published value, not error. The draft\n // item is tagged `_draft:true` so the UI can badge it.\n if (request.previewDrafts && readState !== 'draft') {\n try {\n const findDraft = async (oid: string | null): Promise<any | undefined> => {\n const rec = await this.engine.findOne('sys_metadata', {\n where: { type: request.type, name: request.name, state: 'draft', organization_id: oid },\n });\n if (rec) return rec;\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n return await this.engine.findOne('sys_metadata', {\n where: { type: alt, name: request.name, state: 'draft', organization_id: oid },\n });\n }\n return undefined;\n };\n const draftRec = (orgId ? await findDraft(orgId) : undefined) ?? await findDraft(null);\n if (draftRec) {\n const draftItem = typeof draftRec.metadata === 'string'\n ? JSON.parse(draftRec.metadata)\n : draftRec.metadata;\n if (draftItem && typeof draftItem === 'object') {\n const recPkg = (draftRec as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && (draftItem as any)._packageId === undefined) (draftItem as any)._packageId = recPkg;\n (draftItem as any)._draft = true;\n }\n return { type: request.type, name: request.name, item: decorateMetadataItem(request.type, draftItem) };\n }\n } catch {\n // DB unavailable — fall through to the active read.\n }\n }\n\n // 1. Customization overlay lookup (sys_metadata).\n // Per ADR-0005 (revised), org-scoped row wins; env-wide\n // (organization_id IS NULL) row is the fallback before falling\n // through to the in-memory registry / MetadataService.\n try {\n const findOverlay = async (oid: string | null): Promise<any | undefined> => {\n const where: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n state: readState,\n organization_id: oid,\n };\n const rec = await this.engine.findOne('sys_metadata', { where });\n if (rec) return rec;\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = {\n type: alt,\n name: request.name,\n state: readState,\n organization_id: oid,\n };\n return await this.engine.findOne('sys_metadata', { where: altWhere });\n }\n return undefined;\n };\n const record = (orgId ? await findOverlay(orgId) : undefined)\n ?? await findOverlay(null);\n if (record) {\n item = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Surface the persisted software-package binding (parity with\n // the list path in getMetaItems) so provenance/UI can read it.\n const recPkg = (record as { package_id?: string | null }).package_id ?? undefined;\n if (recPkg && item && typeof item === 'object' && (item as any)._packageId === undefined) {\n (item as any)._packageId = recPkg;\n }\n }\n } catch {\n // DB not available — fall through to registry / MetadataService\n }\n\n // Draft reads stop here — they intentionally do NOT fall through\n // to the runtime registry / MetadataService (which only know\n // about published values). When the draft row is missing we\n // throw `no_draft` (HTTP 404) so the REST contract is identical\n // to `POST /publish` on an empty slot: clients use a single\n // status code to decide \"no pending edit\" without sniffing\n // envelope shape. See ADR-0005 §draft-lifecycle.\n if (readState === 'draft') {\n if (item === undefined) {\n const err: any = new Error(\n `[no_draft] No pending draft exists for ${request.type}/${request.name}.`,\n );\n err.code = 'no_draft';\n err.status = 404;\n throw err;\n }\n return { type: request.type, name: request.name, item: decorateMetadataItem(request.type, item) };\n }\n\n // 2. MetadataService (runtime-registered items: HMR-updated view/page/\n // dashboard/agent/tool, plus FilesystemLoader-sourced items). This\n // is consulted BEFORE the in-memory SchemaRegistry because the\n // registry is a boot-time cache populated by `loadMetadataFromService`\n // and is NOT invalidated on `MetadataManager.register()` (which is\n // how the CLI dev watcher pushes recompiled metadata into the\n // running server). Without this ordering, edits to `*.view.ts`\n // source files appear to take effect (MetadataManager learns the\n // new value) but reads continue to return the stale registry copy.\n if (item === undefined) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n const fromService = await metadataService.get(request.type, request.name);\n if (fromService !== undefined && fromService !== null) {\n item = fromService;\n } else {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altFromService = await metadataService.get(alt, request.name);\n if (altFromService !== undefined && altFromService !== null) {\n item = altFromService;\n }\n }\n }\n }\n } catch {\n // MetadataService not available — fall through\n }\n }\n\n // 3. In-memory SchemaRegistry (artifact-loaded out-of-box values, and\n // items that bypass MetadataService — e.g. some object-schema\n // extension chains registered by AppPlugin directly).\n // Both control-plane (unscoped) and project kernels consult the\n // registry. The previous guard that skipped the registry for\n // project kernels was meant to prevent cross-project leakage at\n // the LIST level — but for a single-item lookup the kernel's own\n // `engine.registry` is project-local (each ObjectQL instance has\n // its own SchemaRegistry), so reading from it is safe and\n // necessary. Without this, project-kernel callers of\n // `GET /api/v1/meta/object/<name>` 404 even though the object is\n // registered and visible via the list endpoint.\n if (item === undefined) {\n item = this.engine.registry.getItem(request.type, request.name);\n if (item === undefined) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) item = this.engine.registry.getItem(alt, request.name);\n }\n }\n\n // Merge registered navigation contributions into a served app\n // (ADR-0029 D7) — parity with the getMetaItems list path so a\n // single-app fetch (GET /meta/app/<name>) also sees the contributed\n // menu entries, not just the empty group-anchor shell.\n if ((request.type === 'app' || request.type === 'apps') && item) {\n item = this.engine.registry.applyNavContributions(item);\n }\n\n // ADR-0010 §3.3 — artifact-level protection (lock/packageId) always\n // wins over any overlay row. The metadata service may return a\n // persisted overlay copy that pre-dates the artifact's `_lock`\n // declaration; we must consult the in-memory artifact registry\n // directly and let its protection envelope override.\n const artifactItem = this.lookupArtifactItem(request.type, request.name);\n let decorated = decorateMetadataItem(\n request.type,\n mergeArtifactProtection(item, artifactItem),\n );\n // ADR-0047 — list views additionally get reference-integrity\n // diagnostics (userFilters/tabs fields must exist on the source\n // object, kanban groupBy must be select-like). Zod cannot see\n // across documents; merge the cross-document errors into the\n // same `_diagnostics` envelope. Defensive: a failed lookup must\n // never break a read.\n if ((request.type === 'view' || request.type === 'views') && decorated && typeof decorated === 'object') {\n try {\n const viewDoc = decorated as Record<string, any>;\n const sourceObject = viewDoc?.object\n ?? viewDoc?.data?.object\n ?? viewDoc?.objectName\n ?? viewDoc?.list?.data?.object;\n const objectDef = typeof sourceObject === 'string'\n ? this.engine.registry.getObject(sourceObject)\n : undefined;\n if (objectDef) {\n const refs = computeViewReferenceDiagnostics(viewDoc, objectDef as any);\n if (!refs.valid) {\n const prior = viewDoc._diagnostics;\n decorated = {\n ...viewDoc,\n _diagnostics: {\n valid: false,\n errors: [\n ...(prior && prior.valid === false && Array.isArray(prior.errors) ? prior.errors : []),\n ...(refs.errors ?? []),\n ],\n },\n } as typeof decorated;\n }\n }\n } catch { /* reference diagnostics are best-effort */ }\n }\n // ADR-0010 — surface lock/provenance flags so Studio can render\n // the correct affordances without a second round trip.\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n const lockState = resolveLockState(decorated, artifactBacked);\n return {\n type: request.type,\n name: request.name,\n item: decorated,\n lock: lockState.lock,\n ...(lockState.lockReason !== undefined ? { lockReason: lockState.lockReason } : {}),\n ...(lockState.lockSource !== undefined ? { lockSource: lockState.lockSource } : {}),\n ...(lockState.lockDocsUrl !== undefined ? { lockDocsUrl: lockState.lockDocsUrl } : {}),\n ...(lockState.provenance !== undefined ? { provenance: lockState.provenance } : {}),\n ...(lockState.packageId !== undefined ? { packageId: lockState.packageId } : {}),\n ...(lockState.packageVersion !== undefined ? { packageVersion: lockState.packageVersion } : {}),\n editable: lockState.editable,\n deletable: lockState.deletable,\n resettable: lockState.resettable,\n };\n }\n\n /**\n * Phase 3a-layered-get: return the 3 layers of a metadata item\n * separately — `code` (artifact-loaded baseline), `overlay` (per-org\n * customisation row, if any), and `effective` (what `getMetaItem`\n * would return, i.e. overlay-wins merge).\n *\n * Drives the \"Code default vs Overlay vs Effective\" diff tab in the\n * generic Metadata Resource Edit page. Admins can see exactly what\n * was customised and reset selectively.\n *\n * `code` is null if no artifact baseline exists; `overlay` is null if\n * no sys_metadata row exists for the requested scope; `effective` is\n * never null when either layer exists.\n */\n async getMetaItemLayered(request: {\n type: string;\n name: string;\n packageId?: string;\n organizationId?: string;\n }): Promise<{\n type: string;\n name: string;\n code: unknown | null;\n overlay: unknown | null;\n overlayScope: 'org' | 'env' | null;\n effective: unknown | null;\n /**\n * Load-time validation result for the effective payload — same\n * shape attached to getMetaItems/getMetaItem by\n * decorateMetadataItem. Undefined for types without a registered\n * Zod schema (function/service/router). Lets the Studio edit\n * page surface invalid-metadata banners + inline field errors\n * without a second round-trip.\n */\n _diagnostics?: MetadataDiagnostics;\n // ── ADR-0010 protection envelope ──\n lock: MetadataLock;\n lockReason?: string;\n lockSource?: 'artifact' | 'package' | 'env-forced' | 'overlay';\n lockDocsUrl?: string;\n provenance?: MetadataProvenance;\n packageId?: string;\n packageVersion?: string;\n editable: boolean;\n deletable: boolean;\n resettable: boolean;\n }> {\n const orgId = request.organizationId;\n\n // ── code layer: MetadataService.get + registry, BYPASSING overlay ──\n let code: unknown | null = null;\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n let fromService = await metadataService.get(request.type, request.name);\n if (fromService === undefined || fromService === null) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) fromService = await metadataService.get(alt, request.name);\n }\n if (fromService !== undefined && fromService !== null) code = fromService;\n }\n } catch {\n // ignore\n }\n if (code === null) {\n // Prefer the artifact-only lookup so an overlay row hydrated\n // into the registry's plain key can't masquerade as the \"code\n // default\" layer; fall back to getItem for runtime-only items.\n let regItem = this.lookupArtifactItem(request.type, request.name)\n ?? this.engine.registry.getItem(request.type, request.name);\n if (regItem === undefined) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) regItem = this.engine.registry.getItem(alt, request.name);\n }\n if (regItem !== undefined) code = regItem;\n }\n\n // ── overlay layer: sys_metadata row (org-scoped wins, then env-wide) ──\n let overlay: unknown | null = null;\n let overlayScope: 'org' | 'env' | null = null;\n try {\n const findOverlay = async (oid: string | null) => {\n const where: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n state: 'active',\n organization_id: oid,\n };\n let rec = await this.engine.findOne('sys_metadata', { where });\n if (!rec) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n rec = await this.engine.findOne('sys_metadata', {\n where: { ...where, type: alt },\n });\n }\n }\n return rec;\n };\n if (orgId) {\n const rec = await findOverlay(orgId);\n if (rec) {\n overlay = typeof rec.metadata === 'string' ? JSON.parse(rec.metadata) : rec.metadata;\n overlayScope = 'org';\n }\n }\n if (overlay === null) {\n const rec = await findOverlay(null);\n if (rec) {\n overlay = typeof rec.metadata === 'string' ? JSON.parse(rec.metadata) : rec.metadata;\n overlayScope = 'env';\n }\n }\n } catch {\n // DB unavailable — overlay stays null\n }\n\n const effective: unknown | null = overlay ?? code;\n\n const _diagnostics =\n effective !== null && effective !== undefined\n ? computeMetadataDiagnostics(request.type, effective)\n : undefined;\n\n // ADR-0010 — surface lock/provenance flags so the Studio editor\n // can render the correct affordances without a second round trip.\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n // Lock resolution: artifact wins over overlay, matching getEffectiveLock.\n const lockSource: any = code ?? overlay ?? {};\n const lockState = resolveLockState(lockSource, artifactBacked);\n\n return {\n type: request.type,\n name: request.name,\n code,\n overlay,\n overlayScope,\n effective,\n ...(_diagnostics ? { _diagnostics } : {}),\n lock: lockState.lock,\n ...(lockState.lockReason !== undefined ? { lockReason: lockState.lockReason } : {}),\n ...(lockState.lockSource !== undefined ? { lockSource: lockState.lockSource } : {}),\n ...(lockState.lockDocsUrl !== undefined ? { lockDocsUrl: lockState.lockDocsUrl } : {}),\n ...(lockState.provenance !== undefined ? { provenance: lockState.provenance } : {}),\n ...(lockState.packageId !== undefined ? { packageId: lockState.packageId } : {}),\n ...(lockState.packageVersion !== undefined ? { packageVersion: lockState.packageVersion } : {}),\n editable: lockState.editable,\n deletable: lockState.deletable,\n resettable: lockState.resettable,\n };\n }\n\n /**\n * ADR-0010 §3.6 / Phase 4.1 — read the metadata-protection audit log\n * for a single item. Returns the most-recent rows of\n * `sys_metadata_audit` for this (type, name) tuple, sorted newest\n * first. Refused (`denied`) and forced (`forced`) writes both appear\n * here — they never reach the `history` endpoint, which only tracks\n * successful body snapshots.\n *\n * The table is provisioned by `platform-objects` and is the\n * compliance surface for the lock-enforcement story. When the\n * environment has not yet provisioned the table (legacy install\n * prior to ADR-0010) the call returns `{ events: [] }` instead of\n * raising, keeping the Studio tab harmless.\n */\n async auditMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string | null;\n limit?: number;\n }): Promise<{\n events: Array<{\n id: unknown;\n occurredAt: string;\n actor: string;\n source: string | null;\n operation: 'save' | 'publish' | 'rollback' | 'delete' | 'reset';\n outcome: 'allowed' | 'denied' | 'forced';\n code: string;\n lockState: MetadataLock | null;\n lockOverridden: boolean;\n requestId: string | null;\n note: string | null;\n }>;\n }> {\n const singular = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const limit = Math.min(\n Math.max(1, request.limit ?? 100),\n 500,\n );\n try {\n // Org-scoped lookup: include rows for the specific org AND\n // env-wide (organization_id IS NULL) rows so the editor\n // sees both tenant overlays and env-level package writes.\n const where: Record<string, unknown> = {\n type: singular,\n name: request.name,\n };\n const rows = await this.engine.find('sys_metadata_audit', {\n where,\n orderBy: [{ field: 'occurred_at', direction: 'desc' }],\n limit,\n } as any);\n const events = (Array.isArray(rows) ? rows : []).map((r: any) => ({\n id: r.id,\n occurredAt:\n typeof r.occurred_at === 'string'\n ? r.occurred_at\n : r.occurred_at instanceof Date\n ? r.occurred_at.toISOString()\n : String(r.occurred_at ?? ''),\n actor: String(r.actor ?? 'system'),\n source: r.source ?? null,\n operation: r.operation,\n outcome: r.outcome,\n code: String(r.code ?? ''),\n lockState: (r.lock_state ?? null) as MetadataLock | null,\n lockOverridden: Boolean(r.lock_overridden),\n requestId: r.request_id ?? null,\n note: r.note ?? null,\n }));\n return { events };\n } catch (err: any) {\n // Table not provisioned (legacy env) or driver doesn't\n // expose `find` — return empty rather than 500ing the tab.\n console.warn(\n `[Protocol] auditMetaItem read failed for ${request.type}/${request.name}: ${err?.message ?? err}`,\n );\n return { events: [] };\n }\n }\n\n async getUiView(request: { object: string, type: 'list' | 'form' }) {\n const schema = this.engine.registry.getObject(request.object);\n if (!schema) throw new Error(`Object ${request.object} not found`);\n\n const fields = schema.fields || {};\n const fieldKeys = Object.keys(fields);\n\n if (request.type === 'list') {\n // Intelligent Column Selection\n // 1. Always include 'name' or name-like fields\n // 2. Limit to 6 columns by default\n const priorityFields = ['name', 'title', 'label', 'subject', 'email', 'status', 'type', 'category', 'created_at'];\n \n let columns = fieldKeys.filter(k => priorityFields.includes(k));\n \n // If few priority fields, add others until 5\n if (columns.length < 5) {\n const remaining = fieldKeys.filter(k => !columns.includes(k) && k !== 'id' && !fields[k].hidden);\n columns = [...columns, ...remaining.slice(0, 5 - columns.length)];\n }\n \n // Sort columns by priority then alphabet or schema order\n // For now, just keep them roughly in order they appear in schema or priority list\n \n return {\n list: {\n type: 'grid' as const,\n object: request.object,\n label: schema.label || schema.name,\n columns: columns.map(f => ({\n field: f,\n label: fields[f]?.label || f,\n sortable: true\n })),\n sort: fields['created_at'] ? ([{ field: 'created_at', order: 'desc' }] as any) : undefined,\n searchableFields: columns.slice(0, 3) // Make first few textual columns searchable\n }\n };\n } else {\n // Form View Generation\n // Simple single-section layout for now\n const formFields = fieldKeys\n .filter(k => k !== 'id' && k !== 'created_at' && k !== 'updated_at' && !fields[k].hidden)\n .map(f => ({\n field: f,\n label: fields[f]?.label,\n required: fields[f]?.required,\n readonly: fields[f]?.readonly,\n type: fields[f]?.type,\n // Default to 2 columns for most, 1 for textareas\n colSpan: (fields[f]?.type === 'textarea' || fields[f]?.type === 'html') ? 2 : 1\n }));\n\n return {\n form: {\n type: 'simple' as const,\n object: request.object,\n label: `Edit ${schema.label || schema.name}`,\n sections: [\n {\n label: 'General Information',\n columns: 2 as const,\n collapsible: false,\n collapsed: false,\n fields: formFields\n }\n ]\n }\n };\n }\n }\n\n async findData(request: { object: string, query?: any, context?: any }) {\n const options: any = { ...request.query };\n // Forward the dispatcher's ExecutionContext so RBAC/RLS middleware\n // can apply per-request enforcement. The protocol layer is purely\n // a normalizer — it must never strip security context.\n if (request.context !== undefined) {\n options.context = request.context;\n }\n\n // ====================================================================\n // Normalize legacy params → QueryAST standard (where/fields/orderBy/offset/expand)\n // ====================================================================\n\n // OData-style `$`-prefixed params → bare aliases that the rest of\n // this function knows how to normalize. Without this step, params\n // like `?$top=2&$orderby=...` survive into the catch-all\n // implicit-filter pass below and get merged into `where` as\n // bogus field-equality predicates (e.g. `where.$top = \"2\"`),\n // which silently returns zero rows for every list endpoint.\n for (const [dollar, bare] of [\n ['$top', 'top'],\n ['$skip', 'skip'],\n ['$orderby', 'orderBy'],\n ['$select', 'select'],\n ['$count', 'count'],\n ] as const) {\n if (options[dollar] != null && options[bare] == null) {\n options[bare] = options[dollar];\n }\n delete options[dollar];\n }\n\n // Numeric fields — normalize top → limit, skip → offset\n if (options.top != null) {\n options.limit = Number(options.top);\n delete options.top;\n }\n if (options.skip != null) {\n options.offset = Number(options.skip);\n delete options.skip;\n }\n if (options.limit != null) options.limit = Number(options.limit);\n if (options.offset != null) options.offset = Number(options.offset);\n\n // Select → fields: comma-separated string → array\n if (typeof options.select === 'string') {\n options.fields = options.select.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(options.select)) {\n options.fields = options.select;\n }\n if (options.select !== undefined) delete options.select;\n\n // Sort/orderBy → orderBy: string → SortNode[] array\n const sortValue = options.orderBy ?? options.sort;\n if (typeof sortValue === 'string') {\n const parsed = sortValue.split(',').map((part: string) => {\n const trimmed = part.trim();\n if (trimmed.startsWith('-')) {\n return { field: trimmed.slice(1), order: 'desc' as const };\n }\n const [field, order] = trimmed.split(/\\s+/);\n return { field, order: (order?.toLowerCase() === 'desc' ? 'desc' : 'asc') as 'asc' | 'desc' };\n }).filter((s: any) => s.field);\n options.orderBy = parsed;\n } else if (Array.isArray(sortValue)) {\n options.orderBy = sortValue;\n }\n delete options.sort;\n\n // Filter/filters/$filter → where: normalize all filter aliases\n const filterValue = options.filter ?? options.filters ?? options.$filter ?? options.where;\n delete options.filter;\n delete options.filters;\n delete options.$filter;\n\n if (filterValue !== undefined) {\n let parsedFilter = filterValue;\n // JSON string → object\n if (typeof parsedFilter === 'string') {\n try { parsedFilter = JSON.parse(parsedFilter); } catch { /* keep as-is */ }\n }\n // Filter AST array → FilterCondition object\n if (isFilterAST(parsedFilter)) {\n parsedFilter = parseFilterAST(parsedFilter);\n }\n options.where = parsedFilter;\n }\n\n // Populate/expand/$expand → expand (Record<string, QueryAST>)\n const populateValue = options.populate;\n const expandValue = options.$expand ?? options.expand;\n const expandNames: string[] = [];\n if (typeof populateValue === 'string') {\n expandNames.push(...populateValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(populateValue)) {\n expandNames.push(...populateValue);\n }\n if (!expandNames.length && expandValue) {\n if (typeof expandValue === 'string') {\n expandNames.push(...expandValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(expandValue)) {\n expandNames.push(...expandValue);\n }\n }\n delete options.populate;\n delete options.$expand;\n // Clean up non-object expand (e.g. string) BEFORE the Record conversion\n // below, so that populate-derived names can create the expand Record even\n // when a legacy string expand was also present.\n if (typeof options.expand !== 'object' || options.expand === null) {\n delete options.expand;\n }\n // Only set expand if not already an object (advanced usage)\n if (expandNames.length > 0 && !options.expand) {\n options.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n options.expand[rel] = { object: rel };\n }\n }\n\n // Boolean fields\n for (const key of ['distinct', 'count']) {\n if (options[key] === 'true') options[key] = true;\n else if (options[key] === 'false') options[key] = false;\n }\n \n // Flat field filters: REST-style query params like ?id=abc&status=open\n // After extracting all known query parameters, any remaining keys are\n // treated as implicit field-level equality filters merged into `where`.\n const knownParams = new Set([\n 'top', 'limit', 'offset',\n 'orderBy',\n 'fields',\n 'where',\n 'expand',\n 'distinct', 'count',\n 'aggregations', 'groupBy',\n 'search', 'context', 'cursor',\n ]);\n if (!options.where) {\n const implicitFilters: Record<string, unknown> = {};\n for (const key of Object.keys(options)) {\n if (!knownParams.has(key)) {\n implicitFilters[key] = options[key];\n delete options[key];\n }\n }\n if (Object.keys(implicitFilters).length > 0) {\n options.where = implicitFilters;\n }\n }\n \n // Route to engine.aggregate() when the query has GROUP BY / aggregations.\n // engine.find() does not do in-memory aggregation fallback, so without\n // this branch a spec-shape aggregate request would silently return\n // ungrouped raw rows on drivers (e.g. SqlDriver) that don't natively\n // honor groupBy/aggregations in find().\n const hasGroupBy = Array.isArray(options.groupBy) && options.groupBy.length > 0;\n const hasAggregations = Array.isArray(options.aggregations) && options.aggregations.length > 0;\n if (hasGroupBy || hasAggregations) {\n const records = await this.engine.aggregate(request.object, {\n where: options.where,\n groupBy: options.groupBy,\n aggregations: options.aggregations,\n context: options.context,\n } as any);\n // Apply limit client-side (EngineAggregateOptions doesn't carry limit)\n const limited = typeof options.limit === 'number' && options.limit > 0\n ? records.slice(0, options.limit)\n : records;\n return {\n object: request.object,\n records: limited,\n total: limited.length,\n hasMore: false,\n };\n }\n\n const records = await this.engine.find(request.object, options);\n // Spec: FindDataResponseSchema — only `records` is returned.\n // OData `value` adaptation (if needed) is handled in the HTTP dispatch layer.\n return {\n object: request.object,\n records,\n total: records.length,\n hasMore: false\n };\n }\n\n async getData(request: { object: string, id: string, expand?: string | string[], select?: string | string[], context?: any }) {\n const queryOptions: any = {\n where: { id: request.id }\n };\n if (request.context !== undefined) {\n queryOptions.context = request.context;\n }\n\n // Support fields for single-record retrieval\n if (request.select) {\n queryOptions.fields = typeof request.select === 'string'\n ? request.select.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.select;\n }\n\n // Support expand for single-record retrieval\n if (request.expand) {\n const expandNames = typeof request.expand === 'string'\n ? request.expand.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.expand;\n queryOptions.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n queryOptions.expand[rel] = { object: rel };\n }\n }\n\n const result = await this.engine.findOne(request.object, queryOptions);\n if (result) {\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n const err = new Error(`Record ${request.id} not found in ${request.object}`) as Error & {\n code?: string;\n status?: number;\n object?: string;\n };\n err.code = 'RECORD_NOT_FOUND';\n err.status = 404;\n err.object = request.object;\n throw err;\n }\n\n async createData(request: { object: string, data: any, context?: any }) {\n const result = await this.engine.insert(\n request.object,\n request.data,\n request.context !== undefined ? { context: request.context } as any : undefined,\n );\n return {\n object: request.object,\n id: result.id,\n record: result\n };\n }\n\n async updateData(request: { object: string, id: string, data: any, expectedVersion?: string, context?: any }) {\n await this.assertVersionMatch(request.object, request.id, request.expectedVersion, request.context);\n const opts: any = { where: { id: request.id } };\n if (request.context !== undefined) opts.context = request.context;\n const result = await this.engine.update(request.object, request.data, opts);\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n\n async deleteData(request: { object: string, id: string, expectedVersion?: string, context?: any }) {\n await this.assertVersionMatch(request.object, request.id, request.expectedVersion, request.context);\n const opts: any = { where: { id: request.id } };\n if (request.context !== undefined) opts.context = request.context;\n await this.engine.delete(request.object, opts);\n return {\n object: request.object,\n id: request.id,\n success: true\n };\n }\n\n /**\n * Optimistic Concurrency Control gate shared by updateData/deleteData.\n *\n * When the caller passes a non-empty `expectedVersion` token (typically\n * the `updated_at` value they read), this fetches the current record\n * and compares its `updated_at` against the token. Mismatch → throw\n * `ConcurrentUpdateError` which the REST layer maps to 409.\n *\n * Behaviour:\n * - Empty/missing token → no check (opt-in semantics; existing callers\n * that haven't yet adopted OCC are unaffected).\n * - Record not found → no check; downstream `engine.update` will\n * surface the usual `RECORD_NOT_FOUND` 404. We intentionally do not\n * treat \"missing record\" as a concurrency conflict.\n * - Record has no `updated_at` field (timestamps disabled) → no check.\n * Logging would be noisy here; OCC is opt-in and the absence of a\n * version column is an explicit \"this object doesn't support OCC\"\n * signal.\n */\n private async assertVersionMatch(\n object: string,\n id: string,\n expectedVersion: string | undefined,\n context: any\n ): Promise<void> {\n const expected = normaliseVersionToken(expectedVersion);\n if (!expected) return;\n const findOpts: any = { where: { id } };\n if (context !== undefined) findOpts.context = context;\n const current = await this.engine.findOne(object, findOpts);\n if (!current) return;\n const currentVersion = normaliseVersionToken((current as any).updated_at);\n if (!currentVersion) return;\n if (currentVersion !== expected) {\n throw new ConcurrentUpdateError({\n currentVersion,\n currentRecord: current,\n message: `Record ${object}/${id} was modified by another user (current version ${currentVersion}, expected ${expected})`,\n });\n }\n }\n\n // ==========================================\n // Global Search (M10.5)\n // ==========================================\n /**\n * Cross-object substring search across all registered objects that opt in\n * via `enable.searchable !== false` and `enable.apiEnabled !== false`.\n * Searches text-like fields (text/textarea/email/url/phone/markdown/html/string)\n * whose `searchable: true` flag is set, falling back to the object's\n * `displayNameField` (or `name`) when no fields are explicitly searchable.\n *\n * The query is split into whitespace-separated terms; each term must match\n * (case-insensitive LIKE) at least one searchable field. RBAC/RLS is\n * enforced by forwarding the caller's `context` to `engine.find` so users\n * only see records they are entitled to read.\n */\n async searchAll(request: {\n q: string;\n objects?: string[];\n limit?: number;\n perObject?: number;\n context?: any;\n }): Promise<{\n query: string;\n hits: Array<{\n object: string;\n id: string;\n title: string;\n snippet?: string;\n record: any;\n }>;\n totalObjects: number;\n totalHits: number;\n truncated: boolean;\n }> {\n const q = (request.q ?? '').trim();\n if (!q) {\n return { query: '', hits: [], totalObjects: 0, totalHits: 0, truncated: false };\n }\n\n const overallLimit = Math.max(1, Math.min(100, Number(request.limit ?? 20)));\n const perObject = Math.max(1, Math.min(25, Number(request.perObject ?? 5)));\n const objectsFilter = request.objects && request.objects.length\n ? new Set(request.objects)\n : null;\n\n // Tokenise: each token must match (LIKE %term%) at least one searchable field\n const terms = q.split(/\\s+/).filter(Boolean).slice(0, 8);\n\n const allObjects = (this.engine as any).registry?.getAllObjects?.() ?? [];\n const hits: Array<{ object: string; id: string; title: string; snippet?: string; record: any }> = [];\n let objectsScanned = 0;\n\n for (const obj of allObjects) {\n if (hits.length >= overallLimit) break;\n if (!obj?.name) continue;\n if (objectsFilter && !objectsFilter.has(obj.name)) continue;\n\n // Skip platform/system tables and opt-outs\n const enable = obj.enable ?? {};\n if (enable.searchable === false) continue;\n if (enable.apiEnabled === false) continue;\n // Skip noisy system tables by name prefix\n if (obj.name.startsWith('sys_audit_log')\n || obj.name.startsWith('sys_activity')\n || obj.name.startsWith('sys_session')\n || obj.name.startsWith('sys_presence')\n || obj.name.startsWith('sys_metadata')\n || obj.name.startsWith('sys_account')) {\n continue;\n }\n\n const fieldsRaw = obj.fields;\n const fields: Array<{ name: string; type: string; searchable?: boolean }> =\n Array.isArray(fieldsRaw)\n ? fieldsRaw\n : (fieldsRaw && typeof fieldsRaw === 'object'\n ? Object.entries(fieldsRaw).map(([name, f]: [string, any]) => ({ name, ...(f || {}) }))\n : []);\n const TEXT_TYPES = new Set(['text', 'textarea', 'string', 'email', 'url', 'phone', 'markdown', 'html']);\n const fieldByName = new Map(fields.map(f => [f.name, f]));\n const hasField = (n: string) => fieldByName.has(n);\n // Resolve title for a record using titleFormat → displayNameField →\n // common conventional fields → id. titleFormat supports simple\n // `{field}` placeholders (the `template` dialect); unresolved\n // placeholders fall through to the next strategy.\n const titleFormatSource = (obj.titleFormat && (obj.titleFormat.source || obj.titleFormat))\n || undefined;\n const renderTitle = (row: any): string => {\n if (typeof titleFormatSource === 'string') {\n let allResolved = true;\n const rendered = titleFormatSource.replace(/\\{\\{?\\s*([a-zA-Z0-9_.]+)\\s*\\}?\\}/g, (_m, key) => {\n const v = row[key];\n if (v == null || v === '') { allResolved = false; return ''; }\n return String(v);\n }).trim();\n if (rendered && allResolved) return rendered;\n if (rendered) return rendered.replace(/\\s+-\\s+$/, '').replace(/^\\s+-\\s+/, '').trim() || row.id;\n }\n const candidates = [\n obj.displayNameField,\n 'name', 'full_name', 'title', 'subject', 'label', 'company',\n ].filter((c): c is string => typeof c === 'string' && hasField(c));\n for (const c of candidates) {\n const v = row[c];\n if (v != null && String(v).trim()) return String(v);\n }\n const fn = row.first_name, ln = row.last_name;\n if (fn || ln) return `${fn ?? ''} ${ln ?? ''}`.trim();\n return String(row.id);\n };\n\n const titleFieldName = obj.displayNameField\n || (hasField('name') ? 'name' : undefined)\n || (hasField('title') ? 'title' : undefined)\n || fields.find(f => TEXT_TYPES.has(f.type))?.name;\n\n let searchableFields = fields\n .filter(f => f && TEXT_TYPES.has(f.type) && f.searchable === true)\n .map(f => f.name as string);\n\n // Fallback: if no field is explicitly searchable, scan the title field\n if (searchableFields.length === 0 && titleFieldName) {\n searchableFields = [titleFieldName];\n }\n if (searchableFields.length === 0) continue;\n\n objectsScanned++;\n\n // Build AND-of-OR filter: every term must hit at least one field.\n // ObjectQL exposes case-insensitive substring matching via `$contains`.\n const andClauses = terms.map(term => ({\n $or: searchableFields.map(f => ({ [f]: { $contains: term } })),\n }));\n const where = andClauses.length === 1 ? andClauses[0] : { $and: andClauses };\n\n try {\n const opts: any = {\n where,\n limit: perObject,\n orderBy: [{ field: 'updated_at', direction: 'desc' }],\n };\n if (request.context !== undefined) opts.context = request.context;\n\n const rows = await this.engine.find(obj.name, opts);\n for (const row of rows || []) {\n if (hits.length >= overallLimit) break;\n const title = renderTitle(row);\n // Build snippet from first searchable field that contains a term\n let snippet: string | undefined;\n for (const f of searchableFields) {\n const v = row[f];\n if (typeof v === 'string' && v) {\n const lc = v.toLowerCase();\n const idx = terms.map(t => lc.indexOf(t.toLowerCase())).find(i => i >= 0);\n if (idx != null && idx >= 0) {\n const start = Math.max(0, idx - 30);\n const end = Math.min(v.length, idx + 90);\n snippet = (start > 0 ? '…' : '') + v.slice(start, end) + (end < v.length ? '…' : '');\n break;\n }\n }\n }\n hits.push({\n object: obj.name,\n id: row.id,\n title,\n snippet,\n record: row,\n });\n }\n } catch {\n // RBAC denial or driver hiccup — skip silently per object\n continue;\n }\n }\n\n return {\n query: q,\n hits,\n totalObjects: objectsScanned,\n totalHits: hits.length,\n truncated: hits.length >= overallLimit,\n };\n }\n\n // ==========================================\n // Lead Convert (M10.6)\n // ==========================================\n /**\n * Convert a qualified Lead into an Account + Contact (+ optional\n * Opportunity) and mark the Lead as converted. Mirrors the Salesforce\n * lead-conversion model:\n *\n * - If `accountId` is provided, the lead's company info is NOT used\n * to create a new account; the new contact and opportunity link to\n * the existing account instead.\n * - If `contactId` is provided, no new contact is created either —\n * useful when the lead is a new contact at an existing account.\n * - `createOpportunity` defaults to true; pass `false` to convert\n * without producing an opportunity (some teams convert \"logos\n * only\" first).\n * - Lead is updated atomically: `is_converted=true`,\n * `converted_account`/`converted_contact`/`converted_opportunity`\n * pointers, `converted_date`, and `status='converted'`.\n *\n * Atomicity is enforced via the default driver's transaction support\n * when available; otherwise a best-effort compensation (delete\n * already-created child records on failure) is attempted. Permission\n * checks on each child object are inherited from the caller's\n * execution context so SecurityPlugin still gates account/contact/\n * opportunity creates.\n */\n async convertLead(request: {\n leadId: string;\n accountId?: string;\n contactId?: string;\n createOpportunity?: boolean;\n opportunity?: {\n name?: string;\n amount?: number;\n close_date?: string;\n stage?: string;\n };\n convertedStatus?: string;\n context?: any;\n }): Promise<{\n lead: any;\n account: any;\n contact: any;\n opportunity: any | null;\n }> {\n const leadId = String(request.leadId || '').trim();\n if (!leadId) {\n const err: any = new Error('leadId is required');\n err.status = 400;\n err.code = 'INVALID_REQUEST';\n throw err;\n }\n const ctx = request.context;\n const ctxOpt = ctx !== undefined ? { context: ctx } : undefined;\n\n // Load lead\n const lead = await this.engine.findOne('lead', { where: { id: leadId }, ...(ctxOpt as any) } as any);\n if (!lead) {\n const err: any = new Error(`Lead '${leadId}' not found`);\n err.status = 404;\n err.code = 'LEAD_NOT_FOUND';\n throw err;\n }\n if (lead.is_converted) {\n const err: any = new Error(`Lead '${leadId}' is already converted`);\n err.status = 409;\n err.code = 'LEAD_ALREADY_CONVERTED';\n throw err;\n }\n\n // Wrap the whole conversion in a single DB transaction so that a\n // partial failure (e.g. opportunity insert fails after we've\n // already created the account/contact) rolls back atomically\n // instead of leaving orphan rows. Falls back to direct execution\n // on drivers without transaction support — in that case the\n // operations are still ordered so callers see the same partial\n // state we'd get from any non-atomic sequence.\n const runConversion = async (trxCtx: any) => {\n const opCtx = trxCtx ?? ctx;\n const trxCtxOpt = opCtx !== undefined ? { context: opCtx } : undefined;\n\n // 1) Account\n let account: any;\n if (request.accountId) {\n account = await this.engine.findOne('account', { where: { id: request.accountId }, ...(trxCtxOpt as any) } as any);\n if (!account) {\n const err: any = new Error(`Account '${request.accountId}' not found`);\n err.status = 404;\n err.code = 'ACCOUNT_NOT_FOUND';\n throw err;\n }\n } else {\n const accountPayload: Record<string, any> = {\n name: lead.company || `${lead.first_name ?? ''} ${lead.last_name ?? ''}`.trim() || 'Untitled Account',\n };\n if (lead.industry) accountPayload.industry = lead.industry;\n if (lead.annual_revenue) accountPayload.annual_revenue = lead.annual_revenue;\n if (lead.number_of_employees) accountPayload.employees = lead.number_of_employees;\n if (lead.website) accountPayload.website = lead.website;\n if (lead.phone) accountPayload.phone = lead.phone;\n if (lead.address) accountPayload.billing_address = lead.address;\n if (lead.owner) accountPayload.owner = lead.owner;\n account = await this.engine.insert('account', accountPayload, trxCtxOpt as any);\n }\n\n // 2) Contact\n let contact: any;\n if (request.contactId) {\n contact = await this.engine.findOne('contact', { where: { id: request.contactId }, ...(trxCtxOpt as any) } as any);\n if (!contact) {\n const err: any = new Error(`Contact '${request.contactId}' not found`);\n err.status = 404;\n err.code = 'CONTACT_NOT_FOUND';\n throw err;\n }\n } else {\n const contactPayload: Record<string, any> = {\n first_name: lead.first_name ?? '',\n last_name: lead.last_name ?? lead.company ?? 'Unknown',\n };\n if (lead.salutation) contactPayload.salutation = lead.salutation;\n if (lead.email) contactPayload.email = lead.email;\n if (lead.phone) contactPayload.phone = lead.phone;\n if (lead.mobile) contactPayload.mobile = lead.mobile;\n if (lead.title) contactPayload.title = lead.title;\n if (lead.address) contactPayload.mailing_address = lead.address;\n if (lead.owner) contactPayload.owner = lead.owner;\n if (account?.id) contactPayload.account = account.id;\n contact = await this.engine.insert('contact', contactPayload, trxCtxOpt as any);\n }\n\n // 3) Opportunity (optional)\n let opportunity: any | null = null;\n const shouldCreateOpp = request.createOpportunity !== false;\n if (shouldCreateOpp) {\n const oppOverrides = request.opportunity ?? {};\n const defaultName = oppOverrides.name\n || `${account?.name ?? lead.company ?? 'Lead'} - New Opportunity`;\n const defaultClose = oppOverrides.close_date\n || new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);\n const oppPayload: Record<string, any> = {\n name: defaultName,\n stage: oppOverrides.stage ?? 'qualification',\n close_date: defaultClose,\n };\n if (oppOverrides.amount !== undefined) oppPayload.amount = oppOverrides.amount;\n else if (lead.annual_revenue) oppPayload.amount = lead.annual_revenue;\n if (account?.id) oppPayload.account = account.id;\n if (contact?.id) oppPayload.primary_contact = contact.id;\n if (lead.owner) oppPayload.owner = lead.owner;\n if (lead.lead_source) oppPayload.lead_source = lead.lead_source;\n opportunity = await this.engine.insert('opportunity', oppPayload, trxCtxOpt as any);\n }\n\n // 4) Mark lead converted\n const leadUpdate: Record<string, any> = {\n is_converted: true,\n status: request.convertedStatus ?? 'converted',\n converted_account: account?.id ?? null,\n converted_contact: contact?.id ?? null,\n converted_opportunity: opportunity?.id ?? null,\n converted_date: new Date().toISOString(),\n };\n const updatedLead = await this.engine.update('lead', leadUpdate, {\n where: { id: leadId },\n ...(trxCtxOpt as any),\n } as any);\n\n return {\n lead: updatedLead ?? { ...lead, ...leadUpdate },\n account,\n contact,\n opportunity,\n };\n };\n\n return (this.engine as any).transaction(runConversion, ctx);\n }\n\n // ==========================================\n // Metadata Caching\n // ==========================================\n\n async getMetaItemCached(request: { type: string, name: string, cacheRequest?: MetadataCacheRequest, locale?: string }): Promise<MetadataCacheResponse> {\n try {\n // Delegate to getMetaItem so the customization-overlay read order\n // (sys_metadata → registry → MetadataService) is honoured here too\n // (ADR-0005). Without this, cached reads silently bypass overlays.\n const result = await this.getMetaItem({ type: request.type, name: request.name });\n const item = (result as any)?.item;\n\n if (!item) {\n throw new Error(`Metadata item ${request.type}/${request.name} not found`);\n }\n\n // Calculate ETag (simple hash of the stringified metadata).\n //\n // The ETag MUST vary by locale. The REST layer translates the\n // response body *after* this validator check, so an ETag computed\n // only from the (untranslated) content would let a language switch\n // match the prior `If-None-Match` and return `304 Not Modified`\n // carrying a stale-locale body — labels/headers stuck in the old\n // language until a hard refresh (issue #1319). Folding the resolved\n // locale into the hash gives each locale a distinct validator.\n const content = JSON.stringify(item);\n const hash = simpleHash(request.locale ? `${request.locale}\u0000${content}` : content);\n const etag = { value: hash, weak: false };\n\n // Check If-None-Match header\n if (request.cacheRequest?.ifNoneMatch) {\n const clientEtag = request.cacheRequest.ifNoneMatch.replace(/^\"(.*)\"$/, '$1').replace(/^W\\/\"(.*)\"$/, '$1');\n if (clientEtag === hash) {\n // Return 304 Not Modified\n return {\n notModified: true,\n etag,\n };\n }\n }\n\n // Return full metadata with cache headers\n return {\n data: item,\n etag,\n lastModified: new Date().toISOString(),\n cacheControl: {\n directives: ['public', 'max-age'],\n maxAge: 3600, // 1 hour\n },\n notModified: false,\n };\n } catch (error: any) {\n throw error;\n }\n }\n\n // ==========================================\n // Batch Operations\n // ==========================================\n\n async batchData(request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {\n const { object, request: batchReq } = request;\n const { operation, records, options } = batchReq;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n switch (operation) {\n case 'create': {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n succeeded++;\n break;\n }\n case 'update': {\n if (!record.id) throw new Error('Record id is required for update');\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n break;\n }\n case 'upsert': {\n // Try update first, then create if not found\n if (record.id) {\n try {\n const existing = await this.engine.findOne(object, { where: { id: record.id } });\n if (existing) {\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n } else {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } catch {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } else {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n }\n succeeded++;\n break;\n }\n case 'delete': {\n if (!record.id) throw new Error('Record id is required for delete');\n await this.engine.delete(object, { where: { id: record.id } });\n results.push({ id: record.id, success: true });\n succeeded++;\n break;\n }\n default:\n results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });\n failed++;\n }\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (options?.atomic) {\n // Abort remaining operations on first failure in atomic mode\n break;\n }\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation,\n total: records.length,\n succeeded,\n failed,\n results: options?.returnRecords !== false ? results : results.map(r => ({ id: r.id, success: r.success, error: r.error })),\n } as BatchUpdateResponse;\n }\n \n async createManyData(request: { object: string, records: any[] }): Promise<any> {\n const records = await this.engine.insert(request.object, request.records);\n return {\n object: request.object,\n records,\n count: records.length\n };\n }\n \n async updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse> {\n const { object, records, options } = request;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n const updated = await this.engine.update(object, record.data, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation: 'update',\n total: records.length,\n succeeded,\n failed,\n results,\n } as BatchUpdateResponse;\n }\n\n async analyticsQuery(request: any): Promise<any> {\n // Map AnalyticsQuery (cube-style) to engine aggregation.\n // cube name maps to object name; measures → aggregations; dimensions → groupBy.\n const { query, cube } = request;\n const object = cube;\n\n // Build groupBy from dimensions\n const groupBy = query.dimensions || [];\n\n // Build aggregations from measures\n // Measures can be simple field names like \"count\" or \"field_name.sum\"\n // Or cube-defined measure names. We support: field.function or just function(field).\n const aggregations: Array<{ field: string; method: string; alias: string }> = [];\n if (query.measures) {\n for (const measure of query.measures) {\n // Support formats: \"count\", \"amount.sum\", \"revenue.avg\"\n if (measure === 'count' || measure === 'count_all') {\n aggregations.push({ field: '*', method: 'count', alias: 'count' });\n } else if (measure.includes('.')) {\n const [field, method] = measure.split('.');\n aggregations.push({ field, method, alias: `${field}_${method}` });\n } else {\n // Treat as count of the field\n aggregations.push({ field: measure, method: 'sum', alias: measure });\n }\n }\n }\n\n // Build filter from analytics filters\n let filter: any = undefined;\n if (query.filters && query.filters.length > 0) {\n const conditions: any[] = query.filters.map((f: any) => {\n const op = this.mapAnalyticsOperator(f.operator);\n if (f.values && f.values.length === 1) {\n return { [f.member]: { [op]: f.values[0] } };\n } else if (f.values && f.values.length > 1) {\n return { [f.member]: { $in: f.values } };\n }\n return { [f.member]: { [op]: true } };\n });\n filter = conditions.length === 1 ? conditions[0] : { $and: conditions };\n }\n\n // Execute via engine.aggregate (which delegates to driver.find with groupBy/aggregations)\n const rows = await this.engine.aggregate(object, {\n where: filter,\n groupBy: groupBy.length > 0 ? groupBy : undefined,\n aggregations: aggregations.length > 0\n ? aggregations.map(a => ({ function: a.method as any, field: a.field, alias: a.alias }))\n : [{ function: 'count' as any, alias: 'count' }],\n });\n\n // Build field metadata\n const fields = [\n ...groupBy.map((d: string) => ({ name: d, type: 'string' })),\n ...aggregations.map(a => ({ name: a.alias, type: 'number' })),\n ];\n\n return {\n success: true,\n data: {\n rows,\n fields,\n },\n };\n }\n\n async getAnalyticsMeta(request: any): Promise<any> {\n // Auto-generate cube metadata from registered objects in SchemaRegistry.\n // Each object becomes a cube; number fields → measures; other fields → dimensions.\n const objects = this.engine.registry.listItems('object');\n const cubeFilter = request?.cube;\n\n const cubes: any[] = [];\n for (const obj of objects) {\n const schema = obj as any;\n if (cubeFilter && schema.name !== cubeFilter) continue;\n\n const measures: Record<string, any> = {};\n const dimensions: Record<string, any> = {};\n const fields = schema.fields || {};\n\n // Always add a count measure\n measures['count'] = {\n name: 'count',\n label: 'Count',\n type: 'count',\n sql: '*',\n };\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n const fd = fieldDef as any;\n const fieldType = fd.type || 'text';\n\n if (['number', 'currency', 'percent'].includes(fieldType)) {\n // Numeric fields become both measures and dimensions\n measures[`${fieldName}_sum`] = {\n name: `${fieldName}_sum`,\n label: `${fd.label || fieldName} (Sum)`,\n type: 'sum',\n sql: fieldName,\n };\n measures[`${fieldName}_avg`] = {\n name: `${fieldName}_avg`,\n label: `${fd.label || fieldName} (Avg)`,\n type: 'avg',\n sql: fieldName,\n };\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'number',\n sql: fieldName,\n };\n } else if (['date', 'datetime'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'time',\n sql: fieldName,\n granularities: ['day', 'week', 'month', 'quarter', 'year'],\n };\n } else if (['boolean'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'boolean',\n sql: fieldName,\n };\n } else {\n // text, select, lookup, etc. → dimension\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'string',\n sql: fieldName,\n };\n }\n }\n\n cubes.push({\n name: schema.name,\n title: schema.label || schema.name,\n description: schema.description,\n sql: schema.name,\n measures,\n dimensions,\n public: true,\n });\n }\n\n return {\n success: true,\n data: { cubes },\n };\n }\n\n private mapAnalyticsOperator(op: string): string {\n const map: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$contains',\n notContains: '$notContains',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n set: '$ne',\n notSet: '$eq',\n };\n return map[op] || '$eq';\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the \"automation\" service.');\n }\n\n async deleteManyData(request: DeleteManyDataRequest): Promise<any> {\n // This expects deleting by IDs.\n return this.engine.delete(request.object, {\n where: { id: { $in: request.ids } },\n ...request.options\n });\n }\n\n /**\n * Metadata types that are customer-overridable via {@link saveMetaItem}/\n * {@link deleteMetaItem} in project-kernel mode. Derived from the canonical\n * registry in {@link DEFAULT_METADATA_TYPE_REGISTRY}: a type opts in by\n * setting `allowOrgOverride: true` on its registry entry. The set is\n * augmented with the plural form of every singular so callers using REST\n * conventions (`/api/v1/meta/views/...`) get the same gate. See ADR-0005\n * §\"Whitelist enforcement\" for the rationale and the per-type rollout\n * checklist.\n */\n private static readonly OVERLAY_ALLOWED_TYPES: ReadonlySet<string> = (() => {\n const out = new Set<string>();\n for (const entry of DEFAULT_METADATA_TYPE_REGISTRY) {\n if (!entry.allowOrgOverride) continue;\n out.add(entry.type);\n const plural = SINGULAR_TO_PLURAL[entry.type];\n if (plural) out.add(plural);\n }\n return out;\n })();\n\n /**\n * Phase 3a-env-writable: parse `OS_METADATA_WRITABLE` once.\n * Comma-separated singular type names. When the env var is set, the\n * listed types get treated as `allowOrgOverride: true` regardless of\n * their static registry entry. This is the runtime escape hatch admins\n * use to enable Studio-side editing of types whose protocol-level flag\n * is still false (object, field, permission, …).\n *\n * Memoised at first call. Tests can override by clearing the cache via\n * {@link ObjectStackProtocolImplementation.resetEnvWritableCache}.\n */\n private static _envWritableTypes: Set<string> | null = null;\n private static envWritableTypes(): ReadonlySet<string> {\n if (this._envWritableTypes !== null) return this._envWritableTypes;\n const raw = readEnvWithDeprecation('OS_METADATA_WRITABLE', 'OBJECTSTACK_METADATA_WRITABLE') || '';\n const set = new Set<string>();\n for (const tok of raw.split(',')) {\n const t = tok.trim();\n if (!t) continue;\n const singular = PLURAL_TO_SINGULAR[t] ?? t;\n set.add(singular);\n const plural = SINGULAR_TO_PLURAL[singular];\n if (plural) set.add(plural);\n }\n this._envWritableTypes = set;\n return set;\n }\n\n /** Test hook — clear the memoised env-writable cache. */\n static resetEnvWritableCache(): void {\n this._envWritableTypes = null;\n }\n\n /**\n * Types that opt into runtime creation of brand-new items (ADR-0005\n * extension — two-tier model). A type may have\n * `allowOrgOverride: false` (cannot overlay artifact-shipped items)\n * yet still set `allowRuntimeCreate: true` (users can author new\n * items in `sys_metadata`). The two flags are orthogonal; see\n * {@link isArtifactBacked} for how the protocol decides which gate\n * applies to a given save/delete.\n */\n /**\n * Set of type names that have a static entry in\n * `DEFAULT_METADATA_TYPE_REGISTRY`. Anything outside this set is\n * runtime-registered (plugin-provided types like `theme`, `api`,\n * `connector`) — the listing endpoint at `getMetaTypes()` synthesises\n * those with `allowRuntimeCreate: true`, so this gate must agree.\n */\n private static readonly STATIC_REGISTRY_TYPES: ReadonlySet<string> = (() => {\n const out = new Set<string>();\n for (const entry of DEFAULT_METADATA_TYPE_REGISTRY) {\n out.add(entry.type);\n const plural = SINGULAR_TO_PLURAL[entry.type];\n if (plural) out.add(plural);\n }\n return out;\n })();\n\n private static readonly RUNTIME_CREATE_ALLOWED_TYPES: ReadonlySet<string> = (() => {\n const out = new Set<string>();\n for (const entry of DEFAULT_METADATA_TYPE_REGISTRY) {\n if (!entry.allowRuntimeCreate) continue;\n out.add(entry.type);\n const plural = SINGULAR_TO_PLURAL[entry.type];\n if (plural) out.add(plural);\n }\n return out;\n })();\n\n /** Normalize plural→singular before consulting the allow-list. */\n private static isOverlayAllowed(type: string): boolean {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (this.OVERLAY_ALLOWED_TYPES.has(singular)\n || this.OVERLAY_ALLOWED_TYPES.has(type)) {\n return true;\n }\n const env = this.envWritableTypes();\n return env.has(singular) || env.has(type);\n }\n\n /** Does this type permit creating brand-new (artifact-free) items? */\n private static isRuntimeCreateAllowed(type: string): boolean {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (this.RUNTIME_CREATE_ALLOWED_TYPES.has(singular)\n || this.RUNTIME_CREATE_ALLOWED_TYPES.has(type)) {\n return true;\n }\n // Runtime-registered types (no static registry entry) are\n // synthesised by getMetaTypes() with allowRuntimeCreate=true;\n // mirror that here so /api/v1/meta and PUT /api/v1/meta agree.\n if (!this.STATIC_REGISTRY_TYPES.has(singular)\n && !this.STATIC_REGISTRY_TYPES.has(type)) {\n return true;\n }\n return false;\n }\n\n /**\n * Does an artifact (npm-package-loaded) item exist at `(type, name)`?\n *\n * The schema registry's `_packageId` tag is set only when\n * `registerItem(..., packageId)` is called with a truthy packageId\n * — and only artifact loaders do that. DB-rehydrated items\n * (sys_metadata rows registered back into the registry by\n * `getMetaItems` / `loadMetaFromDb`) call `registerItem` without a\n * packageId, so they carry no `_packageId` and are correctly\n * excluded here.\n *\n * Used by the two-tier authorization model to distinguish\n * \"overlaying a packaged item\" (requires `allowOrgOverride`) from\n * \"authoring a DB-only item\" (requires only `allowRuntimeCreate`).\n */\n private isArtifactBacked(type: string, name: string): boolean {\n // `lookupArtifactItem` only returns items whose `_packageId` marks a\n // genuine code package (the `'sys_metadata'` rehydration sentinel is\n // excluded), and — via `SchemaRegistry.getArtifactItem` — is immune\n // to plain-key shadows hydrated from overlay rows.\n return this.lookupArtifactItem(type, name) !== undefined;\n }\n\n // ───────────────────────────────────────────────────────────────────\n // ADR-0010 — metadata protection (Phase 1: L3 item-level lock)\n // ───────────────────────────────────────────────────────────────────\n\n /**\n * Look up an item from the artifact registry across both the requested\n * type and its singular/plural twin. Returns `undefined` when the\n * registry is unavailable or the item is not artifact-backed.\n */\n private lookupArtifactItem(type: string, name: string): unknown {\n const registry = (this.engine as any)?.registry;\n if (!registry) return undefined;\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n // Prefer the artifact-only lookup: it scans composite\n // (`<packageId>:<name>`) entries first, so an overlay row hydrated\n // into the plain key (getMetaItems / loadMetaFromDb) can never\n // shadow the packaged artifact's protection envelope (ADR-0010\n // §3.3 — pre-fix, that shadow made a `_lock: full` app read back\n // as unlocked after PUT+GET until restart).\n if (typeof registry.getArtifactItem === 'function') {\n return registry.getArtifactItem(singular, name)\n ?? registry.getArtifactItem(type, name);\n }\n // Partial registry mocks in tests — fall back to getItem and apply\n // the same package-provenance filter inline.\n if (typeof registry.getItem !== 'function') return undefined;\n const item = registry.getItem(singular, name) ?? registry.getItem(type, name);\n if (!item || !(item as any)._packageId || (item as any)._packageId === 'sys_metadata') {\n return undefined;\n }\n return item;\n }\n\n /**\n * Resolve the effective `_lock` for an item by consulting the\n * artifact registry first, then the persisted overlay row. Artifact\n * always wins — by design, an overlay cannot loosen a packaged\n * lock (ADR-0010 §3.3).\n *\n * Returns `'none'` when nothing is locked, which is the common\n * case. Safe to call when `environmentId` is undefined (control-\n * plane bootstrap) — the lock check is only meaningful in tenant\n * scope and the caller is expected to also gate on `environmentId`.\n */\n private async getEffectiveLock(\n type: string,\n name: string,\n organizationId: string | null | undefined,\n ): Promise<{\n lock: MetadataLock;\n lockReason: string | undefined;\n lockSource: 'artifact' | 'overlay' | undefined;\n }> {\n // 1. Artifact wins. `lookupArtifactItem` is shadow-immune: a\n // sys_metadata overlay row hydrated into the registry's plain\n // key cannot mask the packaged artifact's `_lock` envelope.\n const artifactItem = this.lookupArtifactItem(type, name) as any;\n if (artifactItem) {\n const p = extractProtection(artifactItem);\n if (p.lock !== 'none') {\n return { lock: p.lock, lockReason: p.lockReason, lockSource: 'artifact' };\n }\n }\n // 2. Overlay row.\n try {\n const where: Record<string, unknown> = {\n type,\n name,\n state: 'active',\n organization_id: organizationId ?? null,\n };\n const row = await this.engine.findOne('sys_metadata', { where });\n if (row) {\n const body = typeof row.metadata === 'string' ? JSON.parse(row.metadata) : row.metadata;\n const p = extractProtection(body);\n if (p.lock !== 'none') {\n return { lock: p.lock, lockReason: p.lockReason, lockSource: 'overlay' };\n }\n }\n } catch {\n // DB unavailable — fall through to 'none'.\n }\n return { lock: 'none', lockReason: undefined, lockSource: undefined };\n }\n\n /**\n * Best-effort audit-row writer (ADR-0010 §3.6). Failures here are\n * logged but never block the underlying decision: an environment\n * without the audit table provisioned (legacy installs before this\n * ADR landed) still answers normal API calls, just without the\n * compliance trail. Phase 2 will make the audit table a hard\n * dependency.\n */\n private async recordMetadataAudit(entry: {\n type: string;\n name: string;\n organizationId?: string | null;\n operation: 'save' | 'publish' | 'rollback' | 'delete' | 'reset';\n outcome: 'allowed' | 'denied' | 'forced';\n code: string;\n lockState?: MetadataLock;\n lockOverridden?: boolean;\n actor?: string;\n source?: string;\n requestId?: string;\n note?: string;\n }): Promise<void> {\n try {\n await this.engine.insert('sys_metadata_audit', {\n occurred_at: new Date().toISOString(),\n actor: entry.actor ?? 'system',\n source: entry.source ?? 'protocol',\n type: PLURAL_TO_SINGULAR[entry.type] ?? entry.type,\n name: entry.name,\n organization_id: entry.organizationId ?? null,\n operation: entry.operation,\n outcome: entry.outcome,\n code: entry.code,\n lock_state: entry.lockState ?? 'none',\n lock_overridden: entry.lockOverridden ?? false,\n request_id: entry.requestId ?? null,\n note: entry.note ?? null,\n } as any);\n } catch (err: any) {\n // Don't promote audit-table failures to API errors. Log so\n // operators can spot a misconfigured deployment.\n console.warn(\n `[Protocol] sys_metadata_audit write failed for ${entry.type}/${entry.name}: ${err?.message ?? err}`,\n );\n }\n }\n\n /**\n * Phase 1 L3 enforcement for write operations (save / publish /\n * rollback). Returns null on allow. Returns the structured `Error`\n * the caller should `throw` on deny — also records the denial in\n * the audit log so refused attempts are visible in compliance\n * reports (refused writes never reach sys_metadata_history).\n */\n private async assertLockAllowsWrite(args: {\n type: string;\n name: string;\n organizationId?: string;\n operation: 'save' | 'publish' | 'rollback';\n actor?: string;\n source?: string;\n requestId?: string;\n }): Promise<Error | null> {\n if (this.environmentId === undefined) return null;\n const state = await this.getEffectiveLock(args.type, args.name, args.organizationId ?? null);\n const refusal = evaluateLockForWrite(state.lock);\n if (!refusal) return null;\n const reason = state.lockReason ?? refusal.reason;\n const err = new Error(\n `[item_locked] ${args.type}/${args.name} is locked (_lock=${state.lock}${state.lockSource ? `, source=${state.lockSource}` : ''}). `\n + `${reason} — See ADR-0010 §3.3.`,\n );\n (err as any).code = 'item_locked';\n (err as any).status = 403;\n (err as any).lock = state.lock;\n (err as any).lockReason = reason;\n await this.recordMetadataAudit({\n type: args.type,\n name: args.name,\n organizationId: args.organizationId ?? null,\n operation: args.operation,\n outcome: 'denied',\n code: 'item_locked',\n lockState: state.lock,\n actor: args.actor,\n source: args.source ?? `protocol.${args.operation}MetaItem`,\n requestId: args.requestId,\n note: reason,\n });\n return err;\n }\n\n /** Counterpart of {@link assertLockAllowsWrite} for delete. */\n private async assertLockAllowsDelete(args: {\n type: string;\n name: string;\n organizationId?: string;\n actor?: string;\n source?: string;\n requestId?: string;\n }): Promise<Error | null> {\n if (this.environmentId === undefined) return null;\n const state = await this.getEffectiveLock(args.type, args.name, args.organizationId ?? null);\n const refusal = evaluateLockForDelete(state.lock);\n if (!refusal) return null;\n const reason = state.lockReason ?? refusal.reason;\n const err = new Error(\n `[item_locked] ${args.type}/${args.name} is locked (_lock=${state.lock}${state.lockSource ? `, source=${state.lockSource}` : ''}). `\n + `${reason} — See ADR-0010 §3.3.`,\n );\n (err as any).code = 'item_locked';\n (err as any).status = 403;\n (err as any).lock = state.lock;\n (err as any).lockReason = reason;\n await this.recordMetadataAudit({\n type: args.type,\n name: args.name,\n organizationId: args.organizationId ?? null,\n operation: 'delete',\n outcome: 'denied',\n code: 'item_locked',\n lockState: state.lock,\n actor: args.actor,\n source: args.source ?? 'protocol.deleteMetaItem',\n requestId: args.requestId,\n note: reason,\n });\n return err;\n }\n\n /**\n * Mirror an object-type overlay write into the in-memory engine\n * registry so subsequent CRUD finds the new schema. Idempotent and\n * safe to call after a successful persistence call. For the legacy\n * write path this is invoked BEFORE persistence (historical behavior\n * preserved); for the PR-10d.3 repository path it is invoked only\n * AFTER `put()` resolves successfully, so a failed write — DB error,\n * optimistic-lock conflict, validation failure — never leaks a\n * stale schema into the registry.\n */\n private applyObjectRegistryMutation(request: { type: string; name: string; item?: any }): void {\n if (request.type !== 'object' && request.type !== 'objects') return;\n this.engine.registry.registerItem(request.type, request.item, 'name');\n try {\n this.engine.registry.registerObject(request.item as any, 'sys_metadata');\n } catch (err: any) {\n console.warn(\n `[Protocol] registerObject failed for ${request.name}: ${err?.message ?? err}`,\n );\n }\n }\n\n /**\n * Heal the in-memory registry after a metadata reset (overlay-row\n * delete) on control-plane kernels. Two layers:\n *\n * 1. Drop the plain-key runtime shadow so the packaged artifact\n * (registered under `<packageId>:<name>`) becomes the visible\n * value again. The shadow is written by the overlay-hydration\n * paths (`getMetaItems` / `loadMetaFromDb`) and — pre-fix —\n * survived the reset until restart, leaving stale overlay\n * content (and a stripped `_lock` envelope) in every\n * registry-direct read (ADR-0010 §3.3).\n * 2. When no composite-key artifact exists, fall back to the\n * MetadataService baseline (FilesystemLoader-sourced types) and\n * re-register it, preserving the historical refresh behaviour\n * for items the SchemaRegistry never held as artifacts.\n *\n * Best-effort: a failure must never block the delete that already\n * succeeded; the next full reload fixes the registry anyway.\n */\n private async restoreArtifactRegistryView(type: string, name: string): Promise<void> {\n try {\n const registry: any = this.engine.registry;\n let healed = false;\n if (typeof registry.removeRuntimeShadow === 'function') {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n healed = registry.removeRuntimeShadow(singular, name);\n if (type !== singular) {\n healed = registry.removeRuntimeShadow(type, name) || healed;\n }\n }\n if (healed) return;\n // MetadataService re-registration is control-plane-only — it\n // preserves the historical refresh semantics gated on\n // `environmentId === undefined` at the original call sites.\n if (this.environmentId !== undefined) return;\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n const artifactItem = await metadataService.get(type, name);\n if (artifactItem !== undefined) {\n this.engine.registry.registerItem(type, artifactItem, 'name');\n }\n }\n } catch {\n // Best-effort registry refresh; next read fixes it anyway\n }\n }\n\n /**\n * Ensure a just-PUBLISHED object's physical table exists so it is usable\n * for data CRUD immediately — without a server restart. Registering the\n * object (above) only updates the in-memory registry; the table is created\n * by the driver's schema sync, which otherwise only runs at boot. Without\n * this, inserting into a freshly-published object fails with \"no such\n * table\" (surfaced as `object_not_found`) until the next restart.\n * Best-effort + non-fatal: drivers without DDL (or read-only datasources)\n * simply no-op, and a sync failure must not abort the publish.\n */\n private async ensureObjectStorage(type: string, name: string): Promise<void> {\n if (type !== 'object' && type !== 'objects') return;\n try {\n await this.engine.syncObjectSchema(name);\n } catch (err: any) {\n console.warn(`[Protocol] table sync failed for object '${name}': ${err?.message ?? err}`);\n }\n }\n\n /**\n * Inverse of {@link ensureObjectStorage}: drop an object's physical table.\n * DESTRUCTIVE — deletes the table and all its rows. Only invoked when a\n * delete explicitly opts into storage teardown (see {@link deleteMetaItem}'s\n * `dropStorage`), so publishing an object solely to preview it can be undone\n * without leaving an orphan table. Best-effort: a failure is logged, not\n * thrown — the metadata delete already succeeded, and a stray table is\n * reclaimed by the next sync/drop rather than blocking the delete.\n */\n private async dropObjectStorage(type: string, name: string): Promise<void> {\n if (type !== 'object' && type !== 'objects') return;\n try {\n await this.engine.dropObjectSchema(name);\n } catch (err: any) {\n console.warn(`[Protocol] table drop failed for object '${name}': ${err?.message ?? err}`);\n }\n }\n\n /**\n * Guard for storage teardown on delete. Drops a physical table only when\n * the caller opted in AND it is safe: object types only (others have no\n * table), active state only (drafts were never materialised), and never a\n * `sys_`-prefixed platform table.\n */\n private shouldDropStorage(type: string, name: string, dropStorage: boolean | undefined, state: 'active' | 'draft'): boolean {\n if (!dropStorage) return false;\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n if (singular !== 'object') return false;\n if (state !== 'active') return false;\n if (name.startsWith('sys_')) return false;\n return true;\n }\n\n async saveMetaItem(request: { type: string, name: string, item?: any, organizationId?: string, parentVersion?: string | null, actor?: string, force?: boolean, mode?: 'draft' | 'publish', packageId?: string | null }) {\n if (!request.item) {\n throw new Error('Item data is required');\n }\n // Per-item lifecycle (ADR-0005 §\"Drafts\"). Default is `'publish'`\n // (legacy semantics — save goes straight live) to keep callers\n // that predate the draft/publish split working. Studio's\n // designer surface opts into staged drafts by sending\n // `?mode=draft`; the `POST /publish` endpoint then promotes it.\n const mode: 'draft' | 'publish' = request.mode === 'draft' ? 'draft' : 'publish';\n\n // ADR-0005 (extended — two-tier model): project-kernel customization is\n // gated by per-item provenance, not just the type-level flag.\n //\n // • Item exists as a packaged artifact → require `allowOrgOverride`\n // (writing here would overlay code-shipped behaviour; gated for\n // security on executable types like hook/trigger/validation).\n // • Item does NOT exist as an artifact → require `allowRuntimeCreate`\n // OR `allowOrgOverride`. This lets users author brand-new hooks /\n // validations / triggers without unlocking the artifact-shadowing\n // capability. Returns `not_creatable` (vs `not_overridable`) so\n // the UI can present a tailored message.\n if (this.environmentId !== undefined) {\n const overlayAllowed = ObjectStackProtocolImplementation.isOverlayAllowed(request.type);\n const runtimeCreateAllowed = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(request.type);\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n if (artifactBacked && !overlayAllowed) {\n const err = new Error(\n `[not_overridable] Metadata item '${request.type}/${request.name}' is provided by a code package `\n + `and the type has not opted into per-org overlay writes (allowOrgOverride=false). `\n + `Edit the source artifact and redeploy, or set OS_METADATA_WRITABLE to grant a runtime escape hatch. `\n + `See docs/adr/0005-metadata-customization-overlay.md.`\n );\n (err as any).code = 'not_overridable';\n (err as any).status = 403;\n throw err;\n }\n if (!artifactBacked && !overlayAllowed && !runtimeCreateAllowed) {\n const err = new Error(\n `[not_creatable] Metadata type '${request.type}' does not allow runtime creation `\n + `(allowRuntimeCreate=false, allowOrgOverride=false). New items of this type must be defined in source code.`\n );\n (err as any).code = 'not_creatable';\n (err as any).status = 403;\n throw err;\n }\n\n // ADR-0010 L3 — per-item lock. Artifact `_lock` (or persisted\n // overlay `_lock`) blocks save independent of the L1 type-level\n // flag. Records the denial in `sys_metadata_audit` before\n // throwing so refused attempts are visible in compliance reports.\n const lockErr = await this.assertLockAllowsWrite({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n operation: 'save',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.saveMetaItem',\n });\n if (lockErr) throw lockErr;\n }\n\n // Phase 3a-destructive: for object/field writes, diff against the\n // current schema and 409 if the change would drop data — unless the\n // caller has acknowledged the risk with `force: true`. The admin UI\n // surfaces the structured `issues` payload in a confirmation dialog.\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!request.force && (singularType === 'object' || singularType === 'field')) {\n try {\n const existing = await this.getMetaItem({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n } as any);\n const prev = (existing as any)?.item;\n if (prev) {\n const issues = detectDestructiveObjectChanges(prev, request.item);\n if (issues.length > 0) {\n const summary = issues.slice(0, 3).map((i) => i.message).join('; ');\n const err = new Error(\n `[destructive_change] ${request.type}/${request.name} would drop or transform existing data: ${summary}`\n + (issues.length > 3 ? ` (+${issues.length - 3} more)` : '')\n + ` — re-submit with ?force=true to proceed.`\n );\n (err as any).code = 'destructive_change';\n (err as any).status = 409;\n (err as any).issues = issues;\n throw err;\n }\n }\n } catch (err: any) {\n if (err?.code === 'destructive_change') throw err;\n // Other errors during the diff lookup are non-fatal —\n // they just skip the safety check.\n }\n }\n\n // Defense-in-depth: reject the layered *read* envelope as a write body.\n //\n // `getMetaItemLayered` returns a 3-state diagnostic shape\n // `{ type, name, code, overlay, overlayScope, effective, ... }` for the\n // Studio designer's `?layers=true` GET. That envelope is NOT a metadata\n // body — but a designer surface that lacks a dedicated editor for a\n // given type can accidentally PUT the envelope straight back, which (if\n // the per-type Zod schema below is unavailable — e.g. a type with no\n // registered schema, or a stale `@objectstack/spec` build that predates\n // the type being added to the registry) would persist an all-null stub\n // and surface as a metadata diagnostic error in the admin UI. The\n // simultaneous presence of `code`, `overlay`, `overlayScope`, and\n // `effective` is unique to the layered envelope and never appears in a\n // real metadata body, so we reject it here regardless of type/schema.\n {\n const it = request.item as Record<string, unknown>;\n const looksLikeLayeredEnvelope =\n it && typeof it === 'object' && !Array.isArray(it)\n && 'code' in it && 'overlay' in it && 'overlayScope' in it && 'effective' in it;\n if (looksLikeLayeredEnvelope) {\n const err = new Error(\n `[invalid_metadata] ${request.type}/${request.name}: the request body is a layered read `\n + `envelope ({ code, overlay, overlayScope, effective }), not a metadata body. `\n + `Unwrap and send the effective/overlay document instead — the layered shape is read-only `\n + `(GET ?layers=true) and must never be persisted.`\n );\n (err as any).code = 'invalid_metadata';\n (err as any).status = 422;\n throw err;\n }\n }\n\n // Normalize loose `view` bodies to the canonical record shape BEFORE\n // validation + persistence, so no producer (AI tools, hand-authoring,\n // Studio) can persist a view that validates but the console can't bind\n // or render (missing top-level name/object/viewKind). See\n // {@link normalizeViewMetadata}.\n request.item = normalizeViewMetadata(request.type, request.item, request.name);\n\n // Spec-conformance check: if a Zod schema is registered for this\n // overlay type (see OVERLAY_VALIDATION_SCHEMAS), validate the payload\n // before persisting. We surface invalid payloads as `422\n // invalid_metadata` with structured Zod issues so the Studio form can\n // highlight the offending field. The original `item` is kept verbatim\n // — `parsed.data` would strip Studio-only auxiliary fields (e.g.\n // isPinned, isDefault, sortOrder) that intentionally ride along with\n // the overlay document. ADR-0005 §\"Validation\".\n {\n const schema = resolveOverlaySchema(request.type, request.item);\n if (schema) {\n const parsed = schema.safeParse(request.item);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i: z.ZodIssue) => ({\n path: i.path.join('.'),\n message: i.message,\n code: i.code,\n }));\n const summary = issues.slice(0, 3)\n .map((i: { path: string; message: string }) => `${i.path || '<root>'}: ${i.message}`)\n .join('; ');\n const err = new Error(\n `[invalid_metadata] ${request.type}/${request.name} failed spec validation: ${summary}`\n + (issues.length > 3 ? ` (+${issues.length - 3} more)` : '')\n );\n (err as any).code = 'invalid_metadata';\n (err as any).status = 422;\n (err as any).issues = issues;\n throw err;\n }\n }\n }\n\n // 1. Update the in-memory registry (runtime cache) ONLY for the\n // `object` type — schema definitions feed engine.syncSchema and\n // must be reflected immediately for CRUD to work. For all other\n // metadata types (view, dashboard, ...) we deliberately do NOT\n // mutate the artifact-loaded registry — sys_metadata is the\n // authoritative overlay store and `getMetaItem` consults it\n // first (ADR-0005). Mutating the registry here would create a\n // \"stale overlay\" hazard: `deleteMetaItem` cannot restore the\n // original artifact value because it was overwritten in-place.\n // 1. (deferred) — Object-type runtime-registry mutation used to happen\n // here unconditionally. Moved to AFTER successful persistence\n // (PR-10d.3 rubber-duck #3): a failed put() — DB error, optimistic\n // conflict, validation — must not leave a stale object schema in\n // the in-memory registry. See `applyObjectRegistryMutation` below.\n\n // 2. Persist to sys_metadata as a customization overlay row.\n // ADR-0005 (revised 2026-05): isolation key is `organization_id`\n // (each env = its own DB, so environment_id is redundant). Org-scoped\n // rows belong to the active organization in the request; env-wide\n // overlays are written with organization_id = NULL.\n await this.ensureOverlayIndex();\n\n // ADR-0008 — overlay-allowed metadata types ALWAYS route through the\n // repository write path: every mutation appends to the change log\n // and emits a watch event with a monotonic `seq` (which Studio /\n // browser clients consume for HMR). Non-overlay-allowed types\n // (`object`, `flow`, `agent`, ...) take the legacy raw-engine path\n // below — this preserves the control-plane bootstrap semantic where\n // `saveMetaItem` is permitted by the outer protocol gate to write\n // any metadata type when `environmentId` is undefined (the repository's\n // `assertAllowed()` would 403 those writes).\n //\n // PR-10d.6 (this PR) removed the `useRepositoryWritePath` flag.\n // For overlay-allowed types the repo path is no longer opt-out-able.\n //\n // Callers that omit `parentVersion` get backward-compatible\n // \"last-write-wins\" semantics: we read the current row's checksum\n // and use it as the parent, so the conflict check tautologically\n // passes (best-effort — racy under concurrent writes; explicit\n // optimistic-lock is opt-in via `parentVersion`).\n // Callers that pass an explicit `parentVersion` (e.g. Studio after\n // reading an item) get true optimistic-lock conflict detection\n // surfaced as a 409.\n const singularTypeForRepo = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const overlayAllowedForRepo = ObjectStackProtocolImplementation.isOverlayAllowed(singularTypeForRepo);\n const runtimeCreateAllowedForRepo = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularTypeForRepo);\n const useRepoPath = overlayAllowedForRepo || runtimeCreateAllowedForRepo;\n if (useRepoPath) {\n const artifactBacked = this.isArtifactBacked(singularTypeForRepo, request.name);\n const intent: 'override-artifact' | 'runtime-only' = artifactBacked\n ? 'override-artifact'\n : 'runtime-only';\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const ref = {\n type: singularTypeForRepo,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.put>[0];\n let parentVersion: string | null;\n if (request.parentVersion !== undefined) {\n parentVersion = request.parentVersion;\n } else {\n // Parent is scoped to the lifecycle we're about to write:\n // a draft's parent is the current draft hash (or null\n // for the first draft); a publish's parent is the\n // current published hash.\n const current = await repo.get(ref, { state: mode === 'draft' ? 'draft' : 'active' });\n parentVersion = current?.hash ?? null;\n }\n try {\n const result = await repo.put(ref, request.item, {\n parentVersion,\n actor: request.actor ?? 'system',\n source: 'protocol.saveMetaItem',\n intent,\n state: mode === 'draft' ? 'draft' : 'active',\n ...(request.packageId !== undefined ? { packageId: request.packageId } : {}),\n });\n // Persistence succeeded — NOW it's safe to mutate the\n // in-memory object registry. If put() had thrown, the\n // registry would still reflect the prior state. Drafts\n // are NOT live: don't propagate them into the runtime\n // object registry (would defeat the staging buffer).\n if (mode === 'publish') {\n this.applyObjectRegistryMutation(request);\n await this.ensureObjectStorage(request.type, request.name);\n }\n // ADR-0010 — success audit (best-effort).\n await this.recordMetadataAudit({\n type: request.type,\n name: request.name,\n organizationId: orgId,\n operation: 'save',\n outcome: 'allowed',\n code: 'ok',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.saveMetaItem',\n note: mode === 'draft' ? 'draft' : 'active',\n });\n return {\n success: true,\n version: result.version,\n seq: result.seq,\n state: mode === 'draft' ? 'draft' : 'active',\n message: orgId\n ? `Saved customization overlay (org=${orgId}, state=${mode === 'draft' ? 'draft' : 'active'}) — type=${request.type}, name=${request.name} [seq=${result.seq}]`\n : `Saved customization overlay (env-wide, state=${mode === 'draft' ? 'draft' : 'active'}) — type=${request.type}, name=${request.name} [seq=${result.seq}]`,\n };\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict = new Error(\n `[metadata_conflict] ${request.type}/${request.name} has been modified since you loaded it. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n (conflict as any).code = 'metadata_conflict';\n (conflict as any).status = 409;\n (conflict as any).expectedParent = err.expectedParent;\n (conflict as any).actualHead = err.actualHead;\n throw conflict;\n }\n throw err;\n }\n }\n\n // Legacy raw-engine path — taken when the type is NOT overlay-allowed\n // (control-plane bootstrap of `object`/`flow`/etc. when `environmentId` is\n // undefined). This branch is intentionally retained: the repository\n // write path's `assertAllowed()` would 403 these types. There is no\n // change-log / HMR machinery for non-overlay metadata because\n // control-plane mutations are bootstrap-only and not subject to\n // per-org overlay semantics.\n //\n // Note: the registry mutation for the legacy path happens BEFORE\n // persistence (preserved historical behaviour). The overlay-allowed\n // path moved it to AFTER persistence in PR-10d.3 (rubber-duck #3).\n this.applyObjectRegistryMutation(request);\n\n try {\n const now = new Date().toISOString();\n const orgId = request.organizationId ?? null;\n const scopedWhere: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n organization_id: orgId,\n state: 'active',\n };\n const existing = await this.engine.findOne('sys_metadata', {\n where: scopedWhere,\n });\n\n if (existing) {\n const updateRow: Record<string, unknown> = {\n metadata: JSON.stringify(request.item),\n updated_at: now,\n version: (existing.version || 0) + 1,\n state: 'active',\n };\n // Preserve an existing non-null package binding; only fill when\n // unset (mirror of SysMetadataRepository.put semantics).\n const existingPkg = (existing as { package_id?: string | null }).package_id ?? null;\n const nextPkg = existingPkg ?? request.packageId ?? null;\n if (nextPkg !== null) updateRow.package_id = nextPkg;\n await this.engine.update('sys_metadata', updateRow, {\n where: { id: existing.id }\n });\n } else {\n // Use crypto.randomUUID() when available (modern browsers and Node ≥ 14.17);\n // fall back to a time+random ID for older or restricted environments.\n const id = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : `meta_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n const row: Record<string, unknown> = {\n id,\n name: request.name,\n type: request.type,\n // `scope` enum is ['system','platform','user']; per-org\n // overlays use 'platform' as the informational tag. The\n // authoritative isolation key is `organization_id`.\n scope: 'platform',\n metadata: JSON.stringify(request.item),\n state: 'active',\n version: 1,\n created_at: now,\n updated_at: now,\n organization_id: orgId,\n };\n if (request.packageId) row.package_id = request.packageId;\n await this.engine.insert('sys_metadata', row);\n }\n\n return {\n success: true,\n message: orgId\n ? `Saved customization overlay (org=${orgId}) — type=${request.type}, name=${request.name}`\n : `Saved customization overlay (env-wide) — type=${request.type}, name=${request.name}`,\n };\n } catch (dbError: any) {\n // DB write failed — surface as an error rather than silently\n // succeeding (regression from the pre-ADR-0005 \"silent loss\" bug).\n console.error(\n `[Protocol] sys_metadata persistence failed for ${request.type}/${request.name}: ${dbError.message}`,\n );\n const err = new Error(\n `Failed to persist customization overlay to sys_metadata: ${dbError.message}. `\n + `In-memory registry was updated but will be lost on restart.`,\n );\n (err as any).code = 'overlay_persistence_failed';\n (err as any).status = 500;\n throw err;\n }\n }\n\n /**\n * Yield the durable change-log for a single metadata item — every\n * put/delete recorded in `sys_metadata_history` for `(org, type, name)`,\n * in event_seq order. Powers the Studio \"History\" tab and any\n * client-side audit timeline.\n *\n * Returns `[]` for non-overlay-allowed types (the legacy raw-engine\n * path doesn't record history) instead of throwing — callers can treat\n * \"no history\" uniformly.\n */\n async historyMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string;\n sinceSeq?: number;\n limit?: number;\n }): Promise<{ events: import('@objectstack/metadata-core').MetadataEvent[] }> {\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!ObjectStackProtocolImplementation.isOverlayAllowed(singularType)\n && !ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularType)) {\n return { events: [] };\n }\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const ref = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.history>[0];\n\n const events: import('@objectstack/metadata-core').MetadataEvent[] = [];\n const opts: { sinceSeq?: number; limit?: number } = {};\n if (request.sinceSeq !== undefined) opts.sinceSeq = request.sinceSeq;\n if (request.limit !== undefined) opts.limit = request.limit;\n for await (const ev of repo.history(ref, opts)) events.push(ev);\n return { events };\n }\n\n /**\n * Promote the pending draft overlay to the live (`active`) row.\n * Records a history event with `op='publish'`. 404 (`[no_draft]`)\n * when there is nothing to publish.\n */\n async publishMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string;\n actor?: string;\n message?: string;\n /**\n * INTERNAL — `publishPackageDrafts` publishes many drafts and batch-applies\n * every seed body in ONE loader pass afterwards (cross-seed references need\n * multi-pass over the whole set), so it suppresses the per-item apply here.\n */\n _skipSeedApply?: boolean;\n }): Promise<{\n success: boolean;\n version: string;\n seq: number;\n message?: string;\n /**\n * Present when a `seed` draft was published: the result of materializing\n * its rows. Publishing the metadata ALWAYS succeeds independently — a\n * seed-load problem is surfaced here, never thrown, so callers (and UIs)\n * must check `seedApplied.success` instead of assuming data went live.\n */\n seedApplied?: {\n success: boolean;\n inserted: number;\n updated: number;\n error?: string;\n errors?: unknown[];\n };\n }> {\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!ObjectStackProtocolImplementation.isOverlayAllowed(singularType)\n && !ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularType)) {\n const err: any = new Error(\n `[not_overridable] Metadata type '${request.type}' is not draftable — no overlay/runtime-create permission.`,\n );\n err.code = 'not_overridable';\n err.status = 403;\n throw err;\n }\n // ADR-0010 L3 — lock blocks publish too (publishing is a write).\n const _publishLockErr = await this.assertLockAllowsWrite({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n operation: 'publish',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.publishMetaItem',\n });\n if (_publishLockErr) throw _publishLockErr;\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const artifactBacked = this.isArtifactBacked(singularType, request.name);\n const intent: 'override-artifact' | 'runtime-only' = artifactBacked\n ? 'override-artifact' : 'runtime-only';\n const ref = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.promoteDraft>[0];\n try {\n const result = await repo.promoteDraft(ref, {\n actor: request.actor ?? 'system',\n source: 'protocol.publishMetaItem',\n ...(request.message ? { message: request.message } : {}),\n intent,\n });\n // Drafts skipped the registry mutation; on publish we now\n // refresh the runtime object registry so live behaviour\n // catches up immediately (matches saveMetaItem's\n // post-persistence registry update path).\n this.applyObjectRegistryMutation({\n type: request.type,\n name: request.name,\n item: result.item.body,\n });\n // Create the object's table now so it's CRUD-able without a restart.\n await this.ensureObjectStorage(request.type, request.name);\n const response: {\n success: boolean;\n version: string;\n seq: number;\n message?: string;\n seedApplied?: { success: boolean; inserted: number; updated: number; error?: string; errors?: unknown[] };\n } = {\n success: true,\n version: result.version,\n seq: result.seq,\n message: `Published draft — type=${request.type}, name=${request.name} [seq=${result.seq}]`,\n };\n // Publishing a `seed` is what makes its rows live — materialize them\n // NOW (best-effort, never fails the publish) so every publish path\n // (per-ref REST publish, the home banner, package publish-drafts)\n // lands data, not just metadata. The body is already in hand from\n // the promote — no read-back, so no org-scope resolution pitfalls.\n if (singularType === 'seed' && !request._skipSeedApply) {\n response.seedApplied = await this.applySeedBodies([result.item.body], orgId);\n }\n return response;\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict: any = new Error(\n `[metadata_conflict] ${request.type}/${request.name} published row advanced while you held the draft. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n conflict.code = 'metadata_conflict';\n conflict.status = 409;\n conflict.expectedParent = err.expectedParent;\n conflict.actualHead = err.actualHead;\n throw conflict;\n }\n throw err;\n }\n }\n\n /**\n * Materialize published `seed` bodies into data rows via the SeedLoaderService\n * (externalId-keyed upsert, multi-pass for cross-seed references). Passing ALL\n * of a publish's seed bodies in ONE call lets a child seed reference a parent\n * seed's rows regardless of publish order. Best-effort: any failure is\n * returned, never thrown — publishing metadata must not be blocked by a data\n * problem, but the caller surfaces `seedApplied` so the failure is LOUD.\n */\n private async applySeedBodies(\n bodies: unknown[],\n organizationId: string | null,\n ): Promise<{ success: boolean; inserted: number; updated: number; error?: string; errors?: unknown[] }> {\n try {\n const seeds = bodies.filter(\n (b: any) => b && typeof b.object === 'string' && Array.isArray(b.records),\n );\n if (seeds.length === 0) {\n return { success: false, inserted: 0, updated: 0, error: 'seed apply: no readable seed bodies' };\n }\n const { SeedLoaderService } = await import('./seed-loader.js');\n const { SeedLoaderRequestSchema } = await import('@objectstack/spec/data');\n // The loader only needs `getObject` from IMetadataService (dependency\n // graph + field introspection); satisfy it from the protocol's own\n // metadata reads so no kernel service lookup is required.\n const metadataAdapter = {\n getObject: async (name: string) => {\n const wrapper: any = await (this as any).getMetaItem({\n type: 'object',\n name,\n ...(organizationId ? { organizationId } : {}),\n });\n return wrapper?.item ?? wrapper ?? null;\n },\n };\n const loader = new SeedLoaderService(\n this.engine as any,\n metadataAdapter as any,\n console as any,\n );\n const request = SeedLoaderRequestSchema.parse({\n seeds,\n config: {\n defaultMode: 'upsert',\n multiPass: true,\n ...(organizationId ? { organizationId } : {}),\n },\n });\n const r = await loader.load(request);\n return {\n success: r.success,\n inserted: r.summary.totalInserted,\n updated: r.summary.totalUpdated,\n ...(r.errors?.length ? { errors: r.errors } : {}),\n };\n } catch (e: any) {\n return { success: false, inserted: 0, updated: 0, error: e?.message ?? 'seed apply failed' };\n }\n }\n\n /**\n * List pending DRAFT metadata (ADR-0033) for the org, optionally narrowed\n * by `packageId` and/or `type`. The list reads of `getMetaItems` only see\n * the ACTIVE registry; this exposes what an AI authored but a human hasn't\n * published yet, so the console can show a \"pending changes\" surface and a\n * just-built app package isn't displayed as empty. No body is returned.\n */\n async listDrafts(request?: {\n packageId?: string;\n type?: string;\n organizationId?: string;\n }): Promise<{\n drafts: Array<{\n type: string;\n name: string;\n packageId: string | null;\n updatedAt: string | null;\n updatedBy: string | null;\n }>;\n }> {\n await this.ensureOverlayIndex();\n const orgId = request?.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const drafts = await repo.listDrafts({\n ...(request?.type ? { type: PLURAL_TO_SINGULAR[request.type] ?? request.type } : {}),\n ...(request?.packageId ? { packageId: request.packageId } : {}),\n });\n return { drafts };\n }\n\n /**\n * Publish every pending DRAFT bound to a package in one shot (ADR-0033) —\n * the \"publish whole app\" action. Promotes each draft→active by reusing the\n * per-item {@link publishMetaItem} primitive (which runs the overridable /\n * lock guards and refreshes the runtime registry), so this needs NO\n * `metadata` service (unlike `MetadataService.publishPackage`, which reads\n * the in-memory registry and 503s when that service is absent). Per-item\n * failures are collected and do NOT abort the rest.\n */\n async publishPackageDrafts(request: {\n packageId: string;\n organizationId?: string;\n actor?: string;\n }): Promise<{\n success: boolean;\n publishedCount: number;\n failedCount: number;\n published: Array<{ type: string; name: string; version: string }>;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n /** Aggregate result of materializing every published `seed` (absent when no seeds). */\n seedApplied?: { success: boolean; inserted: number; updated: number; error?: string; errors?: unknown[] };\n /**\n * ADR-0038 L3 — post-publish runtime probe report (absent when nothing\n * was publishable). One real read per published artifact: seeded\n * objects must have rows, views must be readable, dashboard widgets'\n * dataset selections must execute and return data. `issues` carries\n * BuildIssue-shaped findings (layer 'runtime') for the agent / chat\n * health surfaces; probes never fail the publish itself.\n */\n probes?: import('./build-probes.js').BuildProbeReport;\n }> {\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const drafts = await repo.listDrafts({ packageId: request.packageId });\n\n const published: Array<{ type: string; name: string; version: string }> = [];\n const failed: Array<{ type: string; name: string; error: string; code?: string }> = [];\n\n // Structure first, seeds LAST — a seed's rows can only land after its\n // object's table exists (publishMetaItem creates it). Within the seeds we\n // batch-apply every body in ONE loader pass below (multi-pass reference\n // resolution across the whole set), so per-item apply is suppressed.\n const ordered = [\n ...drafts.filter((d) => d.type !== 'seed'),\n ...drafts.filter((d) => d.type === 'seed'),\n ];\n const seedBodies: unknown[] = [];\n\n for (const d of ordered) {\n try {\n if (d.type === 'seed') {\n // Capture the body BEFORE promote (the draft row is deleted by\n // the promote, and a post-publish read-back has org-scope\n // resolution pitfalls — reading the draft is unambiguous).\n const ref = { type: d.type, name: d.name, org: orgId ?? 'env' } as unknown as Parameters<typeof repo.get>[0];\n const draft = await repo.get(ref, { state: 'draft' });\n if (draft?.body) seedBodies.push(draft.body);\n }\n const r = await this.publishMetaItem({\n type: d.type,\n name: d.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n message: `publish app package '${request.packageId}'`,\n _skipSeedApply: true,\n });\n published.push({ type: d.type, name: d.name, version: r.version });\n } catch (e: any) {\n failed.push({\n type: d.type,\n name: d.name,\n error: e?.message ?? 'publish failed',\n ...(e?.code ? { code: e.code } : {}),\n });\n }\n }\n\n const seedApplied = seedBodies.length > 0 ? await this.applySeedBodies(seedBodies, orgId) : undefined;\n\n // ADR-0038 L3: exercise what was just published — one real read per\n // artifact — so \"Published!\" can never again mean \"and silently\n // broken\". Best-effort by design: a probe crash is swallowed (the\n // publish already happened and must report as such), and findings ride\n // the response for the agent / chat health card to act on.\n let probes: import('./build-probes.js').BuildProbeReport | undefined;\n if (published.length > 0) {\n try {\n const { runBuildProbes } = await import('./build-probes.js');\n const analytics = this.getServicesRegistry?.().get('analytics');\n probes = await runBuildProbes({\n engine: this.engine as any,\n getItem: async (type, name) => {\n const wrapper: any = await (this as any).getMetaItem({\n type,\n name,\n ...(orgId ? { organizationId: orgId } : {}),\n });\n return wrapper?.item ?? wrapper ?? undefined;\n },\n published,\n ...(analytics && typeof analytics.queryDataset === 'function' ? { analytics } : {}),\n organizationId: orgId,\n });\n } catch {\n probes = undefined;\n }\n }\n\n return {\n success: failed.length === 0 && published.length > 0,\n publishedCount: published.length,\n failedCount: failed.length,\n published,\n failed,\n ...(seedApplied ? { seedApplied } : {}),\n ...(probes ? { probes } : {}),\n };\n }\n\n /**\n * Discard every pending DRAFT bound to a package — the NON-destructive\n * inverse of {@link publishPackageDrafts}. Drops only `state='draft'` rows\n * (via the per-item delete primitive), reverting the package to its last\n * published baseline; active/published metadata and physical tables are\n * left untouched.\n *\n * Use case: \"I edited this app for a while and it turned out worse than\n * before — abandon all my changes.\" Routes through the sys_metadata path\n * (no metadata-service dependency, unlike `POST /packages/:id/revert`).\n */\n async discardPackageDrafts(request: {\n packageId: string;\n organizationId?: string;\n actor?: string;\n }): Promise<{\n success: boolean;\n discardedCount: number;\n failedCount: number;\n discarded: Array<{ type: string; name: string }>;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n }> {\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const drafts = await repo.listDrafts({ packageId: request.packageId });\n\n const discarded: Array<{ type: string; name: string }> = [];\n const failed: Array<{ type: string; name: string; error: string; code?: string }> = [];\n\n for (const d of drafts) {\n try {\n await this.deleteMetaItem({\n type: d.type,\n name: d.name,\n state: 'draft',\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n });\n discarded.push({ type: d.type, name: d.name });\n } catch (e: any) {\n failed.push({\n type: d.type,\n name: d.name,\n error: e?.message ?? 'discard failed',\n ...(e?.code ? { code: e.code } : {}),\n });\n }\n }\n\n return {\n success: failed.length === 0 && discarded.length > 0,\n discardedCount: discarded.length,\n failedCount: failed.length,\n discarded,\n failed,\n };\n }\n\n /**\n * Delete an ENTIRE package: every `sys_metadata` row bound to it (active\n * AND draft) and — by default — the physical table of each object it\n * defined. DESTRUCTIVE: removes the app and its data. Use case: \"I don't\n * want this package anymore.\"\n *\n * Set `keepData: true` to remove the metadata but preserve object tables.\n * The `sys_`-table guard in {@link deleteMetaItem} still applies, so\n * platform storage is never dropped. Drafts are removed before active rows\n * so each object's table is torn down once. Per-item failures are collected\n * without aborting the rest.\n */\n async deletePackage(request: {\n packageId: string;\n organizationId?: string;\n actor?: string;\n keepData?: boolean;\n }): Promise<{\n success: boolean;\n deletedCount: number;\n failedCount: number;\n deleted: Array<{ type: string; name: string; state: string }>;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n }> {\n const where: Record<string, unknown> = { package_id: request.packageId };\n if (request.organizationId) where.organization_id = request.organizationId;\n const rows = (await this.engine.find('sys_metadata', { where })) as any[];\n\n const dropStorage = request.keepData !== true;\n // Delete drafts before active so an object's table is dropped once (on\n // the active delete), not pre-empted by a draft delete.\n const ordered = [...rows].sort((a, b) => (a.state === 'draft' ? 0 : 1) - (b.state === 'draft' ? 0 : 1));\n\n const deleted: Array<{ type: string; name: string; state: string }> = [];\n const failed: Array<{ type: string; name: string; error: string; code?: string }> = [];\n\n for (const row of ordered) {\n const state: 'active' | 'draft' = row.state === 'draft' ? 'draft' : 'active';\n try {\n await this.deleteMetaItem({\n type: row.type,\n name: row.name,\n state,\n ...(row.organization_id ? { organizationId: row.organization_id } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n ...(dropStorage ? { dropStorage: true } : {}),\n });\n deleted.push({ type: row.type, name: row.name, state });\n } catch (e: any) {\n failed.push({\n type: row.type,\n name: row.name,\n error: e?.message ?? 'delete failed',\n ...(e?.code ? { code: e.code } : {}),\n });\n }\n }\n\n return {\n success: failed.length === 0 && deleted.length > 0,\n deletedCount: deleted.length,\n failedCount: failed.length,\n deleted,\n failed,\n };\n }\n\n /**\n * Restore the body recorded at history `toVersion` as the new\n * live row. Writes a history event with `op='revert'`. 404\n * (`[version_not_found]`) when the target version doesn't exist;\n * 409 (`[version_not_restorable]`) when the target is a delete\n * tombstone (no body to bring back).\n */\n async rollbackMetaItem(request: {\n type: string;\n name: string;\n toVersion: number;\n organizationId?: string;\n actor?: string;\n message?: string;\n }): Promise<{\n success: boolean;\n version: string;\n seq: number;\n restoredFromVersion: number;\n message?: string;\n }> {\n if (!Number.isFinite(request.toVersion) || request.toVersion < 1) {\n const err: any = new Error(\n `[invalid_request] rollbackMetaItem requires a positive integer 'toVersion' (got ${request.toVersion}).`,\n );\n err.code = 'invalid_request';\n err.status = 400;\n throw err;\n }\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n if (!ObjectStackProtocolImplementation.isOverlayAllowed(singularType)\n && !ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularType)) {\n const err: any = new Error(\n `[not_overridable] Metadata type '${request.type}' is not revertable — no overlay/runtime-create permission.`,\n );\n err.code = 'not_overridable';\n err.status = 403;\n throw err;\n }\n // ADR-0010 L3 — lock blocks rollback (writes a new active row).\n const _rollbackLockErr = await this.assertLockAllowsWrite({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n operation: 'rollback',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.rollbackMetaItem',\n });\n if (_rollbackLockErr) throw _rollbackLockErr;\n await this.ensureOverlayIndex();\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const artifactBacked = this.isArtifactBacked(singularType, request.name);\n const intent: 'override-artifact' | 'runtime-only' = artifactBacked\n ? 'override-artifact' : 'runtime-only';\n const ref = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.restoreVersion>[0];\n try {\n const result = await repo.restoreVersion(ref, request.toVersion, {\n actor: request.actor ?? 'system',\n source: 'protocol.rollbackMetaItem',\n ...(request.message ? { message: request.message } : {}),\n intent,\n });\n this.applyObjectRegistryMutation({\n type: request.type,\n name: request.name,\n item: result.item.body,\n });\n return {\n success: true,\n version: result.version,\n seq: result.seq,\n restoredFromVersion: request.toVersion,\n message: `Reverted to version ${request.toVersion} — type=${request.type}, name=${request.name} [seq=${result.seq}]`,\n };\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict: any = new Error(\n `[metadata_conflict] ${request.type}/${request.name} advanced during rollback. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n conflict.code = 'metadata_conflict';\n conflict.status = 409;\n conflict.expectedParent = err.expectedParent;\n conflict.actualHead = err.actualHead;\n throw conflict;\n }\n throw err;\n }\n }\n\n /**\n * Compute a shallow structural diff between two historical\n * versions of a metadata item. Either side may be omitted: when\n * `toVersion` is undefined the current active body is used; when\n * `fromVersion` is undefined the immediately previous history row\n * is used. Returns `{ added, removed, changed }` keyed by JSON\n * pointer-style paths for primitive leaves; nested objects/arrays\n * are reported as a single change record.\n */\n async diffMetaItem(request: {\n type: string;\n name: string;\n fromVersion?: number;\n toVersion?: number;\n organizationId?: string;\n }): Promise<{\n type: string;\n name: string;\n fromVersion: number | null;\n toVersion: number | null;\n added: Array<{ path: string; value: unknown }>;\n removed: Array<{ path: string; value: unknown }>;\n changed: Array<{ path: string; from: unknown; to: unknown }>;\n }> {\n const singularType = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const orgId = request.organizationId ?? null;\n const events = (await this.historyMetaItem({\n type: singularType,\n name: request.name,\n ...(orgId ? { organizationId: orgId } : {}),\n })).events;\n const versions = events\n .map((ev: any) => (ev as any).version as number | undefined)\n .filter((v): v is number => typeof v === 'number');\n // The `historyMetaItem` MetadataEvent shape doesn't carry the\n // per-(type,name) `version` directly — re-fetch via the repo\n // to read the underlying history rows with their version.\n const repo = this.getOverlayRepo(orgId);\n const fullRef = {\n type: singularType,\n name: request.name,\n org: orgId ?? 'env',\n } as { type: string; name: string; org: string };\n const histRows: Array<{ version: number; body: Record<string, unknown> | null }> = [];\n try {\n const engineAny = this.engine as any;\n const rows = await engineAny.find('sys_metadata_history', {\n where: {\n organization_id: orgId,\n type: singularType,\n name: request.name,\n },\n });\n rows.sort((a: any, b: any) => (a.version ?? 0) - (b.version ?? 0));\n for (const r of rows) {\n const body = r.metadata == null\n ? null\n : (typeof r.metadata === 'string' ? JSON.parse(r.metadata) : r.metadata);\n histRows.push({ version: r.version ?? 0, body });\n }\n } catch {\n // history table unavailable — fall through with empty list\n }\n const byVersion = new Map<number, Record<string, unknown> | null>();\n for (const r of histRows) byVersion.set(r.version, r.body);\n\n let fromBody: Record<string, unknown> | null = null;\n let toBody: Record<string, unknown> | null = null;\n let fromVersion: number | null = null;\n let toVersion: number | null = null;\n\n if (request.toVersion !== undefined) {\n toVersion = request.toVersion;\n toBody = byVersion.get(request.toVersion) ?? null;\n } else {\n const current = await repo.get(fullRef as any, { state: 'active' });\n toBody = current ? (current.body as Record<string, unknown>) : null;\n toVersion = histRows.length ? histRows[histRows.length - 1]!.version : null;\n }\n if (request.fromVersion !== undefined) {\n fromVersion = request.fromVersion;\n fromBody = byVersion.get(request.fromVersion) ?? null;\n } else if (toVersion !== null) {\n // Use the version immediately preceding `toVersion`\n const sorted = histRows.map((r) => r.version).filter((v) => v < toVersion!);\n if (sorted.length) {\n fromVersion = sorted[sorted.length - 1]!;\n fromBody = byVersion.get(fromVersion) ?? null;\n }\n }\n const diff = diffShallow(fromBody ?? {}, toBody ?? {});\n const _used = versions; void _used;\n return {\n type: request.type,\n name: request.name,\n fromVersion,\n toVersion,\n ...diff,\n };\n }\n\n /**\n * Remove a customization overlay row for the given metadata item, so the\n * next read falls through to the artifact-loaded default. Implements the\n * \"Reset to factory default\" semantic from ADR-0005. Whitelist is shared\n * with {@link saveMetaItem}.\n */\n async deleteMetaItem(request: {\n type: string;\n name: string;\n organizationId?: string;\n parentVersion?: string | null;\n actor?: string;\n state?: 'active' | 'draft';\n /**\n * When true, also drop the object's physical table after the metadata\n * is removed (object + active only; never `sys_`). Default false keeps\n * delete non-destructive to data. Used by the \"discard a previewed\n * object\" flow so a publish-to-preview leaves no orphan table.\n */\n dropStorage?: boolean;\n }): Promise<{\n success: boolean;\n message?: string;\n reset?: boolean;\n seq?: number;\n }> {\n // Two-tier authorization for delete (mirrors saveMetaItem).\n // • Artifact-backed item → delete becomes a tombstone overlay,\n // requires `allowOrgOverride`.\n // • DB-only item → hard delete of a user-created row,\n // requires `allowRuntimeCreate` (or `allowOrgOverride`).\n if (this.environmentId !== undefined) {\n const overlayAllowed = ObjectStackProtocolImplementation.isOverlayAllowed(request.type);\n const runtimeCreateAllowed = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(request.type);\n const artifactBacked = this.isArtifactBacked(request.type, request.name);\n if (artifactBacked && !overlayAllowed) {\n const err = new Error(\n `[not_overridable] Metadata item '${request.type}/${request.name}' is provided by a code package `\n + `and the type has not opted into per-org overlay writes. `\n + `See docs/adr/0005-metadata-customization-overlay.md.`\n );\n (err as any).code = 'not_overridable';\n (err as any).status = 403;\n throw err;\n }\n if (!artifactBacked && !overlayAllowed && !runtimeCreateAllowed) {\n const err = new Error(\n `[not_creatable] Metadata type '${request.type}' does not allow runtime creation or deletion.`\n );\n (err as any).code = 'not_creatable';\n (err as any).status = 403;\n throw err;\n }\n\n // ADR-0010 L3 — lock blocks delete.\n const lockErr = await this.assertLockAllowsDelete({\n type: request.type,\n name: request.name,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.deleteMetaItem',\n });\n if (lockErr) throw lockErr;\n }\n\n const singularTypeForRepo = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const overlayAllowedForRepoDel = ObjectStackProtocolImplementation.isOverlayAllowed(singularTypeForRepo);\n const runtimeCreateAllowedForRepoDel = ObjectStackProtocolImplementation.isRuntimeCreateAllowed(singularTypeForRepo);\n const useRepoPath = overlayAllowedForRepoDel || runtimeCreateAllowedForRepoDel;\n\n // ADR-0008 — overlay-allowed types route through SysMetadataRepository\n // so the delete (a) is wrapped in engine.transaction(), (b) appends a\n // tombstone row to sys_metadata_history, and (c) emits a watch event\n // with a monotonic `seq` for HMR. Non-overlay-allowed types (only\n // reachable in control-plane bootstrap mode where environmentId is\n // undefined) take the legacy raw-engine path below — the repository's\n // `assertAllowed()` whitelist would 403 those deletes.\n if (useRepoPath) {\n const orgId = request.organizationId ?? null;\n const repo = this.getOverlayRepo(orgId);\n const ref = {\n type: singularTypeForRepo,\n name: request.name,\n org: orgId ?? 'env',\n } as Parameters<typeof repo.delete>[0];\n\n try {\n const targetState: 'active' | 'draft' = request.state === 'draft' ? 'draft' : 'active';\n // Probe first — \"no overlay exists\" is a success/no-op, not\n // a conflict. The repo would otherwise throw ConflictError.\n const current = await repo.get(ref, { state: targetState });\n if (!current) {\n // Self-heal: even with no overlay row, a stale runtime\n // shadow may linger in the registry (e.g. pollution from\n // before this fix shipped) — drop it so the artifact\n // view really IS the default we claim below.\n if (targetState === 'active') {\n await this.restoreArtifactRegistryView(request.type, request.name);\n }\n return {\n success: true,\n reset: false,\n message: targetState === 'draft'\n ? `No pending draft for ${request.type}/${request.name}.`\n : `No customization overlay found for ${request.type}/${request.name} — already at artifact default.`,\n };\n }\n\n // Last-write-wins parent resolution unless the caller pinned\n // an explicit version (Studio's \"Reset\" button is unpinned;\n // a future \"delete vN\" flow can pass parentVersion).\n const parentVersion: string = request.parentVersion !== undefined\n ? (request.parentVersion ?? current.hash)\n : current.hash;\n\n const result = await repo.delete(ref, {\n parentVersion,\n actor: request.actor ?? 'system',\n source: 'protocol.deleteMetaItem',\n intent: this.isArtifactBacked(singularTypeForRepo, request.name)\n ? 'override-artifact'\n : 'runtime-only',\n state: targetState,\n });\n\n // Heal the registry: drop the overlay's runtime shadow so the\n // packaged artifact is visible again (all kernels), and on\n // control-plane kernels also refresh from MetadataService —\n // see {@link restoreArtifactRegistryView}. Draft discards\n // skip this: drafts never hydrate into the registry, and the\n // still-active overlay (if any) must keep its shadow.\n if (targetState === 'active') {\n await this.restoreArtifactRegistryView(request.type, request.name);\n }\n\n // Storage teardown (opt-in): drop the now-orphaned physical table\n // for a discarded object so a publish-to-preview leaves no residue.\n if (this.shouldDropStorage(request.type, request.name, request.dropStorage, targetState)) {\n await this.dropObjectStorage(singularTypeForRepo, request.name);\n }\n\n // ADR-0010 — success audit (best-effort).\n await this.recordMetadataAudit({\n type: request.type,\n name: request.name,\n organizationId: orgId,\n operation: 'delete',\n outcome: 'allowed',\n code: 'ok',\n ...(request.actor ? { actor: request.actor } : {}),\n source: 'protocol.deleteMetaItem',\n note: targetState,\n });\n\n return {\n success: true,\n reset: true,\n seq: result.seq,\n message: (request.state === 'draft')\n ? `Draft discarded — ${request.type}/${request.name}. [seq=${result.seq}]`\n : `Customization overlay deleted — ${request.type}/${request.name} reset to artifact default. [seq=${result.seq}]`,\n };\n } catch (err: any) {\n if (err instanceof ConflictError) {\n const conflict = new Error(\n `[metadata_conflict] ${request.type}/${request.name} has been modified since you loaded it. `\n + `Expected parent ${err.expectedParent ?? 'null'} but current is ${err.actualHead ?? 'null'}.`,\n );\n (conflict as any).code = 'metadata_conflict';\n (conflict as any).status = 409;\n (conflict as any).expectedParent = err.expectedParent;\n (conflict as any).actualHead = err.actualHead;\n throw conflict;\n }\n const e = new Error(`Failed to delete customization overlay: ${err.message ?? err}`);\n (e as any).status = err?.status ?? 500;\n throw e;\n }\n }\n\n // ── Legacy raw-engine path: only reachable in control-plane bootstrap\n // (environmentId === undefined) for non-overlay-allowed types like\n // `object`, `flow`, `agent`. No history row, no watch event — these\n // types don't participate in the change-log model.\n const scopedWhere: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n organization_id: request.organizationId ?? null,\n };\n\n try {\n const existing = await this.engine.findOne('sys_metadata', { where: scopedWhere });\n if (!existing) {\n return {\n success: true,\n reset: false,\n message: `No customization overlay found for ${request.type}/${request.name} — already at artifact default.`,\n };\n }\n await this.engine.delete('sys_metadata', { where: { id: existing.id } });\n\n // Storage teardown (opt-in) — see the repo-path branch above.\n {\n const targetState: 'active' | 'draft' = request.state === 'draft' ? 'draft' : 'active';\n if (this.shouldDropStorage(request.type, request.name, request.dropStorage, targetState)) {\n await this.dropObjectStorage(PLURAL_TO_SINGULAR[request.type] ?? request.type, request.name);\n }\n }\n\n if (request.state !== 'draft') {\n await this.restoreArtifactRegistryView(request.type, request.name);\n }\n\n return {\n success: true,\n reset: true,\n message: `Customization overlay deleted — ${request.type}/${request.name} reset to artifact default.`,\n };\n } catch (err: any) {\n const e = new Error(`Failed to delete customization overlay: ${err.message}`);\n (e as any).status = 500;\n throw e;\n }\n }\n\n /**\n * Hydrate SchemaRegistry from the database on startup.\n * Loads all active metadata records and registers them in the in-memory registry.\n * Safe to call repeatedly — idempotent (latest DB record wins).\n *\n * Per ADR-0005, project-kernel mode ALSO hydrates from sys_metadata —\n * customization overlay rows must survive restart. Scope filter\n * (`environment_id = this.environmentId ?? null`) keeps tenants isolated.\n */\n async loadMetaFromDb(): Promise<{ loaded: number; errors: number }> {\n let loaded = 0;\n let errors = 0;\n try {\n // ADR-0005 (revised 2026-05): hydrate only env-wide rows\n // (organization_id IS NULL). Per-org overlays are loaded on\n // demand by getMetaItem to avoid cross-org leakage into the\n // process-wide SchemaRegistry.\n const where: Record<string, unknown> = {\n state: 'active',\n organization_id: null,\n };\n const records = await this.engine.find('sys_metadata', { where });\n for (const record of records) {\n try {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Normalize DB type to singular (DB may store legacy plural forms)\n const normalizedType = PLURAL_TO_SINGULAR[record.type] ?? record.type;\n if (normalizedType === 'object') {\n this.engine.registry.registerObject(data as any, record.packageId || 'sys_metadata');\n } else {\n // Same envelope graft as the getMetaItems hydration:\n // the plain-key entry shadows any packaged artifact,\n // so carry the artifact's `_lock`/`_packageId`/\n // `_provenance` along (ADR-0010 §3.3). When artifacts\n // load after this hydration the merge finds nothing\n // and the row registers unchanged — same as before.\n const artifact = this.lookupArtifactItem(normalizedType, (data as any)?.name);\n this.engine.registry.registerItem(\n normalizedType,\n mergeArtifactProtection(data, artifact) as any,\n 'name' as any,\n );\n }\n loaded++;\n } catch (e) {\n errors++;\n console.warn(`[Protocol] Failed to hydrate ${record.type}/${record.name}: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n } catch (e: any) {\n // \"no such table\" is expected on first run before migrations execute — not an error.\n if (!/no such table/i.test(e.message ?? '')) {\n console.warn(`[Protocol] DB hydration skipped: ${e.message}`);\n }\n }\n return { loaded, errors };\n }\n\n // ==========================================\n // Metadata References (Phase 3a-references)\n // ==========================================\n\n /**\n * Scan all loaded metadata for references pointing at the given\n * `{type, name}` target. Returns one row per referring artifact with\n * the path that produced the hit, so the admin UI can render an\n * \"Used by\" panel before destructive actions (rename / delete /\n * type-narrowing).\n *\n * Coverage is driven by the hand-curated {@link REFERENCE_PATHS}\n * registry. Types not present in the registry simply return no hits\n * — the engine never throws.\n */\n async findReferencesToMeta(request: {\n type: string;\n name: string;\n organizationId?: string;\n }): Promise<{\n references: Array<{\n type: string;\n name: string;\n label?: string;\n path: string;\n kind: string;\n }>;\n }> {\n const singularTarget = PLURAL_TO_SINGULAR[request.type] ?? request.type;\n const targetName = request.name;\n const matchers = REFERENCE_PATHS[singularTarget];\n if (!matchers || matchers.length === 0) {\n return { references: [] };\n }\n\n const seen = new Set<string>(); // dedup key: `${fromType}|${itemName}|${path}`\n const out: Array<{ type: string; name: string; label?: string; path: string; kind: string }> = [];\n\n // Walk distinct source types in parallel.\n await Promise.all(\n matchers.map(async (matcher) => {\n let items: unknown[] = [];\n try {\n const result = await this.getMetaItems({\n type: matcher.fromType,\n ...(request.organizationId ? { organizationId: request.organizationId } : {}),\n });\n items = (result?.items ?? []) as unknown[];\n } catch {\n return;\n }\n for (const raw of items) {\n if (!raw || typeof raw !== 'object') continue;\n const sourceName = (raw as any).name as string | undefined;\n if (!sourceName) continue;\n // Don't list an item as a reference to itself unless the\n // self-reference is meaningful (e.g. object→field path).\n const isSelfReference = matcher.fromType === singularTarget && sourceName === targetName;\n for (const path of matcher.paths) {\n const values = extractPathValues(raw, path);\n if (!values.includes(targetName)) continue;\n if (isSelfReference && !path.includes('[]') && !path.includes('{}')) continue;\n const key = `${matcher.fromType}|${sourceName}|${path}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const label = (raw as any).label as string | undefined;\n out.push({\n type: matcher.fromType,\n name: sourceName,\n ...(label ? { label } : {}),\n path,\n kind: matcher.kind,\n });\n }\n }\n }),\n );\n\n // Stable sort: by type, then by name.\n out.sort((a, b) => a.type.localeCompare(b.type) || a.name.localeCompare(b.name));\n\n return { references: out };\n }\n\n // ==========================================\n // Feed Operations\n // ==========================================\n\n async listFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n return { success: true, data: result };\n }\n\n async createFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.createFeedItem({\n object: request.object,\n recordId: request.recordId,\n type: request.type,\n actor: { type: 'user', id: 'current_user' },\n body: request.body,\n mentions: request.mentions,\n parentId: request.parentId,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async updateFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.updateFeedItem(request.feedId, {\n body: request.body,\n mentions: request.mentions,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async deleteFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n await svc.deleteFeedItem(request.feedId);\n return { success: true, data: { feedId: request.feedId } };\n }\n\n async addReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.addReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async removeReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.removeReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async pinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated pin/unpin — use updateFeedItem to persist pin state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: new Date().toISOString() } };\n }\n\n async unpinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: false } };\n }\n\n async starFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated star/unstar — verify item exists then return state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: true, starredAt: new Date().toISOString() } };\n }\n\n async unstarFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: false } };\n }\n\n async searchFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Search delegates to listFeed with filter since IFeedService doesn't have a dedicated search\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n // Filter by query text in body\n const queryLower = (request.query || '').toLowerCase();\n const filtered = result.items.filter((item: any) =>\n item.body?.toLowerCase().includes(queryLower)\n );\n return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };\n }\n\n async getChangelog(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Changelog retrieves field_change type feed items\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: 'changes_only',\n limit: request.limit,\n cursor: request.cursor,\n });\n const entries = result.items.map((item: any) => ({\n id: item.id,\n object: item.object,\n recordId: item.recordId,\n actor: item.actor,\n changes: item.changes || [],\n timestamp: item.createdAt,\n source: item.source,\n }));\n return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };\n }\n\n async feedSubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const subscription = await svc.subscribe({\n object: request.object,\n recordId: request.recordId,\n userId: 'current_user',\n events: request.events,\n channels: request.channels,\n });\n return { success: true, data: subscription };\n }\n\n async feedUnsubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const unsubscribed = await svc.unsubscribe(request.object, request.recordId, 'current_user');\n return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };\n }\n\n /**\n * Install a package from a manifest — the single canonical write primitive\n * for the package subsystem (ADR-0033 consolidation).\n *\n * It writes BOTH stores that the runtime keeps for packages, so a package\n * surfaces consistently no matter which read path is used:\n * 1. the in-memory `SchemaRegistry` (what the dispatcher's\n * `/api/v1/packages` list/detail and `getMetaItems({type:'package'})`\n * read — i.e. what Studio's package selector shows), and\n * 2. the durable `sys_packages` table via the optional `package` service\n * (so the package survives a restart; that service re-hydrates these\n * rows back into the registry on boot).\n *\n * The DB write is best-effort and non-fatal: when the `package` service is\n * absent (e.g. the `marketplace` capability is off) the package is still\n * registered in-memory and visible for the lifetime of the process.\n */\n async installPackage(request: InstallPackageRequest): Promise<InstallPackageResponse> {\n const manifest = request.manifest;\n const pkg = this.engine.registry.installPackage(manifest as any, request.settings);\n\n // Best-effort durable persistence to `sys_packages`.\n try {\n const services = this.getServicesRegistry?.();\n const pkgSvc = services?.get('package') as\n | { publish?: (data: { manifest: unknown; metadata: unknown }) => Promise<unknown> }\n | undefined;\n if (pkgSvc?.publish && (manifest as any)?.version) {\n await pkgSvc.publish({ manifest, metadata: {} });\n }\n } catch (e) {\n // Non-fatal: registry write already succeeded; log and continue.\n console.warn(\n `[protocol.installPackage] sys_packages persist skipped for '${(manifest as any)?.id}': ${(e as Error)?.message}`,\n );\n }\n\n return { package: pkg as any, message: `Installed package: ${(manifest as any)?.id}` };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ADR-0008 PR-10b — `SysMetadataRepository`.\n *\n * Wraps the existing `sys_metadata` table behind the canonical\n * `MetadataRepository` interface. Implements the *single-row update*\n * semantics that ADR-0005 already ships — append-only event-log\n * persistence is M1 work.\n *\n * What this layer DOES (M0 + M1):\n * - get / put / delete / list against `sys_metadata`\n * - tenancy scope = `organization_id` (per-org overlays only;\n * project/branch concepts removed — see ADR-0008 §0 amendment)\n * - hash stamping with `hashSpec` (PR-10a guarantees stability)\n * - watch() implemented via an in-memory event broadcaster fed by\n * every successful put/delete on THIS instance\n * - whitelist enforcement: refuses to persist types whose registry\n * entry has `allowOrgOverride: false` (Prime Directive #8)\n * - **M1**: every successful put/delete appends a durable row to\n * `sys_metadata_history` inside the same engine.transaction() as the\n * parent `sys_metadata` write. No-op puts (identical hash) skip the\n * history write. Failed optimistic-lock checks abort before any\n * write reaches the database.\n * - **M1**: history() yields events from the durable log, ordered by\n * per-(org,type,name) `version` ASC.\n *\n * What this layer does NOT do (and will not, by design):\n * - cross-replica push notifications (LISTEN/NOTIFY, pub/sub, etc.).\n * The watch() contract is scoped to the local repository instance.\n * Multi-replica deployments are not a supported topology for the\n * metadata overlay — see ADR-0008 §11.\n * - hashSpec backfill for legacy rows missing `checksum`\n *\n * Schema mapping (ADR-0008 PR-10d.2):\n * Repository concept sys_metadata column\n * ─────────────────────── ───────────────────\n * body → metadata (JSON string)\n * hash (sha256) → checksum (text(64))\n * monotonic version int → version (number)\n * org isolation → organization_id (lookup)\n * actor → updated_by (lookup, optional)\n *\n * Composition: PR-10c will compose\n * `LayeredRepository([FileSystemRepository, SysMetadataRepository])`\n * and the manager bridge will route reads through that. Until then this\n * file is intentionally NOT wired into any production path — it has its\n * own test surface so we can build confidence before flipping the\n * switch.\n */\n\nimport { hashSpec, ConflictError } from '@objectstack/metadata-core';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport type {\n MetadataRepository,\n MetaRef,\n MetadataItem,\n MetadataItemHeader,\n MetadataEvent,\n MetadataWriteIntent,\n PutOptions,\n PutResult,\n DeleteOptions,\n DeleteResult,\n ListFilter,\n WatchFilter,\n HistoryOptions,\n} from '@objectstack/metadata-core';\nimport { DEFAULT_METADATA_TYPE_REGISTRY } from '@objectstack/spec/kernel';\nimport { PLURAL_TO_SINGULAR, SINGULAR_TO_PLURAL } from '@objectstack/spec/shared';\n\n/**\n * Overlay-row lifecycle state.\n *\n * - `'active'` → the published, live overlay. `getMetaItem` (the\n * default read path) and runtime loaders observe this row.\n * - `'draft'` → an unpublished pending change. Lives alongside the\n * active row (one of each per `(org,type,name)`). Promoted to\n * `active` via {@link SysMetadataRepository.promoteDraft}.\n *\n * Other lifecycle values defined on `sys_metadata.state` (`'archived'`,\n * `'deprecated'`) are not yet plumbed through the overlay write path;\n * they remain reserved for future flows (item retirement, freeze).\n */\nexport type OverlayState = 'active' | 'draft';\n\n/**\n * Extended history operation tag. The base `'create' | 'update' |\n * 'delete'` operations are emitted by the canonical put/delete paths.\n * `'publish'` is recorded when a draft is promoted, `'revert'` when a\n * historical version is restored. Both are surfaced as MetadataEvent\n * `.op` values via `history()`.\n */\nexport type ExtendedOperation = 'create' | 'update' | 'publish' | 'revert' | 'delete';\n\n/**\n * Sub-set of the ObjectQL engine shape we depend on. Kept narrow so\n * tests can stub it with a plain mock. Mirrors the real engine's\n * `options.context` pattern so transactions can thread through.\n */\nexport interface SysMetadataEngine {\n find(\n table: string,\n options: { where: Record<string, unknown>; limit?: number; orderBy?: any; context?: any },\n ): Promise<any[]>;\n findOne(\n table: string,\n options: { where: Record<string, unknown>; context?: any },\n ): Promise<any | null>;\n insert(\n table: string,\n data: Record<string, unknown>,\n options?: { context?: any },\n ): Promise<{ id: string }>;\n update(\n table: string,\n data: Record<string, unknown>,\n options: { where: Record<string, unknown>; context?: any },\n ): Promise<{ id: string }>;\n delete(\n table: string,\n options: { where: Record<string, unknown>; context?: any },\n ): Promise<{ deleted: number }>;\n /**\n * Optional. Falls through to direct callback invocation if the\n * underlying driver lacks ACID support (matches the real\n * `ObjectQL.transaction` semantics). Repository code must not rely on\n * rollback for correctness against in-memory drivers.\n */\n transaction?<T>(callback: (trxCtx: any) => Promise<T>, baseContext?: any): Promise<T>;\n}\n\nexport interface SysMetadataRepositoryOptions {\n engine: SysMetadataEngine;\n /**\n * Tenancy scope. `null` writes to env-wide overlay rows; a string\n * scopes to one organization (the supported shared-DB tenant model\n * — see ADR-0005 amendment).\n */\n organizationId?: string | null;\n /** Org label embedded in returned MetaRefs. Defaults to organizationId or `\"system\"`. */\n orgLabel?: string;\n}\n\n/** Derived from registry — single source of truth (Prime Directive #8). */\nconst OVERLAY_ALLOWED_TYPES: ReadonlySet<string> = new Set(\n DEFAULT_METADATA_TYPE_REGISTRY\n .filter((e) => e.allowOrgOverride)\n .map((e) => e.type),\n);\n\n/**\n * Types that opt into runtime creation of brand-new items (two-tier\n * model — ADR-0005 extension). These items live only in `sys_metadata`;\n * there is no artifact backing them and `allowOrgOverride` need not be\n * granted on the type. Used by `assertAllowed()` when called with\n * `intent: 'runtime-only'` — a signal from the protocol layer that it\n * has already verified the absence of an artifact-shadowing collision.\n */\n/**\n * Set of type names that have an *explicit* entry in the static registry.\n * Anything outside this set is a runtime-registered type (e.g. plugin-\n * provided `theme`, `api`, `connector`, …) — the listing endpoint\n * (`getMetaTypes()` in protocol.ts) synthesises a descriptor with\n * `allowRuntimeCreate: true` for those, so the write gate must agree.\n */\nconst STATIC_REGISTRY_TYPES: ReadonlySet<string> = new Set(\n DEFAULT_METADATA_TYPE_REGISTRY.map((e) => e.type),\n);\n\nconst RUNTIME_CREATE_ALLOWED_TYPES: ReadonlySet<string> = new Set(\n DEFAULT_METADATA_TYPE_REGISTRY\n .filter((e) => e.allowRuntimeCreate)\n .map((e) => e.type),\n);\n\n/**\n * Phase 3a-env-writable: parse `OS_METADATA_WRITABLE` (comma-\n * separated singular type names). Memoised; tests can reset via\n * {@link resetEnvWritableMetadataTypes}. Mirrors the same helper in\n * ObjectStackProtocolImplementation — both gates must consult the same\n * elevated set so the env-var escape hatch is applied consistently\n * regardless of which write path a caller takes.\n */\nlet _envWritableMetadataTypes: Set<string> | null = null;\nfunction envWritableMetadataTypes(): ReadonlySet<string> {\n if (_envWritableMetadataTypes !== null) return _envWritableMetadataTypes;\n const raw = readEnvWithDeprecation('OS_METADATA_WRITABLE', 'OBJECTSTACK_METADATA_WRITABLE') || '';\n const set = new Set<string>();\n for (const tok of raw.split(',')) {\n const t = tok.trim();\n if (!t) continue;\n const singular = PLURAL_TO_SINGULAR[t] ?? t;\n set.add(singular);\n const plural = SINGULAR_TO_PLURAL[singular];\n if (plural) set.add(plural);\n }\n _envWritableMetadataTypes = set;\n return set;\n}\n\n/** Test hook — clear the memoised env-writable cache. */\nexport function resetEnvWritableMetadataTypes(): void {\n _envWritableMetadataTypes = null;\n}\n\nexport class SysMetadataRepository implements MetadataRepository {\n private readonly engine: SysMetadataEngine;\n private readonly organizationId: string | null;\n private readonly orgLabel: string;\n\n /**\n * Local seq counter for in-memory watch() event broadcasts. Mirrors\n * the durable `event_seq` we write into `sys_metadata_history` on\n * each successful put/delete — assigned AFTER the transaction commits\n * so we never broadcast events that got rolled back.\n */\n private seqCounter = 0;\n private readonly watchers = new Set<(evt: MetadataEvent) => void>();\n private closed = false;\n\n /** Table name for the durable event log. */\n private readonly historyTable = 'sys_metadata_history';\n\n constructor(opts: SysMetadataRepositoryOptions) {\n this.engine = opts.engine;\n this.organizationId = opts.organizationId ?? null;\n this.orgLabel = opts.orgLabel ?? (opts.organizationId ?? 'system');\n }\n\n /**\n * Run `cb` inside `engine.transaction(...)` if the engine supports it,\n * otherwise fall through to a direct call. Matches the real\n * `ObjectQL.transaction` semantics — in-memory drivers (and our test\n * fakes) get no rollback, which is acceptable because production\n * always runs on a SQL driver with real ACID.\n */\n private async withTxn<T>(cb: (ctx: any) => Promise<T>): Promise<T> {\n if (typeof this.engine.transaction === 'function') {\n return this.engine.transaction(cb);\n }\n return cb(undefined);\n }\n\n /**\n * Read the current overlay row. Returns null if no row exists —\n * callers (e.g. LayeredRepository) fall through to lower layers.\n *\n * `opts.state` selects which lifecycle row to read: defaults to the\n * live published row (`'active'`). Pass `'draft'` to read the pending\n * unpublished revision (if any).\n */\n async get(ref: MetaRef, opts?: { state?: OverlayState }): Promise<MetadataItem | null> {\n this.assertOpen();\n const state = opts?.state ?? 'active';\n const row = await this.engine.findOne('sys_metadata', {\n where: this.whereFor(ref, state),\n });\n if (!row) return null;\n return this.rowToItem(ref, row);\n }\n\n /**\n * Resolve a historical version by content hash (ADR-0009).\n *\n * Looks up `sys_metadata_history` by `(organization_id, type, name,\n * checksum)`. Returns null if no row matches. `executionPinned` types\n * are guaranteed to find their body here because history GC skips\n * them.\n */\n async getByHash(ref: MetaRef, hash: string): Promise<MetadataItem | null> {\n this.assertOpen();\n const full = this.fullRef(ref);\n const row = await this.engine.findOne(this.historyTable, {\n where: {\n organization_id: this.organizationId,\n type: full.type,\n name: full.name,\n checksum: hash,\n },\n });\n if (!row) return null;\n const rawBody = (row as any).metadata;\n if (rawBody === null || rawBody === undefined) {\n // Tombstone — body is gone, do not resurrect.\n return null;\n }\n const body =\n typeof rawBody === 'string' ? JSON.parse(rawBody) : (rawBody as Record<string, unknown>);\n return {\n ref: { ...full, version: undefined },\n body: body as Record<string, unknown>,\n hash,\n parentHash: (row as any).previous_checksum ?? null,\n authoredBy: (row as any).recorded_by ?? 'unknown',\n authoredAt: (row as any).recorded_at ?? new Date(0).toISOString(),\n message: (row as any).change_note ?? undefined,\n seq: ((row as any).event_seq as number) ?? 0,\n };\n }\n\n async put(\n ref: MetaRef,\n spec: unknown,\n opts: PutOptions & { state?: OverlayState; opType?: ExtendedOperation },\n ): Promise<PutResult> {\n this.assertOpen();\n this.assertAllowed(ref.type, opts.intent);\n\n const state: OverlayState = opts.state ?? 'active';\n const body = (spec ?? {}) as Record<string, unknown>;\n const hash = hashSpec(body);\n\n // Run all reads + writes inside one transaction so the optimistic\n // lock, the parent-row mutation, and the history append are atomic.\n const result = await this.withTxn(async (ctx) => {\n const existing = await this.engine.findOne('sys_metadata', {\n where: this.whereFor(ref, state),\n context: ctx,\n });\n const existingHash: string | null = existing?.checksum ?? null;\n if (opts.parentVersion !== existingHash) {\n throw new ConflictError(this.fullRef(ref), opts.parentVersion, existingHash);\n }\n\n // No-op short-circuit: identical body → no write, no history row,\n // no event. We re-yield the existing item so callers see the\n // canonical hash but the seqCounter is unchanged.\n if (existing && existingHash === hash) {\n const item = this.rowToItem(ref, existing);\n return { skipped: true as const, version: hash, seq: item.seq, item };\n }\n\n const now = new Date().toISOString();\n const baseOp: 'create' | 'update' = existing ? 'update' : 'create';\n const op: ExtendedOperation = opts.opType ?? baseOp;\n\n // Per-(org,type,name) lineage counter. Use MAX from history so\n // delete+recreate continues incrementing instead of restarting\n // at 1 (which the prior `sys_metadata.version` semantics did).\n const version = await this.nextItemVersion(ref, ctx);\n // Per-org monotonic event log cursor.\n const eventSeq = await this.nextEventSeq(ctx);\n\n const parentRowData: Record<string, unknown> = {\n type: ref.type,\n name: ref.name,\n organization_id: this.organizationId,\n metadata: JSON.stringify(body),\n checksum: hash,\n state,\n version,\n updated_at: now,\n };\n // Software-package binding (Studio package authoring workspace).\n // Create: stamp with the requested package (or null). Update: preserve\n // an existing non-null binding so an edit made with a different package\n // selected never silently re-binds the row; only fill a null binding.\n if (existing) {\n const existingPkg = (existing as { package_id?: string | null }).package_id ?? null;\n parentRowData.package_id = existingPkg ?? opts.packageId ?? null;\n } else {\n parentRowData.package_id = opts.packageId ?? null;\n }\n if (existing) {\n const existingId = (existing as { id?: string }).id;\n if (existingId === undefined) {\n throw new Error(\n `SysMetadataRepository.put: existing row for ${ref.type}/${ref.name} has no id column`,\n );\n }\n await this.engine.update('sys_metadata', parentRowData, {\n where: { id: existingId },\n context: ctx,\n });\n } else {\n parentRowData.created_at = now;\n await this.engine.insert('sys_metadata', parentRowData, { context: ctx });\n }\n\n // Durable history append — same transaction, so the parent write\n // and the audit row commit together or roll back together.\n await this.engine.insert(\n this.historyTable,\n {\n id: this.uuid(),\n event_seq: eventSeq,\n type: ref.type,\n name: ref.name,\n version,\n operation_type: op,\n metadata: JSON.stringify(body),\n checksum: hash,\n previous_checksum: existingHash,\n change_note: opts.message,\n source: opts.source ?? 'sys-metadata-repo',\n organization_id: this.organizationId,\n recorded_by: opts.actor,\n recorded_at: now,\n },\n { context: ctx },\n );\n\n const item: MetadataItem = {\n ref: this.fullRef(ref),\n body,\n hash,\n parentHash: existingHash,\n authoredBy: opts.actor,\n authoredAt: now,\n message: opts.message,\n seq: eventSeq,\n };\n\n return {\n skipped: false as const,\n version: hash,\n seq: eventSeq,\n item,\n op,\n existingHash,\n now,\n source: opts.source ?? 'sys-metadata-repo',\n message: opts.message,\n actor: opts.actor,\n };\n });\n\n if (result.skipped) {\n return { version: result.version, seq: result.seq, item: result.item };\n }\n\n // Broadcast AFTER commit. seqCounter tracks the durable event_seq\n // so watch() consumers and history() consumers see the same cursor.\n this.seqCounter = result.seq;\n // Drafts are explicitly NOT broadcast — the watch() stream models\n // the live overlay surface. A draft is a private staging buffer\n // until `promoteDraft()` records a `publish` event. Subscribers\n // (cache layers, HMR clients) should not react to drafts.\n if (state === 'active') {\n this.broadcast({\n seq: result.seq,\n op: result.op,\n ref: this.fullRef(ref),\n hash: result.version,\n parentHash: result.existingHash,\n actor: result.actor,\n message: result.message,\n ts: result.now,\n source: result.source,\n });\n }\n\n return { version: result.version, seq: result.seq, item: result.item };\n }\n\n async delete(\n ref: MetaRef,\n opts: DeleteOptions & { state?: OverlayState },\n ): Promise<DeleteResult> {\n this.assertOpen();\n this.assertAllowed(ref.type, opts.intent);\n\n const state: OverlayState = opts.state ?? 'active';\n const result = await this.withTxn(async (ctx) => {\n const existing = await this.engine.findOne('sys_metadata', {\n where: this.whereFor(ref, state),\n context: ctx,\n });\n if (!existing) {\n throw new ConflictError(this.fullRef(ref), opts.parentVersion, null);\n }\n const existingHash: string | null = existing.checksum ?? null;\n if (opts.parentVersion !== existingHash) {\n throw new ConflictError(this.fullRef(ref), opts.parentVersion, existingHash);\n }\n\n const existingId = (existing as { id?: string }).id;\n if (existingId === undefined) {\n throw new Error(\n `SysMetadataRepository.delete: existing row for ${ref.type}/${ref.name} has no id column`,\n );\n }\n\n const now = new Date().toISOString();\n // Draft deletions are a private buffer flush — they don't get a\n // history event (no audit value, and no parent for replay). Only\n // active-row deletes write a tombstone.\n let version = 0;\n let eventSeq = 0;\n if (state === 'active') {\n version = await this.nextItemVersion(ref, ctx);\n eventSeq = await this.nextEventSeq(ctx);\n }\n\n await this.engine.delete('sys_metadata', {\n where: { id: existingId },\n context: ctx,\n });\n\n if (state === 'active') {\n // Tombstone row — metadata/checksum are intentionally null.\n // Identity is preserved via (organization_id, type, name, version);\n // the parent row's id is not retained.\n await this.engine.insert(\n this.historyTable,\n {\n id: this.uuid(),\n event_seq: eventSeq,\n type: ref.type,\n name: ref.name,\n version,\n operation_type: 'delete',\n metadata: null,\n checksum: null,\n previous_checksum: existingHash,\n change_note: opts.message,\n source: opts.source ?? 'sys-metadata-repo',\n organization_id: this.organizationId,\n recorded_by: opts.actor,\n recorded_at: now,\n },\n { context: ctx },\n );\n }\n\n return {\n eventSeq,\n existingHash,\n now,\n source: opts.source ?? 'sys-metadata-repo',\n message: opts.message,\n actor: opts.actor,\n };\n });\n\n if (state === 'active') {\n this.seqCounter = result.eventSeq;\n this.broadcast({\n seq: result.eventSeq,\n op: 'delete',\n ref: this.fullRef(ref),\n hash: null,\n parentHash: result.existingHash,\n actor: result.actor,\n message: result.message,\n ts: result.now,\n source: result.source,\n });\n }\n\n return { seq: result.eventSeq };\n }\n\n /**\n * Promote the pending draft row for `ref` into the live (`active`)\n * overlay. Atomic: reads the draft inside the same transaction, runs\n * the canonical `put` to upsert the active row (which appends a\n * history event with `operation_type='publish'`), then deletes the\n * draft row.\n *\n * Errors if no draft exists (callers should 404). The active row's\n * `parentVersion` is computed from the current active hash so this\n * also surfaces optimistic-lock conflicts when something else has\n * published in between (e.g. another admin reverted to an older\n * version since the draft was authored).\n */\n async promoteDraft(\n ref: MetaRef,\n opts: { actor: string; source?: string; message?: string; intent?: MetadataWriteIntent },\n ): Promise<{ version: string; seq: number; item: MetadataItem }> {\n this.assertOpen();\n const draft = await this.get(ref, { state: 'draft' });\n if (!draft) {\n const err: any = new Error(\n `[no_draft] No pending draft exists for ${ref.type}/${ref.name} — nothing to publish.`,\n );\n err.code = 'no_draft';\n err.status = 404;\n throw err;\n }\n const currentActive = await this.get(ref, { state: 'active' });\n const result = await this.put(ref, draft.body, {\n parentVersion: currentActive?.hash ?? null,\n actor: opts.actor,\n source: opts.source ?? 'sys-metadata-repo.publish',\n message: opts.message ?? `publish draft (hash ${draft.hash})`,\n intent: opts.intent ?? 'override-artifact',\n state: 'active',\n opType: 'publish',\n });\n // Drop the draft row — it has been promoted. Tolerate races where\n // a second publisher already drained it.\n try {\n await this.delete(ref, {\n parentVersion: draft.hash,\n actor: opts.actor,\n source: opts.source ?? 'sys-metadata-repo.publish',\n intent: opts.intent ?? 'override-artifact',\n state: 'draft',\n });\n } catch {\n // best-effort: a concurrent publisher may have already drained\n // the draft; the active row's authoritative content is intact.\n }\n return result;\n }\n\n /**\n * Restore the body recorded in history at `targetVersion` (per-org\n * lineage counter) as the new active row. Writes a history event\n * with `operation_type='revert'` so the audit trail captures the\n * intent. Does NOT touch any draft row.\n *\n * Throws `[version_not_found]` (404) if the target version row is\n * missing or is a delete tombstone (no body to restore).\n */\n async restoreVersion(\n ref: MetaRef,\n targetVersion: number,\n opts: { actor: string; source?: string; message?: string; intent?: MetadataWriteIntent },\n ): Promise<{ version: string; seq: number; item: MetadataItem }> {\n this.assertOpen();\n const full = this.fullRef(ref);\n const row = await this.engine.findOne(this.historyTable, {\n where: {\n organization_id: this.organizationId,\n type: full.type,\n name: full.name,\n version: targetVersion,\n },\n });\n if (!row) {\n const err: any = new Error(\n `[version_not_found] No history row at version ${targetVersion} for ${ref.type}/${ref.name}.`,\n );\n err.code = 'version_not_found';\n err.status = 404;\n throw err;\n }\n const raw = (row as any).metadata;\n if (raw === null || raw === undefined) {\n const err: any = new Error(\n `[version_not_restorable] Version ${targetVersion} for ${ref.type}/${ref.name} is a delete tombstone — nothing to restore.`,\n );\n err.code = 'version_not_restorable';\n err.status = 409;\n throw err;\n }\n const body = typeof raw === 'string' ? JSON.parse(raw) : (raw as Record<string, unknown>);\n const currentActive = await this.get(ref, { state: 'active' });\n return this.put(ref, body, {\n parentVersion: currentActive?.hash ?? null,\n actor: opts.actor,\n source: opts.source ?? 'sys-metadata-repo.revert',\n message: opts.message ?? `revert to version ${targetVersion}`,\n intent: opts.intent ?? 'override-artifact',\n state: 'active',\n opType: 'revert',\n });\n }\n\n async *list(filter: ListFilter): AsyncIterable<MetadataItemHeader> {\n this.assertOpen();\n const where: Record<string, unknown> = {\n organization_id: this.organizationId,\n state: 'active',\n };\n if (filter.type) where.type = filter.type;\n const rows = await this.engine.find('sys_metadata', {\n where,\n limit: filter.limit,\n });\n for (const row of rows) {\n if (filter.nameContains && !String(row.name).includes(filter.nameContains)) continue;\n const item = this.rowToItem(\n { ...this.fullRef({ type: row.type, name: row.name } as MetaRef) },\n row,\n );\n // Strip body for the header projection.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { body, ...header } = item;\n yield header;\n }\n }\n\n /**\n * List pending DRAFT rows (ADR-0033) for this org, optionally narrowed by\n * `type` and/or `packageId`. Unlike {@link list} (which is hard-scoped to\n * `state='active'`), this reads `state='draft'` so the console can surface\n * what an AI authored but a human hasn't published yet. Returns a light\n * header projection (no body) suitable for a \"pending changes\" list.\n */\n async listDrafts(filter?: {\n type?: string;\n packageId?: string;\n }): Promise<\n Array<{\n type: string;\n name: string;\n packageId: string | null;\n updatedAt: string | null;\n updatedBy: string | null;\n }>\n > {\n this.assertOpen();\n const where: Record<string, unknown> = {\n organization_id: this.organizationId,\n state: 'draft',\n };\n if (filter?.type) where.type = filter.type;\n if (filter?.packageId) where.package_id = filter.packageId;\n const rows = await this.engine.find('sys_metadata', { where });\n return (rows as any[]).map((row) => ({\n type: row.type,\n name: row.name,\n packageId: row.package_id ?? null,\n updatedAt: row.updated_at ?? row.created_at ?? null,\n updatedBy: row.updated_by ?? row.created_by ?? null,\n }));\n }\n\n /**\n * Yield every history event for `(org, type?, name?)` from the\n * durable log, ordered by per-(type,name) `version` ascending. When\n * `filter.type`/`filter.name` are unset the consumer gets the full\n * org-scoped event stream — still ordered by version within each\n * (type,name) bucket, then by `recorded_at` across buckets (we sort\n * client-side because the test engine doesn't honor `orderBy`).\n */\n async *history(ref: MetaRef, opts?: HistoryOptions): AsyncIterable<MetadataEvent> {\n this.assertOpen();\n const full = this.fullRef(ref);\n const where: Record<string, unknown> = {\n organization_id: this.organizationId,\n type: full.type,\n name: full.name,\n };\n const rows = await this.engine.find(this.historyTable, { where });\n rows.sort((a: any, b: any) => {\n const va = typeof a.event_seq === 'number' ? a.event_seq : 0;\n const vb = typeof b.event_seq === 'number' ? b.event_seq : 0;\n return va - vb;\n });\n let yielded = 0;\n for (const row of rows) {\n if (opts?.sinceSeq !== undefined && (row.event_seq ?? 0) <= opts.sinceSeq) continue;\n if (opts?.limit !== undefined && yielded >= opts.limit) break;\n yielded++;\n yield {\n seq: (row.event_seq as number) ?? 0,\n op: (row.operation_type as MetadataEvent['op']) ?? 'update',\n ref: full,\n hash: (row.checksum as string | null) ?? null,\n parentHash: (row.previous_checksum as string | null) ?? null,\n version: typeof row.version === 'number' ? row.version : undefined,\n actor: (row.recorded_by as string | undefined) ?? 'unknown',\n message: (row.change_note as string | undefined) ?? undefined,\n ts: (row.recorded_at as string) ?? new Date(0).toISOString(),\n source: (row.source as string | undefined) ?? 'sys-metadata-repo',\n };\n }\n }\n\n /**\n * Live event stream. Fires for every successful put/delete on THIS\n * instance — cross-replica fan-out is M1. Manual AsyncIterator (not\n * an async generator) so we can deterministically tear down via\n * `iter.return()`, matching the pattern used by InMemoryRepository.\n */\n watch(filter: WatchFilter, since?: number): AsyncIterable<MetadataEvent> {\n const self = this;\n return {\n [Symbol.asyncIterator]: () => {\n const queue: MetadataEvent[] = [];\n let pendingResolve: ((r: IteratorResult<MetadataEvent>) => void) | null = null;\n let stopped = false;\n\n const dispatch = (evt: MetadataEvent) => {\n if (stopped) return;\n if (!self.matchesFilter(evt, filter)) return;\n if (since !== undefined && evt.seq <= since) return;\n if (pendingResolve) {\n const r = pendingResolve;\n pendingResolve = null;\n r({ value: evt, done: false });\n } else {\n queue.push(evt);\n }\n };\n self.watchers.add(dispatch);\n\n return {\n next(): Promise<IteratorResult<MetadataEvent>> {\n if (stopped) return Promise.resolve({ value: undefined as any, done: true });\n const buffered = queue.shift();\n if (buffered) return Promise.resolve({ value: buffered, done: false });\n return new Promise((resolve) => {\n pendingResolve = resolve;\n });\n },\n return(): Promise<IteratorResult<MetadataEvent>> {\n stopped = true;\n self.watchers.delete(dispatch);\n if (pendingResolve) {\n const r = pendingResolve;\n pendingResolve = null;\n r({ value: undefined as any, done: true });\n }\n return Promise.resolve({ value: undefined as any, done: true });\n },\n };\n },\n };\n }\n\n /** Shut down all watch iterators. */\n close(): void {\n this.closed = true;\n // Drain watchers — each one's `return()` removes itself.\n const snapshot = Array.from(this.watchers);\n for (const w of snapshot) {\n try {\n w({\n seq: -1,\n op: 'delete',\n ref: { org: '', type: 'view', name: '_close' } as MetaRef,\n hash: null,\n parentHash: null,\n actor: 'system',\n ts: new Date().toISOString(),\n source: 'sys-metadata-repo-close',\n });\n } catch { /* noop */ }\n }\n this.watchers.clear();\n }\n\n // ── helpers ─────────────────────────────────────────────────────────\n\n private assertOpen(): void {\n if (this.closed) throw new Error('SysMetadataRepository is closed');\n }\n\n /**\n * Defense-in-depth authorization gate.\n *\n * `intent` defaults to `'override-artifact'` (the historical strict\n * behavior). The protocol layer passes `'runtime-only'` after it has\n * verified — via the schema registry — that no artifact item exists\n * at `(type, name)`. In that case we accept types with\n * `allowRuntimeCreate: true`, even when `allowOrgOverride` is false.\n *\n * The env-var escape hatch (`OS_METADATA_WRITABLE`) still\n * applies to BOTH intents, so operators can opt into artifact\n * overrides at runtime for emergency fixes.\n */\n private assertAllowed(type: string, intent: MetadataWriteIntent = 'override-artifact'): void {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n const allowedByRegistry = OVERLAY_ALLOWED_TYPES.has(singular) || OVERLAY_ALLOWED_TYPES.has(type);\n if (allowedByRegistry) return;\n\n // Two-tier extension: runtime-only writes target a brand-new\n // (artifact-free) item, so they only need `allowRuntimeCreate`.\n // Two cases qualify:\n // 1. Type is statically registered with `allowRuntimeCreate: true`.\n // 2. Type has NO static registry entry — it was added at runtime\n // by a plugin (e.g. `theme`, `api`, `connector`). The listing\n // endpoint synthesises `allowRuntimeCreate: true` for these,\n // so the write gate must accept them too. Otherwise the UI\n // would advertise a writable type that 403s on save.\n if (intent === 'runtime-only') {\n if (RUNTIME_CREATE_ALLOWED_TYPES.has(singular) || RUNTIME_CREATE_ALLOWED_TYPES.has(type)) {\n return;\n }\n if (!STATIC_REGISTRY_TYPES.has(singular) && !STATIC_REGISTRY_TYPES.has(type)) {\n return;\n }\n }\n\n // Phase 3a-env-writable: env-var escape hatch.\n const env = envWritableMetadataTypes();\n if (env.has(singular) || env.has(type)) return;\n\n const allowed = [\n ...OVERLAY_ALLOWED_TYPES,\n ...envWritableMetadataTypes(),\n ];\n const code = intent === 'runtime-only' ? 'not_creatable' : 'not_overridable';\n const detail = intent === 'runtime-only'\n ? `'${type}' has neither allowOrgOverride nor allowRuntimeCreate in the registry. `\n : `'${type}' is not allowOrgOverride in the registry. `;\n const err: any = new Error(\n `[${code}] ${detail}` +\n `Overlay-allowed: ${Array.from(new Set(allowed)).join(', ') || '(none)'}. ` +\n `Set OS_METADATA_WRITABLE to enable additional types at runtime.`,\n );\n err.code = code;\n err.status = 403;\n throw err;\n }\n\n private whereFor(\n ref: Pick<MetaRef, 'type' | 'name'>,\n state: OverlayState = 'active',\n ): Record<string, unknown> {\n return {\n type: ref.type,\n name: ref.name,\n organization_id: this.organizationId,\n state,\n };\n }\n\n private fullRef(ref: Pick<MetaRef, 'type' | 'name'>): MetaRef {\n return {\n org: this.orgLabel,\n type: ref.type,\n name: ref.name,\n };\n }\n\n private rowToItem(ref: Pick<MetaRef, 'type' | 'name'>, row: any): MetadataItem {\n const body: Record<string, unknown> =\n typeof row.metadata === 'string' ? JSON.parse(row.metadata) : (row.metadata ?? {});\n const hash: string = row.checksum ?? hashSpec(body);\n return {\n ref: this.fullRef(ref),\n body,\n hash,\n parentHash: null,\n authoredBy: row.updated_by ?? row.created_by ?? 'unknown',\n authoredAt: row.updated_at ?? row.created_at ?? new Date().toISOString(),\n message: undefined,\n seq: this.seqCounter,\n };\n }\n\n private broadcast(evt: MetadataEvent): void {\n for (const w of Array.from(this.watchers)) {\n try { w(evt); } catch { /* listener errors don't break the repo */ }\n }\n }\n\n private matchesFilter(evt: MetadataEvent, filter: WatchFilter): boolean {\n if (filter.type && evt.ref.type !== filter.type) return false;\n if (filter.name && evt.ref.name !== filter.name) return false;\n if (filter.org && evt.ref.org !== filter.org) return false;\n return true;\n }\n\n /**\n * Per-org monotonic event sequence. Reads `MAX(event_seq) + 1` from\n * `sys_metadata_history` scoped by `organization_id`. MUST be called\n * inside a transaction (the only caller is the put/delete txn body) —\n * concurrent writers in the same org race otherwise.\n */\n private async nextEventSeq(ctx: any): Promise<number> {\n try {\n const rows = await this.engine.find(this.historyTable, {\n where: { organization_id: this.organizationId },\n context: ctx,\n });\n let max = 0;\n for (const row of rows as Array<{ event_seq?: number | null }>) {\n const v = typeof row.event_seq === 'number' ? row.event_seq : 0;\n if (v > max) max = v;\n }\n return max + 1;\n } catch {\n // Table not provisioned yet (fresh DB) — start at 1.\n return 1;\n }\n }\n\n /**\n * Per-(org,type,name) lineage counter. Reads from history (not from\n * `sys_metadata.version`) so delete + recreate continues incrementing\n * instead of restarting at 1.\n */\n private async nextItemVersion(\n ref: Pick<MetaRef, 'type' | 'name'>,\n ctx: any,\n ): Promise<number> {\n try {\n const rows = await this.engine.find(this.historyTable, {\n where: {\n organization_id: this.organizationId,\n type: ref.type,\n name: ref.name,\n },\n context: ctx,\n });\n let max = 0;\n for (const row of rows as Array<{ version?: number | null }>) {\n const v = typeof row.version === 'number' ? row.version : 0;\n if (v > max) max = v;\n }\n return max + 1;\n } catch {\n return 1;\n }\n }\n\n /** Lightweight UUID-ish id for history rows; sufficient for an audit log. */\n private uuid(): string {\n if (typeof globalThis.crypto?.randomUUID === 'function') {\n return globalThis.crypto.randomUUID();\n }\n return `evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Load-time metadata diagnostics.\n *\n * Decorates metadata documents read from `getMetaItems()` /\n * `getMetaItem()` with a `_diagnostics` envelope so Studio (and any\n * other consumer) can render validity badges, inline field errors, and\n * governance dashboards without having to re-implement spec validation\n * on the client.\n *\n * Single source of truth: the same {@link getMetadataTypeSchema} that\n * the save path (`protocol.saveMetaItem` →\n * `resolveOverlaySchema().safeParse()`) and the JSON-Schema emitter\n * (`getMetaTypes() → entries[].schema`) already consult. Adding a new\n * metadata type's Zod schema in one place automatically wires it up\n * for read-time diagnostics, write-time validation, **and** Studio's\n * form renderer.\n *\n * Wire shape (`_diagnostics`) intentionally mirrors the existing\n * {@link MetadataValidationResult} type from\n * `@objectstack/spec/kernel` so consumers can share one type alias\n * across the validate / write / read surfaces.\n */\n\nimport type { z } from 'zod';\nimport { getMetadataTypeSchema } from '@objectstack/spec/kernel';\nimport type { MetadataValidationResult } from '@objectstack/spec/kernel';\nimport { PLURAL_TO_SINGULAR } from '@objectstack/spec/shared';\n\n/**\n * Re-export the canonical validation-result type so callers in this\n * package don't need to dual-import from `@objectstack/spec/kernel`.\n */\nexport type MetadataDiagnostics = MetadataValidationResult;\n\n/**\n * Compute spec diagnostics for a single metadata document.\n *\n * Returns `undefined` when the type has no registered Zod schema\n * (`function` / `service` / `router`, or any plugin type that has not\n * called `registerMetadataTypeSchema()`). Callers MUST treat that as\n * \"no opinion\" — not as \"valid\" — and either skip decoration entirely\n * or surface a `validatable: false` flag if their UI cares.\n */\nexport function computeMetadataDiagnostics(\n type: string,\n item: unknown,\n): MetadataDiagnostics | undefined {\n const singular = PLURAL_TO_SINGULAR[type] ?? type;\n const schema = getMetadataTypeSchema(singular);\n if (!schema) return undefined;\n\n if (item === null || item === undefined || typeof item !== 'object') {\n return {\n valid: false,\n errors: [{\n path: '',\n message: 'Metadata document must be a non-null object',\n code: 'invalid_type',\n }],\n };\n }\n\n // Strip our own decoration before re-validating so it never becomes\n // a false-positive \"unrecognized_keys\" failure on schemas that grow\n // a `.strict()` mode in the future.\n const candidate = '_diagnostics' in (item as Record<string, unknown>)\n ? stripDiagnostics(item as Record<string, unknown>)\n : item;\n\n const parsed = (schema as z.ZodTypeAny).safeParse(candidate);\n if (parsed.success) {\n return { valid: true };\n }\n\n const errors = parsed.error.issues.map((issue) => ({\n path: issue.path.map(String).join('.'),\n message: issue.message,\n code: issue.code as string,\n }));\n\n return { valid: false, errors };\n}\n\nfunction stripDiagnostics(item: Record<string, unknown>): Record<string, unknown> {\n const { _diagnostics: _drop, ...rest } = item;\n void _drop;\n return rest;\n}\n\n/**\n * Attach `_diagnostics` to a single metadata item. Returns the item\n * unchanged when no diagnostics could be computed (unknown type) or\n * when the input is not an object.\n *\n * The returned reference is always a shallow copy when decoration\n * occurs — callers must not assume identity equality with the input.\n */\nexport function decorateMetadataItem<T>(type: string, item: T): T {\n if (!item || typeof item !== 'object') return item;\n const diagnostics = computeMetadataDiagnostics(type, item);\n if (!diagnostics) return item;\n return { ...(item as Record<string, unknown>), _diagnostics: diagnostics } as T;\n}\n\n/**\n * Decorate an array of metadata items. Non-array inputs and non-object\n * elements are returned unchanged, preserving the upstream defensive\n * \"items may be a wrapped or naked array\" contract documented in\n * `rest-server.ts`.\n */\nexport function decorateMetadataItems<T>(type: string, items: T[]): T[] {\n if (!Array.isArray(items)) return items;\n return items.map((item) => decorateMetadataItem(type, item));\n}\n\n// ---------------------------------------------------------------------------\n// ADR-0047 — reference-integrity diagnostics for list views\n// ---------------------------------------------------------------------------\n\n/** Minimal object-definition shape the reference checker needs. */\ninterface ObjectDefLike {\n fields?: Record<string, { type?: string }> | Array<{ name: string; type?: string }>;\n}\n\nfunction fieldMap(objectDef: ObjectDefLike): Map<string, { type?: string }> {\n const map = new Map<string, { type?: string }>();\n const fields = objectDef?.fields;\n if (Array.isArray(fields)) {\n for (const f of fields) if (f?.name) map.set(f.name, f);\n } else if (fields && typeof fields === 'object') {\n for (const [name, f] of Object.entries(fields)) map.set(name, f ?? {});\n }\n return map;\n}\n\n/**\n * Cross-document reference checks Zod cannot express: every field a list\n * view's user-facing filter surface points at must exist on the source\n * object, and binding-dependent visualizations must have resolvable\n * bindings (kanban → select-like `groupByField`).\n *\n * Pure function — callers (read decoration, the ADR-0033 AI apply loop)\n * supply the already-resolved object definition. Returns `{ valid: true }`\n * when every reference resolves; errors use the same wire shape as\n * {@link computeMetadataDiagnostics} so consumers can merge the two.\n *\n * Spec-shape validation stays in `computeMetadataDiagnostics`; this only\n * covers what a schema alone cannot see.\n */\nexport function computeViewReferenceDiagnostics(\n view: Record<string, unknown>,\n objectDef: ObjectDefLike,\n): MetadataDiagnostics {\n const fields = fieldMap(objectDef);\n const errors: NonNullable<MetadataDiagnostics['errors']> = [];\n const requireField = (name: unknown, path: string) => {\n if (typeof name !== 'string' || !name) return;\n if (!fields.has(name)) {\n errors.push({\n path,\n message: `Field \"${name}\" does not exist on the source object`,\n code: 'reference_not_found',\n });\n }\n };\n\n const userFilters = view?.userFilters as\n | { fields?: Array<{ field?: string }>; tabs?: Array<{ filter?: Array<{ field?: string }> }> }\n | undefined;\n userFilters?.fields?.forEach((f, i) => requireField(f?.field, `userFilters.fields.${i}.field`));\n userFilters?.tabs?.forEach((t, i) =>\n t?.filter?.forEach((r, j) => requireField(r?.field, `userFilters.tabs.${i}.filter.${j}.field`)));\n\n (view?.tabs as Array<{ filter?: Array<{ field?: string }> }> | undefined)?.forEach((t, i) =>\n t?.filter?.forEach((r, j) => requireField(r?.field, `tabs.${i}.filter.${j}.field`)));\n\n (view?.filterableFields as string[] | undefined)?.forEach((f, i) =>\n requireField(f, `filterableFields.${i}`));\n\n const kanban = view?.kanban as { groupByField?: string } | undefined;\n if (kanban?.groupByField) {\n requireField(kanban.groupByField, 'kanban.groupByField');\n const def = fields.get(kanban.groupByField);\n if (def && def.type && !['select', 'multi-select', 'boolean', 'lookup', 'master_detail'].includes(def.type)) {\n errors.push({\n path: 'kanban.groupByField',\n message: `Field \"${kanban.groupByField}\" (type \"${def.type}\") cannot group a kanban — use a select-like field`,\n code: 'invalid_binding',\n });\n }\n }\n\n return errors.length ? { valid: false, errors } : { valid: true };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { QueryAST, HookContext, ServiceObject } from '@objectstack/spec/data';\nimport {\n EngineQueryOptions,\n DataEngineInsertOptions,\n EngineUpdateOptions,\n EngineDeleteOptions,\n EngineAggregateOptions,\n EngineCountOptions\n} from '@objectstack/spec/data';\nimport { ExecutionContext, ExecutionContextSchema } from '@objectstack/spec/kernel';\nimport { DriverInterface, IDataEngine, Logger, createLogger } from '@objectstack/core';\nimport { CoreServiceName, StorageNameMapping } from '@objectstack/spec/system';\nimport { IRealtimeService, RealtimeEventPayload } from '@objectstack/spec/contracts';\nimport type { ICryptoProvider, CryptoHandle } from '@objectstack/spec/contracts';\nimport {\n collectSecretFields,\n makeSecretRef,\n parseSecretRef,\n isSecretRef,\n SECRET_MASK,\n} from './secret-fields.js';\nimport { pluralToSingular, ExternalWriteForbiddenError } from '@objectstack/spec/shared';\nimport { SchemaRegistry, computeFQN } from './registry.js';\nimport { ExpressionEngine } from '@objectstack/formula';\nimport type { Expression } from '@objectstack/spec';\nimport { isAggregatedViewContainer, expandViewContainer } from '@objectstack/spec';\nimport { bindHooksToEngine } from './hook-binder.js';\nimport { validateRecord } from './validation/record-validator.js';\nimport { evaluateValidationRules, needsPriorRecord, stripReadonlyWhenFields } from './validation/rule-validator.js';\nimport { applyInMemoryAggregation } from './in-memory-aggregation.js';\n\ninterface FormulaPlanEntry { name: string; expression: Expression; }\n\nfunction planFormulaProjection(\n schema: any,\n requestedFields: string[] | undefined\n): { plan: FormulaPlanEntry[]; projected?: string[] } {\n if (!schema?.fields) return { plan: [] };\n const allFieldNames = Object.keys(schema.fields);\n // When no explicit projection, evaluate every formula field on the schema —\n // matches REST default of \"return everything\". Explicit projection still\n // honours the caller's selection.\n const targets = (Array.isArray(requestedFields) && requestedFields.length > 0)\n ? requestedFields\n : allFieldNames;\n const plan: FormulaPlanEntry[] = [];\n const projected = new Set<string>();\n for (const f of targets) {\n const def = (schema.fields as any)[f];\n if (def?.type === 'formula' && def.expression) {\n // Normalize string-shorthand → Expression envelope (M9 transition).\n const expr: Expression = typeof def.expression === 'string'\n ? { dialect: 'cel', source: def.expression }\n : def.expression;\n plan.push({ name: f, expression: expr });\n // Pre-compile to surface syntax errors at planning stage rather than\n // per-row eval. Dependency discovery (which fields the formula reads)\n // is no longer used — CEL uses dynamic projection via `record.<field>`.\n ExpressionEngine.compile(expr);\n } else if (Array.isArray(requestedFields) && requestedFields.length > 0) {\n projected.add(f);\n }\n }\n if (plan.length === 0) return { plan: [] };\n // For formulas: project all schema fields so CEL `record.<field>` lookups\n // see complete data. Static dependency analysis on AST is M9.7 work.\n if (Array.isArray(requestedFields) && requestedFields.length > 0) {\n if (!projected.has('id')) projected.add('id');\n for (const fname of allFieldNames) {\n // Skip formula fields themselves — they are virtual and not\n // projectable by the underlying driver. Without this guard the\n // SQL driver emits `SELECT response_rate ...` which fails as\n // \"no such column\" and the driver returns [] (silently).\n const fdef = (schema.fields as any)[fname];\n if (fdef?.type === 'formula') continue;\n projected.add(fname);\n }\n return { plan, projected: Array.from(projected) };\n }\n // Implicit/full projection — leave projected undefined so the driver\n // returns its default columns (typically *).\n return { plan };\n}\n\nfunction applyFormulaPlan(plan: FormulaPlanEntry[], records: any[]): void {\n if (!plan.length) return;\n for (const rec of records) {\n if (rec == null) continue;\n for (const fp of plan) {\n const r = ExpressionEngine.evaluate(fp.expression, { record: rec });\n rec[fp.name] = r.ok ? r.value : null;\n }\n }\n}\n\nexport type HookHandler = (context: HookContext) => Promise<void> | void;\n\n/**\n * Per-object hook entry with priority support\n */\nexport interface HookEntry {\n handler: HookHandler;\n object?: string | string[]; // undefined = global hook\n priority: number;\n packageId?: string;\n /**\n * Original metadata-form `Hook` definition this entry was bound from\n * (when registered via `bindHooksToEngine`). Pure code-paths that call\n * `engine.registerHook` directly leave this undefined.\n */\n meta?: any;\n /** Hook `name` from metadata; used for diagnostics & deduplication. */\n hookName?: string;\n}\n\n/** Function registry entry — see `registerFunction`. */\ninterface FunctionEntry {\n handler: HookHandler;\n packageId?: string;\n}\n\n/**\n * Operation Context for Middleware Chain\n */\nexport interface OperationContext {\n object: string;\n operation: 'find' | 'findOne' | 'insert' | 'update' | 'delete' | 'count' | 'aggregate';\n ast?: QueryAST;\n data?: any;\n options?: any;\n context?: ExecutionContext;\n result?: any;\n}\n\n/**\n * Engine Middleware (Onion model)\n */\nexport type EngineMiddleware = (\n ctx: OperationContext,\n next: () => Promise<void>\n) => Promise<void>;\n\n/**\n * Host Context provided to plugins (Internal ObjectQL Plugin System)\n */\nexport interface ObjectQLHostContext {\n ql: ObjectQL;\n logger: Logger;\n // Extensible map for host-specific globals (like HTTP Router, etc.)\n [key: string]: any;\n}\n\n/**\n * Derive the registry key for a metadata item.\n *\n * Most metadata items expose a top-level `name` (or `id`). The `View`\n * container defined by `@objectstack/spec/ui` is special: it aggregates\n * `list / form / listViews / formViews` for a single object and is\n * keyed implicitly by its target object name (see `data.object`).\n *\n * Per spec, `ViewSchema` does NOT have a top-level `name` field\n * (view.zod.ts), so we resolve it from the inner data source. This\n * matches the server-side metadata API contract (`/api/v1/meta/views/:object`).\n */\nfunction resolveMetadataItemName(key: string, item: any): string | undefined {\n if (!item) return undefined;\n if (item.name) return item.name;\n if (item.id) return item.id;\n if (key === 'views') {\n // Independent ViewItems (\"Object has-many View\") carry a top-level `name`\n // (handled above) and bind to their object via `object`. The aggregated\n // container has no top-level name/object, so fall back to its inner data\n // source — matching the loader's expansion key.\n return (\n item?.object ||\n item?.list?.data?.object ||\n item?.form?.data?.object ||\n undefined\n );\n }\n return undefined;\n}\n\n/**\n * ObjectQL Engine\n * \n * Implements the IDataEngine interface for data persistence.\n * Acts as the reference implementation for:\n * - CoreServiceName.data (CRUD)\n * - CoreServiceName.metadata (Schema Registry)\n */\n/** A roll-up `summary` field on a parent object that aggregates a child. */\ninterface SummaryDescriptor {\n parentObject: string;\n summaryField: string;\n /** FK field on the child pointing back to the parent. */\n fkField: string;\n fn: 'count' | 'sum' | 'min' | 'max' | 'avg';\n /** Child field aggregated (unused for count). */\n sourceField: string;\n}\n\nexport class ObjectQL implements IDataEngine {\n /**\n * Ambient transaction store (ADR-0034). While a `transaction()` callback\n * runs, the active transaction handle lives here so that EVERY data\n * operation — including internal reads done during a write (reference\n * checks, hooks, expand) — automatically binds to the same connection\n * instead of asking the pool for another one and deadlocking on the\n * single-connection SQLite pool.\n */\n private readonly txStore = new AsyncLocalStorage<{ transaction: unknown }>();\n\n private drivers = new Map<string, DriverInterface>();\n private defaultDriver: string | null = null;\n private logger: Logger;\n\n // Datasource mapping rules (imported from defineStack)\n private datasourceMapping: Array<{\n namespace?: string;\n package?: string;\n objectPattern?: string;\n default?: boolean;\n datasource: string;\n priority?: number;\n }> = [];\n\n // Package manifests registry (for defaultDatasource lookup)\n private manifests = new Map<string, any>();\n\n // Datasource definitions by name (ADR-0015): carries schemaMode +\n // external.allowWrites so the write gate (Gate 3) can enforce federation\n // ownership. Populated from manifests in registerApp and via\n // registerDatasourceDef. Absent entry ⇒ treated as managed (default DB).\n private datasourceDefs = new Map<string, { schemaMode?: string; external?: { allowWrites?: boolean } }>();\n\n // Per-object hooks with priority support\n private hooks: Map<string, HookEntry[]> = new Map([\n ['beforeFind', []], ['afterFind', []],\n ['beforeInsert', []], ['afterInsert', []],\n ['beforeUpdate', []], ['afterUpdate', []],\n ['beforeDelete', []], ['afterDelete', []],\n ]);\n\n // Middleware chain (onion model)\n private middlewares: Array<{\n fn: EngineMiddleware;\n object?: string;\n }> = [];\n\n // Action registry: key = \"objectName:actionName\"\n private actions = new Map<string, { handler: (ctx: any) => Promise<any> | any; package?: string }>();\n\n // Function registry: name → handler. Used by `bindHooksToEngine` to\n // resolve string-named hook handlers (the JSON-safe form). Populated by\n // `defineStack({ functions })` via `AppPlugin`, or directly via\n // `engine.registerFunction(...)`.\n private functions = new Map<string, FunctionEntry>();\n\n // Host provided context additions (e.g. Server router)\n private hostContext: Record<string, any> = {};\n\n // Realtime service for event publishing\n private realtimeService?: IRealtimeService;\n\n // Crypto provider backing `secret`-typed fields. Optional: when absent,\n // writing an object that declares a secret field fails closed (never\n // persists cleartext). Injected by the host via setCryptoProvider().\n private cryptoProvider?: ICryptoProvider;\n\n // Per-engine SchemaRegistry instance.\n //\n // Historically SchemaRegistry was a process-wide singleton of static state,\n // which broke multi-environment servers: a project kernel would inherit every\n // object registered by the control plane (e.g. sys_metadata), and\n // getDriver()'s owner lookup would route CRUD to the wrong database. Each\n // engine now owns its registry so kernels are fully isolated.\n private _registry: SchemaRegistry = new SchemaRegistry();\n\n constructor(hostContext: Record<string, any> = {}) {\n this.hostContext = hostContext;\n // Use provided logger or create a new one\n this.logger = hostContext.logger || createLogger({ level: 'info', format: 'pretty' });\n // Pick up production hardening switches from env so deployers can\n // enforce strict-body without code changes:\n // OBJECTQL_STRICT_HOOKS=1 → unresolved hooks throw at bind time\n // OBJECTQL_WARN_LEGACY_HANDLER=1 → log a deprecation per legacy bind\n if (process?.env?.OBJECTQL_STRICT_HOOKS === '1') {\n (this as any)._strictHookBinding = true;\n }\n if (process?.env?.OBJECTQL_WARN_LEGACY_HANDLER === '1') {\n (this as any)._warnLegacyHandler = true;\n }\n this.logger.info('ObjectQL Engine Instance Created');\n }\n\n /**\n * Service Status Report\n * Used by Kernel to verify health and capabilities.\n */\n getStatus() {\n return {\n name: CoreServiceName.enum.data,\n status: 'running',\n version: '0.9.0',\n features: ['crud', 'query', 'aggregate', 'transactions', 'metadata']\n };\n }\n\n /**\n * Expose the SchemaRegistry for plugins to register metadata.\n *\n * Returns the per-engine instance, NOT the class. Each ObjectQL engine\n * owns its registry so multi-environment kernels remain isolated.\n */\n get registry(): SchemaRegistry {\n return this._registry;\n }\n\n /**\n * Load and Register a Plugin\n */\n async use(manifestPart: any, runtimePart?: any) {\n this.logger.debug('Loading plugin', { \n hasManifest: !!manifestPart, \n hasRuntime: !!runtimePart \n });\n\n // 1. Validate / Register Manifest\n if (manifestPart) {\n this.registerApp(manifestPart);\n }\n\n // 2. Execute Runtime\n if (runtimePart) {\n const pluginDef = (runtimePart as any).default || runtimePart;\n if (pluginDef.onEnable) {\n this.logger.debug('Executing plugin runtime onEnable');\n \n const context: ObjectQLHostContext = {\n ql: this,\n logger: this.logger,\n // Expose the driver registry helper explicitly if needed\n drivers: {\n register: (driver: DriverInterface) => this.registerDriver(driver)\n },\n ...this.hostContext\n };\n \n await pluginDef.onEnable(context);\n this.logger.debug('Plugin runtime onEnable completed');\n }\n }\n }\n\n /**\n * Register a hook\n * @param event The event name (e.g. 'beforeFind', 'afterInsert')\n * @param handler The handler function\n * @param options Optional: target object(s) and priority\n */\n registerHook(event: string, handler: HookHandler, options?: {\n object?: string | string[];\n priority?: number;\n packageId?: string;\n /** Original metadata Hook definition (set by `bindHooksToEngine`). */\n meta?: any;\n /** Stable name from metadata (set by `bindHooksToEngine`). */\n hookName?: string;\n }) {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n const entries = this.hooks.get(event)!;\n entries.push({\n handler,\n object: options?.object,\n priority: options?.priority ?? 100,\n packageId: options?.packageId,\n meta: options?.meta,\n hookName: options?.hookName,\n });\n // Sort by priority (lower runs first)\n entries.sort((a, b) => a.priority - b.priority);\n this.logger.debug('Registered hook', { event, object: options?.object, priority: options?.priority ?? 100, totalHandlers: entries.length });\n }\n\n /**\n * Remove all hooks registered under a given `packageId`. Used by\n * `bindHooksToEngine` to make re-binding (hot reload, app reinstall)\n * idempotent, and by app uninstall flows.\n */\n unregisterHooksByPackage(packageId: string): number {\n if (!packageId) return 0;\n let removed = 0;\n for (const [event, entries] of this.hooks.entries()) {\n const before = entries.length;\n const kept = entries.filter((e) => e.packageId !== packageId);\n if (kept.length !== before) {\n this.hooks.set(event, kept);\n removed += before - kept.length;\n }\n }\n if (removed > 0) {\n this.logger.debug('Unregistered hooks by package', { packageId, removed });\n }\n return removed;\n }\n\n /**\n * Register a named function handler that can later be referenced by\n * string from a `Hook.handler` field. This is the JSON-safe form of\n * handler binding — declarative metadata persisted to disk or shipped\n * over the wire only carries the name.\n */\n registerFunction(name: string, handler: HookHandler, packageId?: string): void {\n if (!name || typeof handler !== 'function') return;\n this.functions.set(name, { handler, packageId });\n this.logger.debug('Registered function', { name, packageId });\n }\n\n /** Look up a registered function by name. */\n resolveFunction(name: string): HookHandler | undefined {\n return this.functions.get(name)?.handler;\n }\n\n /** Remove all functions registered under a given `packageId`. */\n unregisterFunctionsByPackage(packageId: string): number {\n if (!packageId) return 0;\n let removed = 0;\n for (const [name, entry] of this.functions.entries()) {\n if (entry.packageId === packageId) {\n this.functions.delete(name);\n removed += 1;\n }\n }\n if (removed > 0) {\n this.logger.debug('Unregistered functions by package', { packageId, removed });\n }\n return removed;\n }\n\n /**\n * Bind a list of declarative `Hook` metadata definitions to this engine.\n *\n * Convenience proxy to the canonical `bindHooksToEngine` so callers do\n * not need a separate import. Use `import { bindHooksToEngine } from\n * '@objectstack/objectql'` directly when you want the result object.\n */\n bindHooks(hooks: any[] | undefined, opts?: {\n packageId?: string;\n functions?: Record<string, HookHandler>;\n bodyRunner?: any;\n strict?: boolean;\n warnLegacyHandler?: boolean;\n metrics?: any;\n }): void {\n const merged = { ...(opts ?? {}), logger: this.logger } as any;\n if (!merged.bodyRunner && (this as any)._defaultBodyRunner) {\n merged.bodyRunner = (this as any)._defaultBodyRunner;\n }\n if (merged.strict === undefined && (this as any)._strictHookBinding) {\n merged.strict = true;\n }\n if (merged.warnLegacyHandler === undefined && (this as any)._warnLegacyHandler) {\n merged.warnLegacyHandler = true;\n }\n if (!merged.metrics && (this as any)._hookMetricsRecorder) {\n merged.metrics = (this as any)._hookMetricsRecorder;\n }\n bindHooksToEngine(this, hooks, merged);\n }\n\n /**\n * Install a default body-runner used when `bindHooks` is called without\n * an explicit one. The runtime layer sets this once on each per-project\n * engine so every binding path (template seed, metadata sync, AppPlugin)\n * can execute hook `body.source` consistently.\n */\n setDefaultBodyRunner(runner: any): void {\n (this as any)._defaultBodyRunner = runner;\n }\n\n /**\n * Toggle strict hook-binding mode for this engine. When enabled, every\n * subsequent `bindHooks` call rejects on the first unresolved hook\n * instead of silently warning. Production runtimes should enable this.\n */\n setStrictHookBinding(strict: boolean): void {\n (this as any)._strictHookBinding = strict;\n }\n\n /** Toggle deprecation warnings for hooks still using legacy `handler` ref. */\n setWarnLegacyHandler(warn: boolean): void {\n (this as any)._warnLegacyHandler = warn;\n }\n\n /**\n * Install a metrics recorder used by every subsequent `bindHooks` call.\n * The recorder's methods are invoked per-execution to count outcomes\n * (success / error / timeout / capability_rejected), skips, and retries.\n * Defaults to no-op so the engine pays zero cost when nobody is observing.\n */\n setHookMetricsRecorder(recorder: any): void {\n (this as any)._hookMetricsRecorder = recorder;\n }\n\n /** Read the engine's installed metrics recorder, if any. */\n getHookMetricsRecorder(): any {\n return (this as any)._hookMetricsRecorder;\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const entries = this.hooks.get(event) || [];\n \n if (entries.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: entries.length });\n \n for (const entry of entries) {\n // Per-object matching\n if (entry.object) {\n const targets = Array.isArray(entry.object) ? entry.object : [entry.object];\n if (!targets.includes('*') && !targets.includes(context.object)) {\n continue; // Skip non-matching hooks\n }\n }\n await entry.handler(context);\n }\n }\n\n // ========================================\n // Action System\n // ========================================\n\n /**\n * Register a named action on an object.\n * Actions are custom business logic callable via `repo.execute(actionName, params)`.\n *\n * @param objectName Target object\n * @param actionName Unique action name within the object\n * @param handler Handler function\n * @param packageName Optional package owner (for cleanup)\n */\n registerAction(objectName: string, actionName: string, handler: (ctx: any) => Promise<any> | any, packageName?: string): void {\n const key = `${objectName}:${actionName}`;\n this.actions.set(key, { handler, package: packageName });\n this.logger.debug('Registered action', { objectName, actionName, package: packageName });\n }\n\n /**\n * Execute a named action on an object.\n */\n async executeAction(objectName: string, actionName: string, ctx: any): Promise<any> {\n const entry = this.actions.get(`${objectName}:${actionName}`);\n if (!entry) {\n throw new Error(`Action '${actionName}' on object '${objectName}' not found`);\n }\n return entry.handler(ctx);\n }\n\n /**\n * Remove all actions registered by a specific package.\n */\n removeActionsByPackage(packageName: string): void {\n for (const [key, entry] of this.actions.entries()) {\n if (entry.package === packageName) {\n this.actions.delete(key);\n }\n }\n }\n\n /**\n * Register a middleware function\n * Middlewares execute in onion model around every data operation.\n * @param fn The middleware function\n * @param options Optional: target object filter\n */\n registerMiddleware(fn: EngineMiddleware, options?: { object?: string }): void {\n this.middlewares.push({ fn, object: options?.object });\n this.logger.debug('Registered middleware', { object: options?.object, total: this.middlewares.length });\n }\n\n /**\n * Execute an operation through the middleware chain\n */\n private async executeWithMiddleware(ctx: OperationContext, executor: () => Promise<any>): Promise<any> {\n const applicable = this.middlewares.filter(m =>\n !m.object || m.object === '*' || m.object === ctx.object\n );\n\n let index = 0;\n const next = async (): Promise<void> => {\n if (index < applicable.length) {\n const mw = applicable[index++];\n await mw.fn(ctx, next);\n } else {\n ctx.result = await executor();\n }\n };\n\n await next();\n return ctx.result;\n }\n\n /**\n * Build a HookContext.session from ExecutionContext\n */\n private buildSession(execCtx?: ExecutionContext): HookContext['session'] {\n if (!execCtx) return undefined;\n return {\n userId: execCtx.userId,\n tenantId: execCtx.tenantId,\n roles: execCtx.roles,\n accessToken: execCtx.accessToken,\n // Propagate system-elevated flag so hooks can distinguish engine\n // self-writes (e.g. approval status mirror) from genuine user writes.\n ...((execCtx as any).isSystem ? { isSystem: true } : {}),\n } as HookContext['session'];\n }\n\n /**\n * Build the DriverOptions blob passed to every IDataDriver call.\n *\n * Always carries `tenantId` from the active ExecutionContext so the\n * driver can enforce per-tenant isolation (SQL driver auto-scopes reads\n * and auto-injects the tenant column on writes). Existing user-supplied\n * shapes (transactions, AST extras) are preserved by spreading them\n * first.\n *\n * System / isSystem callers may still cross tenants by clearing\n * `tenantId` themselves on the resulting object; this helper does not\n * mask the system path.\n */\n private buildDriverOptions(execCtx?: ExecutionContext, base?: any): any {\n // The open transaction may arrive explicitly via the context, or ambiently\n // via txStore when an internal query runs during a transactional write\n // (ADR-0034). Explicit wins; ambient is the safety net.\n const tx = execCtx?.transaction !== undefined\n ? execCtx.transaction\n : this.txStore.getStore()?.transaction;\n const hasTx = tx !== undefined;\n const hasTenant = execCtx?.tenantId !== undefined;\n const isSystem = execCtx?.isSystem === true;\n if (!hasTx && !hasTenant && !isSystem) return base;\n const opts: any = base && typeof base === 'object' ? { ...base } : {};\n if (hasTx && opts.transaction === undefined) {\n opts.transaction = tx;\n }\n if (hasTenant && opts.tenantId === undefined) {\n opts.tenantId = execCtx!.tenantId;\n }\n if (isSystem && opts.bypassTenantAudit === undefined) {\n // System-elevated writes (boot-time seeds, internal mirrors, scheduled\n // hooks) are unscoped by design — silence the audit warn for them but\n // still flag genuine user-path bugs.\n opts.bypassTenantAudit = true;\n }\n return opts;\n }\n\n /**\n * Build a HookContext.api: a ScopedContext that hooks can use to\n * read/write other objects within the same execution context.\n * Falls back to a system-elevated empty context when no execCtx\n * is supplied (e.g. system-triggered hooks).\n */\n private buildHookApi(execCtx?: ExecutionContext): ScopedContext {\n const safeCtx: ExecutionContext = execCtx ?? ({ isSystem: true } as any);\n return new ScopedContext(safeCtx, this as unknown as IDataEngine);\n }\n\n /**\n * Apply field defaults to an incoming insert payload. Defaults that are\n * Expression envelopes (e.g. `{ dialect: 'cel', source: 'today()' }`,\n * `{ dialect: 'cel', source: 'os.user.id' }`) are evaluated via\n * `ExpressionEngine` against the calling user/org/now snapshot. Static\n * defaults are applied verbatim. Records that already supplied a value for a\n * field are left untouched.\n *\n * Implements ROADMAP §M9.9b — `defaultValue` accepts Expression so authors\n * can replace \"write a hook to default to today/current-user\" with a\n * declarative `defaultValue: cel\\`today()\\``.\n */\n private applyFieldDefaults(\n object: string,\n record: Record<string, unknown>,\n execCtx?: ExecutionContext,\n nowSnapshot?: Date,\n ): Record<string, unknown> {\n const schema = this.getSchema(object);\n const fieldsRaw = (schema as any)?.fields;\n if (!fieldsRaw || typeof fieldsRaw !== 'object') return record;\n // `fields` may be a Record<string, Field> (canonical) or an array (legacy).\n const fieldEntries: Array<{ name: string; defaultValue?: unknown }> = Array.isArray(fieldsRaw)\n ? fieldsRaw\n : Object.entries(fieldsRaw).map(([name, def]) => ({ name, ...(def as object) }));\n const out = { ...record };\n const now = nowSnapshot ?? new Date();\n for (const f of fieldEntries) {\n if (out[f.name] !== undefined) continue;\n if (f.defaultValue == null) continue;\n const dv = f.defaultValue;\n if (typeof dv === 'object' && dv !== null && (dv as any).dialect && typeof (dv as any).source === 'string') {\n const result = ExpressionEngine.evaluate(dv as any, {\n now,\n user: execCtx?.userId ? { id: String(execCtx.userId), role: execCtx?.roles?.[0] } : undefined,\n org: execCtx?.tenantId ? { id: String(execCtx.tenantId) } : undefined,\n record: out,\n extra: { object },\n });\n if (result.ok) {\n out[f.name] = result.value as unknown;\n } else {\n this.logger.warn('Failed to evaluate default expression', {\n object, field: f.name, error: result.error,\n });\n }\n } else {\n out[f.name] = dv;\n }\n }\n return out;\n }\n\n /**\n * Generate values for empty `autonumber` fields on insert — ONLY for drivers\n * that do not generate them natively (memory, mongodb). For SQL-backed objects\n * the driver owns a persistent, atomic `_objectstack_sequences` table and\n * advertises `supports.autonumber === true`; the engine then defers entirely\n * and never pre-fills (so the persistent sequence is the single source of\n * truth — see #1603). Required-validation exempts `autonumber` either way, so\n * a `required` record number is never rejected for \"missing\" — the runtime\n * owns the value, not the client.\n *\n * In the fallback path the next value is `max(existing) + 1`, seeded once per\n * `object.field` from the store then incremented in memory (monotonic within\n * the process, resilient to deletions). `autonumberFormat` is honored, e.g.\n * `CASE-{0000}` → `CASE-0042`. NOTE: this in-memory seeding is single-instance.\n */\n private async applyAutonumbers(\n object: string,\n record: Record<string, unknown>,\n execCtx?: ExecutionContext,\n driverOwnsAutonumber?: boolean,\n ): Promise<void> {\n if (driverOwnsAutonumber) return; // driver generates persistently in create()\n const fields = (this.getSchema(object) as any)?.fields;\n if (!fields || typeof fields !== 'object' || Array.isArray(fields)) return;\n for (const [name, def] of Object.entries(fields)) {\n if ((def as any)?.type !== 'autonumber') continue;\n const current = record[name];\n if (current != null && current !== '') continue; // respect explicit value\n const key = `${object}.${name}`;\n let next = this.autonumberCounters.get(key);\n if (next == null) next = await this.seedAutonumber(object, name, execCtx);\n next += 1;\n this.autonumberCounters.set(key, next);\n // Honor either the spec-canonical `autonumberFormat` or the shorthand\n // `format` (both appear in metadata; the driver reads both too) — #1603.\n const fmt = (def as any).autonumberFormat ?? (def as any).format;\n record[name] = this.formatAutonumber(fmt, next);\n }\n }\n\n /** Seed the autonumber counter from the current max numeric value in store. */\n private async seedAutonumber(\n object: string,\n field: string,\n execCtx?: ExecutionContext,\n ): Promise<number> {\n try {\n const rows = await this.find(object, {\n select: ['id', field],\n limit: 5000,\n context: execCtx,\n } as any);\n let max = 0;\n for (const r of rows || []) {\n const v = r?.[field];\n if (v == null) continue;\n const m = String(v).match(/(\\d+)(?!.*\\d)/); // last run of digits\n if (m) max = Math.max(max, parseInt(m[1], 10) || 0);\n }\n return max;\n } catch {\n return 0;\n }\n }\n\n /** Apply an autonumber format like `CASE-{0000}`; default to the bare number. */\n private formatAutonumber(format: string | undefined, value: number): string {\n if (!format) return String(value);\n const m = format.match(/\\{(0+)\\}/);\n if (!m) return format.includes('{0}') ? format.replace('{0}', String(value)) : `${format}${value}`;\n const padded = String(value).padStart(m[1].length, '0');\n return format.replace(m[0], padded);\n }\n\n /**\n * Register contribution (Manifest)\n * \n * Installs the manifest as a Package (the unit of installation),\n * then decomposes it into individual metadata items (objects, apps, actions, etc.)\n * and registers each into the SchemaRegistry.\n * \n * Key: Package ≠ App. The manifest is the package. The apps[] array inside\n * the manifest contains UI navigation definitions (AppSchema).\n */\n registerApp(manifest: any) {\n const id = manifest.id || manifest.name;\n const namespace = manifest.namespace as string | undefined;\n this.invalidateSummaryIndex(); // new objects may add/change summary fields\n this.logger.debug('Registering package manifest', { id, namespace });\n console.warn(`[ObjectQL:registerApp] id=${id} flows=${Array.isArray(manifest.flows) ? manifest.flows.length : typeof manifest.flows} keys=${Object.keys(manifest).join(',')}`);\n\n // Store manifest for defaultDatasource lookup\n if (id) {\n this.manifests.set(id, manifest);\n }\n\n // Index datasource definitions (ADR-0015) so the write gate can read\n // schemaMode + external.allowWrites. Manifests may carry `datasources`\n // as an array or a name-keyed map.\n if (manifest.datasources) {\n const dsList = Array.isArray(manifest.datasources)\n ? manifest.datasources\n : Object.entries(manifest.datasources).map(([name, def]) => ({ name, ...(def as any) }));\n for (const ds of dsList) {\n if (ds?.name) this.registerDatasourceDef(ds);\n }\n }\n\n // 1. Register the Package (manifest + lifecycle state)\n this._registry.installPackage(manifest);\n this.logger.debug('Installed Package', { id: manifest.id, name: manifest.name, namespace });\n\n // 2. Register owned objects\n if (manifest.objects) {\n if (Array.isArray(manifest.objects)) {\n this.logger.debug('Registering objects from manifest (Array)', { id, objectCount: manifest.objects.length });\n for (const objDef of manifest.objects) {\n const fqn = this._registry.registerObject(objDef, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n } else {\n this.logger.debug('Registering objects from manifest (Map)', { id, objectCount: Object.keys(manifest.objects).length });\n for (const [name, objDef] of Object.entries(manifest.objects)) {\n // Ensure name in definition matches key\n (objDef as any).name = name;\n const fqn = this._registry.registerObject(objDef as any, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n }\n }\n\n // 2b. Register object extensions (fields added to objects owned by other packages)\n if (Array.isArray(manifest.objectExtensions) && manifest.objectExtensions.length > 0) {\n this.logger.debug('Registering object extensions', { id, count: manifest.objectExtensions.length });\n for (const ext of manifest.objectExtensions) {\n const targetFqn = ext.extend;\n const priority = ext.priority ?? 200;\n // Create a partial object definition for the extension\n const extDef = {\n name: targetFqn, // Use the target FQN as name\n fields: ext.fields,\n label: ext.label,\n pluralLabel: ext.pluralLabel,\n description: ext.description,\n validations: ext.validations,\n indexes: ext.indexes,\n };\n // Register as extension (namespace is undefined since we're targeting by FQN)\n this._registry.registerObject(extDef as any, id, undefined, 'extend', priority);\n this.logger.debug('Registered Object Extension', { target: targetFqn, priority, from: id });\n }\n }\n\n // 3. Register apps (UI navigation definitions) as their own metadata type\n // Resolve short objectName references in navigation to FQN so the\n // Console UI can match them against the object registry.\n if (Array.isArray(manifest.apps) && manifest.apps.length > 0) {\n this.logger.debug('Registering apps from manifest', { id, count: manifest.apps.length });\n for (const app of manifest.apps) {\n const appName = app.name || app.id;\n if (appName) {\n const resolved = namespace ? this.resolveNavObjectNames(app, namespace) : app;\n this._registry.registerApp(resolved, id);\n this.logger.debug('Registered App', { app: appName, from: id });\n }\n }\n }\n\n // 4. If manifest itself looks like an App (has navigation), also register as app\n // This handles the case where the manifest IS the app definition (legacy/simple packages)\n if (manifest.name && manifest.navigation && !manifest.apps?.length) {\n const resolved = namespace ? this.resolveNavObjectNames(manifest, namespace) : manifest;\n this._registry.registerApp(resolved, id);\n this.logger.debug('Registered manifest-as-app', { app: manifest.name, from: id });\n }\n\n // 4b. Register navigation contributions (ADR-0029 D7) — nav items this\n // package injects into apps owned by other packages (e.g. a\n // capability plugin adding its menu into the `setup` app). Merged\n // into the target app's navigation on read by group id + priority.\n if (Array.isArray((manifest as any).navigationContributions) && (manifest as any).navigationContributions.length > 0) {\n for (const contribution of (manifest as any).navigationContributions) {\n this._registry.registerAppNavContribution(contribution, id);\n }\n this.logger.debug('Registered navigation contributions', {\n from: id,\n count: (manifest as any).navigationContributions.length,\n });\n }\n\n // 5. Register all other metadata types generically\n const metadataArrayKeys = [\n // UI Protocol\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'datasets', 'themes',\n // Automation Protocol\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'jobs',\n // Security Protocol\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n // AI Protocol\n 'agents', 'tools', 'skills', 'ragPipelines',\n // API Protocol\n 'apis',\n // Data Extensions\n 'hooks', 'mappings', 'analyticsCubes',\n // Integration Protocol\n 'connectors',\n // System Protocol — package documentation (ADR-0046); inert data\n 'docs',\n ];\n for (const key of metadataArrayKeys) {\n const items = (manifest as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n this.logger.debug(`Registering ${key} from manifest`, { id, count: items.length });\n for (const item of items) {\n const itemName = resolveMetadataItemName(key, item);\n if (itemName) {\n const toRegister = item.name === itemName ? item : { ...item, name: itemName };\n this._registry.registerItem(pluralToSingular(key), toRegister, 'name' as any, id);\n // \"Object has-many View\" (ADR-0017): a `defineView` document\n // aggregates an object's views. Register the container under\n // the bare <object> key (above, back-compat) AND expand it\n // into independent ViewItems registered under <object>.<key>,\n // so `getViewsByObject()` / `GET /meta/view?object=` surface\n // the per-view `package` layer the switcher + Studio consume.\n if (key === 'views' && isAggregatedViewContainer(toRegister)) {\n for (const vi of expandViewContainer(itemName, toRegister)) {\n this._registry.registerItem('view', vi, 'name' as any, id);\n }\n }\n } else {\n this.logger.warn(`Skipping ${pluralToSingular(key)} without a derivable name`, { id });\n }\n }\n }\n }\n\n // 6. Register seed data as metadata (keyed by target object name)\n const seedData = (manifest as any).data;\n if (Array.isArray(seedData) && seedData.length > 0) {\n this.logger.debug('Registering seed data datasets', { id, count: seedData.length });\n for (const dataset of seedData) {\n if (dataset.object) {\n this._registry.registerItem('data', dataset, 'object' as any, id);\n }\n }\n }\n\n // 6. Register contributions\n if (manifest.contributes?.kinds) {\n this.logger.debug('Registering kinds from manifest', { id, kindCount: manifest.contributes.kinds.length });\n for (const kind of manifest.contributes.kinds) {\n this._registry.registerKind(kind);\n this.logger.debug('Registered Kind', { kind: kind.name || kind.type, from: id });\n }\n }\n\n // 7. Recursively register nested plugins\n if (Array.isArray(manifest.plugins) && manifest.plugins.length > 0) {\n this.logger.debug('Processing nested plugins', { id, count: manifest.plugins.length });\n for (const plugin of manifest.plugins) {\n if (plugin && typeof plugin === 'object') {\n const pluginName = plugin.name || plugin.id || 'unnamed-plugin';\n this.logger.debug('Registering nested plugin', { pluginName, parentId: id });\n this.registerPlugin(plugin, id, namespace);\n }\n }\n }\n }\n\n /**\n * Deep-clone an app definition, resolving objectName references in navigation\n * items via the registry. Object names are canonical identifiers — no FQN\n * expansion is applied.\n */\n private resolveNavObjectNames(app: any, namespace: string): any {\n if (!app.navigation) return app;\n\n const resolveItems = (items: any[]): any[] =>\n items.map((item: any) => {\n const resolved = { ...item };\n if (resolved.objectName && !resolved.objectName.includes('__')) {\n resolved.objectName = computeFQN(namespace, resolved.objectName);\n }\n if (Array.isArray(resolved.children)) {\n resolved.children = resolveItems(resolved.children);\n }\n return resolved;\n });\n\n return { ...app, navigation: resolveItems(app.navigation) };\n }\n\n /**\n * Register a nested plugin's metadata (objects, actions, views, etc.)\n *\n * Unlike registerApp(), this does NOT call SchemaRegistry.installPackage()\n * because plugins are not formal manifests — they are lightweight config\n * bundles with objects, actions, triggers, and navigation.\n *\n * @param plugin - The plugin config object\n * @param parentId - The parent package ID (for ownership tracking)\n * @param parentNamespace - The parent package's namespace (for FQN resolution)\n */\n private registerPlugin(plugin: any, parentId: string, parentNamespace?: string) {\n const pluginName = plugin.name || plugin.id || 'unnamed';\n const pluginNamespace = plugin.namespace || parentNamespace;\n\n // Use parentId as the owning package for namespace consistency.\n // The parent package already claimed the namespace — nested plugins\n // contribute objects UNDER the parent's ownership.\n const ownerId = parentId;\n\n // Register objects (supports both Array and Map formats)\n if (plugin.objects) {\n try {\n if (Array.isArray(plugin.objects)) {\n this.logger.debug('Registering plugin objects (Array)', { pluginName, count: plugin.objects.length });\n for (const objDef of plugin.objects) {\n const fqn = this._registry.registerObject(objDef, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n } else {\n const entries = Object.entries(plugin.objects);\n this.logger.debug('Registering plugin objects (Map)', { pluginName, count: entries.length });\n for (const [name, objDef] of entries) {\n (objDef as any).name = name;\n const fqn = this._registry.registerObject(objDef as any, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n }\n } catch (err: any) {\n this.logger.warn('Failed to register plugin objects', { pluginName, error: err.message });\n }\n }\n\n // Register plugin as app if it has navigation (for sidebar display)\n if (plugin.name && plugin.navigation) {\n try {\n const resolved = pluginNamespace ? this.resolveNavObjectNames(plugin, pluginNamespace) : plugin;\n this._registry.registerApp(resolved, ownerId);\n this.logger.debug('Registered plugin-as-app', { app: plugin.name, from: pluginName });\n } catch (err: any) {\n this.logger.warn('Failed to register plugin as app', { pluginName, error: err.message });\n }\n }\n\n // Register metadata arrays (actions, views, triggers, etc.)\n const metadataArrayKeys = [\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'datasets', 'themes',\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n 'agents', 'ragPipelines', 'apis',\n 'hooks', 'mappings', 'analyticsCubes', 'connectors',\n 'docs',\n ];\n for (const key of metadataArrayKeys) {\n const items = (plugin as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n for (const item of items) {\n const itemName = resolveMetadataItemName(key, item);\n if (itemName) {\n const toRegister = item.name === itemName ? item : { ...item, name: itemName };\n this._registry.registerItem(pluralToSingular(key), toRegister, 'name' as any, ownerId);\n }\n }\n }\n }\n }\n\n /**\n * Register a new storage driver\n */\n registerDriver(driver: DriverInterface, isDefault: boolean = false) {\n if (this.drivers.has(driver.name)) {\n this.logger.warn('Driver already registered, skipping', { driverName: driver.name });\n return;\n }\n\n this.drivers.set(driver.name, driver);\n this.logger.info('Registered driver', {\n driverName: driver.name,\n version: driver.version\n });\n\n if (isDefault || this.drivers.size === 1) {\n this.defaultDriver = driver.name;\n this.logger.info('Set default driver', { driverName: driver.name });\n }\n }\n\n /**\n * Register a Datasource *definition* (ADR-0015).\n *\n * Distinct from {@link registerDriver}, which registers a live connection.\n * This captures the declarative `schemaMode` + `external.allowWrites` so the\n * write gate ({@link assertWriteAllowed}) can enforce external-datasource\n * ownership. Safe to call repeatedly; last write wins.\n */\n registerDatasourceDef(def: { name: string; schemaMode?: string; external?: { allowWrites?: boolean } }): void {\n if (!def?.name) return;\n this.datasourceDefs.set(def.name, { schemaMode: def.schemaMode, external: def.external });\n }\n\n /**\n * Write gate — Gate 3 of ADR-0015 §5.3.\n *\n * Blocks insert/update/delete against a federated datasource\n * (`schemaMode !== 'managed'`) unless BOTH the datasource opts in\n * (`external.allowWrites`) AND the object opts in (`external.writable`).\n * Managed datasources (the common case, including the absence of any\n * definition) are unaffected.\n */\n private assertWriteAllowed(objectName: string, operation: 'insert' | 'update' | 'delete'): void {\n const object = this._registry.getObject(objectName) as any;\n const dsName = object?.datasource;\n if (!dsName || dsName === 'default') return;\n\n const ds = this.datasourceDefs.get(dsName);\n // No recorded definition, or an explicitly managed one ⇒ allow.\n if (!ds || !ds.schemaMode || ds.schemaMode === 'managed') return;\n\n const dsAllows = ds.external?.allowWrites ?? false;\n const objAllows = object?.external?.writable ?? false;\n if (!(dsAllows && objAllows)) {\n throw new ExternalWriteForbiddenError(\n `Write '${operation}' blocked on object '${objectName}': datasource '${dsName}' is external ` +\n `(schemaMode=${ds.schemaMode}). Requires datasource.external.allowWrites=true (got ${dsAllows}) ` +\n `AND object.external.writable=true (got ${objAllows}).`,\n );\n }\n }\n\n /**\n * Set the realtime service for publishing data change events.\n * Should be called after kernel resolves the realtime service.\n *\n * @param service - An IRealtimeService instance for event publishing\n */\n setRealtimeService(service: IRealtimeService): void {\n this.realtimeService = service;\n this.logger.info('RealtimeService configured for data events');\n }\n\n /**\n * Register the crypto provider that backs `secret`-typed fields.\n *\n * When set, the engine encrypts secret fields on write (storing ciphertext in\n * `sys_secret` and only an opaque ref on the business row) and masks them on\n * read. When NOT set, writing to an object that declares a secret field is\n * **fail-closed** — the write throws rather than persist cleartext.\n *\n * Mirrors the Settings subsystem's ICryptoProvider wiring; the host (e.g.\n * `serve`) injects `LocalCryptoProvider` in dev and a KMS/Vault-backed\n * provider in production.\n */\n setCryptoProvider(provider: ICryptoProvider): void {\n this.cryptoProvider = provider;\n this.logger.info('CryptoProvider configured for secret fields');\n }\n\n /**\n * Encrypt any `secret`-typed fields on `row` in place before it reaches the\n * driver. Each plaintext is wrapped by the ICryptoProvider, persisted as a\n * `sys_secret` row, and replaced on `row` by an opaque ref. Cleartext never\n * reaches the business table.\n *\n * Rules:\n * - No secret fields on the object ⇒ no-op (fast path, no crypto cost).\n * - `null`/`undefined` value ⇒ left as-is (clears the secret).\n * - Value already a ref (re-save of an unchanged ref) ⇒ left as-is.\n * - Value equal to the read mask ⇒ dropped, so a form round-trip that\n * echoes the mask does not overwrite the stored secret.\n * - **Fail-closed:** any other value with no CryptoProvider registered, or\n * no reachable `sys_secret` store, THROWS — never persists cleartext.\n */\n private async encryptSecretFields(\n object: string,\n row: Record<string, unknown>,\n context: ExecutionContext | undefined,\n driverOptions: unknown,\n ): Promise<void> {\n if (!row || typeof row !== 'object') return;\n const schema = this._registry.getObject(object);\n const secretFields = collectSecretFields(schema);\n if (secretFields.length === 0) return;\n\n for (const field of secretFields) {\n if (!(field in row)) continue;\n const value = row[field];\n\n if (value === null || typeof value === 'undefined') continue; // clear\n if (isSecretRef(value)) continue; // already encrypted ref\n if (value === SECRET_MASK) {\n // The read path masks secrets to SECRET_MASK; a form that echoes it\n // back means \"unchanged\". Drop the key so the stored secret survives.\n delete row[field];\n continue;\n }\n\n if (!this.cryptoProvider) {\n throw new Error(\n `Cannot persist secret field \"${object}.${field}\": no CryptoProvider is registered. `\n + 'Wire one via engine.setCryptoProvider(...) (e.g. LocalCryptoProvider in dev, '\n + 'a KMS/Vault provider in production). Refusing to store cleartext (fail-closed).',\n );\n }\n\n const plain = typeof value === 'string' ? value : JSON.stringify(value);\n const handle: CryptoHandle = await this.cryptoProvider.encrypt(plain, {\n namespace: object,\n key: field,\n tenantId: context?.tenantId,\n });\n\n let secretDriver;\n try {\n secretDriver = this.getDriver('sys_secret');\n } catch {\n throw new Error(\n `Cannot persist secret field \"${object}.${field}\": the sys_secret store is not available. `\n + 'Ensure the platform-objects (sys_secret) are registered before writing secret fields (fail-closed).',\n );\n }\n\n await secretDriver.create(\n 'sys_secret',\n {\n id: handle.id,\n namespace: object,\n key: field,\n kms_key_id: handle.kmsKeyId,\n alg: handle.alg,\n version: handle.version,\n ciphertext: handle.ciphertext,\n created_at: new Date().toISOString(),\n },\n driverOptions as any,\n );\n\n row[field] = makeSecretRef(handle.id);\n }\n }\n\n /**\n * Mask `secret`-typed fields on read so plaintext never leaves the engine\n * through the normal query path. A set secret becomes {@link SECRET_MASK};\n * an unset one stays `null`. Privileged callers that genuinely need the\n * plaintext use {@link resolveSecret} against the stored ref.\n */\n private maskSecretFields(object: string, rows: any): void {\n if (!rows) return;\n const schema = this._registry.getObject(object);\n const secretFields = collectSecretFields(schema);\n if (secretFields.length === 0) return;\n const list = Array.isArray(rows) ? rows : [rows];\n for (const row of list) {\n if (!row || typeof row !== 'object') continue;\n for (const field of secretFields) {\n if (!(field in row)) continue;\n row[field] = row[field] == null ? null : SECRET_MASK;\n }\n }\n }\n\n /**\n * Dereference a stored secret ref back to its plaintext. Intended for\n * privileged, server-side consumers (e.g. a datasource connection-pool\n * binder) — NOT exposed through the generic read path, which only ever\n * returns the mask.\n *\n * Fail-closed: throws when no CryptoProvider is registered or the\n * `sys_secret` row is missing. Returns `null` when `ref` is not a secret ref.\n */\n async resolveSecret(ref: unknown, opts?: { tenantId?: string }): Promise<string | null> {\n const id = parseSecretRef(ref);\n if (!id) return null;\n if (!this.cryptoProvider) {\n throw new Error('Cannot resolve secret: no CryptoProvider is registered (fail-closed).');\n }\n const secretDriver = this.getDriver('sys_secret');\n const found = await secretDriver.find('sys_secret', { object: 'sys_secret', where: { id } } as QueryAST);\n const secret: any = Array.isArray(found) ? found[0] : found;\n if (!secret) {\n throw new Error(`Cannot resolve secret: sys_secret row \"${id}\" not found (fail-closed).`);\n }\n const handle: CryptoHandle = {\n id: secret.id,\n kmsKeyId: secret.kms_key_id,\n alg: secret.alg,\n version: secret.version,\n ciphertext: secret.ciphertext,\n };\n return this.cryptoProvider.decrypt(handle, {\n namespace: secret.namespace,\n key: secret.key,\n tenantId: opts?.tenantId,\n });\n }\n\n /**\n * Helper to get object definition\n */\n getSchema(objectName: string): ServiceObject | undefined {\n return this._registry.getObject(objectName);\n }\n\n /**\n * Resolve any object identifier to the physical storage name used by drivers.\n *\n * Accepts the canonical short name (e.g., 'account') or, for explicit\n * cross-package disambiguation, the canonical object name (e.g., 'account'). The result is\n * the physical table name derived via `StorageNameMapping.resolveTableName`.\n */\n private resolveObjectName(name: string): string {\n const schema = this._registry.getObject(name);\n if (schema) {\n return StorageNameMapping.resolveTableName(schema);\n }\n // Return name as-is (canonical name = table name; no FQN prefix to strip)\n return StorageNameMapping.resolveTableName({ name });\n }\n\n /**\n * Helper to get the target driver\n *\n * Resolution priority (first match wins):\n * 1. Object's explicit `datasource` field (if not 'default')\n * 2. DatasourceMapping rules (namespace/package/pattern matching)\n * 3. Package's `defaultDatasource` from manifest\n * 4. Global default driver\n */\n private getDriver(objectName: string): DriverInterface {\n const object = this._registry.getObject(objectName);\n\n // 1. Object's explicit datasource field (highest priority)\n if (object?.datasource && object.datasource !== 'default') {\n if (this.drivers.has(object.datasource)) {\n return this.drivers.get(object.datasource)!;\n }\n throw new Error(`[ObjectQL] Datasource '${object.datasource}' configured for object '${objectName}' is not registered.`);\n }\n\n // 2. Check datasourceMapping rules\n const mappedDatasource = this.resolveDatasourceFromMapping(objectName, object);\n if (mappedDatasource && this.drivers.has(mappedDatasource)) {\n this.logger.debug('Resolved datasource from mapping', {\n object: objectName,\n datasource: mappedDatasource\n });\n return this.drivers.get(mappedDatasource)!;\n }\n\n // 3. Check package's defaultDatasource\n // Use the object's FQN name (from getObject) for ownership lookup\n const fqn = object?.name || objectName;\n const owner = this._registry.getObjectOwner(fqn);\n if (owner?.packageId) {\n const manifest = this.manifests.get(owner.packageId);\n if (manifest?.defaultDatasource && manifest.defaultDatasource !== 'default') {\n if (this.drivers.has(manifest.defaultDatasource)) {\n this.logger.debug('Resolved datasource from package manifest', {\n object: objectName,\n package: owner.packageId,\n datasource: manifest.defaultDatasource\n });\n return this.drivers.get(manifest.defaultDatasource)!;\n }\n }\n }\n\n // 4. Fallback to global default driver\n if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n return this.drivers.get(this.defaultDriver)!;\n }\n\n throw new Error(`[ObjectQL] No driver available for object '${objectName}'`);\n }\n\n /**\n * Resolve datasource from mapping rules\n *\n * Rules are evaluated in order (or by priority if specified).\n * First matching rule wins.\n */\n private resolveDatasourceFromMapping(\n objectName: string,\n object?: any\n ): string | null {\n if (!this.datasourceMapping || this.datasourceMapping.length === 0) {\n return null;\n }\n\n // Sort rules by priority if any have priority set\n const sortedRules = [...this.datasourceMapping].sort((a, b) => {\n const aPriority = a.priority ?? 1000;\n const bPriority = b.priority ?? 1000;\n return aPriority - bPriority;\n });\n\n for (const rule of sortedRules) {\n // 1. Match by namespace\n if (rule.namespace && object?.namespace === rule.namespace) {\n return rule.datasource;\n }\n\n // 2. Match by package ID\n if (rule.package && object?.packageId === rule.package) {\n return rule.datasource;\n }\n\n // 3. Match by object name pattern (glob-style)\n if (rule.objectPattern && this.matchPattern(objectName, rule.objectPattern)) {\n return rule.datasource;\n }\n\n // 4. Default fallback rule\n if (rule.default) {\n return rule.datasource;\n }\n }\n\n return null;\n }\n\n /**\n * Simple glob pattern matching\n * Supports * (any chars) and ? (single char)\n */\n private matchPattern(objectName: string, pattern: string): boolean {\n const regexPattern = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex special chars\n .replace(/\\*/g, '.*') // * → .*\n .replace(/\\?/g, '.'); // ? → .\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(objectName);\n }\n\n /**\n * Set datasource mapping rules\n * Called by ObjectQLPlugin during bootstrap\n */\n setDatasourceMapping(rules: Array<{\n namespace?: string;\n package?: string;\n objectPattern?: string;\n default?: boolean;\n datasource: string;\n priority?: number;\n }>) {\n this.datasourceMapping = rules;\n this.logger.info('Datasource mapping rules configured', {\n ruleCount: rules.length\n });\n }\n\n /**\n * Initialize the engine and all registered drivers\n */\n async init() {\n this.logger.info('Initializing ObjectQL engine', { \n driverCount: this.drivers.size,\n drivers: Array.from(this.drivers.keys())\n });\n \n const failedDrivers: string[] = [];\n for (const [name, driver] of this.drivers) {\n try {\n await driver.connect();\n this.logger.info('Driver connected successfully', { driverName: name });\n } catch (e) {\n failedDrivers.push(name);\n this.logger.error('Failed to connect driver', e as Error, { driverName: name });\n }\n }\n\n if (failedDrivers.length > 0) {\n this.logger.warn(\n `${failedDrivers.length} of ${this.drivers.size} driver(s) failed initial connect. ` +\n `Operations may recover via lazy reconnection or fail at query time.`,\n { failedDrivers }\n );\n }\n \n this.logger.info('ObjectQL engine initialization complete');\n }\n\n async destroy() {\n this.logger.info('Destroying ObjectQL engine', { driverCount: this.drivers.size });\n \n for (const [name, driver] of this.drivers.entries()) {\n try {\n await driver.disconnect();\n } catch (e) {\n this.logger.error('Error disconnecting driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine destroyed');\n }\n\n // ============================================\n // Helper: Expand Related Records\n // ============================================\n\n /** Maximum depth for recursive expand to prevent infinite loops */\n private static readonly MAX_EXPAND_DEPTH = 3;\n private static readonly MAX_CASCADE_DEPTH = 10;\n /** In-memory next-value cache per `object.field` for autonumber generation,\n * lazily seeded from the current max in the store. */\n private readonly autonumberCounters = new Map<string, number>();\n\n /** Lazily-built index: child object name → roll-up summary descriptors on\n * parent objects that aggregate it. Invalidated when packages register. */\n private summaryIndex: Map<string, SummaryDescriptor[]> | null = null;\n\n /** Invalidate the cached roll-up summary index (call when metadata changes). */\n private invalidateSummaryIndex(): void {\n this.summaryIndex = null;\n }\n\n /** Scan all registered objects for `summary` fields and index them by the\n * child object they aggregate, resolving the child→parent FK field. */\n private buildSummaryIndex(): Map<string, SummaryDescriptor[]> {\n const index = new Map<string, SummaryDescriptor[]>();\n let objects: any[] = [];\n try { objects = (this._registry as any).getAllObjects?.() ?? []; } catch { objects = []; }\n for (const parent of objects) {\n const fields = parent?.fields;\n if (!fields || typeof fields !== 'object' || Array.isArray(fields)) continue;\n for (const [summaryField, def] of Object.entries(fields)) {\n const d: any = def;\n if (d?.type !== 'summary' || !d.summaryOperations) continue;\n const so = d.summaryOperations;\n const childObject = so.object;\n const fn = so.function;\n if (!childObject || !fn) continue;\n // Resolve the FK on the child pointing back to this parent.\n let fkField: string | undefined = so.relationshipField;\n if (!fkField) {\n const child = this._registry.getObject(childObject) as any;\n const cfields = child?.fields || {};\n for (const [cfName, cdef] of Object.entries(cfields)) {\n const cd: any = cdef;\n if ((cd?.type === 'master_detail' || cd?.type === 'lookup') && cd?.reference === parent.name) {\n fkField = cfName;\n break;\n }\n }\n }\n if (!fkField) continue; // can't resolve the relationship — skip\n const list = index.get(childObject) ?? [];\n list.push({ parentObject: parent.name, summaryField, fkField, fn, sourceField: so.field });\n index.set(childObject, list);\n }\n }\n return index;\n }\n\n private getSummaryDescriptors(childObject: string): SummaryDescriptor[] {\n if (!this.summaryIndex) this.summaryIndex = this.buildSummaryIndex();\n return this.summaryIndex.get(childObject) ?? [];\n }\n\n /**\n * Recompute roll-up `summary` fields on parent records after a child write.\n * For each affected parent (the FK value on the changed/old child record), it\n * aggregates the child collection and writes the result onto the parent's\n * summary field. Runs in the caller's execution context so it joins the same\n * transaction (e.g. the cross-object batch) when one is open.\n */\n private async recomputeSummaries(\n childObject: string,\n records: any,\n previous: any,\n execCtx?: ExecutionContext,\n ): Promise<void> {\n const descriptors = this.getSummaryDescriptors(childObject);\n if (descriptors.length === 0) return;\n const recs = Array.isArray(records) ? records : records ? [records] : [];\n const prevs = Array.isArray(previous) ? previous : previous ? [previous] : [];\n for (const desc of descriptors) {\n const ids = new Set<string>();\n for (const r of recs) { const v = r?.[desc.fkField]; if (v != null && v !== '') ids.add(String(v)); }\n for (const p of prevs) { const v = p?.[desc.fkField]; if (v != null && v !== '') ids.add(String(v)); }\n for (const parentId of ids) {\n try {\n const rows = await this.aggregate(childObject, {\n where: { [desc.fkField]: parentId },\n aggregations: [{\n function: desc.fn,\n ...(desc.fn === 'count' ? {} : { field: desc.sourceField }),\n alias: 'value',\n }],\n context: execCtx,\n } as any);\n let value = rows?.[0]?.value;\n if (value == null) value = (desc.fn === 'count' || desc.fn === 'sum') ? 0 : null;\n await this.update(desc.parentObject, { id: parentId, [desc.summaryField]: value }, { context: execCtx } as any);\n } catch (err) {\n this.logger.warn('Roll-up summary recompute failed', {\n childObject, parentObject: desc.parentObject, parentId, field: desc.summaryField,\n error: (err as any)?.message,\n });\n }\n }\n }\n }\n\n /**\n * Post-process expand: resolve lookup/master_detail fields by batch-loading related records.\n * \n * This is a driver-agnostic implementation that uses secondary queries ($in batches)\n * to load related records, then injects them into the result set.\n * \n * @param objectName - The source object name\n * @param records - The records returned by the driver\n * @param expand - The expand map from QueryAST (field name → nested QueryAST)\n * @param depth - Current recursion depth (0-based)\n * @returns Records with expanded lookup fields (IDs replaced by full objects)\n */\n private async expandRelatedRecords(\n objectName: string,\n records: any[],\n expand: Record<string, QueryAST>,\n depth: number = 0,\n execCtx?: ExecutionContext,\n ): Promise<any[]> {\n if (!records || records.length === 0) return records;\n if (depth >= ObjectQL.MAX_EXPAND_DEPTH) return records;\n\n const objectSchema = this._registry.getObject(objectName);\n // If no schema registered, skip expand — return raw data\n if (!objectSchema || !objectSchema.fields) return records;\n\n for (const [fieldName, nestedAST] of Object.entries(expand)) {\n const fieldDef = objectSchema.fields[fieldName];\n\n // Skip if field not found or not a relationship type\n if (!fieldDef || !fieldDef.reference) continue;\n if (fieldDef.type !== 'lookup' && fieldDef.type !== 'master_detail') continue;\n\n const referenceObject = fieldDef.reference;\n\n // Collect all foreign key IDs from records (handle both single and multiple values)\n const allIds: any[] = [];\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n if (Array.isArray(val)) {\n allIds.push(...val.filter((id: any) => id != null));\n } else if (typeof val === 'object') {\n // Already expanded — skip\n continue;\n } else {\n allIds.push(val);\n }\n }\n\n // De-duplicate IDs\n const uniqueIds = [...new Set(allIds)];\n if (uniqueIds.length === 0) continue;\n\n // Batch-load related records using $in query\n try {\n const relatedQuery: QueryAST = {\n object: referenceObject,\n where: { id: { $in: uniqueIds } },\n ...(nestedAST.fields ? { fields: nestedAST.fields } : {}),\n ...(nestedAST.orderBy ? { orderBy: nestedAST.orderBy } : {}),\n };\n\n const driver = this.getDriver(referenceObject);\n // Propagate tenantId so cross-object expansion respects isolation —\n // e.g. a contact expansion only resolves IDs visible to the caller's\n // tenant. Without this the driver returns the raw FK target which\n // would let a maliciously crafted FK reach across tenants.\n const expandOpts = this.buildDriverOptions(execCtx);\n const relatedRecords = await driver.find(referenceObject, relatedQuery, expandOpts) ?? [];\n\n // Build a lookup map: id → record\n const recordMap = new Map<string, any>();\n for (const rec of relatedRecords) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n\n // Recursively expand nested relations if present\n if (nestedAST.expand && Object.keys(nestedAST.expand).length > 0) {\n const expandedRelated = await this.expandRelatedRecords(\n referenceObject,\n relatedRecords,\n nestedAST.expand,\n depth + 1,\n execCtx,\n );\n // Rebuild map with expanded records\n recordMap.clear();\n for (const rec of expandedRelated) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n }\n\n // Inject expanded records back into the original result set\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n\n if (Array.isArray(val)) {\n record[fieldName] = val.map((id: any) => recordMap.get(String(id)) ?? id);\n } else if (typeof val !== 'object') {\n record[fieldName] = recordMap.get(String(val)) ?? val;\n }\n // If val is already an object, leave it as-is\n }\n } catch (e) {\n // Graceful degradation: if expand fails, keep original IDs\n this.logger.warn('Failed to expand relationship field; retaining foreign key IDs', {\n object: objectName,\n field: fieldName,\n reference: referenceObject,\n error: (e as Error).message,\n });\n }\n }\n\n return records;\n }\n\n // ============================================\n // Data Access Methods (IDataEngine Interface)\n // ============================================\n\n async find(object: string, query?: EngineQueryOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n this.logger.debug('Find operation starting', { object, query });\n const driver = this.getDriver(object);\n const ast: QueryAST = { object, ...query };\n // Remove context from the AST — it's not a driver concern\n delete (ast as any).context;\n // Normalize OData `top` alias → standard `limit`\n if ((ast as any).top != null && ast.limit == null) {\n ast.limit = (ast as any).top;\n }\n delete (ast as any).top;\n\n // Plan formula projection: rewrite ast.fields to drop virtual formula\n // names and inject their dependencies, so the driver returns the raw\n // fields needed to compute the formulas after fetch.\n const _findSchema = this._registry.getObject(object);\n const _findFormula = planFormulaProjection(_findSchema, ast.fields as string[] | undefined);\n if (_findFormula.projected) ast.fields = _findFormula.projected;\n\n // Drop any requested field that doesn't exist on the schema. Without\n // this, drivers (notably SqlDriver) emit `SELECT unknown_col FROM ...`\n // which the DB rejects (\"no such column\") — and SqlDriver swallows\n // that error and returns `[]`, making a frontend bug (e.g. a generic\n // view requesting `name`/`due_date` on every object) look like \"no\n // records exist\". Silently filtering matches the existing OData\n // tolerance and Salesforce/Postgres behavior of `SELECT *` semantics.\n if (_findSchema?.fields && Array.isArray(ast.fields) && ast.fields.length > 0) {\n const known = new Set(Object.keys(_findSchema.fields));\n // Always allow the primary key + audit columns even if not present in\n // schema.fields. Without this, callers requesting `select=id,name`\n // silently get the `id` projected away, breaking record navigation.\n known.add('id');\n known.add('created_at');\n known.add('updated_at');\n const filtered = (ast.fields as string[]).filter(f => {\n // Keep relationship paths like `owner.name` — the engine will\n // resolve those via populate; only validate top-level segment.\n const head = String(f).split('.')[0];\n return known.has(head);\n });\n // Guard against an empty projection — fall back to `*` so the\n // request still returns rows. An empty SELECT list would either\n // 400 in Postgres or silently project nothing.\n ast.fields = filtered.length > 0 ? filtered : undefined;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'find',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast: opCtx.ast, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result = await driver.find(object, hookContext.input.ast as QueryAST, hookContext.input.options as any);\n\n // Post-process: evaluate formula virtual fields against the raw rows\n if (Array.isArray(result)) applyFormulaPlan(_findFormula.plan, result);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && Array.isArray(result)) {\n result = await this.expandRelatedRecords(object, result, ast.expand, 0, opCtx.context);\n }\n \n hookContext.event = 'afterFind';\n hookContext.result = result;\n await this.triggerHooks('afterFind', hookContext);\n\n // Never let secret-field plaintext (or its ref) leave through the\n // generic read path — mask after hooks run. Privileged consumers use\n // resolveSecret() against the stored ref instead.\n this.maskSecretFields(object, hookContext.result);\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Find operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result as any[];\n }\n\n async findOne(objectName: string, query?: EngineQueryOptions): Promise<any> {\n objectName = this.resolveObjectName(objectName);\n this.logger.debug('FindOne operation', { objectName });\n const driver = this.getDriver(objectName);\n const ast: QueryAST = { object: objectName, ...query, limit: 1 };\n // Remove context and top alias from the AST\n delete (ast as any).context;\n delete (ast as any).top;\n\n // Plan formula projection (same as find): rewrite ast.fields so the driver\n // returns the raw dependency fields, then evaluate formulas after fetch.\n const _findOneSchema = this._registry.getObject(objectName);\n const _findOneFormula = planFormulaProjection(_findOneSchema, ast.fields as string[] | undefined);\n if (_findOneFormula.projected) ast.fields = _findOneFormula.projected;\n\n // Drop unknown fields — see equivalent block in `find()` for rationale.\n if (_findOneSchema?.fields && Array.isArray(ast.fields) && ast.fields.length > 0) {\n const known = new Set(Object.keys(_findOneSchema.fields));\n // Always allow the primary key + audit columns even if not present\n // in schema.fields (matches `find()` behavior).\n known.add('id');\n known.add('created_at');\n known.add('updated_at');\n const filtered = (ast.fields as string[]).filter(f => known.has(String(f).split('.')[0]));\n ast.fields = filtered.length > 0 ? filtered : undefined;\n }\n\n const opCtx: OperationContext = {\n object: objectName,\n operation: 'findOne',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const findOneOpts = this.buildDriverOptions(opCtx.context);\n let result = await driver.findOne(objectName, opCtx.ast as QueryAST, findOneOpts);\n\n // Post-process: evaluate formula virtual fields against the raw row\n if (result != null) applyFormulaPlan(_findOneFormula.plan, [result]);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && result != null) {\n const expanded = await this.expandRelatedRecords(objectName, [result], ast.expand, 0, opCtx.context);\n result = expanded[0];\n }\n\n // Mask secret fields — plaintext never leaves through the read path.\n this.maskSecretFields(objectName, result);\n\n return result;\n });\n\n return opCtx.result;\n }\n\n async insert(object: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Insert operation starting', { object, isBatch: Array.isArray(data) });\n this.assertWriteAllowed(object, 'insert');\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'insert',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeInsert', hookContext);\n // Thread the open transaction (if any) into the driver-facing\n // options so that knex's `.transacting(trx)` is honoured. Without\n // this, calls inside a `engine.transaction(...)` block would deadlock\n // on SQLite's single-connection pool. Also propagates tenantId so\n // the driver can enforce per-tenant isolation.\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result;\n const nowSnap = new Date();\n const schemaForValidation = this._registry.getObject(object);\n // When the driver generates autonumbers natively (persistent SQL\n // sequence), the engine defers to it — see #1603.\n const driverOwnsAutonumber = (driver as any)?.supports?.autonumber === true;\n if (Array.isArray(hookContext.input.data)) {\n // Bulk Create — apply defaults per row\n const rows = (hookContext.input.data as any[]).map((row) =>\n this.applyFieldDefaults(object, row as Record<string, unknown>, opCtx.context, nowSnap),\n );\n for (const r of rows) {\n await this.applyAutonumbers(object, r as Record<string, unknown>, opCtx.context, driverOwnsAutonumber);\n }\n for (const r of rows) {\n await this.encryptSecretFields(object, r, opCtx.context, hookContext.input.options);\n }\n for (const r of rows) {\n validateRecord(schemaForValidation, r, 'insert');\n evaluateValidationRules(schemaForValidation as any, r, 'insert', { logger: this.logger });\n }\n if (driver.bulkCreate) {\n result = await driver.bulkCreate(object, rows, hookContext.input.options as any);\n } else {\n // Fallback loop\n result = await Promise.all(rows.map((item) => driver.create(object, item, hookContext.input.options as any)));\n }\n } else {\n const row = this.applyFieldDefaults(\n object,\n hookContext.input.data as Record<string, unknown>,\n opCtx.context,\n nowSnap,\n );\n await this.applyAutonumbers(object, row, opCtx.context, driverOwnsAutonumber);\n await this.encryptSecretFields(object, row, opCtx.context, hookContext.input.options);\n validateRecord(schemaForValidation, row, 'insert');\n evaluateValidationRules(schemaForValidation as any, row, 'insert', { logger: this.logger });\n result = await driver.create(object, row, hookContext.input.options as any);\n }\n\n hookContext.event = 'afterInsert';\n hookContext.result = result;\n await this.triggerHooks('afterInsert', hookContext);\n\n // Roll-up: recompute parent summary fields that aggregate this object.\n await this.recomputeSummaries(object, result, null, opCtx.context);\n\n // Publish data.record.created event to realtime service\n if (this.realtimeService) {\n try {\n if (Array.isArray(result)) {\n // Bulk insert - publish event for each record\n for (const record of result) {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: record.id,\n after: record,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n }\n this.logger.debug(`Published ${result.length} data.record.created events`, { object });\n } else {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: result.id,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.created event', { object, recordId: result.id });\n }\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Insert operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async update(object: string, data: any, options?: EngineUpdateOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Update operation starting', { object });\n this.assertWriteAllowed(object, 'update');\n const driver = this.getDriver(object);\n \n // 1. Extract ID from data or where if it's a single update by ID.\n // Only a SCALAR `where.id` means \"update one row by primary key\". An\n // operator object ({ $in: [...] }, { $ne: ... }, …) is a multi-row\n // predicate — treating it as an id would bind the object literally\n // (e.g. `WHERE id = {\"$in\":[...]}`, which SQLite rejects). Leave `id`\n // undefined in that case so the call routes to updateMany (requires\n // options.multi=true), where applyFilters compiles the operator.\n let id = data.id;\n if (!id && options?.where && typeof options.where === 'object' && 'id' in options.where) {\n const whereId = (options.where as Record<string, unknown>).id;\n const t = typeof whereId;\n if (whereId !== null && (t === 'string' || t === 'number' || t === 'bigint')) {\n id = whereId;\n }\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'update',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result;\n // Pre-update snapshot. Exposed to after-hooks via `hookContext.previous`\n // (the HookContext contract documents `previous` for update/delete) and\n // reused for object-level validation rules. Fetched once, only for\n // single-id updates, when either a rule needs it (ADR-0020:\n // state_machine / cross_field / script — a PATCH carries only changed\n // fields) OR an afterUpdate hook is registered. The latter is what makes\n // record-change flow triggers work: their start-condition gate reads\n // `previous.*` (e.g. `status == \"done\" && previous.status != \"done\"`),\n // which silently fails when `previous` is absent.\n let priorRecord: Record<string, unknown> | null = null;\n const updateSchema = this._registry.getObject(object);\n if (hookContext.input.id) {\n await this.encryptSecretFields(object, hookContext.input.data as Record<string, unknown>, opCtx.context, hookContext.input.options);\n validateRecord(updateSchema, hookContext.input.data as Record<string, unknown>, 'update');\n if (needsPriorRecord(updateSchema as any) || (this.hooks.get('afterUpdate')?.length ?? 0) > 0) {\n const priorAst: QueryAST = { object, where: { id: hookContext.input.id }, limit: 1 };\n priorRecord = await driver.findOne(object, priorAst, hookContext.input.options as any);\n }\n // B2: drop writes to fields locked by a TRUE `readonlyWhen` — the\n // field is read-only for this record's state, so the incoming\n // change is ignored (the persisted value is kept).\n hookContext.input.data = stripReadonlyWhenFields(updateSchema as any, hookContext.input.data as Record<string, unknown>, priorRecord, this.logger) as any;\n evaluateValidationRules(updateSchema as any, hookContext.input.data as Record<string, unknown>, 'update', { previous: priorRecord, logger: this.logger });\n result = await driver.update(object, hookContext.input.id as string, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else if (options?.multi && driver.updateMany) {\n await this.encryptSecretFields(object, hookContext.input.data as Record<string, unknown>, opCtx.context, hookContext.input.options);\n validateRecord(updateSchema, hookContext.input.data as Record<string, unknown>, 'update');\n // Multi-row update: per-row prior state is not fetched (one query\n // per matched row would be unbounded). state_machine /\n // cross_field rules are skipped here; warn so the gap is visible.\n if (needsPriorRecord(updateSchema as any)) {\n this.logger.warn('Object-level validation rules (state_machine/cross_field/script) are not enforced on multi-row updates', { object });\n }\n const ast: QueryAST = { object, where: options.where };\n result = await driver.updateMany(object, ast, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else {\n throw new Error('Update requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterUpdate';\n hookContext.result = result;\n if (priorRecord) hookContext.previous = priorRecord;\n await this.triggerHooks('afterUpdate', hookContext);\n\n // Roll-up: recompute parent summaries; pass priorRecord too so a child\n // that moved to a different parent updates BOTH old and new parent.\n await this.recomputeSummaries(object, result, priorRecord, opCtx.context);\n\n // Publish data.record.updated event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.updated',\n object,\n payload: {\n recordId,\n changes: hookContext.input.data,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.updated event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Update operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n /**\n * Apply referential delete behavior for relations pointing AT this record,\n * before it is removed. For every registered object with a `master_detail`\n * or `lookup` field referencing `object`, honor the field's `deleteBehavior`:\n * - `cascade` → delete the dependent rows (recursively, so grandchildren\n * are handled by each child's own delete),\n * - `set_null` → clear the foreign key,\n * - `restrict` → refuse the delete when dependents exist.\n * `master_detail` defaults to `cascade` (the parent owns the child\n * lifecycle); `lookup` defaults to `set_null`. Only runs for single-id\n * deletes — multi/predicate deletes skip cascade (logged).\n */\n private async cascadeDeleteRelations(\n object: string,\n id: string | number,\n context?: ExecutionContext,\n depth = 0,\n ): Promise<void> {\n if (id == null || depth >= ObjectQL.MAX_CASCADE_DEPTH) return;\n let objects: ServiceObject[];\n try {\n objects = this._registry.getAllObjects();\n } catch {\n return;\n }\n for (const child of objects) {\n const childName = (child as any)?.name as string | undefined;\n const fields = (child as any)?.fields as Record<string, any> | undefined;\n if (!childName || !fields) continue;\n for (const [fieldName, fdef] of Object.entries(fields)) {\n if (!fdef || (fdef.type !== 'master_detail' && fdef.type !== 'lookup')) continue;\n const ref = fdef.reference;\n if (!ref) continue;\n // Match the target object by raw or resolved name.\n let resolvedRef: string | undefined;\n try { resolvedRef = this.resolveObjectName(ref); } catch { resolvedRef = undefined; }\n if (ref !== object && resolvedRef !== object) continue;\n\n // A master-detail parent owns its children: cascade by default (the\n // child FK is typically required, so set_null would be invalid). Only\n // an explicit `restrict` deviates. A plain lookup honors its\n // configured deleteBehavior (default set_null).\n const behavior: string =\n fdef.type === 'master_detail'\n ? (fdef.deleteBehavior === 'restrict' ? 'restrict' : 'cascade')\n : (fdef.deleteBehavior || 'set_null');\n\n let dependents: any[];\n try {\n dependents = await this.find(childName, { where: { [fieldName]: id }, context } as any);\n } catch {\n continue;\n }\n if (!dependents || dependents.length === 0) continue;\n\n if (behavior === 'restrict') {\n throw new Error(\n `Cannot delete ${object} (${id}): ${dependents.length} dependent ${childName} record(s) via ${fieldName}`,\n );\n }\n\n for (const dep of dependents) {\n const depId = dep?.id;\n if (depId == null) continue;\n if (behavior === 'cascade') {\n // Recurse via the public delete so the child's own cascade,\n // hooks and events fire.\n await this.delete(childName, { where: { id: depId }, context } as any);\n } else {\n await this.update(childName, { id: depId, [fieldName]: null }, { context } as any);\n }\n }\n }\n }\n }\n\n async delete(object: string, options?: EngineDeleteOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Delete operation starting', { object });\n this.assertWriteAllowed(object, 'delete');\n const driver = this.getDriver(object);\n\n // Extract ID logic similar to update\n let id: any = undefined;\n if (options?.where && typeof options.where === 'object' && 'id' in options.where) {\n id = (options.where as Record<string, unknown>).id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'delete',\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeDelete', hookContext);\n hookContext.input.options = this.buildDriverOptions(opCtx.context, hookContext.input.options as any);\n\n try {\n let result;\n // Capture the row's FK values BEFORE deletion so roll-up summaries can\n // recompute the (now-orphaned) parent. Only when a summary aggregates\n // this object — avoids an extra read on every delete.\n let summaryPrev: any = null;\n if (hookContext.input.id && this.getSummaryDescriptors(object).length > 0) {\n try {\n summaryPrev = await this.findOne(object, { where: { id: hookContext.input.id }, context: opCtx.context } as any);\n } catch { /* best-effort */ }\n }\n if (hookContext.input.id) {\n // Honor referential delete behavior (cascade/set_null/restrict)\n // for relations pointing at this record before removing it.\n await this.cascadeDeleteRelations(object, hookContext.input.id as string | number, opCtx.context);\n result = await driver.delete(object, hookContext.input.id as string, hookContext.input.options as any);\n } else if (options?.multi && driver.deleteMany) {\n const ast: QueryAST = { object, where: options.where };\n result = await driver.deleteMany(object, ast, hookContext.input.options as any);\n } else {\n throw new Error('Delete requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterDelete';\n hookContext.result = result;\n await this.triggerHooks('afterDelete', hookContext);\n\n // Roll-up: recompute the parent summary now that the child is gone.\n if (summaryPrev) await this.recomputeSummaries(object, null, summaryPrev, opCtx.context);\n\n // Publish data.record.deleted event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.deleted',\n object,\n payload: {\n recordId,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.deleted event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Delete operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async count(object: string, query?: EngineCountOptions): Promise<number> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'count',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const countOpts = this.buildDriverOptions(opCtx.context);\n if (driver.count) {\n const ast: QueryAST = { object, where: query?.where };\n return driver.count(object, ast, countOpts);\n }\n // Fallback to find().length\n const res = await this.find(object, { where: query?.where, fields: ['id'], context: opCtx.context });\n return res.length;\n });\n\n return opCtx.result as number;\n }\n\n async aggregate(object: string, query: EngineAggregateOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'aggregate',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const ast: QueryAST = {\n object,\n where: query.where,\n groupBy: query.groupBy as any,\n aggregations: query.aggregations,\n };\n\n // Prefer driver.aggregate() when available — driver.find() in many\n // drivers (e.g. driver-sql) does not honor `groupBy` / `aggregations`\n // and would silently return ungrouped raw rows. Fall back to find()\n // for drivers that handle aggregations through their query AST.\n const drv = driver as any;\n // Structured groupBy items ({field, dateGranularity}) require the\n // driver to advertise per-granularity native bucket support via\n // `supports.queryDateGranularity[g]`. If every structured item is\n // supported we can push the aggregate down to the driver; otherwise\n // we fall back to driver.find() + in-memory bucketing so the result\n // remains correct on partial-support dialects (e.g. SQLite + week).\n const groupByItems = Array.isArray(query.groupBy) ? (query.groupBy as any[]) : [];\n const granularityCaps: Record<string, boolean> | undefined =\n drv?.supports?.queryDateGranularity;\n const structuredItems = groupByItems.filter((g) => typeof g !== 'string');\n const allStructuredSupported = structuredItems.every((g: any) => {\n if (!g?.dateGranularity) return true; // plain {field} object is fine\n return granularityCaps?.[g.dateGranularity] === true;\n });\n if (typeof drv.aggregate === 'function' && allStructuredSupported) {\n return drv.aggregate(object, ast, this.buildDriverOptions(opCtx.context));\n }\n // In-memory fallback path: ask the driver for raw rows, then bucket +\n // aggregate here. This guarantees `groupBy` (incl. structured items\n // carrying `dateGranularity`) and `aggregations` always work even on\n // drivers that have no native aggregation support (driver-rest,\n // driver-memory, partial SQL drivers).\n const raw = await driver.find(object, ast, this.buildDriverOptions(opCtx.context));\n return applyInMemoryAggregation(raw, ast);\n });\n\n return opCtx.result as any[];\n }\n \n /**\n * Run raw driver-specific commands (SQL for SqlDriver, REST for RestDriver, …).\n *\n * ⚠️ **Tenant isolation bypass.** Raw `execute()` does NOT thread the\n * caller's `ExecutionContext.tenantId` into a `WHERE organization_id`\n * predicate — drivers see the command verbatim. Callers MUST inline the\n * tenant filter themselves, or restrict raw execution to genuinely global\n * statements (schema migrations, sys_* / control-plane tables).\n *\n * Prefer the typed entry points (`find`, `update`, `delete`, `count`, …)\n * whenever feasible — they auto-apply tenancy + soft-delete + audit warnings.\n */\n async execute(command: any, options?: Record<string, any>): Promise<any> {\n // Driver selection priority:\n // 1. options.object → route via getDriver(objectName)\n // 2. options.datasource → explicit driver name\n // 3. default driver (set via datasourceMapping or defaultDriver)\n // This lets system services (e.g. PackageService, AuditService) issue raw\n // SQL against the control-plane / default DB without having to know the\n // object name behind every CREATE TABLE / SELECT statement.\n let driver: DriverInterface | undefined;\n if (options?.object) {\n driver = this.getDriver(options.object);\n } else if (options?.datasource && this.drivers.has(options.datasource)) {\n driver = this.drivers.get(options.datasource);\n } else if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n driver = this.drivers.get(this.defaultDriver);\n } else if (this.drivers.size === 1) {\n // Single registered driver — unambiguously the right one.\n driver = this.drivers.values().next().value;\n }\n\n if (!driver) {\n throw new Error(\n 'Execute requires options.object to select a driver, or a default driver to be configured. ' +\n 'Configure datasourceMapping with `default: true` or pass `{ object }` / `{ datasource }` in options.',\n );\n }\n if (!driver.execute) {\n throw new Error('Selected driver does not implement execute()');\n }\n\n // Support both call shapes:\n // execute('SELECT ...', { args: [...] })\n // execute({ sql: 'SELECT ...', args: [...] })\n let rawCommand: any = command;\n let params: any[] | undefined = options?.args ?? options?.params;\n if (command && typeof command === 'object' && !Array.isArray(command) && 'sql' in command) {\n rawCommand = command.sql;\n if (params === undefined) {\n params = command.args ?? command.params;\n }\n }\n\n return driver.execute(rawCommand, params, options);\n }\n\n /**\n * Execute a callback inside a database transaction.\n *\n * The callback receives a context object that should be passed to all\n * downstream `engine.insert/update/delete/find/findOne` calls (as\n * `{ context: trxCtx }`). The transaction handle threads through\n * `OperationContext.context.transaction` and the SQL driver's per-builder\n * `.transacting(trx)` call.\n *\n * - If the default driver does not support `beginTransaction`, the callback\n * runs directly with the supplied base context (no rollback). This keeps\n * the API safe to call on drivers without ACID support (e.g. the\n * in-memory driver in tests).\n * - On callback success the transaction is committed; on any thrown error\n * it is rolled back and the original error is re-thrown.\n *\n * Use case: multi-step operations that must be atomic (e.g. CRM\n * `convertLead`, which creates an account + contact + opportunity + flips\n * the lead in a single unit of work).\n */\n async transaction<T>(\n callback: (trxCtx: any) => Promise<T>,\n baseContext?: any,\n ): Promise<T> {\n const driver = this.defaultDriver ? this.drivers.get(this.defaultDriver) : undefined;\n const drv = driver as any;\n if (!drv?.beginTransaction) {\n return callback(baseContext);\n }\n const trx = await drv.beginTransaction();\n const trxCtx = { ...(baseContext ?? {}), transaction: trx };\n try {\n // Run the callback inside the ambient transaction store so internal\n // queries during writes reuse this transaction's connection (ADR-0034).\n const result = await this.txStore.run({ transaction: trx }, () => callback(trxCtx));\n if (drv.commit) await drv.commit(trx);\n else if (drv.commitTransaction) await drv.commitTransaction(trx);\n return result;\n } catch (err) {\n try {\n if (drv.rollback) await drv.rollback(trx);\n else if (drv.rollbackTransaction) await drv.rollbackTransaction(trx);\n } catch {\n // swallow rollback failures so the original error surfaces\n }\n throw err;\n }\n }\n\n // ============================================\n // Compatibility / Convenience API\n // ============================================\n // These methods provide a higher-level API matching the @objectql/core\n // ObjectQL interface, enabling painless migration from the legacy layer.\n\n /**\n * Register a single object definition.\n * \n * Proxies to SchemaRegistry.registerObject() with sensible defaults.\n * Fields without a `name` property are auto-assigned from their key.\n */\n registerObject(\n schema: ServiceObject,\n packageId: string = '__runtime__',\n namespace?: string\n ): string {\n // Auto-assign field names from keys\n if (schema.fields) {\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field && typeof field === 'object' && !('name' in field)) {\n (field as any).name = key;\n }\n }\n }\n return this._registry.registerObject(schema, packageId, namespace);\n }\n\n /**\n * Unregister a single object by name.\n */\n unregisterObject(name: string, packageId?: string): void {\n if (packageId) {\n this._registry.unregisterObjectsByPackage(packageId);\n } else {\n // Remove from generic metadata as fallback\n this._registry.unregisterItem('object', name);\n }\n }\n\n /**\n * Get an object definition by name.\n * Alias for getSchema() — matches @objectql/core API.\n */\n getObject(name: string): ServiceObject | undefined {\n return this.getSchema(name);\n }\n\n /**\n * Get all registered object configs as a name→config map.\n * Matches @objectql/core getConfigs() API.\n */\n getConfigs(): Record<string, ServiceObject> {\n const result: Record<string, ServiceObject> = {};\n const objects = this._registry.getAllObjects();\n for (const obj of objects) {\n if (obj.name) {\n result[obj.name] = obj;\n }\n }\n return result;\n }\n\n /**\n * Get a registered driver by datasource name.\n * \n * Unlike the private getDriver() (which resolves by object name),\n * this method directly looks up a driver by its registered name.\n */\n getDriverByName(name: string): DriverInterface | undefined {\n return this.drivers.get(name);\n }\n\n /**\n * Introspect a datasource's live remote schema (ADR-0015).\n *\n * Resolves the driver registered under `datasource` and delegates to its\n * `introspectSchema()` capability. Used by the external-datasource service\n * (and CLI/REST) to list remote tables and validate federated objects.\n *\n * @throws if the datasource has no registered driver, or the driver does\n * not support introspection.\n */\n async introspectDatasource(datasource: string): Promise<unknown> {\n const driver = this.drivers.get(datasource) as any;\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${datasource}' has no registered driver to introspect.`);\n }\n if (typeof driver.introspectSchema !== 'function') {\n throw new Error(`[ObjectQL] Driver for datasource '${datasource}' does not support introspectSchema().`);\n }\n return driver.introspectSchema();\n }\n\n /**\n * Get the driver responsible for the given object.\n *\n * Resolves datasource binding from the object's schema definition,\n * falling back to the default driver. This is a public version of\n * the internal getDriver() used by CRUD operations.\n *\n * @param objectName - FQN or short name of the registered object.\n * @returns The resolved DriverInterface, or undefined if no driver is available.\n */\n getDriverForObject(objectName: string): DriverInterface | undefined {\n try {\n return this.getDriver(objectName);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Sync all registered object schemas to their respective drivers.\n * Call this after dynamically registering new objects at runtime\n * (e.g. after template seeding) to ensure tables/collections exist\n * before inserting seed data.\n */\n async syncSchemas(): Promise<void> {\n const allObjects = this._registry.getAllObjects();\n for (const obj of allObjects) {\n const driver = this.getDriverForObject(obj.name);\n if (!driver) continue;\n const tableName = StorageNameMapping.resolveTableName(obj);\n if (typeof (driver as any).syncSchemasBatch === 'function' && (driver as any).supports?.batchSchemaSync) {\n // Already handled per-driver below; skip individual call\n }\n if (typeof (driver as any).syncSchema === 'function') {\n try {\n await (driver as any).syncSchema(tableName, obj);\n } catch {\n // best effort — log suppressed to avoid noise on already-synced tables\n }\n }\n }\n }\n\n /**\n * Sync a SINGLE object's physical storage (create/alter its table) on\n * demand. Boot-time {@link syncSchemas} runs once at startup, so an object\n * that becomes live at runtime (e.g. publishing a drafted object) has a\n * registry entry but no table — data CRUD then fails with \"no such table\"\n * until the next restart. Calling this right after the object is registered\n * makes it immediately usable. Idempotent: the SQL driver only creates the\n * table when absent (and alters to add new columns).\n */\n async syncObjectSchema(objectName: string): Promise<void> {\n const obj = this._registry.getObject(objectName) as any;\n if (!obj) return;\n const driver = this.getDriverForObject(objectName);\n if (!driver || typeof (driver as any).syncSchema !== 'function') return;\n const tableName = StorageNameMapping.resolveTableName(obj);\n await (driver as any).syncSchema(tableName, obj);\n }\n\n /**\n * Drop the physical storage (table/collection) backing an object — the\n * inverse of {@link syncObjectSchema}. DESTRUCTIVE: deletes all rows in the\n * table. Used by the protocol delete path when the caller explicitly opts\n * into storage teardown (e.g. discarding an object that was published only\n * to preview it). No-op when the object's driver does not expose `dropTable`.\n * Resolves the physical table name from the registered definition, falling\n * back to the bare name if the def was already removed.\n */\n async dropObjectSchema(objectName: string): Promise<void> {\n const obj = this._registry.getObject(objectName) as any;\n const driver = this.getDriverForObject(objectName);\n if (!driver || typeof (driver as any).dropTable !== 'function') return;\n const tableName = StorageNameMapping.resolveTableName(obj ?? ({ name: objectName } as any));\n await (driver as any).dropTable(tableName);\n }\n\n /**\n * Get a registered driver by datasource name.\n * Alias matching @objectql/core datasource() API.\n *\n * @throws Error if the datasource is not found\n */\n datasource(name: string): DriverInterface {\n const driver = this.drivers.get(name);\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${name}' not found`);\n }\n return driver;\n }\n\n /**\n * Register a hook handler.\n * Convenience alias for registerHook() matching @objectql/core on() API.\n * \n * Usage:\n * ql.on('beforeInsert', 'user', async (ctx) => { ... });\n */\n on(\n event: string,\n objectName: string,\n handler: (ctx: HookContext) => Promise<void> | void,\n packageId?: string\n ): void {\n this.registerHook(event, handler, { object: objectName, packageId });\n }\n\n /**\n * Remove all hooks, actions, and objects contributed by a package.\n */\n removePackage(packageId: string): void {\n // Remove hooks\n for (const [key, handlers] of this.hooks.entries()) {\n const filtered = handlers.filter(h => h.packageId !== packageId);\n if (filtered.length !== handlers.length) {\n this.hooks.set(key, filtered);\n }\n }\n // Remove actions\n this.removeActionsByPackage(packageId);\n // Remove objects\n this._registry.unregisterObjectsByPackage(packageId, true);\n }\n\n /**\n * Gracefully shut down the engine, disconnecting all drivers.\n * Alias for destroy() — matches @objectql/core close() API.\n */\n async close(): Promise<void> {\n return this.destroy();\n }\n\n /**\n * Create a scoped execution context bound to this engine.\n * \n * Usage:\n * const ctx = engine.createContext({ userId: '...', tenantId: '...' });\n * const users = ctx.object('user');\n * await users.find({ filter: { status: 'active' } });\n */\n createContext(ctx: Partial<ExecutionContext>): ScopedContext {\n return new ScopedContext(\n ExecutionContextSchema.parse(ctx),\n this\n );\n }\n\n /**\n * Static factory: create a fully configured ObjectQL instance.\n * \n * Matches @objectql/core's `new ObjectQL(config)` pattern but also\n * registers drivers and objects, then calls init().\n * \n * Usage:\n * const ql = await ObjectQL.create({\n * datasources: { default: myDriver },\n * objects: { user: { name: 'user', fields: { ... } } }\n * });\n */\n static async create(config: {\n datasources?: Record<string, DriverInterface>;\n objects?: Record<string, ServiceObject>;\n hooks?: Array<{ event: string; object: string; handler: (ctx: HookContext) => Promise<void> | void }>;\n }): Promise<ObjectQL> {\n const ql = new ObjectQL();\n\n // Register drivers\n if (config.datasources) {\n for (const [name, driver] of Object.entries(config.datasources)) {\n // Set driver name if not already set\n if (!driver.name) {\n (driver as any).name = name;\n }\n ql.registerDriver(driver, name === 'default');\n }\n }\n\n // Register objects\n if (config.objects) {\n for (const [_key, schema] of Object.entries(config.objects)) {\n ql.registerObject(schema);\n }\n }\n\n // Register hooks\n if (config.hooks) {\n for (const hook of config.hooks) {\n ql.on(hook.event, hook.object, hook.handler);\n }\n }\n\n // Initialize (connect drivers)\n await ql.init();\n\n return ql;\n }\n}\n\n/**\n * Repository scoped to a single object, bound to an execution context.\n *\n * Provides both IDataEngine-style methods (find, insert, update, delete)\n * and convenience aliases (create, updateById, deleteById) matching\n * the @objectql/core ObjectRepository API.\n */\nexport class ObjectRepository {\n constructor(\n private objectName: string,\n private context: ExecutionContext,\n private engine: IDataEngine & { executeAction?: (o: string, a: string, c: any) => Promise<any> }\n ) {}\n\n async find(query: any = {}): Promise<any[]> {\n return this.engine.find(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async findOne(query: any = {}): Promise<any> {\n return this.engine.findOne(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async insert(data: any): Promise<any> {\n return this.engine.insert(this.objectName, data, {\n context: this.context,\n });\n }\n\n /** Alias for insert() — matches @objectql/core convention */\n async create(data: any): Promise<any> {\n return this.insert(data);\n }\n\n async update(data: any, options: any = {}): Promise<any> {\n return this.engine.update(this.objectName, data, {\n ...options,\n context: this.context,\n });\n }\n\n /** Update a single record by ID */\n async updateById(id: string | number, data: any): Promise<any> {\n return this.engine.update(this.objectName, { ...data, id: id }, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async delete(options: any = {}): Promise<any> {\n return this.engine.delete(this.objectName, {\n ...options,\n context: this.context,\n });\n }\n\n /** Delete a single record by ID */\n async deleteById(id: string | number): Promise<any> {\n return this.engine.delete(this.objectName, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async count(query: any = {}): Promise<number> {\n return this.engine.count(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Aggregate query */\n async aggregate(query: any = {}): Promise<any[]> {\n return this.engine.aggregate(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Execute a named action registered on this object */\n async execute(actionName: string, params?: any): Promise<any> {\n if (this.engine.executeAction) {\n return this.engine.executeAction(this.objectName, actionName, {\n ...params,\n userId: this.context.userId,\n tenantId: this.context.tenantId,\n roles: this.context.roles,\n });\n }\n throw new Error(`Actions not supported by engine`);\n }\n}\n\n/**\n * Scoped execution context with object() accessor.\n * \n * Provides identity (userId, tenantId/spaceId, roles),\n * repository access via object(), privilege escalation via sudo(),\n * and transactional execution via transaction().\n */\nexport class ScopedContext {\n constructor(\n private executionContext: ExecutionContext,\n private engine: IDataEngine\n ) {}\n\n /** Get a repository scoped to this context */\n object(name: string): ObjectRepository {\n return new ObjectRepository(name, this.executionContext, this.engine as any);\n }\n\n /** Create an elevated (system) context */\n sudo(): ScopedContext {\n return new ScopedContext(\n { ...this.executionContext, isSystem: true },\n this.engine\n );\n }\n\n /**\n * Execute a callback within a database transaction.\n *\n * The callback receives a new ScopedContext whose operations\n * share the same transaction handle. If the callback throws,\n * the transaction is rolled back; otherwise it is committed.\n *\n * Falls back to non-transactional execution if the driver\n * does not support transactions.\n */\n async transaction(callback: (trxCtx: ScopedContext) => Promise<any>): Promise<any> {\n const engine = this.engine as any;\n\n // Find the default driver for transaction support\n const driver = engine.defaultDriver\n ? engine.drivers?.get(engine.defaultDriver)\n : undefined;\n\n if (!driver?.beginTransaction) {\n // No transaction support — execute directly\n return callback(this);\n }\n\n const trx = await driver.beginTransaction();\n const trxCtx = new ScopedContext(\n { ...this.executionContext, transaction: trx },\n this.engine\n );\n // Share the engine's ambient transaction store so internal queries during\n // writes reuse this transaction's connection (ADR-0034).\n const txStore = (this.engine as any)?.txStore as\n | { run<R>(s: { transaction: unknown }, fn: () => R): R }\n | undefined;\n const runIn = <R>(fn: () => Promise<R>): Promise<R> =>\n txStore ? txStore.run({ transaction: trx }, fn) : fn();\n\n try {\n const result = await runIn(() => callback(trxCtx));\n if (driver.commit) await driver.commit(trx);\n else if (driver.commitTransaction) await driver.commitTransaction(trx);\n return result;\n } catch (error) {\n if (driver.rollback) await driver.rollback(trx);\n else if (driver.rollbackTransaction) await driver.rollbackTransaction(trx);\n throw error;\n }\n }\n\n get userId() { return this.executionContext.userId; }\n get tenantId() { return this.executionContext.tenantId; }\n /** Alias for tenantId — matches ObjectQLContext.spaceId convention */\n get spaceId() { return this.executionContext.tenantId; }\n get roles() { return this.executionContext.roles; }\n get isSystem() { return this.executionContext.isSystem; }\n\n /** Internal: expose the transaction handle for driver-level access */\n get transactionHandle() { return this.executionContext.transaction; }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Secret-field channel — helpers for the `secret` FieldType.\n *\n * A `secret` field (DB password, API key, token) is **reversible**: the engine\n * encrypts it on write via the registered `ICryptoProvider`, persists the\n * ciphertext as a `sys_secret` row, and stores only an opaque *ref* on the\n * business row. On read the ref is masked, never the plaintext. This mirrors\n * the Settings subsystem (`sys_setting.value_enc → sys_secret.id`), generalized\n * to object fields.\n *\n * Contrast with `password` — a one-way hash owned by the auth subsystem, never\n * decrypted. The two never share a code path.\n */\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n/**\n * Prefix marking a persisted field value as a `sys_secret` handle ref rather\n * than cleartext. Chosen to be unambiguous and human-greppable in a DB dump,\n * while making it obvious that the column holds no plaintext.\n */\nexport const SECRET_REF_PREFIX = 'secret:';\n\n/**\n * Value returned in place of a secret field on a normal read. Indicates\n * \"a secret is set\" without leaking the handle id or the plaintext. A field\n * with no stored secret resolves to `null` instead.\n */\nexport const SECRET_MASK = '••••••••';\n\n/** Wrap a `sys_secret` handle id as the opaque ref persisted on the row. */\nexport function makeSecretRef(handleId: string): string {\n return `${SECRET_REF_PREFIX}${handleId}`;\n}\n\n/** True when `value` is a secret ref previously produced by {@link makeSecretRef}. */\nexport function isSecretRef(value: unknown): value is string {\n return typeof value === 'string' && value.startsWith(SECRET_REF_PREFIX);\n}\n\n/** Extract the `sys_secret` handle id from a ref, or `null` when not a ref. */\nexport function parseSecretRef(value: unknown): string | null {\n return isSecretRef(value) ? (value as string).slice(SECRET_REF_PREFIX.length) : null;\n}\n\n/**\n * Collect the names of `secret`-typed fields declared on an object schema.\n * Returns an empty array when the schema has no fields or no secret fields —\n * callers can fast-path on `length === 0` to skip all crypto work.\n */\nexport function collectSecretFields(schema: ServiceObject | undefined | null): string[] {\n const fields = (schema as any)?.fields as Record<string, { type?: string }> | undefined;\n if (!fields) return [];\n const out: string[] = [];\n for (const [name, def] of Object.entries(fields)) {\n if (def && def.type === 'secret') out.push(name);\n }\n return out;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Declarative Hook Wrappers\n *\n * Turns a raw `HookHandler` into one that honours the declarative metadata\n * fields defined on `HookSchema` (`condition`, `async`, `retryPolicy`,\n * `timeout`, `onError`). This lives outside the engine's `triggerHooks`\n * loop so the engine stays minimal and the semantics are unit-testable in\n * isolation.\n *\n * The resulting wrapped handler keeps the original `(ctx) => Promise<void>`\n * signature, so `engine.registerHook` does not need to know anything about\n * the metadata-driven behaviours.\n */\nimport type { Hook, HookContext } from '@objectstack/spec/data';\nimport type { Expression } from '@objectstack/spec';\nimport type { HookHandler } from './engine.js';\nimport { ExpressionEngine } from '@objectstack/formula';\nimport { noopHookMetricsRecorder, type HookMetricsRecorder, type HookMetricOutcome } from './hook-metrics.js';\n\nexport interface WrapDeclarativeOptions {\n /** Logger for declarative-layer diagnostics (timeouts, retries, swallowed errors). */\n logger?: {\n debug: (msg: string, meta?: any) => void;\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n error: (msg: string, meta?: any) => void;\n };\n /** Optional per-execution metrics sink. Defaults to no-op. */\n metrics?: HookMetricsRecorder;\n}\n\nconst noopLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/**\n * Wrap a hook handler so it honours the declarative fields defined on\n * `HookSchema`. The wrapping order, from outermost to innermost, is:\n *\n * 1. condition → skip when formula evaluates falsy\n * 2. async → fire-and-forget (after* events only)\n * 3. retry → repeat on throw with backoff\n * 4. timeout → abort if handler runs too long\n * 5. onError → swallow when set to 'log'\n *\n * The condition formula is evaluated against the most useful record-shaped\n * payload available on the context (write payloads first, then `previous`,\n * then a flat merge of input). Read events typically have no record yet,\n * so a condition on a `beforeFind` will simply skip when no data is\n * present.\n */\nexport function wrapDeclarativeHook(\n meta: Hook,\n handler: HookHandler,\n opts: WrapDeclarativeOptions = {},\n): HookHandler {\n const logger = opts.logger ?? noopLogger;\n const metrics = opts.metrics ?? noopHookMetricsRecorder;\n const isAfterEvent = meta.events?.some((e) => typeof e === 'string' && e.startsWith('after')) ?? false;\n const hasBody = Boolean((meta as any).body);\n const labelFor = (ctx: HookContext) => ({\n hook: meta.name,\n object: ctx.object ?? (typeof (meta as any).object === 'string' ? (meta as any).object : undefined),\n event: ctx.event,\n body: hasBody,\n });\n\n // Pre-compile condition once so each invocation is cheap.\n let conditionFn: ((record: any) => boolean) | undefined;\n if (meta.condition) {\n // Accept either string shorthand or full Expression envelope.\n const expr: Expression = typeof meta.condition === 'string'\n ? { dialect: 'cel', source: meta.condition }\n : (meta.condition as Expression);\n if (expr.source && expr.source.trim()) {\n const check = ExpressionEngine.compile(expr);\n if (check.ok) {\n conditionFn = (record: any) => {\n const r = ExpressionEngine.evaluate<boolean>(expr, { record: record ?? {} });\n if (!r.ok) {\n logger.warn('[hook] condition evaluation failed; treating as false', {\n hook: meta.name,\n condition: expr.source,\n error: r.error.message,\n });\n return false;\n }\n return Boolean(r.value);\n };\n } else {\n logger.warn('[hook] condition formula failed to compile; condition ignored', {\n hook: meta.name,\n condition: expr.source,\n error: check.error.message,\n });\n }\n }\n }\n\n const retryMax = Math.max(0, Number(meta.retryPolicy?.maxRetries ?? 0));\n const retryBackoffMs = Math.max(0, Number(meta.retryPolicy?.backoffMs ?? 0));\n const timeoutMs = typeof meta.timeout === 'number' && meta.timeout > 0 ? meta.timeout : undefined;\n const onError = meta.onError ?? 'abort';\n // `async` is only meaningful for after* events; ignore on before* (we must\n // wait for the handler to potentially mutate ctx.input).\n const fireAndForget = Boolean(meta.async) && isAfterEvent;\n\n const runWithTimeout = async (ctx: HookContext): Promise<void> => {\n if (!timeoutMs) {\n await handler(ctx);\n return;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n Promise.resolve().then(() => handler(ctx)),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(`Hook '${meta.name}' timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n };\n\n const runWithRetry = async (ctx: HookContext): Promise<void> => {\n let attempt = 0;\n let lastErr: unknown;\n // attempts = 1 + retryMax\n while (attempt <= retryMax) {\n try {\n await runWithTimeout(ctx);\n return;\n } catch (err) {\n lastErr = err;\n attempt += 1;\n if (attempt > retryMax) break;\n if (retryBackoffMs > 0) {\n await new Promise((r) => setTimeout(r, retryBackoffMs * attempt));\n }\n try { metrics.recordRetry(labelFor(ctx), attempt); } catch { /* noop */ }\n logger.warn('[hook] retrying after failure', {\n hook: meta.name,\n attempt,\n maxRetries: retryMax,\n error: (err as any)?.message,\n });\n }\n }\n throw lastErr;\n };\n\n const runWithErrorPolicy = async (ctx: HookContext): Promise<void> => {\n try {\n await runWithRetry(ctx);\n } catch (err) {\n if (onError === 'log') {\n logger.error('[hook] handler failed (onError=log; suppressing)', {\n hook: meta.name,\n object: ctx.object,\n event: ctx.event,\n error: (err as any)?.message,\n });\n return;\n }\n throw err;\n }\n };\n\n return async (ctx: HookContext): Promise<void> => {\n // 1. Condition gate\n if (conditionFn) {\n const record = pickRecordPayload(ctx);\n if (!conditionFn(record)) {\n logger.debug('[hook] skipped by condition', {\n hook: meta.name,\n object: ctx.object,\n event: ctx.event,\n });\n try { metrics.recordSkip(labelFor(ctx), 'condition'); } catch { /* noop */ }\n return;\n }\n }\n\n const restore = installFlatInput(ctx);\n const startedAt = Date.now();\n\n const recordOutcome = (err?: any) => {\n const elapsed = Date.now() - startedAt;\n let outcome: HookMetricOutcome = 'success';\n if (err) {\n const msg = String(err?.message ?? err ?? '');\n if (/timed out after/i.test(msg)) outcome = 'timeout';\n else if (/capability|cap-rejection|capability_rejected/i.test(msg)) outcome = 'capability_rejected';\n else outcome = 'error';\n }\n try { metrics.recordExecution(labelFor(ctx), outcome, elapsed); } catch { /* noop */ }\n };\n\n try {\n // 2. Fire-and-forget for declarative async after* hooks\n if (fireAndForget) {\n try { metrics.recordSkip(labelFor(ctx), 'fire_and_forget'); } catch { /* noop */ }\n // For fire-and-forget we can't keep ctx.input swapped while the\n // engine moves on — copy what we need, restore, and run async.\n void runWithErrorPolicy(ctx)\n .then(() => recordOutcome())\n .catch((err) => {\n recordOutcome(err);\n logger.error('[hook] async handler error (fire-and-forget)', {\n hook: meta.name,\n error: (err as any)?.message,\n });\n });\n return;\n }\n\n try {\n await runWithErrorPolicy(ctx);\n recordOutcome();\n } catch (err) {\n recordOutcome(err);\n throw err;\n }\n } finally {\n restore();\n }\n };\n}\n\n/**\n * Swap `ctx.input` in place for a Proxy that exposes a flat record view\n * over the engine's `{ data, options, id? }` wrapper. Returns a function\n * that restores the original `ctx.input` reference. Reads of\n * `id` / `options` / `ast` / `data` fall through to the wrapper; reads\n * of any other key fall through to `data`. Writes always go to `data`\n * (creating it if missing) so the engine's downstream `input.data`\n * read picks up mutations made by user code as `input.field = value`.\n */\nfunction installFlatInput(ctx: HookContext): () => void {\n const raw: any = ctx.input ?? {};\n const looksWrapped =\n raw && typeof raw === 'object' &&\n ('data' in raw || 'options' in raw || 'id' in raw || 'ast' in raw);\n if (!looksWrapped) return () => {};\n\n const ensureData = (): Record<string, unknown> => {\n if (!raw.data || typeof raw.data !== 'object') {\n raw.data = {};\n }\n return raw.data as Record<string, unknown>;\n };\n\n const proxy = new Proxy(raw, {\n get(target, prop, receiver) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n return Reflect.get(target, prop, receiver);\n }\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) {\n return (data as any)[prop];\n }\n return Reflect.get(target, prop, receiver);\n },\n set(target, prop, value) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n (target as any)[prop] = value;\n return true;\n }\n ensureData()[prop as string] = value;\n return true;\n },\n has(target, prop) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n return prop in target;\n }\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) return true;\n return prop in target;\n },\n ownKeys(target) {\n // Only enumerate the flat record fields. Wrapper keys\n // (id/options/ast/data) remain accessible via dot/bracket notation\n // but are hidden from Object.keys/for-in so user code that does\n // `Object.keys(input).filter(k => input[k] !== previous[k])` only\n // sees actual record fields.\n const dataKeys = target.data && typeof target.data === 'object'\n ? Object.keys(target.data)\n : [];\n return Array.from(new Set(dataKeys));\n },\n getOwnPropertyDescriptor(target, prop) {\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) {\n return { configurable: true, enumerable: true, writable: true, value: (data as any)[prop] };\n }\n // Wrapper keys: still descriptors so `prop in input` works, but\n // marked non-enumerable so they don't appear in Object.keys().\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n const desc = Object.getOwnPropertyDescriptor(target, prop);\n return desc ? { ...desc, enumerable: false } : undefined;\n }\n return Object.getOwnPropertyDescriptor(target, prop);\n },\n });\n\n (ctx as any).input = proxy;\n return () => {\n (ctx as any).input = raw;\n };\n}\n\n/**\n * Choose the record-shaped object the condition formula should evaluate\n * against. Order:\n * 1. ctx.input.data — write operations carry the new record here\n * 2. ctx.previous — update/delete carry pre-image here\n * 3. ctx.input — fall back to flat input bag (read ops, custom shapes)\n */\nfunction pickRecordPayload(ctx: HookContext): any {\n const input: any = ctx.input ?? {};\n if (input && typeof input === 'object' && input.data && typeof input.data === 'object') {\n return input.data;\n }\n if (ctx.previous && typeof ctx.previous === 'object') {\n return ctx.previous;\n }\n return input;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Hook Execution Metrics\n *\n * Lightweight, transport-agnostic recorder interface for per-hook execution\n * counters and latencies. The default implementation is a no-op so the\n * engine pays zero cost when nobody is observing.\n *\n * Wire a real recorder by calling `engine.setHookMetricsRecorder(recorder)`.\n * The runtime / kernel can adapt this to Otel, Prometheus, StatsD, or\n * whatever telemetry pipeline ships with the deployment.\n *\n * Recorded events:\n * - `recordExecution(label, outcome, durationMs)`\n * outcome ∈ 'success' | 'error' | 'timeout' | 'capability_rejected'\n * - `recordSkip(label, reason)`\n * reason ∈ 'condition' | 'fire_and_forget'\n * - `recordRetry(label, attempt)`\n */\n\nexport type HookMetricOutcome =\n | 'success'\n | 'error'\n | 'timeout'\n | 'capability_rejected';\n\nexport type HookSkipReason = 'condition' | 'fire_and_forget';\n\nexport interface HookMetricLabel {\n /** Hook name (stable id from metadata). */\n hook: string;\n /** Object name the hook is bound to. May be undefined for global hooks. */\n object?: string;\n /** Lifecycle event (`beforeInsert`, `afterUpdate`, etc.). */\n event?: string;\n /** True when the handler comes from a metadata `body` (sandboxed JS). */\n body?: boolean;\n}\n\nexport interface HookMetricsRecorder {\n recordExecution(label: HookMetricLabel, outcome: HookMetricOutcome, durationMs: number): void;\n recordSkip(label: HookMetricLabel, reason: HookSkipReason): void;\n recordRetry(label: HookMetricLabel, attempt: number): void;\n}\n\nexport const noopHookMetricsRecorder: HookMetricsRecorder = {\n recordExecution: () => {},\n recordSkip: () => {},\n recordRetry: () => {},\n};\n\n/**\n * In-memory recorder useful for tests, dev-mode dashboards, and as a\n * starting point for adapter implementations. Aggregates counts + a\n * rolling sum of latency per (hook, outcome).\n */\nexport class InMemoryHookMetricsRecorder implements HookMetricsRecorder {\n private executions = new Map<string, { count: number; totalMs: number }>();\n private skips = new Map<string, number>();\n private retries = new Map<string, number>();\n\n recordExecution(label: HookMetricLabel, outcome: HookMetricOutcome, durationMs: number): void {\n const key = `${label.hook}|${outcome}`;\n const cur = this.executions.get(key) ?? { count: 0, totalMs: 0 };\n cur.count += 1;\n cur.totalMs += Math.max(0, durationMs);\n this.executions.set(key, cur);\n }\n\n recordSkip(label: HookMetricLabel, reason: HookSkipReason): void {\n const key = `${label.hook}|${reason}`;\n this.skips.set(key, (this.skips.get(key) ?? 0) + 1);\n }\n\n recordRetry(label: HookMetricLabel, _attempt: number): void {\n this.retries.set(label.hook, (this.retries.get(label.hook) ?? 0) + 1);\n }\n\n snapshot(): {\n executions: Array<{ hook: string; outcome: HookMetricOutcome; count: number; totalMs: number }>;\n skips: Array<{ hook: string; reason: HookSkipReason; count: number }>;\n retries: Array<{ hook: string; count: number }>;\n } {\n return {\n executions: Array.from(this.executions, ([key, v]) => {\n const [hook, outcome] = key.split('|');\n return { hook, outcome: outcome as HookMetricOutcome, count: v.count, totalMs: v.totalMs };\n }),\n skips: Array.from(this.skips, ([key, count]) => {\n const [hook, reason] = key.split('|');\n return { hook, reason: reason as HookSkipReason, count };\n }),\n retries: Array.from(this.retries, ([hook, count]) => ({ hook, count })),\n };\n }\n\n reset(): void {\n this.executions.clear();\n this.skips.clear();\n this.retries.clear();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Hook Binder\n *\n * Single, canonical entry point that turns declarative `Hook` metadata into\n * runtime registrations on the `ObjectQL` engine. Every metadata source —\n * `defineStack({ hooks })` (consumed by `AppPlugin`), the per-project\n * template seeder (`MultiProjectPlugin`), and the metadata service\n * (`ObjectQLPlugin.loadMetadataFromService`) — funnels through here so\n * that:\n *\n * - Inline function handlers and string-named handlers share one resolver.\n * - Declarative fields (`condition`, `async`, `retryPolicy`, `timeout`,\n * `onError`) are honoured uniformly via `wrapDeclarativeHook`.\n * - Hooks can be unregistered as a unit via `packageId`, enabling clean\n * hot-reload and app uninstall.\n *\n * The ObjectQL engine itself stays simple — it knows how to store and\n * trigger handlers, but knows nothing about declarative semantics. All\n * metadata-aware behaviour lives in this binder + the wrapper module.\n */\n\nimport type { Hook } from '@objectstack/spec/data';\nimport type { ObjectQL, HookHandler } from './engine.js';\nimport { wrapDeclarativeHook } from './hook-wrappers.js';\nimport type { HookMetricsRecorder } from './hook-metrics.js';\n\nexport interface BindHooksOptions {\n /** Owning package / app id — used for `unregisterHooksByPackage`. */\n packageId?: string;\n\n /**\n * Optional name → function map for resolving string `handler` references.\n * Typically supplied by `defineStack({ functions })` and merged with any\n * functions previously registered on the engine.\n */\n functions?: Record<string, HookHandler>;\n\n /**\n * Optional factory that converts a metadata-only `Hook.body` (L1 expression\n * or L2 sandboxed JS source) into an executable `HookHandler`. The runtime\n * package wires this up using `QuickJSScriptRunner`; objectql itself stays\n * sandbox-free so it can run in lightweight environments.\n *\n * If `hook.body` is set and this factory is missing, the hook is skipped\n * with a clear error.\n */\n bodyRunner?: (hook: Hook) => HookHandler | undefined;\n\n /**\n * When true, treat unresolved hooks (body present but no runner, or handler\n * string with no implementation) as fatal errors instead of warnings. Used\n * by production runtimes to fail fast on misconfiguration. Defaults false.\n */\n strict?: boolean;\n\n /**\n * When true, emit a deprecation warning for every hook that still relies\n * on a `handler` ref string instead of the metadata-only `body`. Used by\n * the CLI (compile time) and runtime (boot time) to nudge users away from\n * the legacy `.mjs` runtime bundle path. Defaults false.\n */\n warnLegacyHandler?: boolean;\n\n /** Per-hook execution metrics sink. Defaults to no-op. */\n metrics?: HookMetricsRecorder;\n\n /** Logger; defaults to a silent no-op. */\n logger?: {\n debug: (msg: string, meta?: any) => void;\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n error: (msg: string, meta?: any) => void;\n };\n}\n\nconst noopLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/** Counter for stats. */\nexport interface BindHooksResult {\n registered: number;\n skipped: number;\n errors: Array<{ hook: string; reason: string }>;\n}\n\n/**\n * Bind a list of declarative `Hook` definitions to a running ObjectQL engine.\n *\n * Idempotent on `(packageId, hook.name, event, object)`: re-binding the\n * same set after a hot reload first calls `unregisterHooksByPackage`\n * (when `packageId` is provided).\n */\nexport function bindHooksToEngine(\n engine: ObjectQL,\n hooks: Hook[] | undefined,\n opts: BindHooksOptions = {},\n): BindHooksResult {\n const logger = opts.logger ?? noopLogger;\n const result: BindHooksResult = { registered: 0, skipped: 0, errors: [] };\n\n if (!Array.isArray(hooks) || hooks.length === 0) {\n return result;\n }\n\n // Hot-reload friendly: drop anything we previously bound under this\n // packageId so the new set fully replaces the old.\n if (opts.packageId && typeof (engine as any).unregisterHooksByPackage === 'function') {\n try {\n (engine as any).unregisterHooksByPackage(opts.packageId);\n } catch (err: any) {\n logger.warn('[hook-binder] unregister-by-package failed; continuing', {\n packageId: opts.packageId,\n error: err?.message,\n });\n }\n }\n\n // Pre-load any inline functions supplied via `bundle.functions` so\n // string-handler resolution works.\n if (opts.functions && typeof (engine as any).registerFunction === 'function') {\n for (const [name, fn] of Object.entries(opts.functions)) {\n try {\n (engine as any).registerFunction(name, fn, opts.packageId);\n } catch (err: any) {\n logger.warn('[hook-binder] failed to register function', {\n name,\n error: err?.message,\n });\n }\n }\n }\n\n for (const hook of hooks) {\n try {\n const resolved = resolveHandler(engine, hook, opts);\n if (!resolved) {\n result.skipped += 1;\n const reason = (hook as any).body\n ? `hook body present but no bodyRunner supplied to bindHooksToEngine (runtime must wire QuickJSScriptRunner)`\n : typeof hook.handler === 'string'\n ? `unknown function '${hook.handler}'`\n : 'no handler';\n result.errors.push({ hook: hook.name, reason });\n if (opts.strict) {\n throw new Error(`[hook-binder] strict: cannot bind hook '${hook.name}': ${reason}`);\n }\n logger.warn('[hook-binder] skipping hook with unresolved handler', {\n hook: hook.name,\n handler: hook.handler,\n hasBody: Boolean((hook as any).body),\n });\n continue;\n }\n\n if (opts.warnLegacyHandler && !(hook as any).body && typeof hook.handler === 'string') {\n logger.warn('[hook-binder] DEPRECATED: hook uses legacy handler ref without body', {\n hook: hook.name,\n handler: hook.handler,\n hint: 'Move the handler source into Hook.body so the artifact stays metadata-only and the .mjs runtime bundle can be dropped.',\n });\n }\n\n const wrapped = wrapDeclarativeHook(hook, resolved, { logger, metrics: opts.metrics });\n const objects = normalizeObjects(hook.object);\n const events = Array.isArray(hook.events) ? hook.events : [];\n\n for (const event of events) {\n for (const object of objects) {\n engine.registerHook(event, wrapped, {\n object,\n priority: typeof hook.priority === 'number' ? hook.priority : 100,\n packageId: opts.packageId,\n // Reflect metadata so future tooling can introspect / unregister\n // and so we can detect duplicate name collisions.\n // The engine ignores unknown options today; this is forward-only.\n ...({ meta: hook, hookName: hook.name } as any),\n } as any);\n result.registered += 1;\n }\n }\n } catch (err: any) {\n result.errors.push({ hook: hook.name, reason: err?.message ?? String(err) });\n logger.error('[hook-binder] failed to bind hook', {\n hook: hook.name,\n error: err?.message,\n });\n }\n }\n\n if (result.registered > 0) {\n logger.debug('[hook-binder] hooks bound', {\n packageId: opts.packageId,\n registered: result.registered,\n skipped: result.skipped,\n });\n }\n\n return result;\n}\n\nfunction normalizeObjects(target: Hook['object']): string[] {\n if (Array.isArray(target)) return target.length > 0 ? target : ['*'];\n if (typeof target === 'string' && target.length > 0) return [target];\n return ['*'];\n}\n\nfunction resolveHandler(\n engine: ObjectQL,\n hook: Hook,\n opts: BindHooksOptions,\n): HookHandler | undefined {\n // Metadata-only body (L1 expression or L2 sandboxed JS) takes precedence\n // over the legacy `handler` field. This is the cloud-deployable path —\n // the body string ships inside the artifact JSON and runs under a\n // capability-gated sandbox supplied by the runtime.\n const body = (hook as any).body;\n if (body && typeof body === 'object') {\n let runner = opts.bodyRunner;\n if (typeof runner !== 'function') {\n const fallback = (engine as any)?._defaultBodyRunner;\n if (typeof fallback === 'function') runner = fallback;\n }\n if (typeof runner !== 'function') {\n return undefined;\n }\n const fn = runner(hook);\n if (typeof fn === 'function') return fn;\n return undefined;\n }\n\n const h = hook.handler;\n if (typeof h === 'function') return h as HookHandler;\n if (typeof h === 'string' && h.length > 0) {\n // Try the per-bundle map first (hot path during initial bind),\n // then fall back to whatever the engine already knows.\n const fromBundle = opts.functions?.[h];\n if (typeof fromBundle === 'function') return fromBundle;\n if (typeof (engine as any).resolveFunction === 'function') {\n const fn = (engine as any).resolveFunction(h);\n if (typeof fn === 'function') return fn as HookHandler;\n }\n }\n return undefined;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Record Validator\n *\n * Validates an incoming insert/update payload against the canonical\n * `Field` metadata of an `ObjectSchema`. Implements ROADMAP §M10.4 —\n * \"Zod-at-rest\" — but does not require constructing a Zod schema:\n * we walk the field map directly, which is both faster and lets us\n * produce per-field error envelopes shaped for REST consumption.\n *\n * Rules applied (in order, stop at first error per field):\n *\n * - `required` missing/null/empty-string is rejected (insert only;\n * PATCH validates only fields actually supplied)\n * - `maxLength` / `minLength` (text/textarea/email/url/phone/password)\n * - `min` / `max` (number/currency/percent/rating/slider)\n * - format email / url / phone (lightweight RFC-aware regex)\n * - select / multiselect: value must appear in `options`\n * - boolean / toggle: must coerce to boolean\n * - date / datetime: must be ISO-parsable\n *\n * System-injected fields (`id`, `created_at`, `created_by`,\n * `updated_at`, `updated_by`, `organization_id`) are never validated\n * here — the engine and the audit plugin manage them.\n *\n * On failure, a `ValidationError` is thrown with `.fields[]` holding\n * one entry per offending field. REST translates this into a\n * `400 { code: 'VALIDATION_FAILED', message, fields }` envelope so\n * the UI can highlight the specific input.\n */\n\nconst SKIP_FIELDS = new Set<string>([\n 'id', 'created_at', 'created_by', 'updated_at', 'updated_by',\n 'organization_id', 'tenant_id',\n]);\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n// Permissive URL pattern: accept any scheme:// + non-empty body so that\n// non-HTTP URIs used by drivers (libsql://, postgres://, mysql://, file://, s3://, …)\n// pass field-level validation. Stricter per-field checks can be enforced\n// via custom validators where needed.\nconst URL_RE = /^[a-z][a-z0-9+.\\-]*:\\/\\/[^\\s]+$/i;\nconst PHONE_RE = /^[+()\\-\\s\\d.]{5,}$/;\n\nexport interface FieldValidationError {\n field: string;\n code:\n | 'required'\n | 'min_length'\n | 'max_length'\n | 'min_value'\n | 'max_value'\n | 'invalid_email'\n | 'invalid_url'\n | 'invalid_phone'\n | 'invalid_number'\n | 'invalid_boolean'\n | 'invalid_date'\n | 'invalid_option'\n // Object-level validation rules (ADR-0020, see rule-validator.ts)\n | 'invalid_transition'\n | 'rule_violation'\n | 'invalid_format'\n | 'invalid_json'\n | 'json_schema_violation';\n message: string;\n /** Allowed values for select/multiselect, when applicable. */\n options?: string[];\n}\n\nexport class ValidationError extends Error {\n readonly code = 'VALIDATION_FAILED';\n readonly fields: FieldValidationError[];\n constructor(fields: FieldValidationError[]) {\n super(\n `Validation failed for ${fields.length} field(s): ` +\n fields.map((f) => `${f.field} (${f.code})`).join(', '),\n );\n this.name = 'ValidationError';\n this.fields = fields;\n }\n}\n\ntype Mode = 'insert' | 'update';\n\ninterface FieldDef {\n name?: string;\n type: string;\n required?: boolean;\n readonly?: boolean;\n system?: boolean;\n multiple?: boolean;\n maxLength?: number;\n minLength?: number;\n min?: number;\n max?: number;\n options?: Array<{ value: string | number; label?: string } | string | number>;\n}\n\nfunction isMissing(v: unknown): boolean {\n return v === undefined || v === null || (typeof v === 'string' && v.trim() === '');\n}\n\nfunction optionValues(options: FieldDef['options']): string[] {\n if (!Array.isArray(options)) return [];\n return options.map((o) =>\n typeof o === 'object' && o !== null ? String((o as any).value) : String(o),\n );\n}\n\nfunction validateOne(name: string, def: FieldDef, value: unknown): FieldValidationError | null {\n // ── required ────────────────────────────────────────────────────\n // `autonumber` is runtime-owned: the value is generated by the engine /\n // driver (the SQL driver assigns it from a persistent sequence AFTER this\n // validation runs), so a missing value is never a client error — see #1603.\n if (def.required && isMissing(value) && def.type !== 'autonumber') {\n return { field: name, code: 'required', message: `${name} is required` };\n }\n if (isMissing(value)) return null; // nothing else to check\n\n const t = def.type;\n\n // ── string types ────────────────────────────────────────────────\n if (t === 'text' || t === 'textarea' || t === 'email' || t === 'url' || t === 'phone' || t === 'password' || t === 'markdown' || t === 'html' || t === 'richtext' || t === 'code') {\n const s = typeof value === 'string' ? value : String(value);\n if (def.maxLength !== undefined && s.length > def.maxLength) {\n return { field: name, code: 'max_length', message: `${name} must be ≤ ${def.maxLength} characters (got ${s.length})` };\n }\n if (def.minLength !== undefined && s.length < def.minLength) {\n return { field: name, code: 'min_length', message: `${name} must be ≥ ${def.minLength} characters (got ${s.length})` };\n }\n if (t === 'email' && !EMAIL_RE.test(s)) {\n return { field: name, code: 'invalid_email', message: `${name} must be a valid email address` };\n }\n if (t === 'url' && !URL_RE.test(s)) {\n return { field: name, code: 'invalid_url', message: `${name} must be a valid URL (scheme://...)` };\n }\n if (t === 'phone' && !PHONE_RE.test(s)) {\n return { field: name, code: 'invalid_phone', message: `${name} must be a valid phone number` };\n }\n return null;\n }\n\n // ── number types ────────────────────────────────────────────────\n if (t === 'number' || t === 'currency' || t === 'percent' || t === 'rating' || t === 'slider') {\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) {\n return { field: name, code: 'invalid_number', message: `${name} must be a number` };\n }\n if (def.min !== undefined && n < def.min) {\n return { field: name, code: 'min_value', message: `${name} must be ≥ ${def.min}` };\n }\n if (def.max !== undefined && n > def.max) {\n return { field: name, code: 'max_value', message: `${name} must be ≤ ${def.max}` };\n }\n return null;\n }\n\n // ── boolean ────────────────────────────────────────────────────\n if (t === 'boolean' || t === 'toggle') {\n if (typeof value === 'boolean') return null;\n if (value === 0 || value === 1 || value === '0' || value === '1' || value === 'true' || value === 'false') return null;\n return { field: name, code: 'invalid_boolean', message: `${name} must be true or false` };\n }\n\n // ── date/datetime ───────────────────────────────────────────────\n if (t === 'date' || t === 'datetime' || t === 'time') {\n if (value instanceof Date) return null;\n if (typeof value === 'string' && !Number.isNaN(Date.parse(value))) return null;\n return { field: name, code: 'invalid_date', message: `${name} must be a valid ${t} (ISO-8601)` };\n }\n\n // ── select / multiselect / radio ────────────────────────────────\n if (t === 'select' || t === 'radio') {\n const allowed = optionValues(def.options);\n if (allowed.length > 0 && !allowed.includes(String(value))) {\n return { field: name, code: 'invalid_option', message: `${name} must be one of: ${allowed.join(', ')}`, options: allowed };\n }\n return null;\n }\n if (t === 'multiselect' || t === 'checkboxes' || t === 'tags') {\n const allowed = optionValues(def.options);\n if (allowed.length === 0) return null;\n const arr = Array.isArray(value) ? value : [value];\n for (const v of arr) {\n if (!allowed.includes(String(v))) {\n return { field: name, code: 'invalid_option', message: `${name}: \"${v}\" is not one of: ${allowed.join(', ')}`, options: allowed };\n }\n }\n return null;\n }\n\n // Other types (lookup, file, formula, json, location, etc.) — no\n // strict shape check at this layer; reference integrity is handled\n // elsewhere (lookup) and the rest are opaque payloads.\n return null;\n}\n\n/**\n * Validate a payload against a list of declared fields. `objectSchema`\n * comes from `ObjectQL.getRegistry().getObject(name)` and exposes a\n * `fields` map of `{ [fieldName]: FieldDef }`.\n *\n * Returns void on success; throws `ValidationError` on failure.\n */\nexport function validateRecord(\n objectSchema: { fields?: Record<string, FieldDef> } | undefined | null,\n data: Record<string, unknown> | undefined | null,\n mode: Mode,\n): void {\n if (!objectSchema?.fields || !data) return;\n\n const errors: FieldValidationError[] = [];\n const fields = objectSchema.fields;\n\n if (mode === 'insert') {\n // Walk all declared fields — required check applies even when\n // the caller didn't supply the field at all.\n for (const [name, def] of Object.entries(fields)) {\n if (SKIP_FIELDS.has(name)) continue;\n if (def.system || def.readonly) continue;\n const err = validateOne(name, def, data[name]);\n if (err) errors.push(err);\n }\n } else {\n // Update — validate only supplied fields, skip required check.\n for (const [name, value] of Object.entries(data)) {\n if (SKIP_FIELDS.has(name)) continue;\n const def = fields[name];\n if (!def) continue;\n if (def.system || def.readonly) continue;\n // Clone def with required=false so PATCH-omitted-fields don't 400.\n const err = validateOne(name, { ...def, required: false }, value);\n if (err) errors.push(err);\n }\n }\n\n if (errors.length > 0) throw new ValidationError(errors);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Validation-Rule Evaluator (ADR-0020)\n *\n * Where `record-validator.ts` checks field *shape* (types, lengths, option\n * membership), this module enforces the object-level **business rules**\n * declared in `ObjectSchema.validations` — the discriminated union of\n * `state_machine`, `cross_field`, `script`, … rules.\n *\n * Until ADR-0020 these rules were pure declaration: nothing on the write\n * path ever read `objectSchema.validations`, so a `state_machine` rule that\n * said \"an account can't jump from churned straight back to prospect\"\n * silently allowed exactly that. This evaluator closes that gap.\n *\n * ## What runs here\n *\n * - `state_machine` — the headline guardrail. On update, if the state field\n * changed and the new value is not in `transitions[oldValue]`, the write\n * is rejected. Needs the **prior** record (see plumbing note below).\n * - `script` / `cross_field` — CEL predicates. If the predicate evaluates\n * TRUE the rule is violated. These share the prior-record gap with\n * `state_machine` (a PATCH carries only changed fields), so they are\n * evaluated against the *merged* record `{ ...previous, ...patch }`.\n * - `format` — a single field's value against a regex and/or a named format\n * (`email` / `url` / `phone` / `json`). Only runs when the write touches\n * the field and the value is non-empty (emptiness is the field-shape\n * validator's job, not the format rule's).\n * - `json_schema` — a JSON field validated against a JSON Schema via ajv.\n * - `conditional` — evaluates the `when` CEL predicate and then recurses into\n * `then` (true) or `otherwise` (false). The nested rule's violation message\n * is surfaced; the *outer* conditional's `severity` decides whether it\n * blocks (so `when`-gated guards can be advisory as a unit).\n *\n * Every variant declared by `ValidationRuleSchema` is enforced here — the\n * schema deliberately excludes anything that would need I/O or a handler model\n * (uniqueness → DB index, async → form layer, custom → lifecycle hook), so\n * there are no silent no-ops.\n *\n * ## Execution-control semantics (from `BaseValidationSchema`)\n *\n * - `active: false` → rule skipped entirely.\n * - `events` → rule only runs for the matching write context\n * (`insert` / `update`). `delete` is not a write\n * payload context here.\n * - `priority` → rules evaluated low-number-first (stable).\n * - `severity` → only `error` blocks the write. `warning` / `info`\n * are logged (best-effort) and never throw.\n *\n * ## Fail-open for *broken* rules, fail-closed for *violated* rules\n *\n * A CEL predicate that cannot be evaluated (parse error, references an\n * unbound variable, …) is a broken rule, not a violated one — it is logged\n * and skipped rather than bricking every write to the object. A predicate\n * that evaluates cleanly to \"violated\", or a transition that is definitively\n * illegal, is fail-closed (the write is rejected).\n *\n * ## Prior-record plumbing\n *\n * `state_machine` and the field-spanning predicates are meaningful only with\n * the record's prior state. The engine fetches it once (see\n * `engine.update`) and threads it in via `opts.previous`. On `insert` there\n * is no prior state, so `state_machine` is a no-op (the field-level select\n * check already constrains the initial value to a declared option).\n */\n\nimport { ExpressionEngine } from '@objectstack/formula';\nimport type { Expression } from '@objectstack/spec';\nimport Ajv, { type ValidateFunction } from 'ajv';\nimport { ValidationError, type FieldValidationError } from './record-validator.js';\n\ntype Mode = 'insert' | 'update';\n\ninterface BaseRule {\n type: string;\n name: string;\n message: string;\n active?: boolean;\n events?: Array<'insert' | 'update' | 'delete'>;\n priority?: number;\n severity?: 'error' | 'warning' | 'info';\n}\n\ninterface StateMachineRule extends BaseRule {\n type: 'state_machine';\n field: string;\n transitions: Record<string, string[]>;\n}\n\ninterface PredicateRule extends BaseRule {\n type: 'script' | 'cross_field';\n condition: string | Expression;\n fields?: string[];\n}\n\ninterface FormatRule extends BaseRule {\n type: 'format';\n field: string;\n regex?: string;\n format?: 'email' | 'url' | 'phone' | 'json';\n}\n\ninterface JsonSchemaRule extends BaseRule {\n type: 'json_schema';\n field: string;\n schema: Record<string, unknown>;\n}\n\ninterface ConditionalRule extends BaseRule {\n type: 'conditional';\n when: string | Expression;\n then: BaseRule;\n otherwise?: BaseRule;\n}\n\n/**\n * Context threaded through every rule evaluation. `data` is the raw incoming\n * write (a PATCH on update); `merged` overlays it on the prior record so a\n * predicate referencing an unchanged field still sees its persisted value.\n * Field-scoped rules (`state_machine`, `format`, `json_schema`) key off `data`\n * to decide whether the write actually touched their field.\n */\ninterface RuleContext {\n data: Record<string, unknown>;\n merged: Record<string, unknown>;\n previous: Record<string, unknown> | undefined;\n mode: Mode;\n logger: EvaluateRulesOptions['logger'];\n}\n\n/**\n * Shared ajv instance. `strict: false` tolerates author-written JSON Schemas\n * that use vendor keywords; `compile` results are memoised per schema object\n * (see `jsonSchemaCache`) so we don't recompile on every write.\n */\nconst ajv = new Ajv({ allErrors: true, strict: false });\nconst jsonSchemaCache = new WeakMap<object, ValidateFunction>();\n\nexport interface EvaluateRulesOptions {\n /** Prior persisted record (update only). Absent on insert. */\n previous?: Record<string, unknown> | null;\n /** Optional logger for non-blocking diagnostics (broken rules, warnings). */\n logger?: { warn?: (msg: string, meta?: any) => void };\n}\n\n/**\n * Returns true when the object declares at least one validation rule whose\n * correct evaluation needs the prior record (so the engine knows whether the\n * extra fetch on the update path is worth it).\n */\nexport function needsPriorRecord(\n objectSchema: { validations?: unknown[]; fields?: Record<string, ConditionalFieldDef> } | undefined | null,\n): boolean {\n const rules = objectSchema?.validations;\n const ruleNeeds = Array.isArray(rules) && rules.some((r) => ruleNeedsPrior(r));\n return !!(ruleNeeds || fieldsNeedPrior(objectSchema?.fields));\n}\n\n/**\n * Strip fields whose `readonlyWhen` CEL predicate is TRUE for the (merged)\n * record from an UPDATE payload — the field is locked, so an incoming change is\n * ignored (the persisted value is kept) rather than rejected. Returns the same\n * object when nothing is locked, else a shallow copy with the locked keys\n * removed. A broken predicate is fail-open (the change is allowed through).\n */\nexport function stripReadonlyWhenFields(\n objectSchema: { fields?: Record<string, ConditionalFieldDef> } | undefined | null,\n data: Record<string, unknown> | undefined | null,\n previous: Record<string, unknown> | undefined | null,\n logger?: EvaluateRulesOptions['logger'],\n): Record<string, unknown> | undefined | null {\n const fields = objectSchema?.fields;\n if (!fields || !data) return data;\n const merged = { ...(previous ?? {}), ...data };\n let result = data;\n for (const [name, def] of Object.entries(fields)) {\n if (!def?.readonlyWhen || !(name in data)) continue;\n const res = ExpressionEngine.evaluate<boolean>(toExpression(def.readonlyWhen), {\n record: merged,\n previous: previous ?? undefined,\n });\n if (!res.ok) {\n logger?.warn?.(`readonlyWhen for '${name}' failed to evaluate — change allowed through`);\n continue;\n }\n if (res.value === true) {\n if (result === data) result = { ...data };\n delete (result as Record<string, unknown>)[name];\n logger?.warn?.(`Field '${name}' is read-only (readonlyWhen) — ignoring incoming change`);\n }\n }\n return result;\n}\n\n/**\n * A rule needs the prior record if it reasons about the transition or compares\n * against unchanged fields (`state_machine` / `cross_field` / `script`), or if\n * it is a `conditional` whose branches (or `when`) recursively do. `format` and\n * `json_schema` only inspect the incoming value, so they never need it.\n */\nfunction ruleNeedsPrior(r: unknown): boolean {\n if (r == null || typeof r !== 'object') return false;\n const type = (r as BaseRule).type;\n if (type === 'state_machine' || type === 'cross_field' || type === 'script') {\n return true;\n }\n if (type === 'conditional') {\n const c = r as ConditionalRule;\n // `when` is evaluated against the merged record; the branches may need prior\n // state. Be conservative and fetch if either branch does.\n return ruleNeedsPrior(c.then) || ruleNeedsPrior(c.otherwise);\n }\n return false;\n}\n\n/** Field-level conditional rules (B2): a field is required / read-only when its\n * CEL predicate is TRUE over the record. */\ninterface ConditionalFieldDef {\n requiredWhen?: string | Expression;\n conditionalRequired?: string | Expression; // back-compat alias of requiredWhen\n readonlyWhen?: string | Expression;\n}\n\nfunction isMissing(v: unknown): boolean {\n return v === undefined || v === null || (typeof v === 'string' && v.trim() === '');\n}\n\n/** True when any field declares a conditional rule that needs the merged/prior\n * record to evaluate (so the engine fetches `previous` on update). */\nfunction fieldsNeedPrior(fields: Record<string, ConditionalFieldDef> | undefined): boolean {\n if (!fields) return false;\n return Object.values(fields).some(\n (f) => f && (f.requiredWhen || f.conditionalRequired || f.readonlyWhen),\n );\n}\n\n/** Normalize an author-time ExpressionInput into the canonical envelope. */\nfunction toExpression(cond: string | Expression): Expression {\n return typeof cond === 'string' ? { dialect: 'cel', source: cond } : cond;\n}\n\n/**\n * Evaluate an object's declared validation rules against an incoming write.\n *\n * Throws `ValidationError` (the same envelope `validateRecord` uses, so REST\n * surfaces a single `400 VALIDATION_FAILED`) when one or more `error`-severity\n * rules are violated. Returns void otherwise.\n */\nexport function evaluateValidationRules(\n objectSchema: { validations?: unknown[]; fields?: Record<string, ConditionalFieldDef> } | undefined | null,\n data: Record<string, unknown> | undefined | null,\n mode: Mode,\n opts: EvaluateRulesOptions = {},\n): void {\n if (!data) return;\n const rules = objectSchema?.validations;\n const hasRules = Array.isArray(rules) && rules.length > 0;\n const fields = objectSchema?.fields;\n const hasFieldRules = fieldsNeedPrior(fields);\n if (!hasRules && !hasFieldRules) return;\n\n const previous = opts.previous ?? undefined;\n // Merged view used by predicate rules: prior state overlaid with the PATCH,\n // so a rule referencing an unchanged field still sees its persisted value.\n const merged: Record<string, unknown> = { ...(previous ?? {}), ...data };\n const ctx: RuleContext = { data, merged, previous, mode, logger: opts.logger };\n\n const errors: FieldValidationError[] = [];\n\n // Field-level conditional rules (B2): a field whose `requiredWhen`\n // (or its `conditionalRequired` alias) predicate is TRUE over the merged\n // record must have a value — enforced server-side so the rule can't be\n // bypassed. (`readonlyWhen` is handled by stripReadonlyWhenFields on the\n // write path, not here.) A broken predicate is fail-open (logged, skipped).\n if (hasFieldRules && fields) {\n for (const [name, def] of Object.entries(fields)) {\n const pred = def?.requiredWhen ?? def?.conditionalRequired;\n if (!pred) continue;\n const res = ExpressionEngine.evaluate<boolean>(toExpression(pred), { record: merged, previous });\n if (!res.ok) {\n opts.logger?.warn?.(`requiredWhen for '${name}' failed to evaluate — skipped`);\n continue;\n }\n if (res.value === true && isMissing(merged[name])) {\n errors.push({ field: name, code: 'required', message: `${name} is required` });\n }\n }\n }\n\n const ordered = (hasRules ? rules! : [])\n .filter((r): r is BaseRule => r != null && typeof r === 'object')\n .filter((r) => r.active !== false)\n .filter((r) => {\n const events = r.events ?? ['insert', 'update'];\n return events.includes(mode);\n })\n .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));\n\n for (const rule of ordered) {\n let violation: FieldValidationError | null = null;\n try {\n violation = evaluateRule(rule, ctx);\n } catch (err) {\n // Defensive: a broken rule must never brick a write.\n opts.logger?.warn?.(`Validation rule '${rule.name}' threw — skipped`, err);\n continue;\n }\n\n if (!violation) continue;\n\n const severity = rule.severity ?? 'error';\n if (severity === 'error') {\n errors.push(violation);\n } else {\n opts.logger?.warn?.(\n `Validation rule '${rule.name}' (${severity}): ${violation.message}`,\n );\n }\n }\n\n if (errors.length > 0) throw new ValidationError(errors);\n}\n\n/**\n * Dispatch a single rule to its checker, returning the violation (or null).\n * Shared by the top-level loop and by `checkConditional`, which recurses into\n * its `then` / `otherwise` branch. Unknown types return null — but the schema\n * (`ValidationRuleSchema`) only admits the types handled below, so in practice\n * every declared rule is covered.\n */\nfunction evaluateRule(rule: BaseRule, ctx: RuleContext): FieldValidationError | null {\n switch (rule.type) {\n case 'state_machine':\n return checkStateMachine(rule as StateMachineRule, ctx.mode, ctx.data, ctx.previous);\n case 'script':\n case 'cross_field':\n return checkPredicate(rule as PredicateRule, ctx.merged, ctx.previous, ctx.logger);\n case 'format':\n return checkFormat(rule as FormatRule, ctx.data, ctx.logger);\n case 'json_schema':\n return checkJsonSchema(rule as JsonSchemaRule, ctx.data, ctx.logger);\n case 'conditional':\n return checkConditional(rule as ConditionalRule, ctx);\n default:\n return null;\n }\n}\n\n/**\n * State-machine transition check.\n *\n * Only meaningful on update with a prior record: if the state field changed,\n * the new value must appear in `transitions[oldValue]`. Lenient where it\n * cannot reason (no prior record, unchanged value, or a prior state with no\n * declared transitions) so it never blocks legitimate or legacy data.\n */\nfunction checkStateMachine(\n rule: StateMachineRule,\n mode: Mode,\n data: Record<string, unknown>,\n previous: Record<string, unknown> | undefined,\n): FieldValidationError | null {\n // Insert has no prior state — the field-level select check already\n // constrains the initial value to a declared option.\n if (mode === 'insert' || !previous) return null;\n // The PATCH didn't touch the state field → no transition to validate.\n if (!(rule.field in data)) return null;\n\n const from = previous[rule.field];\n const to = data[rule.field];\n // No change, or clearing the value → nothing to enforce.\n if (from === to || to === undefined || to === null) return null;\n\n const fromKey = String(from);\n const allowed = rule.transitions[fromKey];\n // Prior state not described by the FSM (legacy / external write) — cannot\n // reason about its legal targets, so don't block.\n if (!Array.isArray(allowed)) return null;\n\n if (!allowed.includes(String(to))) {\n return {\n field: rule.field,\n code: 'invalid_transition',\n message:\n rule.message ||\n `Invalid transition for ${rule.field}: ${fromKey} → ${String(to)}`,\n };\n }\n return null;\n}\n\n/**\n * CEL predicate check (`script` / `cross_field`). The predicate expresses the\n * *failure* condition: if it evaluates TRUE the rule is violated. An\n * un-evaluable predicate is treated as a broken rule (logged, skipped).\n */\nfunction checkPredicate(\n rule: PredicateRule,\n record: Record<string, unknown>,\n previous: Record<string, unknown> | undefined,\n logger: EvaluateRulesOptions['logger'],\n): FieldValidationError | null {\n const expr = toExpression(rule.condition);\n const result = ExpressionEngine.evaluate<boolean>(expr, {\n record,\n previous: previous ?? undefined,\n });\n\n if (!result.ok) {\n logger?.warn?.(\n `Validation rule '${rule.name}' predicate failed to evaluate (${result.error.kind}: ${result.error.message}) — skipped`,\n );\n return null;\n }\n\n if (result.value === true) {\n return {\n field: rule.fields?.[0] ?? '_record',\n code: 'rule_violation',\n message: rule.message,\n };\n }\n return null;\n}\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n// Lenient phone matcher: optional leading +, then 7–20 digits with spaces,\n// dashes, dots and parens allowed as separators. Intentionally permissive —\n// strict national formats belong in a `regex`.\nconst PHONE_RE = /^\\+?[\\d\\s().-]{7,20}$/;\n\n/**\n * Format check (`format`). Validates a single field's value against an optional\n * `regex` and/or a named `format`. Only runs when the write touches the field\n * (mirrors `state_machine`) and the value is non-empty — requiredness and\n * type-shape are the field-level validator's job, so an absent/blank value is\n * not a *format* violation. A malformed `regex` is a broken rule (logged,\n * fail-open), not a violation.\n */\nfunction checkFormat(\n rule: FormatRule,\n data: Record<string, unknown>,\n logger: EvaluateRulesOptions['logger'],\n): FieldValidationError | null {\n if (!(rule.field in data)) return null;\n const value = data[rule.field];\n if (value === null || value === undefined || value === '') return null;\n const str = String(value);\n\n if (rule.regex) {\n let re: RegExp;\n try {\n re = new RegExp(rule.regex);\n } catch {\n logger?.warn?.(`Validation rule '${rule.name}' has an invalid regex — skipped`);\n return null;\n }\n if (!re.test(str)) return formatViolation(rule);\n }\n\n if (rule.format && !matchesNamedFormat(rule.format, str)) {\n return formatViolation(rule);\n }\n return null;\n}\n\nfunction matchesNamedFormat(format: FormatRule['format'], str: string): boolean {\n switch (format) {\n case 'email':\n return EMAIL_RE.test(str);\n case 'phone':\n return PHONE_RE.test(str);\n case 'url':\n try {\n // eslint-disable-next-line no-new\n new URL(str);\n return true;\n } catch {\n return false;\n }\n case 'json':\n try {\n JSON.parse(str);\n return true;\n } catch {\n return false;\n }\n default:\n return true;\n }\n}\n\nfunction formatViolation(rule: FormatRule): FieldValidationError {\n return { field: rule.field, code: 'invalid_format', message: rule.message };\n}\n\n/**\n * JSON Schema check (`json_schema`). Validates a JSON field against the rule's\n * schema via ajv. The field value may be a parsed object or a JSON string (a\n * string that fails to parse is itself a violation). Only runs when the write\n * touches the field and the value is non-null. A schema ajv cannot compile is a\n * broken rule (logged, fail-open).\n */\nfunction checkJsonSchema(\n rule: JsonSchemaRule,\n data: Record<string, unknown>,\n logger: EvaluateRulesOptions['logger'],\n): FieldValidationError | null {\n if (!(rule.field in data)) return null;\n let value = data[rule.field];\n if (value === null || value === undefined) return null;\n\n if (typeof value === 'string') {\n try {\n value = JSON.parse(value);\n } catch {\n return { field: rule.field, code: 'invalid_json', message: rule.message };\n }\n }\n\n let validate = jsonSchemaCache.get(rule.schema);\n if (!validate) {\n try {\n validate = ajv.compile(rule.schema);\n } catch (err) {\n logger?.warn?.(\n `Validation rule '${rule.name}' has an uncompilable JSON Schema — skipped`,\n err,\n );\n return null;\n }\n jsonSchemaCache.set(rule.schema, validate);\n }\n\n if (!validate(value)) {\n return { field: rule.field, code: 'json_schema_violation', message: rule.message };\n }\n return null;\n}\n\n/**\n * Conditional check (`conditional`). Evaluates the `when` predicate against the\n * merged record, then recurses into `then` (true) or `otherwise` (false) via\n * `evaluateRule`. An un-evaluable `when` is a broken rule (logged, fail-open).\n * The nested rule supplies the violation (field/code/message); the *outer*\n * conditional's `severity` governs whether it blocks (handled by the caller).\n */\nfunction checkConditional(\n rule: ConditionalRule,\n ctx: RuleContext,\n): FieldValidationError | null {\n const result = ExpressionEngine.evaluate<boolean>(toExpression(rule.when), {\n record: ctx.merged,\n previous: ctx.previous ?? undefined,\n });\n\n if (!result.ok) {\n ctx.logger?.warn?.(\n `Validation rule '${rule.name}' when-predicate failed to evaluate (${result.error.kind}: ${result.error.message}) — skipped`,\n );\n return null;\n }\n\n const branch = result.value === true ? rule.then : rule.otherwise;\n if (!branch || branch.active === false) return null;\n return evaluateRule(branch, ctx);\n}\n\n/**\n * Introspection helper (ADR-0020 D3.3): given an object's schema, a state\n * field, and a current state, return the legal next states declared by the\n * matching `state_machine` rule. Returns `null` when no such rule exists (so\n * callers can distinguish \"no FSM governs this field\" from \"a dead-end state\n * with zero outgoing transitions\", which returns `[]`).\n */\nexport function legalNextStates(\n objectSchema: { validations?: unknown[] } | undefined | null,\n field: string,\n currentState: string,\n): string[] | null {\n const rules = objectSchema?.validations;\n if (!Array.isArray(rules)) return null;\n const rule = rules.find(\n (r): r is StateMachineRule =>\n r != null &&\n typeof r === 'object' &&\n (r as BaseRule).type === 'state_machine' &&\n (r as StateMachineRule).field === field,\n );\n if (!rule) return null;\n return rule.transitions[currentState] ?? [];\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n//\n// In-memory implementation of the QueryAST aggregation contract.\n//\n// This module is the engine's last-resort path: when the underlying driver\n// returned raw rows but the caller asked for `groupBy` / `aggregations`, the\n// engine pipes the rows through here so the abstract contract is always\n// honoured even on drivers without native aggregation (driver-rest, partial\n// SQL drivers, mock drivers in tests).\n//\n// Capabilities:\n// * Flat groupBy strings: `['region']`\n// * Structured groupBy with date bucketing: `[{ field: 'closed_at',\n// dateGranularity: 'quarter' }]`\n// * Aggregation functions: count, count_distinct, sum, avg, min, max,\n// array_agg, string_agg\n// * `distinct: true` on aggregations (collapse duplicates before applying\n// the function)\n// * `filter: FilterCondition` on aggregations is **not** evaluated here —\n// the engine routes filtered aggregations through the driver where\n// possible; the in-memory fallback ignores the per-aggregation filter and\n// logs a warning if one is present.\n//\n// Date bucketing uses ISO-8601 conventions (weeks start Monday). Null /\n// invalid values bucket as the literal string `'(null)'` to remain\n// consistent with the client `useReportData` hook.\n\nimport type { QueryAST, GroupByNode, AggregationNode, DateGranularityValue } from '@objectstack/spec/data';\n\n/**\n * Group + aggregate raw rows according to the AST's `groupBy` /\n * `aggregations`. When neither is present, returns the rows unchanged.\n */\nexport function applyInMemoryAggregation(\n rows: any[],\n ast: Pick<QueryAST, 'groupBy' | 'aggregations'>,\n): any[] {\n const groupBy = (ast.groupBy ?? []) as GroupByNode[];\n const aggregations = (ast.aggregations ?? []) as AggregationNode[];\n if (groupBy.length === 0 && aggregations.length === 0) return rows;\n\n if (groupBy.length === 0) {\n // Pure aggregation — single result row.\n return [aggregateBucket(rows, aggregations)];\n }\n\n const buckets = new Map<string, { key: Record<string, any>; rows: any[] }>();\n for (const row of rows) {\n const key: Record<string, any> = {};\n const parts: string[] = [];\n for (const g of groupBy) {\n const fieldName = typeof g === 'string' ? g : (g.alias ?? g.field);\n const value = projectGroupValue(row, g);\n key[fieldName] = value;\n parts.push(`${fieldName}=${value}`);\n }\n const id = parts.join('\\u0001');\n let bucket = buckets.get(id);\n if (!bucket) {\n bucket = { key, rows: [] };\n buckets.set(id, bucket);\n }\n bucket.rows.push(row);\n }\n\n const out: any[] = [];\n for (const { key, rows: bucketRows } of buckets.values()) {\n const aggValues = aggregateBucket(bucketRows, aggregations);\n out.push({ ...key, ...aggValues });\n }\n return out;\n}\n\nfunction projectGroupValue(row: any, g: GroupByNode): string {\n const field = typeof g === 'string' ? g : g.field;\n const v = row?.[field];\n if (typeof g !== 'string' && g.dateGranularity) {\n return bucketDateValue(v, g.dateGranularity);\n }\n return v == null ? '(null)' : String(v);\n}\n\nfunction aggregateBucket(rows: any[], aggregations: AggregationNode[]): Record<string, any> {\n const out: Record<string, any> = {};\n for (const agg of aggregations) {\n const alias = agg.alias;\n const fn = agg.function;\n if (fn === 'count') {\n if (!agg.field) {\n out[alias] = rows.length;\n } else {\n out[alias] = rows.reduce(\n (acc, r) => (r[agg.field as string] != null ? acc + 1 : acc),\n 0,\n );\n }\n continue;\n }\n const field = agg.field;\n if (!field) {\n out[alias] = null;\n continue;\n }\n const values = collectValues(rows, field, !!agg.distinct);\n\n switch (fn) {\n case 'count_distinct':\n out[alias] = new Set(values.filter((v) => v != null)).size;\n break;\n case 'sum':\n out[alias] = values.reduce((a, b) => a + toNumber(b), 0);\n break;\n case 'avg': {\n const nums = values.filter((v) => v != null).map(toNumber);\n out[alias] = nums.length === 0 ? null : nums.reduce((a, b) => a + b, 0) / nums.length;\n break;\n }\n case 'min': {\n const defined = values.filter((v) => v != null);\n out[alias] = defined.length === 0 ? null : defined.reduce((a, b) => (a < b ? a : b));\n break;\n }\n case 'max': {\n const defined = values.filter((v) => v != null);\n out[alias] = defined.length === 0 ? null : defined.reduce((a, b) => (a > b ? a : b));\n break;\n }\n case 'array_agg':\n out[alias] = values.slice();\n break;\n case 'string_agg':\n out[alias] = values.filter((v) => v != null).map(String).join(',');\n break;\n default:\n out[alias] = null;\n }\n }\n return out;\n}\n\nfunction collectValues(rows: any[], field: string, distinct: boolean): any[] {\n if (!distinct) return rows.map((r) => r?.[field]);\n const seen = new Set<unknown>();\n const out: any[] = [];\n for (const r of rows) {\n const v = r?.[field];\n if (seen.has(v)) continue;\n seen.add(v);\n out.push(v);\n }\n return out;\n}\n\nfunction toNumber(v: any): number {\n if (typeof v === 'number') return v;\n if (v == null) return 0;\n const n = Number(v);\n return Number.isFinite(n) ? n : 0;\n}\n\n/**\n * Bucket a date-like value into an ISO-formatted period label. Weeks start\n * Monday and use ISO week numbering.\n */\nexport function bucketDateValue(value: unknown, granularity: DateGranularityValue): string {\n if (value == null) return '(null)';\n const d = value instanceof Date ? value : new Date(String(value));\n if (Number.isNaN(d.getTime())) return '(null)';\n const y = d.getUTCFullYear();\n const m = d.getUTCMonth() + 1;\n switch (granularity) {\n case 'year':\n return String(y);\n case 'quarter':\n return `${y}-Q${Math.floor((m - 1) / 3) + 1}`;\n case 'month':\n return `${y}-${String(m).padStart(2, '0')}`;\n case 'day':\n return `${y}-${String(m).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;\n case 'week': {\n // ISO-8601 week date: week 1 contains the first Thursday of the year.\n const target = new Date(Date.UTC(y, d.getUTCMonth(), d.getUTCDate()));\n const dayNum = (target.getUTCDay() + 6) % 7; // Mon=0..Sun=6\n target.setUTCDate(target.getUTCDate() - dayNum + 3);\n const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4));\n const weekNo = 1 + Math.round(\n ((target.getTime() - firstThursday.getTime()) / 86400000 - 3 + ((firstThursday.getUTCDay() + 6) % 7)) / 7,\n );\n return `${target.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;\n }\n default:\n return String(value);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * MetadataFacade\n *\n * Provides a clean, injectable interface over SchemaRegistry.\n * Registered as the 'metadata' kernel service to eliminate\n * downstream packages needing to manually wrap SchemaRegistry.\n *\n * Implements the async IMetadataService interface.\n * Internally delegates to SchemaRegistry (in-memory) with Promise wrappers.\n *\n * Each facade is bound to a specific SchemaRegistry instance — passed in the\n * constructor — so that multi-kernel servers can give every kernel its own\n * metadata surface without leaking state across tenants.\n */\nexport class MetadataFacade {\n constructor(private registry: SchemaRegistry) {}\n\n /**\n * Register a metadata item\n */\n async register(type: string, name: string, data: any): Promise<void> {\n const definition = typeof data === 'object' && data !== null\n ? { ...data, name: data.name ?? name }\n : data;\n // Pass through the item's own source package id (when stamped by an\n // artifact loader) so provenance survives re-registration. Never\n // synthesize one here — unstamped items are runtime-authored by\n // definition and must not become artifact-backed (protocol.ts\n // isArtifactBacked gates write authorization on _packageId).\n const packageId = definition?._packageId;\n if (type === 'object') {\n this.registry.registerItem(type, definition, 'name' as any, packageId);\n } else {\n this.registry.registerItem(type, definition, definition.id ? 'id' as any : 'name' as any, packageId);\n }\n }\n\n /**\n * Get a metadata item by type and name\n */\n async get(type: string, name: string): Promise<any> {\n const item = this.registry.getItem(type, name) as any;\n return item?.content ?? item;\n }\n\n /**\n * Get the raw entry (with metadata wrapper)\n */\n getEntry(type: string, name: string): any {\n return this.registry.getItem(type, name);\n }\n\n /**\n * List all items of a type\n */\n async list(type: string): Promise<any[]> {\n const items = this.registry.listItems(type);\n return items.map((item: any) => item?.content ?? item);\n }\n\n /**\n * Unregister a metadata item\n */\n async unregister(type: string, name: string): Promise<void> {\n this.registry.unregisterItem(type, name);\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n const item = this.registry.getItem(type, name);\n return item !== undefined && item !== null;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const items = this.registry.listItems(type);\n return items.map((item: any) => item?.name ?? item?.content?.name ?? '').filter(Boolean);\n }\n\n /**\n * Unregister all metadata from a package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n this.registry.unregisterObjectsByPackage(packageName);\n }\n\n /**\n * Convenience: get object definition\n */\n async getObject(name: string): Promise<any> {\n return this.registry.getObject(name);\n }\n\n /**\n * Convenience: list all objects\n */\n async listObjects(): Promise<any[]> {\n return this.registry.getAllObjects();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectQL } from './engine.js';\nimport { ObjectStackProtocolImplementation } from './protocol.js';\nimport { Plugin, PluginContext } from '@objectstack/core';\nimport { StorageNameMapping } from '@objectstack/spec/system';\nimport {\n SysMetadataObject,\n SysMetadataHistoryObject,\n SysMetadataAuditObject,\n SysViewDefinitionObject,\n} from '@objectstack/metadata-core';\n\nexport type { Plugin, PluginContext };\n\n/**\n * Protocol extension for DB-based metadata hydration.\n * `loadMetaFromDb` is implemented by ObjectStackProtocolImplementation but\n * is NOT (yet) part of the canonical ObjectStackProtocol wire-contract in\n * `@objectstack/spec`, since it is a server-side bootstrap concern only.\n */\ninterface ProtocolWithDbRestore {\n loadMetaFromDb(): Promise<{ loaded: number; errors: number }>;\n}\n\n/** Type guard — checks whether the service exposes `loadMetaFromDb`. */\nfunction hasLoadMetaFromDb(service: unknown): service is ProtocolWithDbRestore {\n return (\n typeof service === 'object' &&\n service !== null &&\n typeof (service as Record<string, unknown>)['loadMetaFromDb'] === 'function'\n );\n}\n\n/**\n * Options for ObjectQLPlugin.\n *\n * `environmentId` scopes all metadata writes + reads to a specific project.\n * When set, `protocol.saveMetaItem` stamps `environment_id = <environmentId>` on\n * new sys_metadata rows, and `protocol.loadMetaFromDb` filters by the same\n * column. Leave undefined in single-kernel / self-hosted mode — rows land\n * in the platform-global scope (environment_id IS NULL).\n */\nexport interface ObjectQLPluginOptions {\n /** Optional pre-built engine. When absent, one is lazily created in init. */\n ql?: ObjectQL;\n /** Passed to `new ObjectQL(...)` when `ql` is not supplied. */\n hostContext?: Record<string, any>;\n /** Scope sys_metadata reads/writes to this project. */\n environmentId?: string;\n /**\n * Override the kernel's default plugin-start timeout for this plugin.\n * Defaults to 120000 (120s). Schema sync to a remote SQL backend\n * (Neon/Postgres/Turso) is latency-bound — the SQL driver currently\n * does NOT support `batchSchemaSync`, so it issues one round-trip per\n * registered object × twice (Phase 1 + Phase 3 in `start()`). On a\n * cold remote DB with N tables this can blow past the kernel's\n * default 30s easily, even though everything is healthy.\n */\n startupTimeout?: number;\n /**\n * Skip both `syncRegisteredSchemas()` calls inside `start()` and\n * assume DDL is managed out-of-band (e.g. an `apps/cloud/scripts/migrate.ts`\n * run before deploy that connects directly to the database and creates\n * all `sys_*` + custom tables once).\n *\n * Use this on cold-start-sensitive runtimes (Cloudflare Containers,\n * Lambda) where the platform's inbound-request budget is shorter than\n * a fresh remote-DB schema sync. The plugin still hydrates the\n * SchemaRegistry from `sys_metadata` (Phase 2), so custom user\n * objects come up — they just aren't re-DDL'd on every cold boot.\n *\n * Falls back to `process.env.OS_SKIP_SCHEMA_SYNC === '1'` when the\n * option is unset, so containers can flip it via their env without a\n * code change.\n */\n skipSchemaSync?: boolean;\n}\n\nexport class ObjectQLPlugin implements Plugin {\n name = 'com.objectstack.engine.objectql';\n type = 'objectql';\n version = '1.0.0';\n /**\n * Schema sync to remote SQL DBs is latency-bound (one round-trip per\n * table × 2 phases). Default to 120s instead of the kernel's 30s so\n * cold Neon/Turso starts don't get killed mid-sync.\n */\n startupTimeout = 120_000;\n\n private ql: ObjectQL | undefined;\n private hostContext?: Record<string, any>;\n private environmentId?: string;\n private skipSchemaSync = false;\n /** Unsubscribe handles for metadata-event subscriptions (ADR-0008 PR-7). */\n private metadataUnsubscribes: Array<() => void> = [];\n\n constructor(qlOrOptions?: ObjectQL | ObjectQLPluginOptions, hostContext?: Record<string, any>) {\n // Back-compat: legacy callers passed `(ObjectQL, hostContext)` positionally.\n if (qlOrOptions instanceof ObjectQL) {\n this.ql = qlOrOptions;\n this.hostContext = hostContext;\n return;\n }\n // New signature: options bag.\n const opts = (qlOrOptions as ObjectQLPluginOptions | undefined) ?? {};\n if (opts.ql) {\n this.ql = opts.ql;\n }\n this.hostContext = opts.hostContext ?? hostContext;\n this.environmentId = opts.environmentId;\n if (typeof opts.startupTimeout === 'number' && opts.startupTimeout > 0) {\n this.startupTimeout = opts.startupTimeout;\n }\n this.skipSchemaSync =\n typeof opts.skipSchemaSync === 'boolean'\n ? opts.skipSchemaSync\n : process.env.OS_SKIP_SCHEMA_SYNC === '1';\n }\n\n init = async (ctx: PluginContext) => {\n if (!this.ql) {\n // Pass kernel logger to engine to avoid creating a separate logger instance\n const hostCtx = { ...this.hostContext, logger: ctx.logger };\n this.ql = new ObjectQL(hostCtx);\n }\n \n // Register as provider for Core Kernel Services\n ctx.registerService('objectql', this.ql);\n\n ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n\n // Register manifest service for direct app/package registration.\n // Plugins call ctx.getService('manifest').register(manifestData)\n // instead of the legacy ctx.registerService('app.<id>', manifestData) convention.\n const ql = this.ql;\n ctx.registerService('manifest', {\n register: (manifest: any) => {\n ql.registerApp(manifest);\n ctx.logger.debug('Manifest registered via manifest service', {\n id: manifest.id || manifest.name\n });\n }\n });\n\n ctx.logger.info('ObjectQL engine registered', {\n services: ['objectql', 'data', 'manifest'],\n });\n\n // Register the metadata-storage objects this engine's own protocol reads\n // and writes — `sys_metadata` (loadMetaFromDb / getMetaItems / saveMetaItem),\n // its history/audit siblings, and `sys_view_definition`. Doing it here\n // guarantees their tables get schema-synced in start() even when no\n // MetadataPlugin is present (e.g. standalone \"host config\" apps, where the\n // CLI auto-registers a bare ObjectQLPlugin and nothing else owns these\n // tables → \"no such table: sys_metadata\" on every read).\n //\n // Gated on `environmentId === undefined` — the SAME condition that gates\n // `restoreMetadataFromDb` below: platform / standalone kernels own their\n // local sys_metadata, whereas per-project (cloud) kernels source metadata\n // from the control plane and must NOT provision these tables locally.\n // Definitions live in @objectstack/metadata-core (shared by this protocol\n // and the metadata layer's DatabaseLoader). registerApp is idempotent, so\n // a MetadataPlugin that also registers them is harmless.\n if (this.environmentId === undefined) {\n this.ql.registerApp({\n id: 'com.objectstack.metadata-objects',\n name: 'Metadata Platform Objects',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n objects: [\n SysMetadataObject,\n SysMetadataHistoryObject,\n SysMetadataAuditObject,\n SysViewDefinitionObject,\n ],\n });\n }\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(\n this.ql,\n () => ctx.getServices ? ctx.getServices() : new Map(),\n undefined,\n this.environmentId,\n );\n\n ctx.registerService('protocol', protocolShim);\n ctx.logger.info('Protocol service registered');\n\n // Register an `analytics` service adapter that maps the dispatcher's\n // expected interface (query / getMeta / generateSql) onto the\n // protocol shim's `analyticsQuery`. Without this, HttpDispatcher's\n // `handleAnalytics` cannot resolve a service and `/api/v1/analytics/*`\n // returns ROUTE_NOT_FOUND, even though discovery advertises the route\n // (objectql's getDiscovery hardcodes `analytics: enabled:true`). The\n // adapter delegates `query` to the cube → engine.aggregate translator\n // already implemented in protocol.ts; getMeta/generateSql return a\n // structured \"not implemented\" payload so callers see something\n // useful instead of a 500.\n ctx.registerService('analytics', {\n // HttpDispatcher passes the raw POST body (AnalyticsQuery shape:\n // `{ cube, measures, dimensions, where?, filters?, ... }`). The\n // protocol shim's `analyticsQuery` expects the wrapped envelope\n // `{ cube, query }` and destructures `request.query` for dims /\n // measures. Reshape here so the destructure resolves to the\n // analytics query instead of `undefined` (which caused\n // \"Cannot read properties of undefined (reading 'dimensions')\").\n //\n // `analyticsQuery` also returns its own `{ success, data: { rows,\n // fields } }` envelope. HttpDispatcher wraps service responses\n // again with `success(result)`, so without unwrapping here the\n // client sees `{success, data:{success, data:{rows, fields}}}` —\n // KPI widgets read `data.rows` and silently get nothing. Unwrap\n // to the inner `{ rows, fields }` payload so a single wrap from\n // the dispatcher yields the canonical shape.\n query: async (body: any) => {\n const envelope = body && typeof body === 'object' && 'query' in body && 'cube' in body\n ? body\n : { cube: body?.cube, query: body };\n const result = await protocolShim.analyticsQuery(envelope);\n // Unwrap an inner `{ success, data }` envelope (one level only).\n if (result && typeof result === 'object' && 'success' in result && 'data' in result) {\n return (result as any).data;\n }\n return result;\n },\n getMeta: async () => ({\n cubes: [],\n message: 'Analytics meta endpoint not implemented by ObjectQL adapter',\n }),\n generateSql: async (_body: any) => ({\n sql: null,\n message: 'Analytics SQL generation not implemented by ObjectQL adapter',\n }),\n });\n }\n\n start = async (ctx: PluginContext) => {\n ctx.logger.info('ObjectQL engine starting...');\n\n // Sync from external metadata service (e.g. MetadataPlugin) if available\n try {\n const metadataService = ctx.getService('metadata') as any;\n if (metadataService && typeof metadataService.loadMany === 'function' && this.ql) {\n await this.loadMetadataFromService(metadataService, ctx);\n }\n // ── ADR-0008 PR-7: subscribe to object metadata events so the\n // SchemaRegistry cache is invalidated on edits (Studio HMR).\n // The metadata service bubbles repo events through its own\n // `subscribe(type, cb)` API (PR-6 bridge), so we don't talk\n // to the repo directly here — this keeps ObjectQL decoupled\n // from the storage backend.\n if (metadataService && typeof metadataService.subscribe === 'function' && this.ql) {\n this.subscribeToMetadataEvents(metadataService, ctx);\n }\n } catch (e: any) {\n ctx.logger.debug('No external metadata service to sync from');\n }\n \n // Discover features from Kernel Services\n if (ctx.getServices && this.ql) {\n const services = ctx.getServices();\n for (const [name, service] of services.entries()) {\n if (name.startsWith('driver.')) {\n // Register Driver\n this.ql.registerDriver(service);\n ctx.logger.debug('Discovered and registered driver service', { serviceName: name });\n }\n if (name.startsWith('app.')) {\n // Legacy fallback: discover app.* services (DEPRECATED)\n ctx.logger.warn(\n `[DEPRECATED] Service \"${name}\" uses legacy app.* convention. ` +\n `Migrate to ctx.getService('manifest').register(data).`\n );\n this.ql.registerApp(service); // service is Manifest\n ctx.logger.debug('Discovered and registered app service (legacy)', { serviceName: name });\n }\n }\n\n // Bridge realtime service from kernel service registry to ObjectQL.\n // RealtimeServicePlugin registers as 'realtime' service during init().\n // This enables ObjectQL to publish data change events.\n try {\n const realtimeService = ctx.getService('realtime');\n if (realtimeService && typeof realtimeService === 'object' && 'publish' in realtimeService) {\n ctx.logger.info('[ObjectQLPlugin] Bridging realtime service to ObjectQL for event publishing');\n this.ql.setRealtimeService(realtimeService as any);\n }\n } catch (e: any) {\n ctx.logger.debug('[ObjectQLPlugin] No realtime service found — data events will not be published', {\n error: e.message,\n });\n }\n }\n\n // Initialize drivers (calls driver.connect() which sets up persistence)\n await this.ql?.init();\n\n // Phase 1: Sync built-in schemas so sys_metadata table exists before reading it.\n //\n // Cold-start-sensitive runtimes (Cloudflare Containers, Lambda) can\n // opt out via `skipSchemaSync` / `OS_SKIP_SCHEMA_SYNC=1`. In that\n // mode an out-of-band migration must have already created every\n // table; we only assume the DDL is in place and skip straight to\n // hydration. This avoids one round-trip per table × N objects on\n // every cold boot.\n if (this.skipSchemaSync) {\n ctx.logger.info('Skipping schema sync (OS_SKIP_SCHEMA_SYNC=1) — assuming DDL is managed out-of-band');\n } else {\n await this.syncRegisteredSchemas(ctx);\n }\n\n // Phase 2: Hydrate SchemaRegistry from sys_metadata (loads custom/template objects).\n // Project kernels (environmentId set) never persist sys_metadata locally —\n // metadata is sourced from the artifact (MetadataPlugin) or routed to the\n // control plane via ControlPlaneProxyDriver. Skip to avoid querying a table\n // that does not exist on local project DBs.\n if (this.environmentId === undefined) {\n await this.restoreMetadataFromDb(ctx);\n } else {\n ctx.logger.info('Project kernel — skipping sys_metadata hydration (metadata sourced from artifact)');\n }\n\n // Phase 3: Sync any new schemas that were just hydrated from the DB\n // (e.g. CRM objects seeded via template — they must have tables before use).\n if (!this.skipSchemaSync) {\n await this.syncRegisteredSchemas(ctx);\n }\n\n // Bridge all SchemaRegistry objects to metadata service.\n //\n // `SchemaRegistry` is a process-wide singleton, so project kernels in a\n // multi-environment server would otherwise inherit every object ever\n // registered by any sibling project. When this plugin was constructed\n // with a `environmentId`, the kernel is project-scoped — its\n // metadata comes from the artifact (MetadataPlugin) or the\n // control-plane proxy, not from local sys_metadata. The bridge would\n // only pollute its metadata service with cross-project leakage, so\n // skip it in that case.\n if (this.environmentId === undefined) {\n await this.bridgeObjectsToMetadataService(ctx);\n }\n\n // Register built-in audit hooks\n this.registerAuditHooks(ctx);\n\n // Tenant isolation is now handled by `@objectstack/plugin-security`\n // via the `member_default` permission set's RLS rule\n // (`organization_id = current_user.organization_id`, with\n // field-existence guards). The legacy hard-coded `tenant_id` filter\n // middleware was removed because it (a) collided with the\n // SecurityPlugin RLS pipeline and (b) blindly filtered tables that\n // don't have a `tenant_id` column (e.g. `sys_organization`),\n // returning 0 rows instead of all rows.\n\n ctx.logger.info('ObjectQL engine started', {\n driversRegistered: this.ql?.['drivers']?.size || 0,\n objectsRegistered: this.ql?.registry?.getAllObjects?.()?.length || 0\n });\n }\n\n stop = async (ctx: PluginContext) => {\n // ADR-0008 PR-7: tear down metadata subscriptions on plugin stop so\n // tests don't leak watchers and reloaded plugins don't double-subscribe.\n for (const unsub of this.metadataUnsubscribes) {\n try { unsub(); } catch (e: any) {\n ctx.logger.debug('[ObjectQLPlugin] metadata-event unsubscribe failed', { error: e?.message });\n }\n }\n this.metadataUnsubscribes = [];\n }\n\n /**\n * Subscribe to `object` metadata events from the metadata service and\n * invalidate the SchemaRegistry merge cache on each event (ADR-0008\n * PR-7). For create/update we also re-load the affected object from\n * the metadata service so subsequent reads see the new definition;\n * for delete we unregister it from every contributing package.\n *\n * Events are filtered to the canonical `object` type — view/dashboard\n * /flow edits go through their own consumers (Studio SSE, REST cache).\n *\n * Stored unsubscribe handle is invoked from {@link stop}.\n */\n private subscribeToMetadataEvents(metadataService: any, ctx: PluginContext) {\n const handler = async (evt: any) => {\n if (!this.ql) return;\n const name: string = evt?.name ?? '';\n if (!name) return;\n const eventType: 'added' | 'changed' | 'deleted' =\n evt?.type === 'added' || evt?.type === 'changed' || evt?.type === 'deleted'\n ? evt.type\n : 'changed';\n\n try {\n // Drop the merged-schema cache entry first so any in-flight\n // resolveObject() races recompute against the new state.\n this.ql.registry.invalidate(name);\n\n if (eventType === 'deleted') {\n ctx.logger.info('[ObjectQLPlugin] object metadata deleted — registry invalidated', { name });\n return;\n }\n\n // Re-fetch the canonical definition from the metadata service.\n // The metadata service goes through its loader chain (FS, DB,\n // attached repository), so this picks up edits from any source.\n const fresh = typeof metadataService.get === 'function'\n ? await metadataService.get('object', name)\n : undefined;\n if (fresh && typeof fresh === 'object') {\n // Re-register with the original contributor metadata. We use\n // 'metadata-service' as packageId to match how the initial\n // load enrolls these objects (see `loadMetadataFromService`).\n const packageId = (fresh as any)._packageId ?? 'metadata-service';\n const namespace = (fresh as any).namespace;\n this.ql.registry.registerObject(\n fresh as any,\n packageId,\n namespace,\n 'own',\n );\n ctx.logger.info('[ObjectQLPlugin] object metadata updated — registry refreshed', {\n name,\n packageId,\n });\n } else {\n ctx.logger.debug('[ObjectQLPlugin] object event received but metadata service has no fresh body', { name });\n }\n } catch (e: any) {\n ctx.logger.warn('[ObjectQLPlugin] metadata event handler failed', {\n name,\n error: e?.message,\n });\n }\n };\n\n const unsub = metadataService.subscribe('object', handler);\n if (typeof unsub === 'function') {\n this.metadataUnsubscribes.push(unsub);\n } else if (unsub && typeof unsub.unsubscribe === 'function') {\n // Support `MetadataWatchHandle` style return shape.\n this.metadataUnsubscribes.push(() => unsub.unsubscribe());\n }\n ctx.logger.info('[ObjectQLPlugin] subscribed to object metadata events (ADR-0008 PR-7)');\n }\n\n /**\n * Register built-in audit hooks for auto-stamping created_by/updated_by\n * and fetching previousData for update/delete operations. These are\n * declared as canonical `Hook` metadata and bound through the same\n * `bindHooksToEngine` path used by `defineStack({ hooks })`, so the\n * engine's built-ins flow through the same rails as user code\n * (dogfooding the protocol).\n */\n private registerAuditHooks(ctx: PluginContext) {\n if (!this.ql) return;\n\n const stamp = () => new Date().toISOString();\n\n /**\n * Returns true when the resolved object schema declares a field with the\n * given name. Audit fields (`created_by`, `updated_by`, `tenant_id`) are\n * NOT auto-injected by the SQL driver, so we must only stamp values for\n * fields the user has explicitly declared on the object — otherwise the\n * driver will issue an INSERT against a column that does not exist in\n * the physical table (e.g. `table lead has no column named created_by`).\n *\n * `created_at`/`updated_at` are unconditional because driver-sql creates\n * them as built-in columns on every table.\n */\n const hasField = (objectName: string, field: string): boolean => {\n try {\n const schema: any = this.ql?.getSchema?.(objectName);\n if (!schema || typeof schema !== 'object') return false;\n const fields = schema.fields;\n if (!fields || typeof fields !== 'object') return false;\n return Object.prototype.hasOwnProperty.call(fields, field);\n } catch {\n return false;\n }\n };\n\n const applyToRecord = (\n record: Record<string, any>,\n objectName: string,\n session: any,\n isInsert: boolean,\n ) => {\n const now = stamp();\n if (isInsert) {\n record.created_at = record.created_at ?? now;\n }\n record.updated_at = now;\n if (session?.userId) {\n if (isInsert && hasField(objectName, 'created_by')) {\n record.created_by = record.created_by ?? session.userId;\n }\n if (hasField(objectName, 'updated_by')) {\n record.updated_by = session.userId;\n }\n }\n if (isInsert && session?.tenantId && hasField(objectName, 'tenant_id')) {\n record.tenant_id = record.tenant_id ?? session.tenantId;\n }\n };\n\n const stampData = (\n data: unknown,\n objectName: string,\n session: any,\n isInsert: boolean,\n ) => {\n if (Array.isArray(data)) {\n for (const row of data) {\n if (row && typeof row === 'object') {\n applyToRecord(row as Record<string, any>, objectName, session, isInsert);\n }\n }\n } else if (data && typeof data === 'object') {\n applyToRecord(data as Record<string, any>, objectName, session, isInsert);\n }\n };\n\n const builtinHooks: any[] = [\n {\n name: 'sys_stamp_audit_insert',\n object: '*',\n events: ['beforeInsert'],\n priority: 10,\n description: 'Auto-stamp created_by / updated_by / created_at / updated_at / tenant_id on insert (only when the field exists on the object schema)',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.data) {\n stampData(hookCtx.input.data, hookCtx.object, hookCtx.session, true);\n }\n },\n },\n {\n name: 'sys_stamp_audit_update',\n object: '*',\n events: ['beforeUpdate'],\n priority: 10,\n description: 'Auto-stamp updated_by / updated_at on update (only when the field exists on the object schema)',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.data) {\n stampData(hookCtx.input.data, hookCtx.object, hookCtx.session, false);\n }\n },\n },\n {\n name: 'sys_fetch_previous_update',\n object: '*',\n events: ['beforeUpdate'],\n priority: 5,\n description: 'Auto-fetch the previous record for update hooks',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id },\n context: {\n roles: [],\n permissions: [],\n isSystem: true,\n ...(hookCtx.transaction ? { transaction: hookCtx.transaction } : {}),\n } as any,\n });\n if (existing) hookCtx.previous = existing;\n } catch (_e) {\n // Non-fatal: some objects may not support findOne\n }\n }\n },\n },\n {\n name: 'sys_fetch_previous_delete',\n object: '*',\n events: ['beforeDelete'],\n priority: 5,\n description: 'Auto-fetch the previous record for delete hooks',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id },\n context: {\n roles: [],\n permissions: [],\n isSystem: true,\n ...(hookCtx.transaction ? { transaction: hookCtx.transaction } : {}),\n } as any,\n });\n if (existing) hookCtx.previous = existing;\n } catch (_e) {\n // Non-fatal\n }\n }\n },\n },\n ];\n\n if (typeof (this.ql as any).bindHooks === 'function') {\n (this.ql as any).bindHooks(builtinHooks, { packageId: 'sys:audit' });\n } else {\n // Defensive fallback if binder isn't available (older builds).\n for (const h of builtinHooks) {\n for (const event of h.events) {\n this.ql.registerHook(event, h.handler, {\n object: h.object,\n priority: h.priority,\n packageId: 'sys:audit',\n });\n }\n }\n }\n\n ctx.logger.debug('Audit hooks registered via binder (created_by/updated_by, previousData)');\n }\n\n /**\n * Tenant isolation moved to `@objectstack/plugin-security`'s\n * `member_default` permission set RLS\n * (`organization_id = current_user.organization_id`, with\n * field-existence guards). The legacy `registerTenantMiddleware`\n * method was removed because it (a) collided with SecurityPlugin's\n * RLS pipeline and (b) blindly filtered tables that don't have a\n * `tenant_id` column (e.g. `sys_organization`), returning 0 rows\n * instead of all rows.\n */\n\n /**\n * Synchronize all registered object schemas to the database.\n *\n * Groups objects by their responsible driver, then:\n * - If the driver advertises `supports.batchSchemaSync` and implements\n * `syncSchemasBatch()`, submits all schemas in a single call (reducing\n * network round-trips for remote drivers like Turso).\n * - Otherwise falls back to sequential `syncSchema()` per object.\n *\n * This is idempotent — drivers must tolerate repeated calls without\n * duplicating tables or erroring out.\n *\n * Drivers that do not implement `syncSchema` are silently skipped.\n */\n private async syncRegisteredSchemas(ctx: PluginContext) {\n if (!this.ql) return;\n\n const allObjects = this.ql.registry?.getAllObjects?.() ?? [];\n if (allObjects.length === 0) return;\n\n let synced = 0;\n let skipped = 0;\n\n // Group objects by driver for potential batch optimization\n const driverGroups = new Map<any, Array<{ obj: any; tableName: string }>>();\n\n for (const obj of allObjects) {\n const driver = this.ql.getDriverForObject(obj.name);\n if (!driver) {\n ctx.logger.debug('No driver available for object, skipping schema sync', {\n object: obj.name,\n });\n skipped++;\n continue;\n }\n\n if (typeof driver.syncSchema !== 'function') {\n ctx.logger.debug('Driver does not support syncSchema, skipping', {\n object: obj.name,\n driver: driver.name,\n });\n skipped++;\n continue;\n }\n\n const tableName = StorageNameMapping.resolveTableName(obj);\n\n let group = driverGroups.get(driver);\n if (!group) {\n group = [];\n driverGroups.set(driver, group);\n }\n group.push({ obj, tableName });\n }\n\n // Process each driver group\n for (const [driver, entries] of driverGroups) {\n // Batch path: driver supports batch schema sync\n if (\n driver.supports?.batchSchemaSync &&\n typeof driver.syncSchemasBatch === 'function'\n ) {\n const batchPayload = entries.map((e) => ({\n object: e.tableName,\n schema: e.obj,\n }));\n try {\n await driver.syncSchemasBatch(batchPayload);\n synced += entries.length;\n ctx.logger.debug('Batch schema sync succeeded', {\n driver: driver.name,\n count: entries.length,\n });\n } catch (e: unknown) {\n ctx.logger.warn('Batch schema sync failed, falling back to sequential', {\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n // Fallback: sequential sync for this driver's objects\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (seqErr: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: seqErr instanceof Error ? seqErr.message : String(seqErr),\n });\n }\n }\n }\n } else {\n // Sequential path: no batch support\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (e: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n }\n }\n\n if (synced > 0 || skipped > 0) {\n ctx.logger.info('Schema sync complete', { synced, skipped, total: allObjects.length });\n }\n }\n\n /**\n * Restore persisted metadata from the database (sys_metadata) on startup.\n *\n * Calls `protocol.loadMetaFromDb()` to bulk-load all active metadata\n * records (objects, views, apps, etc.) into the in-memory SchemaRegistry.\n * This closes the persistence loop so that user-created schemas survive\n * kernel cold starts and redeployments.\n *\n * Gracefully degrades when:\n * - The protocol service is unavailable (e.g., in-memory-only mode).\n * - `loadMetaFromDb` is not implemented by the protocol shim.\n * - The underlying driver/table does not exist yet (first-run scenario).\n */\n private async restoreMetadataFromDb(ctx: PluginContext): Promise<void> {\n // Phase 1: Resolve protocol service (separate from DB I/O for clearer diagnostics)\n let protocol: ProtocolWithDbRestore;\n try {\n const service = ctx.getService('protocol');\n if (!service || !hasLoadMetaFromDb(service)) {\n ctx.logger.debug('Protocol service does not support loadMetaFromDb, skipping DB restore');\n return;\n }\n protocol = service;\n } catch (e: unknown) {\n ctx.logger.debug('Protocol service unavailable, skipping DB restore', {\n error: e instanceof Error ? e.message : String(e),\n });\n return;\n }\n\n // Phase 2: DB hydration (loads into SchemaRegistry)\n try {\n const { loaded, errors } = await protocol.loadMetaFromDb();\n\n if (loaded > 0 || errors > 0) {\n ctx.logger.info('Metadata restored from database to SchemaRegistry', { loaded, errors });\n } else {\n ctx.logger.debug('No persisted metadata found in database');\n }\n } catch (e: unknown) {\n // Non-fatal: first-run or in-memory driver may not have sys_metadata yet\n ctx.logger.debug('DB metadata restore failed (non-fatal)', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Bridge all SchemaRegistry objects to the metadata service.\n *\n * This ensures objects registered by plugins and loaded from sys_metadata\n * are visible to AI tools and other consumers that query IMetadataService.\n *\n * Runs after both restoreMetadataFromDb() and syncRegisteredSchemas() to\n * catch all objects in the SchemaRegistry regardless of their source.\n */\n private async bridgeObjectsToMetadataService(ctx: PluginContext): Promise<void> {\n try {\n const metadataService = ctx.getService<any>('metadata');\n if (!metadataService || typeof metadataService.register !== 'function') {\n ctx.logger.debug('Metadata service unavailable for bridging, skipping');\n return;\n }\n\n if (!this.ql?.registry) {\n ctx.logger.debug('SchemaRegistry unavailable for bridging, skipping');\n return;\n }\n\n const objects = this.ql.registry.getAllObjects();\n let bridged = 0;\n\n for (const obj of objects) {\n try {\n // Check if object is already in metadata service to avoid duplicates\n const existing = await metadataService.getObject(obj.name);\n if (!existing) {\n // Register object that exists in SchemaRegistry but not in metadata service\n await metadataService.register('object', obj.name, obj);\n bridged++;\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge object to metadata service', {\n object: obj.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n if (bridged > 0) {\n ctx.logger.info('Bridged objects from SchemaRegistry to metadata service', {\n count: bridged,\n total: objects.length\n });\n } else {\n ctx.logger.debug('No objects needed bridging (all already in metadata service)');\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge objects to metadata service', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Load metadata from external metadata service into ObjectQL registry\n * This enables ObjectQL to use file-based or remote metadata\n */\n private async loadMetadataFromService(metadataService: any, ctx: PluginContext) {\n ctx.logger.info('Syncing metadata from external service into ObjectQL registry...');\n \n // Metadata types to sync (ADR-0020: no `workflow` type — record state\n // machines are a `state_machine` validation rule on the object)\n const metadataTypes = ['object', 'view', 'app', 'flow', 'function', 'hook'];\n let totalLoaded = 0;\n \n for (const type of metadataTypes) {\n try {\n // Check if service has loadMany method\n if (typeof metadataService.loadMany === 'function') {\n const items = await metadataService.loadMany(type);\n\n if (items && items.length > 0) {\n // Functions arrive as JSON-safe records ({name, handler})\n // where `handler` is a function reference or compiled code\n // already attached by the metadata pipeline. Register them\n // BEFORE binding hooks so string-named hook handlers can\n // resolve.\n if (type === 'function' && this.ql && typeof (this.ql as any).registerFunction === 'function') {\n for (const item of items) {\n if (item?.name && typeof item.handler === 'function') {\n (this.ql as any).registerFunction(item.name, item.handler, 'metadata-service');\n }\n }\n }\n\n items.forEach((item: any) => {\n // Determine key field (usually 'name' or 'id')\n const keyField = item.id ? 'id' : 'name';\n \n // For objects, use the ownership-aware registration\n if (type === 'object' && this.ql) {\n // Objects are registered differently (ownership model)\n // Skip for now - handled by app registration\n return;\n }\n \n // Register other types in the registry. Pass through\n // the item's own source package id (stamped by the\n // metadata plugin's artifact loader) so registerItem's\n // applyProtection re-stamps _packageId/_provenance and\n // GET /meta consumers can tell package-shipped items\n // from user-authored ones. Items without _packageId\n // (FS project files, runtime-authored rows) must stay\n // unstamped — a synthetic id like 'metadata-service'\n // would flip isArtifactBacked() and the two-tier write\n // authorization for genuinely runtime-authored items.\n if (this.ql?.registry?.registerItem) {\n this.ql.registry.registerItem(type, item, keyField, item._packageId);\n }\n });\n\n // Hooks need to be wired into the execution pipeline,\n // not just stored in the registry. Funnel through the\n // canonical binder so declarative semantics (condition,\n // retry, timeout, async, onError, priority, packageId)\n // are honoured uniformly with the AppPlugin path.\n if (type === 'hook' && this.ql && typeof (this.ql as any).bindHooks === 'function') {\n (this.ql as any).bindHooks(items, {\n packageId: 'metadata-service',\n });\n }\n\n totalLoaded += items.length;\n ctx.logger.info(`Synced ${items.length} ${type}(s) from metadata service`);\n }\n }\n } catch (e: any) {\n // Type might not exist in metadata service - that's ok\n ctx.logger.debug(`No ${type} metadata found or error loading`, { \n error: e.message \n });\n }\n }\n \n if (totalLoaded > 0) {\n ctx.logger.info(`Metadata sync complete: ${totalLoaded} items loaded into ObjectQL registry`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectKernel } from '@objectstack/core';\nimport { ObjectQLPlugin } from './plugin.js';\nimport type { Plugin } from '@objectstack/core';\n\n/**\n * Options for creating an ObjectQL Kernel.\n */\nexport interface ObjectQLKernelOptions {\n /**\n * Additional plugins to register with the kernel.\n */\n plugins?: Plugin[];\n}\n\n/**\n * Convenience factory for creating an ObjectQL-ready kernel.\n *\n * Creates an ObjectKernel pre-configured with the ObjectQLPlugin\n * (data engine, schema registry, protocol implementation) plus any\n * additional plugins provided.\n *\n * @example\n * ```typescript\n * import { createObjectQLKernel } from '@objectstack/objectql';\n *\n * const kernel = createObjectQLKernel({\n * plugins: [myDriverPlugin, myAuthPlugin],\n * });\n * await kernel.bootstrap();\n * ```\n */\nexport async function createObjectQLKernel(options: ObjectQLKernelOptions = {}): Promise<ObjectKernel> {\n const kernel = new ObjectKernel();\n\n // Register the core ObjectQLPlugin first\n await kernel.use(new ObjectQLPlugin());\n\n // Register any additional plugins\n if (options.plugins) {\n for (const plugin of options.plugins) {\n await kernel.use(plugin);\n }\n }\n\n return kernel;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n// ── Introspection Types ──────────────────────────────────────────────────────\n\n/**\n * Column metadata from database introspection.\n */\nexport interface IntrospectedColumn {\n /** Column name */\n name: string;\n /** Native database type (e.g., 'varchar', 'integer', 'timestamp') */\n type: string;\n /** Whether the column is nullable */\n nullable: boolean;\n /** Default value if any */\n defaultValue?: unknown;\n /** Whether this is a primary key */\n isPrimary?: boolean;\n /** Whether this column has a unique constraint */\n isUnique?: boolean;\n /** Maximum length for string types */\n maxLength?: number;\n}\n\n/**\n * Foreign key relationship metadata.\n */\nexport interface IntrospectedForeignKey {\n /** Column name in the source table */\n columnName: string;\n /** Referenced table name */\n referencedTable: string;\n /** Referenced column name */\n referencedColumn: string;\n /** Constraint name */\n constraintName?: string;\n}\n\n/**\n * Table metadata from database introspection.\n */\nexport interface IntrospectedTable {\n /** Table name */\n name: string;\n /** List of columns */\n columns: IntrospectedColumn[];\n /** List of foreign key relationships */\n foreignKeys: IntrospectedForeignKey[];\n /** Primary key columns */\n primaryKeys: string[];\n}\n\n/**\n * Complete database schema introspection result.\n */\nexport interface IntrospectedSchema {\n /** Map of table name to table metadata */\n tables: Record<string, IntrospectedTable>;\n}\n\n// ── Utility Functions ────────────────────────────────────────────────────────\n\n/**\n * Convert a snake_case or plain string to Title Case.\n *\n * @example\n * toTitleCase('first_name') // => 'First Name'\n * toTitleCase('project_task') // => 'Project Task'\n */\nexport function toTitleCase(str: string): string {\n return str\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Map a native database column type to an ObjectStack FieldType.\n */\nfunction mapDatabaseTypeToFieldType(\n dbType: string\n): 'text' | 'textarea' | 'number' | 'boolean' | 'datetime' | 'date' | 'time' | 'json' {\n const type = dbType.toLowerCase();\n\n // Text types\n if (type.includes('char') || type.includes('varchar') || type.includes('text')) {\n if (type.includes('text')) return 'textarea';\n return 'text';\n }\n\n // Numeric types\n if (\n type.includes('int') || type === 'integer' || type === 'bigint' || type === 'smallint'\n ) {\n return 'number';\n }\n if (\n type.includes('float') || type.includes('double') || type.includes('decimal') ||\n type.includes('numeric') || type === 'real'\n ) {\n return 'number';\n }\n\n // Boolean\n if (type.includes('bool')) {\n return 'boolean';\n }\n\n // Date / Time types\n if (type.includes('timestamp') || type === 'datetime') {\n return 'datetime';\n }\n if (type === 'date') {\n return 'date';\n }\n if (type === 'time') {\n return 'time';\n }\n\n // JSON types\n if (type === 'json' || type === 'jsonb') {\n return 'json';\n }\n\n // Default to text\n return 'text';\n}\n\n/**\n * Convert an introspected database schema to ObjectStack object definitions.\n *\n * This allows using existing database tables without manually defining metadata.\n *\n * @param introspectedSchema - The schema returned from driver.introspectSchema()\n * @param options - Optional filtering / conversion settings\n * @returns Array of ServiceObject definitions that can be registered with ObjectQL\n *\n * @example\n * ```typescript\n * const schema = await driver.introspectSchema();\n * const objects = convertIntrospectedSchemaToObjects(schema);\n * for (const obj of objects) {\n * engine.registerObject(obj);\n * }\n * ```\n */\nexport function convertIntrospectedSchemaToObjects(\n introspectedSchema: IntrospectedSchema,\n options?: {\n /** Tables to exclude from conversion */\n excludeTables?: string[];\n /** Tables to include (if specified, only these will be converted) */\n includeTables?: string[];\n /** Whether to skip system columns like id, created_at, updated_at (default: true) */\n skipSystemColumns?: boolean;\n }\n): ServiceObject[] {\n const objects: ServiceObject[] = [];\n const excludeTables = options?.excludeTables || [];\n const includeTables = options?.includeTables;\n const skipSystemColumns = options?.skipSystemColumns !== false;\n\n for (const [tableName, table] of Object.entries(introspectedSchema.tables)) {\n if (excludeTables.includes(tableName)) continue;\n if (includeTables && !includeTables.includes(tableName)) continue;\n\n const fields: Record<string, any> = {};\n\n for (const column of table.columns) {\n // Skip system columns if requested\n if (skipSystemColumns && ['id', 'created_at', 'updated_at'].includes(column.name)) {\n continue;\n }\n\n // Check for foreign key → lookup field\n const foreignKey = table.foreignKeys.find((fk) => fk.columnName === column.name);\n\n if (foreignKey) {\n fields[column.name] = {\n name: column.name,\n type: 'lookup' as const,\n reference: foreignKey.referencedTable,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n } else {\n const fieldType = mapDatabaseTypeToFieldType(column.type);\n\n const field: Record<string, any> = {\n name: column.name,\n type: fieldType,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n\n if (column.isUnique) {\n field.unique = true;\n }\n if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {\n field.maxLength = column.maxLength;\n }\n if (column.defaultValue != null) {\n field.defaultValue = column.defaultValue;\n }\n\n fields[column.name] = field;\n }\n }\n\n objects.push({\n name: tableName,\n label: toTitleCase(tableName),\n fields,\n } as ServiceObject);\n }\n\n return objects;\n}\n"],"mappings":"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","names":["import_data","import_types","import_types","import_kernel","import_shared","item","import_metadata_core","import_data","import_shared","import_ui","import_kernel","import_kernel","import_shared","records","SeedLoaderService","runBuildProbes","import_kernel","import_system","import_shared","import_formula","import_formula","noopLogger","import_formula","Ajv","isMissing","EMAIL_RE","PHONE_RE","import_system","import_metadata_core","import_core"]}