@objectstack/objectql 7.3.0 → 7.4.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.d.mts +322 -9
- package/dist/index.d.ts +322 -9
- package/dist/index.js +538 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +531 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/registry.ts","../src/protocol.ts","../src/sys-metadata-repository.ts","../src/metadata-diagnostics.ts","../src/engine.ts","../src/hook-wrappers.ts","../src/hook-metrics.ts","../src/hook-binder.ts","../src/validation/record-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\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 {\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 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","// 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. When `true`, the\n * registry auto-injects `organization_id` (lookup → sys_organization)\n * into every registered user object that doesn't already declare it and\n * isn't `managedBy` an external subsystem or explicitly opted-out via\n * `systemFields: false`.\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` — multi-tenant deployments. Required-false (the\n * SecurityPlugin populates it on insert; nullable rows are still\n * filtered out by the `tenant_isolation` RLS USING clause).\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 const wantTenant = opts.multiTenant && 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: true,\n hidden: true,\n readonly: true,\n system: true,\n description: 'Tenant scope (auto-populated by SecurityPlugin on insert).',\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 * 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 * 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 return this.getItem('app', name);\n }\n\n getAllApps(): any[] {\n return this.listItems('app');\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.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} 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 } from '@objectstack/spec/ui';\nimport { METADATA_FORM_REGISTRY } from '@objectstack/spec/system';\nimport { DEFAULT_METADATA_TYPE_REGISTRY, getMetadataTypeSchema } 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 * 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 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 };\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 };\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 }) {\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 // 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 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' }) {\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 // 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 // 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 }): 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 const content = JSON.stringify(item);\n const hash = simpleHash(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 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 // 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 }\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 }): Promise<{\n success: boolean;\n version: string;\n seq: number;\n message?: string;\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 return {\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 } 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 * 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 }): 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 // 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 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","// 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 * 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 { 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 { pluralToSingular } from '@objectstack/spec/shared';\nimport { SchemaRegistry, computeFQN } from './registry.js';\nimport { ExpressionEngine } from '@objectstack/formula';\nimport type { Expression } from '@objectstack/spec';\nimport { bindHooksToEngine } from './hook-binder.js';\nimport { validateRecord } from './validation/record-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 return (\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 */\nexport class ObjectQL implements IDataEngine {\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 // 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 // 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 const hasTx = execCtx?.transaction !== 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 = execCtx!.transaction;\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 * 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.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 // 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 // 5. Register all other metadata types generically\n const metadataArrayKeys = [\n // UI Protocol\n 'actions', 'views', 'pages', 'dashboards', 'reports', '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 } 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', '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 * 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 * 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\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 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 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 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 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) validateRecord(schemaForValidation, r, 'insert');\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 validateRecord(schemaForValidation, row, 'insert');\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 // 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 const driver = this.getDriver(object);\n \n // 1. Extract ID from data or where if it's a single update by ID\n let id = data.id;\n if (!id && 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: '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 if (hookContext.input.id) {\n validateRecord(this._registry.getObject(object), hookContext.input.data as Record<string, unknown>, 'update');\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 validateRecord(this._registry.getObject(object), hookContext.input.data as Record<string, unknown>, 'update');\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 await this.triggerHooks('afterUpdate', hookContext);\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 async delete(object: string, options?: EngineDeleteOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Delete operation starting', { object });\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 if (hookContext.input.id) {\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 // 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 const result = await 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 * 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 * 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\n try {\n const result = await 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 * 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 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 if (def.required && isMissing(value)) {\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// 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';\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 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\n const metadataTypes = ['object', 'view', 'app', 'flow', 'workflow', '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_types","import_types","import_kernel","import_shared","item","import_metadata_core","import_data","import_shared","import_kernel","import_kernel","import_shared","records","import_kernel","import_system","import_shared","import_formula","noopLogger","import_system","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../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\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","// 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. When `true`, the\n * registry auto-injects `organization_id` (lookup → sys_organization)\n * into every registered user object that doesn't already declare it and\n * isn't `managedBy` an external subsystem or explicitly opted-out via\n * `systemFields: false`.\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` — multi-tenant deployments. Required-false (the\n * SecurityPlugin populates it on insert; nullable rows are still\n * filtered out by the `tenant_isolation` RLS USING clause).\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 const wantTenant = opts.multiTenant && 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: true,\n hidden: true,\n readonly: true,\n system: true,\n description: 'Tenant scope (auto-populated by SecurityPlugin on insert).',\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} 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 * 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 }) {\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 // 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' }) {\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 // 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 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 // 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 }\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 }): Promise<{\n success: boolean;\n version: string;\n seq: number;\n message?: string;\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 return {\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 } 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 * 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 }): 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 // 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 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","// 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 * 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 { 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 } 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 */\nexport class ObjectQL implements IDataEngine {\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 const hasTx = execCtx?.transaction !== 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 = execCtx!.transaction;\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 * 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.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', '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', '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 `InMemoryCryptoProvider` 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. InMemoryCryptoProvider 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\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 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.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.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 // 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 let id = data.id;\n if (!id && 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: '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 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 // 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 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 if (hookContext.input.id) {\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 // 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 const result = await 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 * 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\n try {\n const result = await 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 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 if (def.required && isMissing(value)) {\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 (Phase 1)\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 *\n * Other rule variants (`unique`, `format`, `json_schema`, `async`,\n * `custom`, `conditional`) are not yet enforced here; they fall through\n * untouched and remain declarative until a later phase wires them.\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 { 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\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[] } | undefined | null,\n): boolean {\n const rules = objectSchema?.validations;\n if (!Array.isArray(rules)) return false;\n return rules.some(\n (r) =>\n r != null &&\n typeof r === 'object' &&\n ((r as BaseRule).type === 'state_machine' ||\n (r as BaseRule).type === 'cross_field' ||\n (r as BaseRule).type === 'script'),\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[] } | undefined | null,\n data: Record<string, unknown> | undefined | null,\n mode: Mode,\n opts: EvaluateRulesOptions = {},\n): void {\n const rules = objectSchema?.validations;\n if (!Array.isArray(rules) || rules.length === 0 || !data) 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\n const errors: FieldValidationError[] = [];\n\n const ordered = 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 if (rule.type === 'state_machine') {\n violation = checkStateMachine(rule as StateMachineRule, mode, data, previous);\n } else if (rule.type === 'script' || rule.type === 'cross_field') {\n violation = checkPredicate(rule as PredicateRule, merged, previous, opts.logger);\n }\n // Other rule types are not enforced on the write path (yet).\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 * 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\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';\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 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_types","import_types","import_kernel","import_shared","item","import_metadata_core","import_data","import_shared","import_ui","import_kernel","import_kernel","import_shared","records","import_kernel","import_system","import_shared","import_formula","noopLogger","import_formula","import_system","import_core"]}
|