@objectstack/rest 9.9.0 → 9.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/rest-server.ts","../src/route-manager.ts","../src/package-routes.ts","../src/external-datasource-routes.ts","../src/rest-api-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n// REST Server\nexport { RestServer } from './rest-server.js';\n\n// Route Management\nexport { RouteManager, RouteGroupBuilder } from './route-manager.js';\nexport type { RouteEntry } from './route-manager.js';\n\n// REST API Plugin\nexport { createRestApiPlugin } from './rest-api-plugin.js';\nexport type { RestApiPluginConfig } from './rest-api-plugin.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { IHttpServer, resolveApiKeyPrincipal } from '@objectstack/core';\nimport { RouteManager } from './route-manager.js';\nimport { RestServerConfig, RestApiConfig, CrudEndpointsConfig, MetadataEndpointsConfig, BatchEndpointsConfig, RouteGenerationConfig } from '@objectstack/spec/api';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\n\n// Node-safe logger — avoids importing 'console' which is absent from ES2020 lib typings.\nconst logError = (...args: unknown[]) => (globalThis as any).console?.error(...args);\n\n/**\n * Metadata types whose user-facing labels are localized at the REST boundary\n * via `translateMetadataDocument`. Keep in sync with the type dispatch in\n * `@objectstack/spec/system`'s `translateMetadataDocument`.\n */\nconst TRANSLATABLE_META_TYPES = new Set(['view', 'action', 'object', 'app', 'dashboard']);\n\n/**\n * Detect the `getMetaItem` response envelope (`{ type, name, item, lock, … }`)\n * whose translatable metadata document is nested at `.item`. The cached read\n * path and `getMetaItems` element shape hand back the already-unwrapped\n * document instead, so translation helpers must distinguish the two: an\n * envelope carries a nested `item` object alongside its own `type`/`name`,\n * which a bare metadata document never does.\n */\nfunction isMetaEnvelope(value: any): boolean {\n return !!value\n && typeof value === 'object'\n && typeof value.type === 'string'\n && typeof value.name === 'string'\n && value.item != null\n && typeof value.item === 'object'\n && !Array.isArray(value.item);\n}\n\n/**\n * Map a data-layer error to a clean HTTP response. Unknown-object errors\n * (SQLite \"no such table\", PG \"relation does not exist\", protocol\n * \"object not found\", etc.) are surfaced as a 404 with `code: 'object_not_found'`\n * so clients can distinguish \"object isn't registered\" from real server\n * faults. Anything else becomes a 400 (bad request) preserving prior\n * behavior. Genuine 500s are still logged.\n *\n * `PermissionDeniedError` (thrown by `SecurityPlugin`) MUST be caught\n * before the unknown-object heuristic, otherwise its message —\n * \"[Security] Access denied: operation 'insert' on object 'sys_user' is\n * not permitted …\" — trips the `'<obj>' … not` substring check and\n * returns a misleading 404.\n */\nexport function mapDataError(error: any, object?: string): { status: number; body: Record<string, unknown> } {\n // Referential-integrity restrict on delete → 409 with the dependent count.\n // Surfaced FIRST so the structured fields survive the generic catch-alls.\n if (error?.code === 'DELETE_RESTRICTED') {\n return {\n status: 409,\n body: {\n error: error?.message ?? 'Cannot delete: dependent records exist',\n code: 'DELETE_RESTRICTED',\n ...(error?.dependentObject ? { dependentObject: error.dependentObject } : {}),\n ...(typeof error?.dependentCount === 'number' ? { dependentCount: error.dependentCount } : {}),\n ...(object ? { object } : {}),\n },\n };\n }\n // Optimistic-Concurrency-Control mismatch → 409 with current state.\n // Surfaced FIRST so the structured fields (`currentVersion`,\n // `currentRecord`) are preserved instead of being squashed into the\n // generic SQL-leak / catch-all paths below.\n if (error?.code === 'CONCURRENT_UPDATE' || error?.name === 'ConcurrentUpdateError') {\n return {\n status: 409,\n body: {\n error: error?.message ?? 'Record was modified by another user',\n code: 'CONCURRENT_UPDATE',\n ...(error?.currentVersion ? { currentVersion: error.currentVersion } : {}),\n ...(error?.currentRecord ? { currentRecord: error.currentRecord } : {}),\n ...(object ? { object } : {}),\n },\n };\n }\n // Validation failures → 400 with per-field envelope. Handled FIRST\n // because the validator throws a typed error before any SQL ever\n // runs, and we want callers to differentiate \"your payload was\n // invalid\" (fixable client-side) from generic 400s.\n if (error?.code === 'VALIDATION_FAILED' || error?.name === 'ValidationError') {\n return {\n status: 400,\n body: {\n error: error?.message ?? 'Validation failed',\n code: 'VALIDATION_FAILED',\n fields: Array.isArray(error?.fields) ? error.fields : [],\n ...(object ? { object } : {}),\n },\n };\n }\n // Short-circuit: explicit security denial → 403. Match by `code` /\n // `name` to avoid pulling a runtime dependency on plugin-security.\n if (\n error?.code === 'PERMISSION_DENIED' ||\n error?.name === 'PermissionDeniedError' ||\n (typeof error?.message === 'string' && error.message.startsWith('[Security] Access denied'))\n ) {\n return {\n status: 403,\n body: {\n error: error?.message ?? 'Permission denied',\n code: 'PERMISSION_DENIED',\n ...(object ? { object } : {}),\n },\n };\n }\n const raw = String(error?.message ?? error ?? '');\n const lower = raw.toLowerCase();\n\n // EnvironmentKernelFactory: project missing database_url/driver — typically\n // means provisioning is in flight or the project record was never\n // fully provisioned. 503 (with Retry-After implied) is more accurate\n // than the default 400/500: clients can poll until the project is\n // active.\n if (\n raw.includes('[EnvironmentKernelFactory]') &&\n (lower.includes('missing database_url') || lower.includes('not found'))\n ) {\n const isProvisioning = lower.includes(\"status='provisioning'\") || lower.includes(\"status='pending'\");\n const isFailed = lower.includes(\"status='failed'\");\n return {\n status: isProvisioning ? 503 : isFailed ? 502 : 404,\n body: {\n error: raw,\n code: isProvisioning\n ? 'PROJECT_PROVISIONING'\n : isFailed\n ? 'PROJECT_PROVISIONING_FAILED'\n : 'PROJECT_NOT_FOUND',\n },\n };\n }\n\n // Record-level not-found from ObjectQL (`getData` / `updateData` /\n // `deleteData`). These are normal client mistakes (stale UI link,\n // hand-typed id, deleted record) and should be a quiet 404 — not\n // a \"[REST] Unhandled error\" log entry that scares operators.\n if (\n error?.code === 'RECORD_NOT_FOUND' ||\n /^Record\\s+\\S+\\s+not found in\\s+\\S+/i.test(raw)\n ) {\n return {\n status: 404,\n body: {\n error: raw,\n code: 'RECORD_NOT_FOUND',\n ...(object ? { object } : {}),\n },\n };\n }\n\n // Schema-mismatch & required-field violations are CLIENT errors (a bad\n // payload the caller can fix), not server faults — so map them to a\n // structured 4xx BEFORE the unknown-object / SQL-leak branches, which\n // would otherwise bury them in a generic 404 or 500. Driver phrasing\n // varies by dialect; cover SQLite / Postgres / MySQL:\n // unknown column → SQLite \"table X has no column named c\" /\n // \"no such column: c\"; Postgres 'column \"c\" of\n // relation \"X\" does not exist'; MySQL \"Unknown\n // column 'c' in 'field list'\".\n // not-null → SQLite \"NOT NULL constraint failed: X.c\";\n // Postgres 'null value in column \"c\" ... violates\n // not-null constraint'; MySQL \"Column 'c' cannot\n // be null\".\n // NOTE: this is a last-resort safety net — the validation layer should\n // ideally reject these before they reach the driver (see follow-ups on\n // unknown-field rejection + provenance-aware required checks).\n const unknownColumn =\n /has no column named\\s+[\"'`]?([a-z0-9_]+)/i.exec(raw) ||\n /no such column:\\s*[\"'`]?([a-z0-9_.]+)/i.exec(raw) ||\n /unknown column\\s+[\"'`]([a-z0-9_]+)[\"'`]/i.exec(raw) ||\n /column\\s+[\"'`]([a-z0-9_]+)[\"'`]\\s+of relation\\s+\\S+\\s+does not exist/i.exec(raw);\n if (unknownColumn) {\n const field = unknownColumn[1]?.split('.').pop();\n return {\n status: 400,\n body: {\n error: field\n ? `Unknown field '${field}'${object ? ` on object '${object}'` : ''}`\n : 'Request references a field that does not exist',\n code: 'INVALID_FIELD',\n ...(field ? { field } : {}),\n ...(object ? { object } : {}),\n },\n };\n }\n\n const notNull =\n /not null constraint failed:\\s*\\S*?\\.([a-z0-9_]+)/i.exec(raw) ||\n /null value in column\\s+[\"'`]([a-z0-9_]+)[\"'`]/i.exec(raw) ||\n /column\\s+[\"'`]([a-z0-9_]+)[\"'`]\\s+cannot be null/i.exec(raw);\n if (notNull) {\n const field = notNull[1];\n return {\n status: 400,\n body: {\n error: `${field} is required`,\n code: 'VALIDATION_FAILED',\n fields: [{ field, code: 'required', message: `${field} is required` }],\n ...(object ? { object } : {}),\n },\n };\n }\n\n const looksLikeUnknownObject =\n lower.includes('no such table') ||\n lower.includes('relation') && lower.includes('does not exist') ||\n lower.includes('table not found') ||\n lower.includes('unknown object') ||\n lower.includes('object not found') ||\n lower.includes('no driver available') ||\n (object !== undefined && lower.includes(`'${object.toLowerCase()}'`) && lower.includes('not'));\n if (looksLikeUnknownObject) {\n return {\n status: 404,\n body: {\n error: object ? `Object '${object}' is not registered` : 'Object not found',\n code: 'object_not_found',\n object,\n },\n };\n }\n // Default: do NOT leak raw SQL or driver internals. If the message\n // looks like a SQL/driver dump, replace it with a generic envelope\n // and rely on server logs for the full diagnostic.\n const looksLikeSqlLeak =\n lower.includes('sqlite_') ||\n lower.includes('sqlstate') ||\n lower.startsWith('insert into ') ||\n lower.startsWith('update ') ||\n lower.startsWith('select ') ||\n lower.startsWith('delete from ') ||\n lower.includes('constraint failed') ||\n lower.includes('unique constraint') ||\n lower.includes('foreign key');\n if (looksLikeSqlLeak) {\n // Surface unique-constraint violations as a structured 409 so\n // the UI can map them to \"this value already exists\".\n if (lower.includes('unique constraint') || lower.includes('unique violation')) {\n return {\n status: 409,\n body: {\n error: 'A record with this value already exists',\n code: 'UNIQUE_VIOLATION',\n ...(object ? { object } : {}),\n },\n };\n }\n return {\n status: 500,\n body: { error: 'Internal data error', code: 'DATABASE_ERROR' },\n };\n }\n return { status: 400, body: { error: raw || 'Bad request' } };\n}\n\n/**\n * Centralized error responder for all REST handlers. Ensures raw driver\n * messages (SQLite/Postgres dumps, stack traces, unique-constraint\n * payloads with table names, etc.) never reach clients. Honors\n * structured errors that already carry an explicit `status` so callers\n * can surface domain-specific codes (e.g. 422 from a metadata save\n * validator), and routes everything else through `mapDataError` so the\n * security / validation / SQL-leak / unknown-object envelopes apply\n * uniformly across CRUD, batch, metadata, UI and discovery routes.\n */\nfunction sendError(res: any, error: any, object?: string): void {\n if (typeof error?.status === 'number' && error.status >= 400 && error.status < 600) {\n const safeMsg = typeof error.message === 'string' && error.message.length < 500\n ? error.message\n : 'Request failed';\n res.status(error.status).json({\n error: safeMsg,\n ...(error.code ? { code: error.code } : {}),\n ...(Array.isArray(error.issues) ? { issues: error.issues } : {}),\n });\n return;\n }\n const mapped = mapDataError(error, object);\n res.status(mapped.status).json(mapped.body);\n}\n\n/**\n * Whether a mapped data-error status represents an *expected* client/lifecycle\n * outcome (and therefore shouldn't be logged as \"[REST] Unhandled error\").\n * - 403 PERMISSION_DENIED is a normal RBAC denial\n * - 404 unknown object / project not found is a normal client mistake\n * - 502/503 mean the underlying project is provisioning or failed; the\n * handler will emit the response and the operator can inspect\n * sys_environment.metadata.provisioningError if needed.\n */\nfunction isExpectedDataStatus(status: number): boolean {\n return status === 403 || status === 404 || status === 409 || status === 502 || status === 503;\n}\n\n/**\n * Minimal RFC-4180-style CSV parser used by the bulk-import endpoint\n * (M10.9). Handles quoted fields (including embedded quotes via \"\" and\n * embedded commas/newlines) and both CRLF and LF line endings.\n *\n * The first non-empty line is treated as the header row. Header names\n * can be re-mapped to canonical field names via the optional `mapping`\n * argument (e.g. `{ \"First Name\": \"first_name\" }`); unmapped headers\n * pass through unchanged. Empty cells become empty strings.\n *\n * Kept dependency-free so REST stays runtime-portable (Hono / Express\n * adapters both consume this without pulling a CSV lib transitively).\n */\nfunction parseCsvToRows(csv: string, mapping: Record<string, string> = {}): Array<Record<string, any>> {\n const text = csv.replace(/^\\uFEFF/, ''); // strip BOM\n const cells: string[][] = [];\n let cur = '';\n let row: string[] = [];\n let inQuotes = false;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (inQuotes) {\n if (ch === '\"') {\n if (text[i + 1] === '\"') { cur += '\"'; i++; }\n else { inQuotes = false; }\n } else {\n cur += ch;\n }\n continue;\n }\n if (ch === '\"') { inQuotes = true; continue; }\n if (ch === ',') { row.push(cur); cur = ''; continue; }\n if (ch === '\\r') { continue; }\n if (ch === '\\n') {\n row.push(cur); cur = '';\n cells.push(row); row = [];\n continue;\n }\n cur += ch;\n }\n if (cur.length > 0 || row.length > 0) { row.push(cur); cells.push(row); }\n\n // Drop fully-empty trailing rows so a stray newline at EOF doesn't\n // produce a phantom empty record.\n while (cells.length > 0 && cells[cells.length - 1].every(c => c === '')) cells.pop();\n if (cells.length < 2) return [];\n\n const header = cells[0].map(h => h.trim());\n const fields = header.map(h => mapping[h] ?? h);\n const out: Array<Record<string, any>> = [];\n for (let r = 1; r < cells.length; r++) {\n const row = cells[r];\n const obj: Record<string, any> = {};\n for (let c = 0; c < fields.length; c++) {\n const key = fields[c];\n if (!key) continue;\n const raw = row[c] ?? '';\n obj[key] = raw;\n }\n out.push(obj);\n }\n return out;\n}\n\n/**\n * Escape a single value into an RFC-4180 CSV cell. Values containing\n * commas, quotes, CR, or LF are wrapped in double-quotes with embedded\n * quotes doubled. `null` / `undefined` become an empty cell. Objects and\n * arrays are serialised as compact JSON so nested data round-trips\n * without flattening surprises.\n */\nfunction formatCsvCell(value: any): string {\n if (value === null || value === undefined) return '';\n let s: string;\n if (typeof value === 'string') s = value;\n else if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') s = String(value);\n else if (value instanceof Date) s = value.toISOString();\n else { try { s = JSON.stringify(value); } catch { s = String(value); } }\n if (/[\",\\r\\n]/.test(s)) {\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n }\n return s;\n}\n\n/**\n * Serialise a list of rows to RFC-4180 CSV text. Caller supplies the\n * ordered list of field names; unknown fields produce empty cells.\n */\nfunction rowsToCsv(fields: string[], rows: Array<Record<string, any>>, includeHeader: boolean): string {\n const lines: string[] = [];\n if (includeHeader) lines.push(fields.map(formatCsvCell).join(','));\n for (const row of rows) {\n lines.push(fields.map(f => formatCsvCell(row?.[f])).join(','));\n }\n return lines.join('\\r\\n') + (lines.length > 0 ? '\\r\\n' : '');\n}\n\n/**\n * Structural subset of `KernelManager` that RestServer needs in order to\n * resolve a per-project protocol at request time. Typed locally to avoid\n * an @objectstack/runtime → @objectstack/rest → @objectstack/runtime\n * package cycle.\n */\nexport interface RestKernelManager {\n getOrCreate(environmentId: string): Promise<{\n getServiceAsync<T = unknown>(name: string): Promise<T>;\n }>;\n}\n\n/**\n * Normalized REST Server Configuration\n * All nested properties are required after normalization\n */\ntype NormalizedRestServerConfig = {\n api: {\n version: string;\n basePath: string;\n apiPath: string | undefined;\n enableCrud: boolean;\n enableMetadata: boolean;\n enableUi: boolean;\n enableBatch: boolean;\n enableDiscovery: boolean;\n enableOpenApi: boolean;\n enableSearch?: boolean;\n enableProjectScoping: boolean;\n projectResolution: 'required' | 'optional' | 'auto';\n requireAuth: boolean;\n documentation: RestApiConfig['documentation'];\n responseFormat: RestApiConfig['responseFormat'];\n };\n crud: {\n operations: {\n create: boolean;\n read: boolean;\n update: boolean;\n delete: boolean;\n list: boolean;\n };\n patterns: CrudEndpointsConfig['patterns'];\n dataPrefix: string;\n objectParamStyle: 'path' | 'query';\n };\n metadata: {\n prefix: string;\n enableCache: boolean;\n cacheTtl: number;\n endpoints: {\n types: boolean;\n items: boolean;\n item: boolean;\n schema: boolean;\n };\n };\n batch: {\n maxBatchSize: number;\n enableBatchEndpoint: boolean;\n operations: {\n createMany: boolean;\n updateMany: boolean;\n deleteMany: boolean;\n upsertMany: boolean;\n };\n defaultAtomic: boolean;\n };\n routes: {\n includeObjects: string[] | undefined;\n excludeObjects: string[] | undefined;\n nameTransform: 'none' | 'plural' | 'kebab-case' | 'camelCase';\n overrides: RouteGenerationConfig['overrides'];\n };\n};\n\n/**\n * RestServer\n * \n * Provides automatic REST API endpoint generation for ObjectStack.\n * Generates standard RESTful CRUD endpoints, metadata endpoints, and batch operations\n * based on the configured protocol provider.\n * \n * Features:\n * - Automatic CRUD endpoint generation (GET, POST, PUT, PATCH, DELETE)\n * - Metadata API endpoints (/meta)\n * - Batch operation endpoints (/batch, /createMany, /updateMany, /deleteMany)\n * - Discovery endpoint\n * - Configurable path prefixes and patterns\n * \n * @example\n * const restServer = new RestServer(httpServer, protocolProvider, {\n * api: {\n * version: 'v1',\n * basePath: '/api'\n * },\n * crud: {\n * dataPrefix: '/data'\n * }\n * });\n * \n * restServer.registerRoutes();\n */\n/**\n * Minimal env registry shape consumed by the REST server for hostname →\n * environmentId resolution and `X-Environment-Id` header validation on unscoped\n * routes. Mirrors the surface of `EnvironmentDriverRegistry` defined in\n * `@objectstack/service-cloud`.\n */\nexport interface RestEnvRegistry {\n resolveByHostname(hostname: string): Promise<{ environmentId: string } | null | undefined>;\n /**\n * Look up a project by id. Returns a truthy value (typically an\n * `IDataDriver`) when the project exists and is bound, `null` when\n * unknown. The REST server only uses the truthiness; it does not\n * touch the driver itself (the actual driver is loaded later via\n * `KernelManager.getOrCreate(environmentId)`).\n */\n resolveById?(environmentId: string): Promise<unknown | null>;\n}\n\nexport class RestServer {\n private protocol: ObjectStackProtocol;\n private config: NormalizedRestServerConfig;\n private routeManager: RouteManager;\n private kernelManager?: RestKernelManager;\n private envRegistry?: RestEnvRegistry;\n /**\n * Short-TTL cache for `hostname → environmentId` (P1-4). `resolveByHostname`\n * is a control-plane lookup (typically a DB query) that otherwise runs on\n * *every* unscoped request; caching it — including negative results, so\n * unknown hosts don't hammer the registry — removes that per-request cost.\n * The TTL is short so a newly-bound hostname becomes routable quickly.\n */\n private readonly hostnameCache = new Map<string, { value: { environmentId: string } | null; expiresAt: number }>();\n private readonly hostnameCacheTtlMs = 30_000;\n private defaultEnvironmentIdProvider?: () => string | undefined;\n private authServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private objectQLProvider?: (environmentId?: string) => Promise<any | undefined>;\n private emailServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private sharingServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private reportsServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private approvalsServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private sharingRulesServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private i18nServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private analyticsServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n\n constructor(\n server: IHttpServer,\n protocol: ObjectStackProtocol,\n config: RestServerConfig = {},\n kernelManager?: RestKernelManager,\n envRegistry?: RestEnvRegistry,\n defaultEnvironmentIdProvider?: () => string | undefined,\n authServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n objectQLProvider?: (environmentId?: string) => Promise<any | undefined>,\n emailServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n sharingServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n reportsServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n approvalsServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n sharingRulesServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n i18nServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n analyticsServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n ) {\n this.protocol = protocol;\n this.config = this.normalizeConfig(config);\n this.routeManager = new RouteManager(server);\n this.kernelManager = kernelManager;\n this.envRegistry = envRegistry;\n this.defaultEnvironmentIdProvider = defaultEnvironmentIdProvider;\n this.authServiceProvider = authServiceProvider;\n this.objectQLProvider = objectQLProvider;\n this.emailServiceProvider = emailServiceProvider;\n this.sharingServiceProvider = sharingServiceProvider;\n this.reportsServiceProvider = reportsServiceProvider;\n this.approvalsServiceProvider = approvalsServiceProvider;\n this.sharingRulesServiceProvider = sharingRulesServiceProvider;\n this.i18nServiceProvider = i18nServiceProvider;\n this.analyticsServiceProvider = analyticsServiceProvider;\n }\n\n /**\n * Resolve the protocol for a given request. When `environmentId` is present\n * and a KernelManager is wired, fetch the per-project kernel's\n * `protocol` service so metadata / data / UI reads hit the project's\n * own registry and datastore.\n *\n * When `environmentId` is absent on an unscoped route and an `envRegistry`\n * is wired (runtime mode), the resolution chain is:\n * 1. Hostname → environmentId (`envRegistry.resolveByHostname`)\n * 2. `X-Environment-Id` header → environmentId (`envRegistry.resolveById`)\n * 3. Default-project fallback (`defaultEnvironmentIdProvider`, set by\n * `createSingleEnvironmentPlugin`)\n * 4. Control-plane protocol captured at boot.\n *\n * Special case: `environmentId === 'platform'` is a reserved virtual id used\n * by Studio to address the control plane through the regular project\n * URL shape (`/projects/platform/...`). It is NOT a row in the projects\n * table, so we must never call `KernelManager.getOrCreate('platform')`.\n * Instead, return the control-plane protocol directly. This lets Studio\n * (and any other client) speak a single, uniform URL family without\n * duplicating route logic for the platform surface.\n */\n /**\n * Cached wrapper around `envRegistry.resolveByHostname` (P1-4). Returns the\n * cached result while fresh; on a miss it queries the registry and caches the\n * outcome (positive *and* negative) for {@link hostnameCacheTtlMs}. Registry\n * errors are not cached so a transient control-plane blip self-heals on the\n * next request.\n */\n private async resolveHostnameCached(host: string): Promise<{ environmentId: string } | null | undefined> {\n const now = Date.now();\n const hit = this.hostnameCache.get(host);\n if (hit && hit.expiresAt > now) return hit.value;\n const result = (await this.envRegistry!.resolveByHostname(host)) ?? null;\n this.hostnameCache.set(host, { value: result, expiresAt: now + this.hostnameCacheTtlMs });\n return result;\n }\n\n /**\n * Resolve the environment a request targets: explicit id → tenant hostname\n * → `X-Environment-Id` header → single-project default. Returns undefined\n * for control-plane requests. Shared by every per-environment service\n * resolution (protocol, analytics, …) so they can never disagree about\n * which kernel a request belongs to.\n */\n private async resolveRequestEnvironmentId(environmentId?: string, req?: any): Promise<string | undefined> {\n if (environmentId) return environmentId;\n if (req && this.envRegistry && this.kernelManager) {\n const host = this.extractHostname(req);\n if (host) {\n try {\n const result = await this.resolveHostnameCached(host);\n if (result?.environmentId) return result.environmentId;\n } catch {\n // fall through to next strategy\n }\n }\n // 2. `X-Environment-Id` request header → environmentId. Lets clients\n // explicitly target a project when the URL is unscoped and\n // no hostname binding exists (e.g. a single shared origin\n // serving multiple compiled bundles via OS_PROJECT_ARTIFACTS).\n // We validate the id through the env registry to avoid\n // routing to a non-existent kernel.\n if (typeof this.envRegistry.resolveById === 'function') {\n const headerVal = this.extractProjectIdHeader(req);\n if (headerVal) {\n try {\n const driver = await this.envRegistry.resolveById(headerVal);\n if (driver) return headerVal;\n } catch {\n // fall through to default fallback\n }\n }\n }\n }\n // 3. Single-project default fallback. Registered by\n // `createSingleEnvironmentPlugin()` so bare `/api/v1/data/...` URLs\n // (no `/projects/<id>` prefix, no hostname mapping, no header)\n // resolve to the lone project's kernel rather than the control\n // plane.\n if (this.defaultEnvironmentIdProvider) {\n try {\n const def = this.defaultEnvironmentIdProvider();\n if (def) return def;\n } catch { /* fall through */ }\n }\n return undefined;\n }\n\n private async resolveProtocol(environmentId?: string, req?: any): Promise<ObjectStackProtocol> {\n if (environmentId === 'platform') return this.protocol;\n const envId = await this.resolveRequestEnvironmentId(environmentId, req);\n if (!envId || !this.kernelManager) return this.protocol;\n const kernel = await this.kernelManager.getOrCreate(envId);\n return kernel.getServiceAsync<ObjectStackProtocol>('protocol');\n }\n\n /**\n * Resolve the i18n service for the request's project (or control plane\n * when no project id is in scope). Returns `undefined` when no service is\n * registered, so callers can short-circuit and skip translation rather\n * than failing.\n *\n * Mirrors `resolveProtocol`'s lookup chain: explicit `environmentId` from the\n * route → kernel-managed `i18n` service. Control-plane / unscoped\n * requests intentionally return `undefined` because the platform kernel\n * does not own per-app translation bundles.\n */\n private async resolveI18nService(environmentId?: string, req?: any): Promise<any | undefined> {\n if (environmentId === 'platform') return undefined;\n // Mirror resolveProtocol's fallback chain so unscoped routes (single-\n // project dev servers, hostname-routed multi-tenants, X-Environment-Id\n // headers) can still pick up per-project translation bundles.\n if (!environmentId && req && this.envRegistry && this.kernelManager) {\n const host = this.extractHostname(req);\n if (host) {\n try {\n const result = await this.resolveHostnameCached(host);\n if (result?.environmentId) environmentId = result.environmentId;\n } catch { /* fall through */ }\n }\n if (!environmentId && typeof this.envRegistry.resolveById === 'function') {\n const headerVal = this.extractProjectIdHeader(req);\n if (headerVal) {\n try {\n const driver = await this.envRegistry.resolveById(headerVal);\n if (driver) environmentId = headerVal;\n } catch { /* fall through */ }\n }\n }\n }\n if (!environmentId && this.defaultEnvironmentIdProvider) {\n try {\n const def = this.defaultEnvironmentIdProvider();\n if (def) environmentId = def;\n } catch { /* fall through */ }\n }\n // Multi-tenant kernel lookup first; falls back to the single-kernel\n // provider supplied by RestApiPlugin in dev / standalone mode.\n if (environmentId && this.kernelManager) {\n try {\n const kernel = await this.kernelManager.getOrCreate(environmentId);\n const svc = await kernel.getServiceAsync<any>('i18n');\n if (svc) return svc;\n } catch { /* fall through */ }\n }\n if (this.i18nServiceProvider) {\n try {\n return await this.i18nServiceProvider(environmentId);\n } catch { return undefined; }\n }\n return undefined;\n }\n\n /**\n * Reject anonymous requests with HTTP 401 when `api.requireAuth` is set.\n * Returns `true` if the response was sent and the caller should stop\n * processing. Returns `false` to continue.\n *\n * The check is intentionally narrow: only `context?.userId` counts as\n * \"authenticated\". `isSystem` flags are never set on inbound HTTP\n * requests (they're internal-only), so they cannot bypass this gate.\n */\n private enforceAuth(req: any, res: any, context: any): boolean {\n if (!this.config.api.requireAuth) return false;\n if (context?.userId) return false;\n if (req?.method === 'OPTIONS') return false;\n res.status(401).json({\n error: 'unauthenticated',\n message: 'Authentication is required to access this endpoint.',\n });\n return true;\n }\n\n /**\n * Enforce object-level API exposure (ObjectSchema `enable.apiEnabled` /\n * `enable.apiMethods`) on the REST data surface — the *external* API boundary\n * only. Internal callers (hooks, flows, raw objectql) are unaffected, which is\n * the point: `apiEnabled` controls automatic API exposure, not data access.\n *\n * - `enable.apiEnabled === false` → object hidden from the API (404, so its\n * existence isn't revealed).\n * - `enable.apiMethods` (non-empty whitelist) → unlisted operations rejected (405).\n *\n * Default-allow: objects with no `enable` block (or `apiEnabled` unset/true and\n * no `apiMethods` whitelist) behave exactly as before — no regression. Unknown\n * objects fall through to the normal 404 path. A metadata-read failure does not\n * block (the data call itself needs the same metadata and will surface the\n * error). Returns `true` when the request was blocked (response already sent).\n *\n * See ADR-0049 (#1889): shipping a non-enforcing `apiEnabled` is false security.\n */\n private async enforceApiAccess(\n req: any,\n res: any,\n p: ObjectStackProtocol,\n environmentId: string | undefined,\n operation: string,\n ): Promise<boolean> {\n const objectName = req?.params?.object;\n if (!objectName) return false;\n let enable: any;\n try {\n const r: any = await (p as any).getMetaItems?.({\n type: 'object',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(r?.items) ? r.items : Array.isArray(r) ? r : [];\n const obj = items.find((o: any) => o?.name === objectName);\n if (!obj) return false; // unknown object → let the data path 404\n enable = obj.enable;\n } catch {\n return false; // metadata unavailable → don't block (data call needs it too)\n }\n if (!enable) return false;\n if (enable.apiEnabled === false) {\n res.status(404).json({\n error: `Object '${objectName}' is not exposed via the API`,\n code: 'OBJECT_API_DISABLED',\n object: objectName,\n });\n return true;\n }\n if (Array.isArray(enable.apiMethods) && enable.apiMethods.length > 0 && !enable.apiMethods.includes(operation)) {\n res.status(405).json({\n error: `API operation '${operation}' is not allowed on object '${objectName}'`,\n code: 'OBJECT_API_METHOD_NOT_ALLOWED',\n object: objectName,\n allowed: enable.apiMethods,\n });\n return true;\n }\n return false;\n }\n\n /**\n * Resolve the request's execution context (RBAC/RLS/FLS) by looking up\n * the better-auth session via the project's `auth` service. Returns\n * `undefined` for anonymous requests so callers can pass `context` as-is\n * to the protocol layer (the SecurityPlugin treats undefined as anon).\n */\n private async resolveExecCtx(environmentId: string | undefined, req: any): Promise<any | undefined> {\n try {\n // For multi-tenant hosts (objectos), incoming requests on unscoped\n // URLs like `/api/v1/data/:object` arrive with `environmentId === undefined`.\n // The route's protocol resolver already maps hostname → environmentId\n // (see resolveProtocol). We mirror that here so getSession() can\n // find the right per-project auth service. Without this, the\n // hostname-routed requests fall through to defaultEnvironmentIdProvider/\n // authServiceProvider (neither of which is wired in objectos) and\n // every authenticated user sees 401.\n if (!environmentId && req && this.envRegistry && this.kernelManager) {\n const host = this.extractHostname(req);\n if (host) {\n try {\n const result = await this.resolveHostnameCached(host);\n if (result?.environmentId) environmentId = result.environmentId;\n } catch { /* fall through */ }\n }\n if (!environmentId && typeof this.envRegistry.resolveById === 'function') {\n const headerVal = this.extractProjectIdHeader(req);\n if (headerVal) {\n try {\n const driver = await this.envRegistry.resolveById(headerVal);\n if (driver) environmentId = headerVal;\n } catch { /* fall through */ }\n }\n }\n }\n // Look up the auth service in the right kernel. For unscoped\n // single-environment apps the kernelManager will hand us the lone\n // tenant kernel; for multi-environment hosts we use the resolved\n // environmentId.\n let authService: any;\n let kernel: any;\n if (environmentId && environmentId !== 'platform' && this.kernelManager) {\n kernel = await this.kernelManager.getOrCreate(environmentId);\n authService = await kernel.getServiceAsync('auth').catch(() => undefined);\n }\n if (!authService && this.defaultEnvironmentIdProvider && this.kernelManager) {\n try {\n const def = this.defaultEnvironmentIdProvider();\n if (def) {\n kernel = await this.kernelManager.getOrCreate(def);\n authService = await kernel.getServiceAsync('auth').catch(() => undefined);\n }\n } catch { /* fall through */ }\n }\n // Single-kernel deployment fallback — no kernelManager, but\n // the plugin wired an `authServiceProvider` that hits the\n // local kernel directly.\n if (!authService && this.authServiceProvider) {\n authService = await this.authServiceProvider(environmentId).catch(() => undefined);\n }\n if (!authService) return undefined;\n // The auth service may be the AuthManager wrapper (which exposes\n // `getApi()`) or the raw better-auth instance (which exposes\n // `.api` directly). Normalize to the raw API object.\n let api: any = authService.api;\n if (!api && typeof authService.getApi === 'function') {\n api = await authService.getApi();\n }\n if (!api?.getSession) return undefined;\n\n // better-auth's `getSession` requires a Web `Headers` instance\n // (it calls `headers.get('cookie')`). Adapter req.headers may\n // already be one, or a plain object — normalize.\n const rawHeaders: any = req?.headers;\n let headers: any;\n if (rawHeaders && typeof rawHeaders.get === 'function') {\n headers = rawHeaders;\n } else if (rawHeaders && typeof rawHeaders === 'object') {\n headers = new (globalThis as any).Headers();\n for (const [k, v] of Object.entries(rawHeaders)) {\n if (Array.isArray(v)) v.forEach((x) => headers.append(k, String(x)));\n else if (v != null) headers.set(k, String(v));\n }\n } else {\n return undefined;\n }\n\n const permissions: string[] = [];\n const systemPermissions: string[] = [];\n const roles: string[] = [];\n\n // Resolve the data engine once — needed by the API-key verifier and\n // reused by the role/permission lookups below.\n let identityQl: any;\n if (kernel) identityQl = await kernel.getServiceAsync('objectql').catch(() => undefined);\n if (!identityQl && this.objectQLProvider) {\n identityQl = await this.objectQLProvider(environmentId).catch(() => undefined);\n }\n\n // ── Identity: API key (sys_api_key) takes precedence, then session.\n // Verified by the SAME `resolveApiKeyPrincipal` (@objectstack/core)\n // the dispatcher/MCP path uses, so REST + MCP never drift on how a\n // key authenticates. Anonymous (neither) → undefined → 401.\n let userId: string;\n let tenantId: string | undefined;\n const keyPrincipal = await resolveApiKeyPrincipal(identityQl, headers).catch(() => undefined);\n if (keyPrincipal) {\n userId = keyPrincipal.userId;\n tenantId = keyPrincipal.tenantId;\n for (const s of keyPrincipal.scopes) if (!permissions.includes(s)) permissions.push(s);\n } else {\n const session = await api.getSession({ headers });\n if (!session?.user?.id) return undefined;\n userId = session.user.id;\n tenantId = session.session?.activeOrganizationId ?? undefined;\n }\n // Look up the link tables to surface roles + permission set names.\n // Skipping this lookup would silently ignore admin/role grants —\n // including the platform-admin promotion seeded by\n // `bootstrapPlatformAdmin` — and force every authenticated user\n // through the `member_default` fallback path.\n try {\n let ql: any;\n if (kernel) {\n ql = await kernel.getServiceAsync('objectql').catch(() => undefined);\n }\n if (!ql && this.objectQLProvider) {\n ql = await this.objectQLProvider(environmentId).catch(() => undefined);\n }\n if (ql && typeof ql.find === 'function') {\n const sysOpts = { context: { isSystem: true } };\n const memberRows = await ql.find('sys_member', {\n where: tenantId ? { user_id: userId, organization_id: tenantId } : { user_id: userId },\n limit: 50,\n ...sysOpts,\n } as any).catch(() => []);\n for (const m of (memberRows ?? []) as any[]) {\n if (typeof m.role === 'string') {\n for (const r of m.role.split(',').map((s: string) => s.trim()).filter(Boolean)) {\n if (!roles.includes(r)) roles.push(r);\n }\n }\n }\n const upsRows = await ql.find('sys_user_permission_set', {\n where: { user_id: userId },\n limit: 100,\n ...sysOpts,\n } as any).catch(() => []);\n const psIds = new Set<string>();\n for (const r of (upsRows ?? []) as any[]) {\n const orgScope = r.organization_id ?? null;\n if (!orgScope || (tenantId && orgScope === tenantId)) {\n const pid = r.permission_set_id ?? r.permissionSetId;\n if (pid) psIds.add(pid);\n }\n }\n if (psIds.size > 0) {\n const psRows = await ql.find('sys_permission_set', {\n where: { id: { $in: Array.from(psIds) } },\n limit: 500,\n ...sysOpts,\n } as any).catch(() => []);\n for (const ps of (psRows ?? []) as any[]) {\n if (ps.name && !permissions.includes(ps.name)) permissions.push(ps.name);\n // System permissions may be stored as a JSON string\n // (driver-sql round-trips array columns as text).\n // Mirrors runtime/src/security/resolve-execution-context.ts.\n const rawSys = typeof ps.system_permissions === 'string'\n ? (() => { try { return JSON.parse(ps.system_permissions); } catch { return []; } })()\n : (ps.system_permissions ?? ps.systemPermissions);\n if (Array.isArray(rawSys)) {\n for (const sp of rawSys) {\n if (typeof sp === 'string' && !systemPermissions.includes(sp)) {\n systemPermissions.push(sp);\n }\n }\n }\n }\n }\n }\n } catch { /* fall through with empty perms */ }\n // Pre-resolve fellow-org user IDs so RLS can scope identity\n // tables (sys_user) to org collaborators. Cap at 1000. See\n // `@objectstack/runtime/security/resolve-execution-context.ts`\n // for the mirror implementation in the dispatcher path.\n let org_user_ids: string[] = [userId];\n if (tenantId) {\n try {\n let ql: any;\n if (kernel) {\n ql = await kernel.getServiceAsync('objectql').catch(() => undefined);\n }\n if (!ql && this.objectQLProvider) {\n ql = await this.objectQLProvider(environmentId).catch(() => undefined);\n }\n if (ql && typeof ql.find === 'function') {\n const sysOpts = { context: { isSystem: true } };\n const memberRows = await ql.find('sys_member', {\n where: { organization_id: tenantId },\n limit: 1000,\n ...sysOpts,\n } as any).catch(() => []);\n const ids = new Set<string>([userId]);\n for (const m of (memberRows ?? []) as any[]) {\n const uid = m.user_id ?? m.userId;\n if (typeof uid === 'string' && uid.length > 0) ids.add(uid);\n }\n org_user_ids = Array.from(ids);\n }\n } catch { /* fall back to self-only */ }\n }\n return {\n userId,\n tenantId,\n roles,\n permissions,\n systemPermissions,\n isSystem: false,\n org_user_ids,\n } as any;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Filter an `App` metadata item by the current user's `systemPermissions`.\n *\n * - Drops the app entirely if its top-level `requiredPermissions` are not\n * a subset of the user's system permissions.\n * - Recursively strips child navigation entries (groups, items) whose\n * `requiredPermissions` are not satisfied. Empty groups collapse so\n * the sidebar doesn't render a label with no children.\n *\n * Returns `null` when the app should be hidden from the user. Returns a\n * shallow copy with a filtered `navigation` tree otherwise — the original\n * is never mutated so cached metadata stays clean.\n */\n private filterAppForUser(item: any, sysPerms: Set<string>): any | null {\n if (!item || typeof item !== 'object') return item;\n // ADR-0045: an unpublished app (`hidden: true`) is externally\n // unobservable — only builders (studio/setup access) receive it at all,\n // for direct-URL preview. The launcher's client-side hidden filter is a\n // listing courtesy; THIS is the visibility gate.\n if (item.hidden === true && !sysPerms.has('studio.access') && !sysPerms.has('setup.access')) {\n return null;\n }\n const reqApp = Array.isArray(item.requiredPermissions) ? item.requiredPermissions : [];\n if (reqApp.length > 0 && !reqApp.every((p: string) => sysPerms.has(p))) {\n return null;\n }\n const nav = Array.isArray(item.navigation) ? item.navigation : null;\n if (!nav) return item;\n\n const filterNav = (entries: any[]): any[] => {\n const out: any[] = [];\n for (const e of entries) {\n if (!e || typeof e !== 'object') continue;\n const req = Array.isArray(e.requiredPermissions) ? e.requiredPermissions : [];\n if (req.length > 0 && !req.every((p: string) => sysPerms.has(p))) continue;\n if (Array.isArray(e.children) && e.children.length > 0) {\n const kids = filterNav(e.children);\n // Drop empty groups so the sidebar doesn't render a label\n // with nothing under it (matches AppSidebar UX).\n if (e.type === 'group' && kids.length === 0) continue;\n out.push({ ...e, children: kids });\n } else {\n out.push(e);\n }\n }\n return out;\n };\n\n return { ...item, navigation: filterNav(nav) };\n }\n\n /**\n * Build a `TranslationBundle` (`Record<locale, TranslationData>`) from an\n * `II18nService` instance. Returns `undefined` when no locales are\n * registered so callers can avoid translation work.\n */\n private buildTranslationBundle(i18n: any): any | undefined {\n if (!i18n || typeof i18n.getLocales !== 'function' || typeof i18n.getTranslations !== 'function') {\n return undefined;\n }\n const locales: string[] = i18n.getLocales();\n if (!locales.length) return undefined;\n const bundle: Record<string, any> = {};\n for (const locale of locales) {\n const data = i18n.getTranslations(locale);\n if (data && typeof data === 'object') bundle[locale] = data;\n }\n return Object.keys(bundle).length ? bundle : undefined;\n }\n\n /**\n * Parse the highest-priority locale from an `Accept-Language` header.\n * Falls back to a `?locale=` query parameter, then to the i18n service's\n * default locale. Returns `undefined` when no preference is expressed\n * (callers will then return untranslated metadata).\n */\n private extractLocale(req: any, i18n?: any): string | undefined {\n const headers = req?.headers;\n let header: string | undefined;\n if (headers) {\n header = typeof headers.get === 'function'\n ? headers.get('accept-language') ?? undefined\n : headers['accept-language'] ?? headers['Accept-Language'];\n }\n if (typeof header === 'string' && header.length > 0) {\n const top = header.split(',')[0]?.split(';')[0]?.trim();\n if (top) return top;\n }\n const queryLocale = req?.query?.locale;\n if (typeof queryLocale === 'string' && queryLocale.length > 0) return queryLocale;\n if (i18n && typeof i18n.getDefaultLocale === 'function') {\n const def = i18n.getDefaultLocale();\n if (typeof def === 'string' && def.length > 0) return def;\n }\n return undefined;\n }\n\n /**\n * Translate a single metadata document (view or action) when an i18n\n * service is registered for the request's project and the requested\n * locale yields a match. Falls through unchanged for unsupported types\n * or missing translations.\n */\n private async translateMetaItem(req: any, type: string, environmentId: string | undefined, item: any, i18nService?: any): Promise<any> {\n if (!item || typeof item !== 'object') return item;\n if (!TRANSLATABLE_META_TYPES.has(type)) return item;\n // The cached read path resolves the i18n service up-front (to build a\n // locale-aware ETag) and passes it here so we don't repeat the\n // potentially registry-hitting lookup on every request.\n const i18n = i18nService !== undefined ? i18nService : await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n if (!bundle) return item;\n const locale = this.extractLocale(req, i18n);\n if (!locale) return item;\n const { translateMetadataDocument } = await import('@objectstack/spec/system');\n // `getMetaItem` returns an envelope `{ type, name, item, lock, ... }`\n // whose translatable document is nested at `.item`; the cached read\n // path hands us the already-unwrapped document. Translate whichever\n // shape we received — nav/field labels live on the inner doc, so\n // translating the envelope's top level (which has no `navigation`)\n // would leave the menu untranslated.\n if (isMetaEnvelope(item)) {\n return { ...item, item: translateMetadataDocument(type, item.item, bundle, { locale }) };\n }\n return translateMetadataDocument(type, item, bundle, { locale });\n }\n\n /**\n * Translate a list of metadata documents using `translateMetaItem`.\n */\n private async translateMetaItems(req: any, type: string, environmentId: string | undefined, items: any): Promise<any> {\n if (!TRANSLATABLE_META_TYPES.has(type)) return items;\n // `getMetaItems` may hand back a bare array or an `{ items: [...] }`\n // envelope. Unwrap so list responses are localized the same way the\n // single-item route is; a non-array, non-envelope value is returned\n // untouched.\n const arr: any[] | null = Array.isArray(items)\n ? items\n : (items && typeof items === 'object' && Array.isArray(items.items) ? items.items : null);\n if (!arr) return items;\n const i18n = await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n if (!bundle) return items;\n const locale = this.extractLocale(req, i18n);\n if (!locale) return items;\n const { translateMetadataDocument } = await import('@objectstack/spec/system');\n const translated = arr.map((item) =>\n isMetaEnvelope(item)\n ? { ...item, item: translateMetadataDocument(type, item.item, bundle, { locale }) }\n : translateMetadataDocument(type, item, bundle, { locale }),\n );\n return Array.isArray(items) ? translated : { ...items, items: translated };\n }\n\n /**\n * Translate the `entries` payload returned by `getMetaTypes()` — applies\n * the active locale to each entry's `label`, `description`, and the\n * nested `form` layout (section labels, field labels, helpText,\n * placeholders) via `metadataForms.<type>` translation namespace.\n *\n * No-ops when no i18n service / locale / matching bundle entry exists,\n * so this is safe to call unconditionally from the `/meta` handler.\n */\n private async translateMetaTypesResponse(req: any, environmentId: string | undefined, payload: any): Promise<any> {\n if (!payload || typeof payload !== 'object' || !Array.isArray(payload.entries)) return payload;\n const i18n = await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n if (!bundle) return payload;\n const locale = this.extractLocale(req, i18n);\n if (!locale) return payload;\n const {\n resolveMetadataTypeLabel,\n resolveMetadataTypeDescription,\n resolveMetadataFormLabels,\n } = await import('@objectstack/spec/system');\n const opts = { locale } as const;\n const entries = payload.entries.map((entry: any) => {\n if (!entry || typeof entry !== 'object' || typeof entry.type !== 'string') return entry;\n const next: any = { ...entry };\n next.label = resolveMetadataTypeLabel(bundle, entry.type, entry.label ?? entry.type, opts);\n const desc = resolveMetadataTypeDescription(bundle, entry.type, entry.description, opts);\n if (desc !== undefined) next.description = desc;\n if (entry.form) {\n next.form = resolveMetadataFormLabels(entry.form, entry.type, bundle, opts);\n }\n return next;\n });\n return { ...payload, entries };\n }\n\n /**\n * Pull the request hostname (without port) from a Node-style `req` or\n * a Fetch-style request wrapper. Returns undefined when no Host header\n * is available.\n */\n private extractHostname(req: any): string | undefined {\n const headers = req?.headers;\n let host: string | undefined;\n if (headers) {\n if (typeof headers.get === 'function') {\n host = headers.get('host') ?? undefined;\n } else {\n host = headers.host ?? headers.Host;\n }\n }\n if (!host && typeof req?.hostname === 'string') host = req.hostname;\n if (!host && typeof req?.url === 'string') {\n // Fetch-style requests expose the hostname via `req.url` even\n // when the (forbidden) `Host` header has been stripped by the\n // runtime. This branch keeps hostname-routing working when\n // tests build a `Request` object through `app.fetch(...)`.\n try {\n host = new (globalThis as any).URL(req.url).host;\n } catch { /* ignore */ }\n }\n if (!host) return undefined;\n return String(host).split(':')[0].toLowerCase();\n }\n\n /**\n * Pull the `X-Environment-Id` header from a Node- or Fetch-style request.\n * Header names are case-insensitive; we probe both casings to cover\n * adapters that don't normalize headers (e.g. raw Node http).\n */\n private extractProjectIdHeader(req: any): string | undefined {\n const headers = req?.headers;\n if (!headers) return undefined;\n let val: unknown;\n if (typeof headers.get === 'function') {\n val = headers.get('x-environment-id') ?? headers.get('X-Environment-Id');\n } else {\n val = headers['x-environment-id'] ?? headers['X-Environment-Id'];\n }\n if (Array.isArray(val)) val = val[0];\n if (typeof val !== 'string') return undefined;\n const trimmed = val.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n }\n \n /**\n * Normalize configuration with defaults\n */\n private normalizeConfig(config: RestServerConfig): NormalizedRestServerConfig {\n const api = (config.api ?? {}) as Partial<RestApiConfig>;\n const crud = (config.crud ?? {}) as Partial<CrudEndpointsConfig>;\n const metadata = (config.metadata ?? {}) as Partial<MetadataEndpointsConfig>;\n const batch = (config.batch ?? {}) as Partial<BatchEndpointsConfig>;\n const routes = (config.routes ?? {}) as Partial<RouteGenerationConfig>;\n \n return {\n api: {\n version: api.version ?? 'v1',\n basePath: api.basePath ?? '/api',\n apiPath: api.apiPath,\n enableCrud: api.enableCrud ?? true,\n enableMetadata: api.enableMetadata ?? true,\n enableUi: api.enableUi ?? true,\n enableBatch: api.enableBatch ?? true,\n enableDiscovery: api.enableDiscovery ?? true,\n enableOpenApi: (api as any).enableOpenApi ?? true,\n enableSearch: (api as any).enableSearch ?? true,\n enableProjectScoping: api.enableProjectScoping ?? false,\n projectResolution: api.projectResolution ?? 'auto',\n requireAuth: (api as any).requireAuth ?? false,\n documentation: api.documentation,\n responseFormat: api.responseFormat,\n },\n crud: {\n operations: crud.operations ?? {\n create: true,\n read: true,\n update: true,\n delete: true,\n list: true,\n },\n patterns: crud.patterns,\n dataPrefix: crud.dataPrefix ?? '/data',\n objectParamStyle: crud.objectParamStyle ?? 'path',\n },\n metadata: {\n prefix: metadata.prefix ?? '/meta',\n enableCache: metadata.enableCache ?? true,\n cacheTtl: metadata.cacheTtl ?? 3600,\n endpoints: metadata.endpoints ?? {\n types: true,\n items: true,\n item: true,\n schema: true,\n },\n },\n batch: {\n maxBatchSize: batch.maxBatchSize ?? 200,\n enableBatchEndpoint: batch.enableBatchEndpoint ?? true,\n operations: batch.operations ?? {\n createMany: true,\n updateMany: true,\n deleteMany: true,\n upsertMany: true,\n },\n defaultAtomic: batch.defaultAtomic ?? true,\n },\n routes: {\n includeObjects: routes.includeObjects,\n excludeObjects: routes.excludeObjects,\n nameTransform: routes.nameTransform ?? 'none',\n overrides: routes.overrides,\n },\n };\n }\n \n /**\n * Get the full API base path\n */\n private getApiBasePath(): string {\n const { api } = this.config;\n return api.apiPath ?? `${api.basePath}/${api.version}`;\n }\n\n /**\n * Get the project-scoped base path for a given unscoped base.\n * Example: `/api/v1` → `/api/v1/environments/:environmentId`.\n */\n private getScopedBasePath(basePath: string): string {\n return `${basePath}/environments/:environmentId`;\n }\n\n /**\n * Register all REST API routes\n *\n * When `enableProjectScoping` is true, routes are registered under\n * `/api/v1/environments/:environmentId/...`. The `projectResolution` strategy\n * controls whether unscoped legacy routes remain available:\n * - `required` → only scoped routes registered.\n * - `optional` / `auto` → both scoped and unscoped routes registered.\n */\n registerRoutes(): void {\n const basePath = this.getApiBasePath();\n const { enableProjectScoping, projectResolution } = this.config.api;\n\n const registerForBase = (bp: string) => {\n if (this.config.api.enableDiscovery) {\n this.registerDiscoveryEndpoints(bp);\n }\n if (this.config.api.enableOpenApi ?? true) {\n this.registerOpenApiEndpoints(bp);\n }\n if (this.config.api.enableMetadata) {\n this.registerMetadataEndpoints(bp);\n }\n if (this.config.api.enableUi) {\n this.registerUiEndpoints(bp);\n }\n if (this.config.api.enableSearch ?? true) {\n this.registerSearchEndpoints(bp);\n }\n this.registerEmailEndpoints(bp);\n // Public (anonymous) form endpoints — opt-in via FormView.sharing.\n // Registered BEFORE the greedy `/data/:object` matcher so the\n // `/forms/:slug` and `/forms/:slug/submit` paths can't be\n // shadowed by a literal object named \"forms\".\n this.registerFormEndpoints(bp);\n // Capability routes (sharing rules, reports, approvals) live at\n // the top of the API surface (`/api/v1/{capability}/...`) rather\n // than under `/data/`, so they don't collide with the greedy\n // CRUD `/:object` matcher and don't pretend to be records on a\n // single object.\n this.registerSharingEndpoints(bp);\n this.registerSharingRuleEndpoints(bp);\n this.registerReportsEndpoints(bp);\n this.registerApprovalsEndpoints(bp);\n this.registerAnalyticsEndpoints(bp);\n if (this.config.api.enableCrud) {\n this.registerCrudEndpoints(bp);\n }\n this.registerDataActionEndpoints(bp);\n if (this.config.api.enableBatch) {\n this.registerBatchEndpoints(bp);\n }\n };\n\n if (enableProjectScoping) {\n const scopedBase = this.getScopedBasePath(basePath);\n if (projectResolution === 'required') {\n // Strict: only scoped routes\n registerForBase(scopedBase);\n } else {\n // 'optional' | 'auto' — keep both so legacy callers keep working\n registerForBase(basePath);\n registerForBase(scopedBase);\n }\n } else {\n registerForBase(basePath);\n }\n }\n \n /**\n * Register discovery endpoints\n */\n private registerDiscoveryEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n const discoveryHandler = async (req: any, res: any) => {\n try {\n const discovery = await this.protocol.getDiscovery();\n\n // Override discovery information with actual server configuration\n discovery.version = this.config.api.version;\n\n // Substitute the resolved environmentId into the advertised routes so\n // clients can consume them verbatim (e.g. /api/v1/environments/abc/data).\n const realBase = isScoped\n ? basePath.replace(':environmentId', req.params?.environmentId ?? ':environmentId')\n : basePath;\n\n if (discovery.routes) {\n // Ensure routes match the actual mounted paths\n if (this.config.api.enableCrud) {\n discovery.routes.data = `${realBase}${this.config.crud.dataPrefix}`;\n }\n\n if (this.config.api.enableMetadata) {\n discovery.routes.metadata = `${realBase}${this.config.metadata.prefix}`;\n }\n\n if (this.config.api.enableUi) {\n discovery.routes.ui = `${realBase}/ui`;\n }\n\n // MCP (Streamable HTTP) is opt-in per env — advertise it\n // only when OS_MCP_SERVER_ENABLED=true so the objectui\n // Integrations page surfaces the connect card. The /mcp\n // route is mounted bare (not project-scoped), so point at\n // the unscoped base. This `/discovery` (served by\n // @objectstack/rest) is separate from the dispatcher's\n // getDiscoveryInfo — both must advertise `mcp`.\n const mcpEnabled =\n (globalThis as any)?.process?.env?.OS_MCP_SERVER_ENABLED === 'true';\n if (mcpEnabled) {\n const unscopedBase = isScoped\n ? basePath.replace(/\\/(environments|projects)\\/:environmentId$/, '')\n : basePath;\n (discovery.routes as any).mcp = `${unscopedBase}/mcp`;\n } else {\n delete (discovery.routes as any).mcp;\n }\n\n // Align auth route with the versioned base path if present.\n // Auth is a control-plane concern, so use the unscoped base.\n if (discovery.routes.auth) {\n const unscopedBase = isScoped\n ? basePath.replace(/\\/projects\\/:environmentId$/, '')\n : basePath;\n discovery.routes.auth = `${unscopedBase}/auth`;\n }\n }\n\n // Attach scoping metadata so clients can detect dual-mode routing.\n (discovery as any).scoping = {\n enabled: this.config.api.enableProjectScoping,\n resolution: this.config.api.projectResolution,\n scoped: isScoped,\n environmentId: isScoped ? req.params?.environmentId : undefined,\n };\n\n res.json(discovery);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n };\n\n // Register at basePath (e.g. /api/v1)\n this.routeManager.register({\n method: 'GET',\n path: basePath,\n handler: discoveryHandler,\n metadata: {\n summary: 'Get API discovery information',\n tags: ['discovery'],\n },\n });\n\n // Register at basePath/discovery (e.g. /api/v1/discovery)\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/discovery`,\n handler: discoveryHandler,\n metadata: {\n summary: 'Get API discovery information',\n tags: ['discovery'],\n },\n });\n }\n\n /**\n * Register OpenAPI 3.1 spec + interactive docs viewer.\n *\n * GET <basePath>/openapi.json → enriched OpenAPI document\n * GET <basePath>/docs → Scalar-rendered HTML (CDN, no dep)\n *\n * Enrichment at request time:\n * - servers[0].url — derived from the request's Host header\n * - paths — `{object}` placeholders expanded into\n * one concrete path per registered object\n * from the protocol's discovery metadata\n *\n * The base spec is loaded lazily from @objectstack/spec/openapi.json\n * (shipped pre-generated by spec's build pipeline) so we don't pay\n * the cost of regenerating on every request, and a missing or\n * malformed file degrades to a stub instead of crashing.\n */\n private registerOpenApiEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const openApiHandler = async (req: any, res: any) => {\n try {\n const spec = await this.loadOpenApiSpec();\n if (!spec) {\n res.status?.(503);\n res.json({\n error: 'openapi_unavailable',\n message: 'OpenAPI spec is not bundled with this runtime.',\n });\n return;\n }\n\n // Clone shallowly so per-request mutations (server URL,\n // expanded paths) don't bleed into the cached base spec.\n const enriched: any = { ...spec, servers: [...(spec.servers ?? [])] };\n\n // 1) Override servers[0] with the actual request origin so\n // \"Try it\" works straight from the docs viewer.\n const host = req.headers?.host ?? req.headers?.['host'];\n const proto = (req.headers?.['x-forwarded-proto'] as string)\n || (req.protocol as string)\n || 'http';\n if (host) {\n enriched.servers = [\n { url: `${proto}://${host}`, description: 'Current server' },\n ...(spec.servers ?? []),\n ];\n }\n\n // 2) Expand `{object}` path placeholders into concrete\n // routes for every registered data object. Falls back\n // silently if discovery isn't available.\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const protocol = await this.resolveProtocol(environmentId, req);\n const items = await protocol?.getMetaItems?.({ type: 'object' }).catch(() => null) as any;\n const objects: string[] = Array.isArray(items?.items)\n ? items.items.map((i: any) => i?.name).filter(Boolean)\n : Array.isArray(items)\n ? items.map((i: any) => i?.name).filter(Boolean)\n : [];\n if (objects.length > 0 && enriched.paths) {\n const expanded: Record<string, unknown> = {};\n for (const [p, def] of Object.entries(enriched.paths)) {\n if (p.includes('{object}')) {\n // Keep the template under x-template for tooling\n // that wants the generic shape, and emit one\n // concrete copy per registered object.\n expanded[p] = { ...(def as object), 'x-template': true };\n for (const obj of objects) {\n expanded[p.replace('{object}', obj)] = def;\n }\n } else {\n expanded[p] = def;\n }\n }\n enriched.paths = expanded;\n }\n } catch {\n // Enrichment is best-effort — never fail the spec serve.\n }\n\n // Surface the runtime version so consumers don't pin to\n // the spec package's compile-time version.\n if (enriched.info) {\n enriched.info = {\n ...enriched.info,\n version: this.config.api.version || enriched.info.version,\n };\n }\n\n res.json(enriched);\n } catch (error: any) {\n logError('[REST] openapi.json error:', error);\n sendError(res, error);\n }\n };\n\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/openapi.json`,\n handler: openApiHandler,\n metadata: {\n summary: 'OpenAPI 3.1 specification (machine-readable)',\n tags: ['openapi'],\n },\n });\n\n // Scalar HTML viewer — single inline page that loads the spec from\n // the sibling /openapi.json endpoint. No build-time bundling, no\n // server-side render cost.\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/docs`,\n handler: async (req: any, res: any) => {\n // Resolve the openapi.json URL relative to the current\n // request so the docs page works for any host / scoped\n // base path (e.g. /api/v1 vs /api/v1/environments/abc).\n const reqPath: string = req.path || req.url || `${basePath}/docs`;\n // Strip the trailing /docs to get the API base.\n const apiBase = reqPath.replace(/\\/docs\\/?$/, '');\n const specUrl = `${apiBase}/openapi.json`;\n const html = `<!doctype html>\n<html>\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>ObjectStack API Docs</title>\n</head>\n<body>\n<script id=\"api-reference\" data-url=\"${specUrl}\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n</body>\n</html>`;\n if (res.setHeader) res.setHeader('content-type', 'text/html; charset=utf-8');\n if (res.send) res.send(html);\n else if (res.body) res.body = html;\n else res.json?.(html);\n },\n metadata: {\n summary: 'Interactive API docs (Scalar viewer)',\n tags: ['openapi'],\n },\n });\n }\n\n /**\n * Lazily load the OpenAPI spec JSON shipped by @objectstack/spec.\n * Cached after first read. Resilient to missing files / parse errors\n * so a degraded environment still boots.\n */\n private _openApiSpecCache: any | null | undefined = undefined;\n private async loadOpenApiSpec(): Promise<any | null> {\n if (this._openApiSpecCache !== undefined) return this._openApiSpecCache;\n try {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore — node built-in, no @types/node in this package\n const mod: any = await import('module');\n const requireFn = mod.createRequire((import.meta as any).url);\n const pkgJsonPath: string = requireFn.resolve('@objectstack/spec/package.json');\n // @ts-ignore\n const pathMod: any = await import('path');\n // @ts-ignore\n const fsMod: any = await import('fs');\n const specPath = pathMod.join(pathMod.dirname(pkgJsonPath), 'json-schema', 'openapi.json');\n const raw = await fsMod.promises.readFile(specPath, 'utf-8');\n this._openApiSpecCache = JSON.parse(raw);\n return this._openApiSpecCache;\n } catch (err: any) {\n logError('[REST] Failed to load OpenAPI spec:', err?.message ?? err);\n this._openApiSpecCache = null;\n return null;\n }\n }\n \n /**\n * Register metadata endpoints\n */\n private registerMetadataEndpoints(basePath: string): void {\n const { metadata } = this.config;\n const metaPath = `${basePath}${metadata.prefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n // GET /meta - List all metadata types\n if (metadata.endpoints.types !== false) {\n this.routeManager.register({\n method: 'GET',\n path: metaPath,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const types = await p.getMetaTypes();\n const translated = await this.translateMetaTypesResponse(req, environmentId, types);\n res.header('Vary', 'Accept-Language');\n res.json(translated);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List all metadata types',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/diagnostics - Cross-type spec-validation sweep\n //\n // Returns every metadata entry that fails its registered Zod\n // schema, scoped to the environment (and optionally org /\n // package) of the request. Powers the Studio governance\n // dashboard and `os doctor`-style CLI checks.\n //\n // Registered BEFORE `/meta/:type` so the `diagnostics` segment\n // is not captured as a `:type` parameter.\n if (metadata.endpoints.items !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/diagnostics`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).getMetaDiagnostics !== 'function') {\n res.status(501).json({\n error: 'not_implemented',\n message: 'protocol.getMetaDiagnostics() is not available in this kernel',\n });\n return;\n }\n const severityParam = (req.query?.severity as string | undefined) ?? 'error';\n const severity = severityParam === 'warning' ? 'warning' : 'error';\n const result = await (p as any).getMetaDiagnostics({\n type: (req.query?.type as string | undefined) || undefined,\n severity,\n packageId: (req.query?.package as string | undefined) || undefined,\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List metadata entries that fail spec validation',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/_drafts - Pending DRAFT items (ADR-0033)\n //\n // Surfaces draft-state metadata that the active-only `/meta/:type`\n // list hides, so the console can show a \"pending changes\" view and\n // draft-aware package contents (a just-built app package no longer\n // looks empty). Optionally narrowed by `?packageId=` and/or `?type=`.\n //\n // Registered BEFORE `/meta/:type` so the `_drafts` segment is not\n // captured as a `:type` parameter.\n if (metadata.endpoints.items !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/_drafts`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).listDrafts !== 'function') {\n res.status(501).json({\n error: 'not_implemented',\n message: 'protocol.listDrafts() is not available in this kernel',\n });\n return;\n }\n const result = await (p as any).listDrafts({\n packageId: (req.query?.packageId as string | undefined) || undefined,\n type: (req.query?.type as string | undefined) || undefined,\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List pending draft metadata items',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/:type - List items of a type\n if (metadata.endpoints.items !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type`,\n handler: async (req: any, res: any) => {\n try {\n const packageId = req.query?.package || undefined;\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n // ADR-0033/0037 draft-overlay preview: `?preview=draft`\n // overlays pending drafts on the active list, exactly as\n // the runtime dispatcher's /metadata/:type route does —\n // the console's draft preview (Live Canvas) reads THIS\n // route, so dropping the flag here silently renders the\n // published-only world.\n const previewDrafts = typeof req.query?.preview === 'string'\n && req.query.preview.toLowerCase() === 'draft';\n const items = await p.getMetaItems({\n type: req.params.type,\n packageId,\n ...(previewDrafts ? { previewDrafts: true } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any);\n\n // RBAC-filter app metadata for authenticated users so\n // privileged apps (Studio, Setup, etc.) and gated nav\n // items are stripped before reaching the client. We\n // intentionally leave anonymous responses untouched —\n // the existing `requireAuth` gate (when enabled) blocks\n // them upstream; when disabled, the demo / public\n // surface keeps its prior behaviour.\n //\n // `getMetaItems` is typed as `{type, items[]}` but the\n // objectql implementation actually returns the raw\n // array. Handle both shapes defensively.\n let visible: any = items;\n if (req.params.type === 'app') {\n const raw = items as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (ctx?.userId) {\n const sysPerms = new Set<string>(\n Array.isArray(ctx.systemPermissions) ? ctx.systemPermissions : [],\n );\n const filtered = list\n .map((it: any) => this.filterAppForUser(it, sysPerms))\n .filter((it: any) => it != null);\n visible = Array.isArray(raw)\n ? filtered\n : { ...(raw as any), items: filtered };\n }\n }\n }\n\n // View switcher query: GET /meta/view?object=<object>\n // returns ONLY the independent ViewItems bound to that\n // object (the `package` layer of \"Object has-many\n // View\"), sorted for the switcher / left rail. The\n // aggregated container and other objects' views are\n // excluded. Runtime `shared` / `personal` views\n // (sys_view_definition) are merged client-side via the\n // generic data API.\n if (req.params.type === 'view' && req.query?.object) {\n const obj = String(req.query.object);\n const raw = visible as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const filtered = list\n .filter((v: any) => v && typeof v === 'object' && v.viewKind && v.object === obj)\n .sort((a: any, b: any) =>\n ((a.order ?? 0) as number) - ((b.order ?? 0) as number) ||\n String(a.name).localeCompare(String(b.name)));\n visible = Array.isArray(raw) ? filtered : { ...(raw as any), items: filtered };\n }\n }\n\n // ADR-0046 i18n: collapse each doc to the request\n // locale (localized label/description, `translations`\n // map dropped) before the content-strip step below.\n if (req.params.type === 'doc') {\n const locale = this.extractLocale(req);\n const { resolveDocLocale } = await import('@objectstack/spec/system');\n const raw = visible as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const localized = list.map((it: any) =>\n it && typeof it === 'object' ? resolveDocLocale(it as any, locale) : it);\n visible = Array.isArray(raw) ? localized : { ...(raw as any), items: localized };\n }\n }\n\n // ADR-0046: `doc` list responses omit `content` by\n // default — manuals are the one metadata payload that\n // grows unbounded, and the list surface only needs\n // name + label. `?include=content` opts back in; the\n // single-item GET /meta/doc/:name always returns the\n // full body.\n if (req.params.type === 'doc' && req.query?.include !== 'content') {\n const raw = visible as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const slim = list.map((it: any) => {\n if (!it || typeof it !== 'object') return it;\n const { content: _content, ...rest } = it;\n return rest;\n });\n visible = Array.isArray(raw) ? slim : { ...(raw as any), items: slim };\n }\n }\n\n const translated = await this.translateMetaItems(req, req.params.type, environmentId, visible);\n res.header('Vary', 'Accept-Language');\n res.json(translated);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List metadata items of a type',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/:type/:name - Get specific item\n if (metadata.endpoints.item !== false) {\n // Phase 3a-references: /meta/:type/:name/references must be\n // registered BEFORE /meta/:type/:name so the more-specific\n // path wins under any first-match router strategy.\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/references`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).findReferencesToMeta !== 'function') {\n res.json({ references: [] });\n return;\n }\n const result = await (p as any).findReferencesToMeta({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List metadata items that reference this item',\n tags: ['metadata'],\n },\n });\n\n // ADR-0046 §6 — GET /meta/book/:name/tree\n // Resolve a book spine against the docs that exist *now* into a\n // rendered tree (membership is DERIVED, never stored — §6.2.1). An\n // unknown name is treated as a package id and resolved against the\n // implicit per-package book (§6.4). Anonymous requests only see a\n // book whose `audience` is `public` (§6.7 read-layer gating).\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/book/:name/tree`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const prot = await this.resolveProtocol(environmentId, req);\n const locale = this.extractLocale(req);\n const packageId = req.query?.package || undefined;\n const { resolveBookTree, deriveImplicitPackageBook, isPublicAudience, resolveDocLocale } =\n await import('@objectstack/spec/system');\n\n const norm = (raw: any): any[] =>\n Array.isArray(raw) ? raw : (raw && Array.isArray(raw.items) ? raw.items : []);\n\n const books = norm(await prot.getMetaItems({\n type: 'book',\n ...(packageId ? { packageId } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any));\n let book = books.find((b: any) => b && b.name === req.params.name);\n if (!book) {\n // Unknown name → the implicit per-package book (§6.4).\n book = deriveImplicitPackageBook(req.params.name, req.params.name);\n }\n\n // §6.7 — anonymous callers only get `public` books.\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (!ctx?.userId && !isPublicAudience((book as any).audience)) {\n sendError(res, { code: 'unauthorized', message: 'This documentation requires sign-in', status: 401 });\n return;\n }\n\n const docs = norm(await prot.getMetaItems({\n type: 'doc',\n ...(packageId ? { packageId } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any))\n .map((d: any) => (d && typeof d === 'object' ? resolveDocLocale(d, locale) : d))\n .map((d: any) => ({\n name: d.name,\n label: d.label,\n description: d.description,\n order: d.order,\n group: d.group,\n tags: d.tags,\n packageId: d._packageId,\n }));\n\n const tree = resolveBookTree(book as any, docs, (book as any)._packageId);\n res.json(tree);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Resolve a documentation book spine into its rendered tree (ADR-0046 §6)',\n tags: ['metadata'],\n },\n });\n\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n\n // Phase 3a-layered-get: opt-in 3-state view when client\n // asks for `?layers=true` (or any non-empty value).\n // Skips the cache path entirely — layered view is a\n // diagnostic endpoint, not on the hot read path.\n const wantLayered = req.query?.layers !== undefined && req.query?.layers !== '';\n if (wantLayered && typeof (p as any).getMetaItemLayered === 'function') {\n // ADR-0048 — thread `?package=` so the layered (Studio\n // editor) view is package-scoped; the editor passes the\n // edited item's owning package, not the studio app's.\n const layeredPackageId = req.query?.package || undefined;\n const layered = await (p as any).getMetaItemLayered({\n type: req.params.type,\n name: req.params.name,\n ...(layeredPackageId ? { packageId: layeredPackageId } : {}),\n ...(environmentId ? { environmentId } : {}),\n });\n res.json(layered);\n return;\n }\n\n // Check if cached version is available.\n // For `app` metadata we skip the cache path so the\n // per-user RBAC filter below can apply without\n // corrupting shared ETags across admin vs member\n // viewers of the same app schema. Drafts also\n // bypass cache: the cache is keyed on the\n // published checksum and drafts are out-of-band.\n const isAppType = req.params.type === 'app';\n const isDraftRead = typeof req.query?.state === 'string'\n && req.query.state.toLowerCase() === 'draft';\n // ADR-0033/0037 — `?preview=draft` overlays a pending\n // draft on the active item (draft wins, falls back to\n // active). Must also bypass the cache: ETags are keyed\n // on the published checksum, so a cached 304 would pin\n // the preview to the stale published world.\n const previewDrafts = typeof req.query?.preview === 'string'\n && req.query.preview.toLowerCase() === 'draft';\n // ADR-0048 — a `?package=` read is package-scoped\n // (prefer-local). The cached path keys ETags on\n // type+name only and does NOT thread `packageId` into\n // `getMetaItemCached`, so two installed packages shipping\n // the same type/name would share one cache entry and the\n // scope hint would be silently dropped. Bypass the cache\n // when a package scope is requested so the disambiguating\n // `getMetaItem(type, name, packageId)` path runs.\n const packageScoped = typeof req.query?.package === 'string'\n && req.query.package.length > 0;\n if (metadata.enableCache && p.getMetaItemCached && !isAppType && !isDraftRead && !previewDrafts && !packageScoped && req.params.type !== 'doc') {\n const cacheRequest = {\n ifNoneMatch: req.headers['if-none-match'] as string,\n ifModifiedSince: req.headers['if-modified-since'] as string,\n };\n\n // Resolve the response locale up-front and fold it\n // into the cache key. The body is translated below\n // (`translateMetaItem`) *after* this validator runs,\n // so without a locale-aware ETag a language switch\n // would return a stale-locale 304 (issue #1319).\n const cacheI18n = await this.resolveI18nService(environmentId, req);\n const cacheLocale = this.extractLocale(req, cacheI18n);\n\n const result = await p.getMetaItemCached({\n type: req.params.type,\n name: req.params.name,\n cacheRequest,\n ...(cacheLocale ? { locale: cacheLocale } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any);\n\n if (result.notModified) {\n res.status(304).send();\n return;\n }\n\n // Set cache headers\n if (result.etag) {\n const etagValue = result.etag.weak\n ? `W/\"${result.etag.value}\"`\n : `\"${result.etag.value}\"`;\n res.header('ETag', etagValue);\n }\n if (result.lastModified) {\n res.header('Last-Modified', new Date(result.lastModified).toUTCString());\n }\n if (result.cacheControl) {\n const directives = result.cacheControl.directives.join(', ');\n const maxAge = result.cacheControl.maxAge\n ? `, max-age=${result.cacheControl.maxAge}`\n : '';\n res.header('Cache-Control', directives + maxAge);\n }\n\n res.header('Vary', 'Accept-Language');\n res.json(await this.translateMetaItem(req, req.params.type, environmentId, result.data, cacheI18n));\n } else {\n // Non-cached version\n const packageId = req.query?.package || undefined;\n const stateParam = typeof req.query?.state === 'string'\n ? req.query.state.toLowerCase()\n : undefined;\n const item = await p.getMetaItem({\n type: req.params.type,\n name: req.params.name,\n packageId,\n ...(stateParam === 'draft' ? { state: 'draft' } : {}),\n ...(previewDrafts ? { previewDrafts: true } : {}),\n } as any);\n\n // Same per-user RBAC filtering as the list endpoint:\n // for `app` items, drop entirely (404) when the user\n // lacks the app's `requiredPermissions`, and strip\n // forbidden nav entries from the returned schema.\n let visible: any = item;\n if (isAppType && item) {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (ctx?.userId) {\n const sysPerms = new Set<string>(\n Array.isArray(ctx.systemPermissions) ? ctx.systemPermissions : [],\n );\n visible = this.filterAppForUser(item, sysPerms);\n if (visible == null) {\n res.status(404).json({\n error: 'not_found',\n message: 'Metadata item not found or access denied.',\n });\n return;\n }\n }\n }\n\n // ADR-0046 i18n: collapse the doc to the request\n // locale (label/description/content) and drop the\n // `translations` map so consumers get one body.\n if (req.params.type === 'doc' && visible) {\n const locale = this.extractLocale(req);\n const { resolveDocLocale } = await import('@objectstack/spec/system');\n visible = isMetaEnvelope(visible)\n ? { ...visible, item: resolveDocLocale(visible.item as any, locale) }\n : resolveDocLocale(visible as any, locale);\n }\n\n res.header('Vary', 'Accept-Language');\n res.json(await this.translateMetaItem(req, req.params.type, environmentId, visible));\n }\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Get specific metadata item',\n tags: ['metadata'],\n },\n });\n }\n\n // PUT /meta/:type/:name - Save metadata item\n // We always register this route, but return 501 if protocol doesn't support it\n // This makes it discoverable even if not implemented\n this.routeManager.register({\n method: 'PUT',\n path: `${metaPath}/:type/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!p.saveMetaItem) {\n res.status(501).json({ error: 'Save operation not supported by protocol implementation' });\n return;\n }\n\n // Accept both `{ ...itemFields }` (bare) and `{ metadata: {...} }`\n // / `{ item: {...} }` envelope shapes. Studio and direct API\n // callers historically use either; ADR-0005 settles on\n // unwrapping to a single payload before persistence.\n const body = req.body ?? {};\n const item = (body && typeof body === 'object' && 'metadata' in body)\n ? (body as any).metadata\n : (body && typeof body === 'object' && 'item' in body)\n ? (body as any).item\n : body;\n\n // Opt-in OCC under ADR-0008 PR-10d.3: callers (Studio,\n // CLI) may set `If-Match: <sha256:...>` to enforce that\n // the overlay row has not advanced since they last read\n // it. A `null`/empty body or no header preserves the\n // legacy last-write-wins behaviour.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const parentVersion = typeof ifMatchHeader === 'string'\n ? ifMatchHeader.replace(/^\"|\"$/g, '') // strip ETag-style quotes\n : undefined;\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n // Phase 3a-destructive: `?force=true` opts past the\n // destructive-change safety check. Accept any truthy\n // string ('true', '1', 'yes') for resilience.\n const forceRaw = req.query?.force;\n const force = typeof forceRaw === 'string'\n ? ['true', '1', 'yes', 'on'].includes(forceRaw.toLowerCase())\n : !!forceRaw;\n\n // Software-package binding (Studio package authoring).\n // `?package=<id>` binds the saved row to that package\n // (sys_metadata.package_id). 'all'/empty = env-local overlay.\n const packageRaw = req.query?.package;\n const packageId = typeof packageRaw === 'string' && packageRaw && packageRaw !== 'all'\n ? packageRaw\n : undefined;\n\n const result = await p.saveMetaItem({\n type: req.params.type,\n name: req.params.name,\n item,\n ...(environmentId ? { environmentId } : {}),\n ...(parentVersion !== undefined ? { parentVersion } : {}),\n ...(actor ? { actor } : {}),\n ...(force ? { force: true } : {}),\n ...(packageId ? { packageId } : {}),\n ...((typeof req.query?.mode === 'string'\n && req.query.mode.toLowerCase() === 'draft')\n ? { mode: 'draft' } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Save specific metadata item',\n tags: ['metadata'],\n },\n });\n\n // DELETE /meta/:type/:name - Reset metadata item to artifact default\n // Removes a customization overlay row from sys_metadata (ADR-0005).\n // Returns 200 even when no overlay existed (idempotent reset).\n this.routeManager.register({\n method: 'DELETE',\n path: `${metaPath}/:type/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).deleteMetaItem) {\n res.status(501).json({\n error: 'Reset operation not supported by protocol implementation',\n });\n return;\n }\n // Mirror saveMetaItem's OCC + actor plumbing (ADR-0008\n // PR-10d wiring): `If-Match` pins the expected current\n // version so concurrent edits get a 409 instead of a\n // silent reset; `X-Actor` (or req.user) flows into the\n // history tombstone row.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const parentVersion = typeof ifMatchHeader === 'string'\n ? ifMatchHeader.replace(/^\"|\"$/g, '')\n : undefined;\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n\n const stateParam = typeof req.query?.state === 'string'\n && req.query.state.toLowerCase() === 'draft'\n ? 'draft' as const\n : undefined;\n\n // `?dropStorage=true` also tears down the object's physical\n // table (object + active only). Used by the \"discard a\n // previewed object\" flow so a publish-to-preview leaves no\n // orphan table. Destructive — opt-in, defaults off.\n const dropStorage = req.query?.dropStorage === 'true' || req.query?.dropStorage === '1';\n\n const result = await (p as any).deleteMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(parentVersion !== undefined ? { parentVersion } : {}),\n ...(actor ? { actor } : {}),\n ...(stateParam ? { state: stateParam } : {}),\n ...(dropStorage ? { dropStorage: true } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Reset metadata item to artifact default (deletes customization overlay)',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:name/history — durable change-log for one item.\n // Returns the sys_metadata_history events that the Studio \"History\"\n // tab renders as an audit timeline. Overlay-only metadata types\n // (view/dashboard/report/email_template) return real events;\n // non-overlay types return `{ events: [] }` (the legacy raw-engine\n // path does not record history).\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/history`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).historyMetaItem) {\n res.status(501).json({\n error: 'History query not supported by protocol implementation',\n });\n return;\n }\n const sinceSeq = req.query?.sinceSeq !== undefined\n ? Number(req.query.sinceSeq)\n : undefined;\n const limit = req.query?.limit !== undefined\n ? Number(req.query.limit)\n : undefined;\n const result = await (p as any).historyMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(sinceSeq !== undefined && Number.isFinite(sinceSeq) ? { sinceSeq } : {}),\n ...(limit !== undefined && Number.isFinite(limit) ? { limit } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List durable history events for a metadata item',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:name/audit — ADR-0010 §3.6 / Phase 4.1.\n // Compliance trail for the metadata-protection layer: returns\n // recent sys_metadata_audit rows (save/publish/rollback/delete/\n // reset attempts, both allowed and denied) so Studio's \"审计\n // 日志 / Audit log\" tab can show who tried what and whether\n // a lock blocked it. Empty array on environments where the\n // table is not yet provisioned.\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/audit`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).auditMetaItem !== 'function') {\n res.json({ events: [] });\n return;\n }\n const limit = req.query?.limit !== undefined\n ? Number(req.query.limit)\n : undefined;\n const result = await (p as any).auditMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(limit !== undefined && Number.isFinite(limit) ? { limit } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List protection-audit events for a metadata item',\n tags: ['metadata'],\n },\n });\n\n // POST /meta/:type/:name/publish — promote the pending draft\n // overlay to live. 404 [no_draft] when nothing to publish.\n this.routeManager.register({\n method: 'POST',\n path: `${metaPath}/:type/:name/publish`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).publishMetaItem) {\n res.status(501).json({\n error: 'Publish operation not supported by protocol implementation',\n });\n return;\n }\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n const body = (req.body && typeof req.body === 'object') ? req.body : {};\n const message = typeof body.message === 'string' ? body.message : undefined;\n const result = await (p as any).publishMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(actor ? { actor } : {}),\n ...(message ? { message } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Publish the pending draft overlay (promotes draft → active)',\n tags: ['metadata'],\n },\n });\n\n // POST /meta/:type/:name/rollback — restore a historical version\n // as the new live overlay. Body: { toVersion: <number>, message? }.\n this.routeManager.register({\n method: 'POST',\n path: `${metaPath}/:type/:name/rollback`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).rollbackMetaItem) {\n res.status(501).json({\n error: 'Rollback operation not supported by protocol implementation',\n });\n return;\n }\n const body = (req.body && typeof req.body === 'object') ? req.body : {};\n const toVersionRaw = body.toVersion ?? body.version ?? req.query?.toVersion;\n const toVersion = Number(toVersionRaw);\n if (!Number.isFinite(toVersion) || toVersion < 1) {\n res.status(400).json({\n error: `'toVersion' (positive integer) is required`,\n code: 'invalid_request',\n });\n return;\n }\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n const message = typeof body.message === 'string' ? body.message : undefined;\n const result = await (p as any).rollbackMetaItem({\n type: req.params.type,\n name: req.params.name,\n toVersion,\n ...(environmentId ? { environmentId } : {}),\n ...(actor ? { actor } : {}),\n ...(message ? { message } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Restore the body at the given history version as the new live row',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:name/diff?from=N&to=M — structural diff\n // between two historical versions (or one version vs current).\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/diff`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).diffMetaItem) {\n res.status(501).json({\n error: 'Diff operation not supported by protocol implementation',\n });\n return;\n }\n const parseV = (raw: any): number | undefined => {\n if (raw === undefined || raw === null || raw === '') return undefined;\n const n = Number(raw);\n return Number.isFinite(n) ? n : undefined;\n };\n const fromVersion = parseV(req.query?.from ?? req.query?.fromVersion);\n const toVersion = parseV(req.query?.to ?? req.query?.toVersion);\n const result = await (p as any).diffMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(fromVersion !== undefined ? { fromVersion } : {}),\n ...(toVersion !== undefined ? { toVersion } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Diff two metadata versions (from/to query params; omit for previous-vs-current)',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:section/:name - Get specific item with compound name\n // Compound names express sub-resources of a type (e.g. a view of an\n // object, a flow under an automation). The protocol layer treats\n // `<section>/<name>` as a single opaque key.\n if (metadata.endpoints.item !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:section/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const compoundName = `${req.params.section}/${req.params.name}`;\n const packageId = req.query?.package || undefined;\n const item = await p.getMetaItem({\n type: req.params.type,\n name: compoundName,\n packageId,\n } as any);\n res.header('Vary', 'Accept-Language');\n res.json(await this.translateMetaItem(req, req.params.type, environmentId, item));\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Get specific metadata item by compound name',\n tags: ['metadata'],\n },\n });\n }\n\n // PUT /meta/:type/:section/:name - Save metadata item with compound name\n this.routeManager.register({\n method: 'PUT',\n path: `${metaPath}/:type/:section/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!p.saveMetaItem) {\n res.status(501).json({ error: 'Save operation not supported by protocol implementation' });\n return;\n }\n\n const compoundName = `${req.params.section}/${req.params.name}`;\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const parentVersion = typeof ifMatchHeader === 'string'\n ? ifMatchHeader.replace(/^\"|\"$/g, '')\n : undefined;\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n\n const packageRaw = req.query?.package;\n const packageId = typeof packageRaw === 'string' && packageRaw && packageRaw !== 'all'\n ? packageRaw\n : undefined;\n\n const result = await p.saveMetaItem({\n type: req.params.type,\n name: compoundName,\n item: req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(parentVersion !== undefined ? { parentVersion } : {}),\n ...(actor ? { actor } : {}),\n ...(packageId ? { packageId } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Save specific metadata item by compound name',\n tags: ['metadata'],\n },\n });\n }\n\n /**\n * Register UI endpoints\n */\n private registerUiEndpoints(basePath: string): void {\n const uiPath = `${basePath}/ui`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n // GET /ui/view/:object/:type - Resolve view for object\n this.routeManager.register({\n method: 'GET',\n path: `${uiPath}/view/:object/:type`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (p.getUiView) {\n const view = await p.getUiView({\n object: req.params.object,\n type: req.params.type as any,\n ...(environmentId ? { environmentId } : {}),\n } as any);\n res.json(view);\n } else {\n res.status(501).json({ error: 'UI View resolution not supported by protocol implementation' });\n }\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Resolve UI View for object',\n tags: ['ui'],\n },\n });\n }\n \n /**\n * Register CRUD endpoints for data operations\n */\n private registerCrudEndpoints(basePath: string): void {\n const { crud } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const operations = crud.operations;\n\n // GET /data/:object - List/query records\n if (operations.list) {\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'list')) return;\n const result = await p.findData({\n object: req.params.object,\n query: req.query,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (mapped.status === 404 || mapped.status === 503 || mapped.status === 502) {\n res.status(mapped.status).json(mapped.body);\n } else {\n logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n }\n },\n metadata: {\n summary: 'Query records',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // GET /data/:object/:id - Get single record\n if (operations.read) {\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const { select, expand } = req.query || {};\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'get')) return;\n const result = await p.getData({\n object: req.params.object,\n id: req.params.id,\n ...(select != null ? { select } : {}),\n ...(expand != null ? { expand } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status === 400 ? 404 : mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Get record by ID',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // POST /data/:object - Create record\n if (operations.create) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'create')) return;\n const result = await p.createData({\n object: req.params.object,\n data: req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.status(201).json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Create record',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // POST /data/:object/query — Spec-shape advanced query (QueryAST in body).\n // Supports server-side aggregation via { groupBy, aggregations, where, ... }\n // per spec/data/query.zod.ts. Mirrors what `client.data.query()` posts.\n // Returns FindDataResponse = { object, records, total? }.\n if (operations.list) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/query`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'list')) return;\n const result = await p.findData({\n object: req.params.object,\n query: req.body || {},\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status)) logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Advanced query (QueryAST in body)',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // PATCH /data/:object/:id - Update record\n if (operations.update) {\n this.routeManager.register({\n method: 'PATCH',\n path: `${dataPath}/:object/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n // OCC: clients opt in by sending either the standard\n // `If-Match` header or an `expectedVersion` field in\n // the JSON body. Body wins when both are present\n // (lets callers override per-request without\n // touching headers). See ConcurrentUpdateError in\n // packages/objectql/src/protocol.ts.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const bodyVersion = (req.body && typeof req.body === 'object')\n ? (req.body as any).expectedVersion\n : undefined;\n const expectedVersion = bodyVersion ?? ifMatchHeader;\n // Strip the meta field out of the data payload so it\n // doesn't get written as a column.\n let data = req.body;\n if (data && typeof data === 'object' && 'expectedVersion' in (data as any)) {\n const { expectedVersion: _drop, ...rest } = data as any;\n data = rest;\n }\n if (await this.enforceApiAccess(req, res, p, environmentId, 'update')) return;\n const result = await p.updateData({\n object: req.params.object,\n id: req.params.id,\n data,\n ...(expectedVersion ? { expectedVersion: String(expectedVersion) } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Update record',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // DELETE /data/:object/:id - Delete record\n if (operations.delete) {\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/:object/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n // OCC: same opt-in protocol as PATCH (`If-Match`\n // header or `expectedVersion` query string). DELETE\n // has no JSON body, so we only accept the header\n // and a query parameter.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const queryVersion = (req.query && typeof req.query === 'object')\n ? (req.query as any).expectedVersion\n : undefined;\n const expectedVersion = queryVersion ?? ifMatchHeader;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'delete')) return;\n const result = await p.deleteData({\n object: req.params.object,\n id: req.params.id,\n ...(expectedVersion ? { expectedVersion: String(expectedVersion) } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Delete record',\n tags: ['data', 'crud'],\n },\n });\n }\n }\n \n /**\n * Register object-specific action endpoints that don't fit the\n * generic CRUD shape — domain operations where the protocol does its\n * own orchestration and we just need a thin HTTP route.\n *\n * POST {basePath}/data/:object/:id/clone — record clone (gated by\n * `enable.clone`). This is object-agnostic by design: it works for any\n * authored object regardless of namespace, unlike a hardcoded\n * per-object route would.\n */\n private registerDataActionEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n const { crud } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n\n // POST /data/:object/:id/clone — duplicate a record (gated by the\n // object's `enable.clone` capability, default on). Optional JSON body\n // `{ overrides?: {...} }` (or a bare field map) is applied on top of\n // the copied values, e.g. to set a new name or clear a unique field.\n // Distinct path segment (`/clone`) keeps it clear of the greedy\n // `/data/:object/:id` matchers.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/:id/clone`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'create')) return;\n const cloneData = (p as any).cloneData;\n if (typeof cloneData !== 'function') {\n res.status(501).json({ code: 'NOT_IMPLEMENTED', error: 'Clone not supported by this protocol' });\n return;\n }\n const body = req.body ?? {};\n // Accept both `{ overrides: {...} }` and a bare field map so\n // callers can POST overrides directly without nesting.\n const overrides = (body && typeof body === 'object' && 'overrides' in body)\n ? body.overrides\n : body;\n const result = await cloneData.call(p, {\n object: req.params.object,\n id: req.params.id,\n ...(overrides && typeof overrides === 'object' ? { overrides } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n res.status(201).json(result);\n } catch (error: any) {\n // Clone's domain errors (CLONE_DISABLED/RECORD_NOT_FOUND)\n // carry an explicit `.status`; fall back to mapDataError for\n // driver/validation faults. Only log genuine server faults.\n const status = typeof error?.status === 'number'\n ? error.status\n : mapDataError(error, req.params?.object).status;\n if (!isExpectedDataStatus(status) && error?.code !== 'VALIDATION_FAILED') logError('[REST] Unhandled error:', error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Clone a record (gated by enable.clone)',\n tags: ['data', 'clone'],\n },\n });\n\n // POST /data/:object/import — bulk CSV/JSON ingestion (M10.9)\n //\n // Body shapes:\n // { format: 'csv', csv: '...header,row,...', dryRun?: boolean, mapping?: {<csvCol>:<field>} }\n // { format: 'json', rows: [...], dryRun?: boolean }\n //\n // Returns per-row outcome so a UI can present an import report.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/import`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const objectName = String(req.params.object || '');\n if (!objectName) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'object is required' });\n return;\n }\n if (await this.enforceApiAccess(req, res, p, environmentId, 'import')) return;\n const body = req.body ?? {};\n const dryRun = body.dryRun === true;\n const mapping: Record<string, string> = body.mapping ?? {};\n\n // Build rows[] from either explicit JSON array or CSV text.\n let rows: Array<Record<string, any>> = [];\n if (body.format === 'json' && Array.isArray(body.rows)) {\n rows = body.rows as Array<Record<string, any>>;\n } else if ((body.format === 'csv' || typeof body.csv === 'string') && typeof body.csv === 'string') {\n rows = parseCsvToRows(body.csv, mapping);\n } else if (Array.isArray(body)) {\n // Permissive: a bare JSON array at the top level.\n rows = body as Array<Record<string, any>>;\n } else {\n res.status(400).json({\n code: 'INVALID_REQUEST',\n error: 'Provide either format:\"csv\" with csv text or format:\"json\" with rows[]',\n });\n return;\n }\n\n const max = 5000;\n if (rows.length > max) {\n res.status(413).json({\n code: 'PAYLOAD_TOO_LARGE',\n error: `Import limit is ${max} rows per request (got ${rows.length})`,\n });\n return;\n }\n\n const results: Array<{ row: number; ok: boolean; id?: string; error?: string; code?: string }> = [];\n let okCount = 0;\n let errCount = 0;\n\n for (let i = 0; i < rows.length; i++) {\n const data = rows[i];\n try {\n if (dryRun) {\n // Validate via protocol's metadata layer when available, else\n // best-effort: treat any non-empty row as syntactically OK.\n const validate = (p as any).validate;\n if (typeof validate === 'function') {\n await validate.call(p, { object: objectName, data, context });\n }\n results.push({ row: i + 1, ok: true });\n okCount++;\n } else {\n const created = await (p as any).createData({ object: objectName, data, context });\n const id = (created as any)?.id ?? (created as any)?.record?.id;\n results.push({ row: i + 1, ok: true, id });\n okCount++;\n }\n } catch (err: any) {\n errCount++;\n const code = err?.code ?? 'IMPORT_ROW_FAILED';\n const message = typeof err?.message === 'string' ? err.message.slice(0, 300) : 'Row failed';\n results.push({ row: i + 1, ok: false, error: message, code });\n }\n }\n\n res.json({\n object: objectName,\n dryRun,\n total: rows.length,\n ok: okCount,\n errors: errCount,\n results,\n });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, String(req.params?.object || ''));\n }\n },\n metadata: {\n summary: 'Bulk-import rows into an object (CSV or JSON, with optional dry-run)',\n tags: ['data', 'import'],\n },\n });\n\n // GET /data/:object/export — streaming export (M10.21 / C.21)\n //\n // Query params:\n // format=csv|json (default: csv. json emits a JSON array.)\n // fields=a,b,c (default: derive from object schema; falls back to keys of the first row)\n // filter=<json> ($filter as URL-encoded JSON, same shape as list endpoint)\n // orderby=field:desc (optional ordering, mirrors $orderby semantics)\n // limit=<n> (default 10000, hard cap 50000)\n // page=<n> (driver chunk size, default 500, max 5000)\n //\n // Streams the response so 50k-row exports do not buffer in memory.\n // Filename suggests `${object}-${YYYY-MM-DD}.${ext}` for browsers.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object/export`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const objectName = String(req.params.object || '');\n if (!objectName) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'object is required' });\n return;\n }\n if (await this.enforceApiAccess(req, res, p, environmentId, 'export')) return;\n const q = req.query ?? {};\n const format = (String(q.format ?? 'csv')).toLowerCase() === 'json' ? 'json' : 'csv';\n const HARD_CAP = 50_000;\n const MAX_CHUNK = 5_000;\n const requestedLimit = q.limit != null ? Math.max(1, Number(q.limit) || 0) : 10_000;\n const limit = Math.min(requestedLimit, HARD_CAP);\n const chunkSize = Math.min(MAX_CHUNK, Math.max(50, q.page != null ? Number(q.page) || 500 : 500));\n\n let filter: any = undefined;\n if (typeof q.filter === 'string' && q.filter.length > 0) {\n try { filter = JSON.parse(q.filter); }\n catch {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'filter must be JSON' });\n return;\n }\n } else if (q.filter && typeof q.filter === 'object') {\n filter = q.filter;\n }\n\n let orderby: any = undefined;\n if (typeof q.orderby === 'string' && q.orderby.length > 0) {\n // Accept \"field:dir,field2:dir\" shorthand or a JSON object.\n if (q.orderby.startsWith('{') || q.orderby.startsWith('[')) {\n try { orderby = JSON.parse(q.orderby); } catch { /* leave undefined */ }\n } else {\n const obj: Record<string, 'asc' | 'desc'> = {};\n for (const part of q.orderby.split(',')) {\n const [field, dir] = part.split(':').map((s: string) => s.trim());\n if (field) obj[field] = dir?.toLowerCase() === 'desc' ? 'desc' : 'asc';\n }\n if (Object.keys(obj).length > 0) orderby = obj;\n }\n }\n\n // Resolve fields: explicit param > schema fields > derived from first row.\n let fields: string[] | undefined;\n if (typeof q.fields === 'string' && q.fields.length > 0) {\n fields = q.fields.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(q.fields)) {\n fields = q.fields.filter((s: any) => typeof s === 'string' && s.length > 0);\n }\n if (!fields || fields.length === 0) {\n try {\n const schema = await (p as any).getObjectSchema?.(objectName, environmentId);\n const schemaFields = schema?.fields;\n if (Array.isArray(schemaFields)) {\n fields = schemaFields.map((f: any) => f.name).filter((n: any) => typeof n === 'string');\n }\n } catch { /* fall back to first-row derivation */ }\n }\n\n // Prepare streaming response. Set headers BEFORE first write.\n const stamp = new Date().toISOString().slice(0, 10);\n const safeObj = objectName.replace(/[^A-Za-z0-9_.-]/g, '_');\n if (format === 'csv') {\n res.header('Content-Type', 'text/csv; charset=utf-8');\n res.header('Content-Disposition', `attachment; filename=\"${safeObj}-${stamp}.csv\"`);\n } else {\n res.header('Content-Type', 'application/json; charset=utf-8');\n res.header('Content-Disposition', `attachment; filename=\"${safeObj}-${stamp}.json\"`);\n }\n res.header('X-Export-Format', format);\n res.header('X-Export-Limit', String(limit));\n res.header('Cache-Control', 'no-store');\n\n let exported = 0;\n let firstChunk = true;\n let skip = 0;\n if (format === 'json') res.write('[');\n\n while (exported < limit) {\n const take = Math.min(chunkSize, limit - exported);\n const findArgs: any = {\n object: objectName,\n query: {\n ...(filter ? { $filter: filter } : {}),\n ...(orderby ? { $orderby: orderby } : {}),\n $top: take,\n $skip: skip,\n },\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n };\n const result: any = await (p as any).findData(findArgs);\n const rows: any[] = Array.isArray(result?.data) ? result.data\n : Array.isArray(result?.rows) ? result.rows\n : Array.isArray(result) ? result : [];\n\n if (rows.length === 0) break;\n\n if (format === 'csv') {\n // Derive fields from the first row if schema lookup failed.\n if ((!fields || fields.length === 0) && firstChunk) {\n fields = Object.keys(rows[0] ?? {});\n }\n const text = rowsToCsv(fields ?? [], rows, firstChunk);\n res.write(text);\n } else {\n for (let i = 0; i < rows.length; i++) {\n const prefix = (firstChunk && i === 0) ? '' : ',';\n res.write(prefix + JSON.stringify(rows[i]));\n }\n }\n firstChunk = false;\n exported += rows.length;\n skip += rows.length;\n if (rows.length < take) break;\n }\n if (format === 'json') res.write(']');\n res.end();\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n // Best-effort error envelope; if headers already sent the\n // client receives a truncated stream which signals failure.\n try { sendError(res, error, String(req.params?.object || '')); }\n catch { try { res.end(); } catch { /* swallow */ } }\n }\n },\n metadata: {\n summary: 'Streaming export of object rows (CSV or JSON)',\n tags: ['data', 'export'],\n },\n });\n }\n\n /**\n * Register global cross-object search endpoint (M10.5).\n * GET {basePath}/search?q=acme&objects=lead,account&limit=20&perObject=5\n */\n private registerSearchEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/search`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const searchAll = (p as any).searchAll;\n if (typeof searchAll !== 'function') {\n res.status(501).json({ code: 'NOT_IMPLEMENTED', message: 'Search not supported by this protocol' });\n return;\n }\n const q = String(req.query?.q ?? req.query?.query ?? '');\n const objectsParam = req.query?.objects;\n const objects = typeof objectsParam === 'string'\n ? objectsParam.split(',').map((s: string) => s.trim()).filter(Boolean)\n : Array.isArray(objectsParam) ? objectsParam : undefined;\n const result = await searchAll.call(p, {\n q,\n objects,\n limit: req.query?.limit ? Number(req.query.limit) : undefined,\n perObject: req.query?.perObject ? Number(req.query.perObject) : undefined,\n ...(context ? { context } : {}),\n });\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== 'VALIDATION_FAILED') {\n logError('[REST] Unhandled error:', error);\n }\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Global cross-object search',\n tags: ['search'],\n },\n });\n }\n\n /**\n * Register email endpoints (M11.B1 / M10.7).\n *\n * POST {basePath}/email/send — send a transactional email via the\n * `IEmailService` provider registered by EmailServicePlugin. Returns\n * 501 when no provider is wired so deployments without email\n * configured fail cleanly.\n *\n * Request body:\n * {\n * to: \"a@b.com\" | [\"a@b.com\", { name, address }],\n * from?: ..., cc?: ..., bcc?: ..., replyTo?: ...,\n * subject: string,\n * text?: string, html?: string, // at least one required\n * attachments?: [{ filename, content, contentType?, cid? }],\n * headers?: { [name]: value },\n * relatedObject?: string, relatedId?: string,\n * }\n */\n private registerEmailEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/email/send`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n\n if (!this.emailServiceProvider) {\n res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Email service is not configured on this deployment',\n });\n return;\n }\n const emailService = await this.emailServiceProvider(environmentId).catch(() => undefined);\n if (!emailService || typeof emailService.send !== 'function') {\n res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Email service is not configured on this deployment',\n });\n return;\n }\n\n const body = req.body ?? {};\n if (!body || typeof body !== 'object') {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'JSON body required' });\n return;\n }\n // Stamp sentBy from the authenticated context when caller didn't supply one.\n const input = {\n ...body,\n ...(body.sentBy === undefined && (context as any)?.userId\n ? { sentBy: (context as any).userId }\n : {}),\n };\n\n try {\n const result = await emailService.send(input);\n if (result?.status === 'sent') {\n res.status(200).json(result);\n } else {\n // failed / queued — still surface to client with 200 so clients can branch on status.\n res.status(200).json(result);\n }\n } catch (err: any) {\n // Validation errors from normalizeMessage are surfaced as 400.\n const message = String(err?.message ?? err ?? 'send failed');\n if (message.startsWith('VALIDATION_FAILED')) {\n res.status(400).json({\n code: 'VALIDATION_FAILED',\n error: message.replace(/^VALIDATION_FAILED:\\s*/, ''),\n });\n return;\n }\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Email send unhandled error:', error);\n res.status(500).json({\n code: 'EMAIL_SEND_FAILED',\n error: String(error?.message ?? error ?? 'send failed').slice(0, 500),\n });\n }\n },\n metadata: {\n summary: 'Send a transactional email via the configured EmailService',\n tags: ['email'],\n },\n });\n }\n\n /**\n * Register public (anonymous) form endpoints.\n *\n * Public forms are opt-in: a `FormView` becomes accessible to anonymous\n * visitors only when `sharing.allowAnonymous === true` AND a\n * `sharing.publicLink` slug is configured. Two routes are registered:\n *\n * GET {basePath}/forms/:slug → resolved form spec\n * POST {basePath}/forms/:slug/submit → INSERT record (no auth required)\n *\n * Both routes bypass `enforceAuth` even when `requireAuth=true` on the\n * deployment (e.g. ObjectOS multi-tenant). Security is delegated to the\n * `guest_portal` permission set carried on the execution context — the\n * SecurityPlugin enforces INSERT-only access to the target object. If\n * the deployment hasn't registered a `guest_portal` profile, the\n * security middleware falls open with `permissions: []` (no userId),\n * matching the existing anonymous-access semantics; deployers must\n * keep `requireAuth=true` deployments paired with a `guest_portal`\n * profile (the CRM example does this) to enforce the INSERT-only\n * contract.\n *\n * The matched FormView's parent ViewSchema is found by scanning\n * `protocol.getMetaItems({ type: 'view' })`. For each entry we inspect\n * `form.sharing` and every entry in `formViews`; the first FormView\n * whose `sharing.publicLink` matches `/forms/:slug` (or just `:slug`)\n * wins. The response carries the matched form view under `form` and\n * the inferred target object, matching what the frontend's\n * `mapViewSpecToEmbeddableConfig` expects.\n */\n private registerFormEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const slugMatchesPublicLink = (publicLink: string | undefined, slug: string): boolean => {\n if (!publicLink || typeof publicLink !== 'string') return false;\n // Accept `/forms/:slug`, `forms/:slug`, or a bare slug.\n const normalized = publicLink.replace(/^\\/+/, '').replace(/^forms\\//, '');\n return normalized === slug;\n };\n\n const findPublicFormView = (views: any[], slug: string): { view: any; form: any; object: string } | null => {\n for (const view of views ?? []) {\n if (!view || typeof view !== 'object') continue;\n const candidates: Array<{ form: any; key?: string }> = [];\n // Authoring/nested shape (defineView): { form, formViews: { key: {...} } }.\n if (view.form && view.form.sharing) candidates.push({ form: view.form });\n const formViews = view.formViews;\n if (formViews && typeof formViews === 'object') {\n for (const [key, fv] of Object.entries(formViews)) {\n if (fv && typeof fv === 'object' && (fv as any).sharing) {\n candidates.push({ form: fv as any, key });\n }\n }\n }\n // Flattened registered shape (getMetaItems → one item per view:\n // { name, object, viewKind:'form', config:{ data, sections, sharing } }).\n // A form view carries its sharing under `config`; without this branch\n // public-form resolution silently fails for the standard view metadata.\n if (view.viewKind === 'form' && view.config && typeof view.config === 'object'\n && (view.config as any).sharing) {\n candidates.push({ form: view.config, key: view.name });\n }\n for (const c of candidates) {\n const sharing = c.form?.sharing;\n if (!sharing || sharing.allowAnonymous !== true) continue;\n if (!slugMatchesPublicLink(sharing.publicLink, slug)) continue;\n const objectName =\n c.form?.data?.object ??\n view?.list?.data?.object ??\n view?.form?.data?.object ??\n view?.object;\n if (!objectName) continue;\n return { view, form: c.form, object: objectName };\n }\n }\n return null;\n };\n\n const resolveFormBySlug = async (\n environmentId: string | undefined,\n req: any,\n slug: string,\n ): Promise<{ view: any; form: any; object: string } | null> => {\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).getMetaItems !== 'function') return null;\n const result: any = await (p as any).getMetaItems({\n type: 'view',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(result?.items)\n ? result.items\n : Array.isArray(result)\n ? result\n : [];\n return findPublicFormView(items, slug);\n };\n\n // GET /forms/:slug — resolve and return the public form spec\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/forms/:slug`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const slug = String(req.params?.slug ?? '').trim();\n if (!slug) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'slug is required' });\n return;\n }\n const match = await resolveFormBySlug(environmentId, req, slug);\n if (!match) {\n res.status(404).json({\n code: 'FORM_NOT_FOUND',\n error: `No public form configured at /forms/${slug}`,\n });\n return;\n }\n // Embed the target object's schema (limited to fields\n // referenced by the form) so anonymous front-ends can\n // render the form without a separate, auth-protected\n // meta lookup. The submit handler still enforces the\n // field whitelist server-side.\n let objectSchema: any = null;\n try {\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).getMetaItems === 'function') {\n const r: any = await (p as any).getMetaItems({\n type: 'object',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(r?.items) ? r.items : Array.isArray(r) ? r : [];\n const obj = items.find((o: any) => o?.name === match.object);\n if (obj && obj.fields && typeof obj.fields === 'object') {\n const allowed = new Set<string>();\n for (const sec of match.form?.sections ?? []) {\n for (const f of sec?.fields ?? []) {\n if (typeof f === 'string') allowed.add(f);\n else if (f?.field) allowed.add(f.field);\n }\n }\n const fields: Record<string, any> = {};\n for (const [name, def] of Object.entries(obj.fields)) {\n if (allowed.size === 0 || allowed.has(name)) {\n fields[name] = def;\n }\n }\n objectSchema = { name: obj.name, label: obj.label, fields };\n // Localize labels / help text / option labels so anonymous\n // clients render in the visitor's preferred language. The\n // form payload is otherwise un-translated (resolveFormBySlug\n // returns the raw view spec), so we hydrate the schema here.\n try {\n const i18n = await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n const locale = this.extractLocale(req, i18n);\n if (bundle && locale) {\n const { translateMetadataDocument } = await import('@objectstack/spec/system');\n objectSchema = translateMetadataDocument('object', objectSchema, bundle, { locale });\n }\n } catch (e: any) {\n logError('[REST] Public form schema translation failed:', e);\n }\n }\n }\n } catch (e: any) {\n logError('[REST] Public form schema load failed:', e);\n }\n // Anonymous public forms must NEVER include a lookup or\n // master-detail field unless the form designer has\n // explicitly opted-in via `publicPicker` on that field's\n // section entry (mirroring Airtable's \"Allow linking to\n // existing records\" toggle). Strip non-conforming\n // lookups defensively here so a stray spec mistake can\n // never expose unrestricted record search to the\n // internet — the related `/forms/:slug/lookup/:field`\n // endpoint also re-validates `publicPicker` server-side.\n const safeForm = (() => {\n if (!match.form || !Array.isArray(match.form.sections)) return match.form;\n const allow = (name: string, cfg: any): boolean => {\n const def = objectSchema?.fields?.[name];\n const t = def?.type;\n if (t !== 'lookup' && t !== 'master_detail') return true;\n return !!cfg?.publicPicker;\n };\n const sections = match.form.sections.map((sec: any) => {\n const fields = (sec?.fields ?? []).filter((f: any) => {\n const name = typeof f === 'string' ? f : f?.field;\n if (!name) return false;\n const cfg = typeof f === 'string' ? {} : f;\n return allow(name, cfg);\n });\n return { ...sec, fields };\n });\n return { ...match.form, sections };\n })();\n res.header('Vary', 'Accept-Language');\n res.json({\n slug,\n object: match.object,\n label: match.view?.label ?? match.form?.label,\n form: safeForm,\n objectSchema,\n });\n } catch (error: any) {\n logError('[REST] Public form resolve error:', error);\n res.status(500).json({\n code: 'FORM_RESOLVE_FAILED',\n error: String(error?.message ?? error ?? 'resolve failed').slice(0, 500),\n });\n }\n },\n metadata: {\n summary: 'Resolve a public form spec by slug (anonymous)',\n tags: ['forms', 'public'],\n },\n });\n\n // POST /forms/:slug/submit — INSERT a record on the target object\n // with the `guest_portal` permission set attached.\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/forms/:slug/submit`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const slug = String(req.params?.slug ?? '').trim();\n if (!slug) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'slug is required' });\n return;\n }\n const match = await resolveFormBySlug(environmentId, req, slug);\n if (!match) {\n res.status(404).json({\n code: 'FORM_NOT_FOUND',\n error: `No public form configured at /forms/${slug}`,\n });\n return;\n }\n\n // Only allow the fields declared on the matched FormView.\n // This prevents a public visitor from stuffing privileged\n // columns (owner_id, status, internal_notes, …) into the\n // row. Object hooks (`beforeInsert`) are still responsible\n // for stamping server-side defaults — see the CRM\n // `lead.hook.ts` / `case.hook.ts` for the canonical pattern.\n const allowedFields = new Set<string>();\n for (const section of match.form?.sections ?? []) {\n for (const f of section?.fields ?? []) {\n if (typeof f === 'string') allowedFields.add(f);\n else if (f?.field) allowedFields.add(f.field);\n }\n }\n const rawBody = (req.body && typeof req.body === 'object') ? req.body : {};\n const filteredData: Record<string, unknown> = {};\n if (allowedFields.size > 0) {\n for (const [k, v] of Object.entries(rawBody)) {\n if (allowedFields.has(k)) filteredData[k] = v;\n }\n } else {\n Object.assign(filteredData, rawBody);\n }\n\n // Anonymous execution context. Carries the `guest_portal`\n // permission set name so the SecurityPlugin resolves it\n // and enforces INSERT-only on the target object.\n // Leaving `userId` undefined keeps `ctx.user?.id` falsy\n // in object hooks (the canonical guest-detection check).\n const context: any = {\n permissions: ['guest_portal'],\n anonymous: true,\n };\n\n const p = await this.resolveProtocol(environmentId, req);\n const result = await p.createData({\n object: match.object,\n data: filteredData,\n ...(environmentId ? { environmentId } : {}),\n context,\n } as any);\n res.status(201).json(result);\n } catch (error: any) {\n const mapped = mapDataError(error);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== 'VALIDATION_FAILED') {\n logError('[REST] Public form submit error:', error);\n }\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Submit an anonymous public form',\n tags: ['forms', 'public'],\n },\n });\n\n // GET /forms/:slug/lookup/:field — scoped picker for public-form\n // lookup widgets. Mirrors Airtable's per-form linked-record search:\n // the field MUST be declared in the form spec with an explicit\n // `publicPicker` block; otherwise the request is rejected with 403.\n // Records are projected to `publicPicker.displayFields`, capped at\n // `publicPicker.maxResults` (hard ceiling 50), and pre-filtered by\n // `publicPicker.filter`. Anonymous visitors can search but cannot\n // enumerate / paginate, so a leaked endpoint cannot exfiltrate the\n // table.\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/forms/:slug/lookup/:field`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const slug = String(req.params?.slug ?? '').trim();\n const fieldName = String(req.params?.field ?? '').trim();\n if (!slug || !fieldName) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'slug and field are required' });\n return;\n }\n const match = await resolveFormBySlug(environmentId, req, slug);\n if (!match) {\n res.status(404).json({\n code: 'FORM_NOT_FOUND',\n error: `No public form configured at /forms/${slug}`,\n });\n return;\n }\n\n // Locate the field config and require an opt-in\n // `publicPicker` block. Without it the lookup is\n // considered private — return 403, not 404, so a\n // misconfigured form is loud rather than silent.\n let fieldCfg: any = null;\n for (const sec of match.form?.sections ?? []) {\n for (const f of sec?.fields ?? []) {\n const name = typeof f === 'string' ? f : f?.field;\n if (name === fieldName) {\n fieldCfg = typeof f === 'string' ? {} : f;\n break;\n }\n }\n if (fieldCfg) break;\n }\n const picker = fieldCfg?.publicPicker;\n if (!picker) {\n res.status(403).json({\n code: 'LOOKUP_NOT_PUBLIC',\n error: `Field \"${fieldName}\" is not enabled for public lookup on this form`,\n });\n return;\n }\n\n // Resolve the referenced object — prefer the explicit\n // `publicPicker.object` override, fall back to the\n // field def on the parent object.\n const p = await this.resolveProtocol(environmentId, req);\n let referenceTo: string | undefined = picker.object;\n if (!referenceTo && typeof (p as any).getMetaItems === 'function') {\n try {\n const r: any = await (p as any).getMetaItems({\n type: 'object',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(r?.items) ? r.items : Array.isArray(r) ? r : [];\n const obj = items.find((o: any) => o?.name === match.object);\n const def = obj?.fields?.[fieldName];\n referenceTo = def?.referenceTo ?? def?.target ?? def?.options?.objectName;\n } catch {/* ignore */}\n }\n if (!referenceTo) {\n res.status(500).json({\n code: 'LOOKUP_TARGET_MISSING',\n error: `Could not resolve referenced object for \"${fieldName}\"`,\n });\n return;\n }\n\n const displayFields: string[] = Array.isArray(picker.displayFields) && picker.displayFields.length > 0\n ? picker.displayFields.slice(0, 5)\n : ['name'];\n const hardCap = 50;\n const maxResults = Math.min(Math.max(1, Number(picker.maxResults) || 20), hardCap);\n const q = String(req.query?.q ?? '').trim().slice(0, 100);\n\n // Compose filters: form-defined static filter first,\n // then the search predicate over displayFields. The\n // search predicate uses `contains` on the first\n // display field so non-indexed columns still work.\n const filters: any[] = [];\n if (Array.isArray(picker.filter)) filters.push(...picker.filter);\n if (q) filters.push({ field: displayFields[0], operator: 'contains', value: q });\n\n const context: any = {\n permissions: ['guest_portal'],\n anonymous: true,\n };\n\n const result: any = await (p as any).findData({\n object: referenceTo,\n query: {\n limit: maxResults,\n offset: 0,\n filters,\n select: ['id', ...displayFields],\n sort: picker.sort ?? [{ field: displayFields[0], order: 'asc' }],\n },\n ...(environmentId ? { environmentId } : {}),\n context,\n } as any);\n\n // Project the response server-side too — never trust\n // that the driver respected `select`.\n const rows: any[] = Array.isArray(result?.data) ? result.data : Array.isArray(result?.items) ? result.items : [];\n const projected = rows.slice(0, maxResults).map((row: any) => {\n const out: any = { id: row?.id };\n for (const f of displayFields) {\n if (row && Object.prototype.hasOwnProperty.call(row, f)) out[f] = row[f];\n }\n return out;\n });\n res.json({\n data: projected,\n total: projected.length,\n truncated: rows.length >= maxResults,\n displayFields,\n });\n } catch (error: any) {\n const mapped = mapDataError(error);\n if (!isExpectedDataStatus(mapped.status)) {\n logError('[REST] Public form lookup error:', error);\n }\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Scoped lookup picker for a public form field (anonymous)',\n tags: ['forms', 'public'],\n },\n });\n }\n\n /**\n * Register record-level sharing endpoints (M11.C17).\n *\n * Surfaces `ISharingService` over HTTP so the UI can list, create\n * and revoke per-record grants without going through ObjectQL. The\n * three routes mirror the share-management drawer in Salesforce /\n * ServiceNow:\n *\n * GET {basePath}/data/:object/:id/shares\n * POST {basePath}/data/:object/:id/shares\n * DELETE {basePath}/data/:object/:id/shares/:shareId\n *\n * All three resolve via `sharingServiceProvider`; routes return 501\n * when no sharing service is configured so a deployment without the\n * `@objectstack/plugin-sharing` plugin fails cleanly.\n */\n /**\n * ADR-0021 — analytics dataset preview/query endpoint.\n *\n * POST {basePath}/analytics/dataset/query\n * body: { dataset?: <inline Dataset>, datasetName?: string, selection: DatasetSelection }\n *\n * Compiles the dataset (an inline draft for Studio preview, or a saved one\n * by name) and runs the selection through the analytics service's\n * `queryDataset`, threading the request ExecutionContext so tenant/RLS\n * scoping (ADR-0021 D-C) applies. Returns 501 when no analytics service\n * (or one without `queryDataset`) is configured, so a deployment without\n * `@objectstack/service-analytics` fails cleanly.\n */\n private registerAnalyticsEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n // Resolve the ENVIRONMENT's analytics service first — its strategy\n // bridges are bound to the env kernel's own data engine. The host\n // provider (whose 'data' is the host kernel's engine) is only a\n // fallback: serving a tenant's dataset query from the host engine\n // reads the WRONG database and silently aggregates over nothing\n // (the staging \"Total Spend: 0 on a populated table\" incident).\n const resolveService = async (environmentId?: string, req?: any) => {\n try {\n const envId = await this.resolveRequestEnvironmentId(environmentId, req);\n if (envId && envId !== 'platform' && this.kernelManager) {\n const kernel = await this.kernelManager.getOrCreate(envId);\n const svc = await kernel.getServiceAsync<any>('analytics').catch(() => undefined);\n if (svc) return svc;\n }\n } catch { /* fall back to the host service */ }\n if (!this.analyticsServiceProvider) return undefined;\n try { return await this.analyticsServiceProvider(environmentId); }\n catch { return undefined; }\n };\n\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/analytics/dataset/query`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n\n const svc = await resolveService(environmentId, req);\n if (!svc || typeof svc.queryDataset !== 'function') {\n return res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Analytics dataset query is not available on this deployment (no analytics service with queryDataset).',\n });\n }\n\n const body = req.body ?? {};\n const selection = body.selection;\n if (!selection || !Array.isArray(selection.measures) || selection.measures.length === 0) {\n return res.status(400).json({\n code: 'VALIDATION_FAILED',\n message: 'body.selection.measures must be a non-empty array of measure names.',\n });\n }\n\n // ADR-0037 P3 — draft data preview: the canvas / preview\n // pages pass the flag so (a) the dataset lookup sees\n // draft-overlaid definitions and (b) the selection runs\n // over the pending seed draft's rows when one exists.\n const previewDrafts = body.previewDrafts === true || req.query?.preview === 'draft';\n\n // Resolve the dataset definition: inline draft (Studio\n // preview) or a saved dataset by name.\n let dataset = body.dataset;\n if (!dataset && body.datasetName) {\n const p = await this.resolveProtocol(environmentId, req);\n const items = await (p as any).getMetaItems?.({ type: 'dataset', previewDrafts }).catch(() => null);\n const list = Array.isArray(items?.items) ? items.items : (Array.isArray(items) ? items : []);\n dataset = list.find((d: any) => d?.name === body.datasetName);\n if (!dataset) {\n return res.status(404).json({ code: 'NOT_FOUND', message: `Dataset \"${body.datasetName}\" not found.` });\n }\n }\n if (!dataset) {\n return res.status(400).json({ code: 'VALIDATION_FAILED', message: 'Provide body.dataset (inline) or body.datasetName.' });\n }\n\n // Validate against the spec schema so a malformed draft\n // yields a clean 400 instead of a runtime throw.\n try {\n const { DatasetSchema } = await import('@objectstack/spec/ui');\n dataset = (DatasetSchema as any).parse(dataset);\n } catch (verr: any) {\n return res.status(400).json({\n code: 'VALIDATION_FAILED',\n message: 'Invalid dataset definition.',\n detail: String(verr?.message ?? verr).slice(0, 1000),\n });\n }\n\n const result = await svc.queryDataset(\n dataset,\n selection,\n context ?? undefined,\n previewDrafts ? { previewDrafts: true } : undefined,\n );\n res.json(result);\n } catch (error: any) {\n const msg = String(error?.message ?? error ?? '');\n // Dataset-compiler D-C / unsupported-aggregate / read-scope\n // errors are client-side mistakes — surface as 400.\n if (/not declared in the dataset|not backed by a declared relationship|not supported by the v1 dataset runtime|read-scope-sql/.test(msg)) {\n return res.status(400).json({ code: 'DATASET_INVALID', message: msg.slice(0, 1000) });\n }\n logError('[REST] Analytics dataset query error:', error);\n res.status(500).json({ code: 'ANALYTICS_QUERY_FAILED', error: msg.slice(0, 500) });\n }\n },\n metadata: { summary: 'Run a semantic-layer dataset (preview/query)', tags: ['analytics'] },\n });\n }\n\n private registerSharingEndpoints(basePath: string): void {\n const { crud } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.sharingServiceProvider) return undefined;\n try { return await this.sharingServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Sharing service is not configured on this deployment',\n });\n\n // GET — list shares on a record.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object/:id/shares`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listShares(req.params.object, req.params.id, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List shares error:', error);\n res.status(500).json({ code: 'SHARES_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List per-record sharing grants', tags: ['sharing'] },\n });\n\n // POST — grant access.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/:id/shares`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n const input = {\n object: req.params.object,\n recordId: req.params.id,\n recipientType: body.recipientType ?? body.recipient_type,\n recipientId: body.recipientId ?? body.recipient_id,\n accessLevel: body.accessLevel ?? body.access_level,\n source: body.source,\n sourceId: body.sourceId ?? body.source_id,\n reason: body.reason,\n };\n try {\n const row = await svc.grant(input, context ?? {});\n res.status(201).json(row);\n } catch (err: any) {\n const msg = String(err?.message ?? err ?? '');\n if (msg.startsWith('VALIDATION_FAILED')) {\n res.status(400).json({\n code: 'VALIDATION_FAILED',\n error: msg.replace(/^VALIDATION_FAILED:\\s*/, ''),\n });\n return;\n }\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Grant share error:', error);\n res.status(500).json({ code: 'SHARE_GRANT_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Grant a per-record share to a principal', tags: ['sharing'] },\n });\n\n // DELETE — revoke a share by id.\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/:object/:id/shares/:shareId`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.revoke(req.params.shareId, context ?? {});\n res.status(204).end();\n } catch (error: any) {\n logError('[REST] Revoke share error:', error);\n res.status(500).json({ code: 'SHARE_REVOKE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Revoke a per-record share by id', tags: ['sharing'] },\n });\n }\n\n /**\n * Register sharing-rule endpoints (M10.17). Mirrors the existing\n * sharing endpoints but operates on `sys_sharing_rule` rows.\n *\n * GET {basePath}/sharing/rules?object=&activeOnly=\n * POST {basePath}/sharing/rules\n * GET {basePath}/sharing/rules/:idOrName\n * DELETE {basePath}/sharing/rules/:idOrName\n * POST {basePath}/sharing/rules/:idOrName/evaluate\n *\n * Returns 501 when no sharing-rule service is configured.\n */\n private registerSharingRuleEndpoints(basePath: string): void {\n // Sharing-rule routes live at the top of the API surface (e.g.\n // `/api/v1/sharing/rules`) — they administer rules across the whole\n // tenant rather than acting on a single CRUD object, so anchoring\n // them on `basePath` keeps them out of the `/data/:object` namespace\n // where greedy CRUD matchers would otherwise swallow them.\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.sharingRulesServiceProvider) return undefined;\n try { return await this.sharingRulesServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Sharing-rule service is not configured on this deployment',\n });\n const handleError = (err: any, res: any, defaultCode: string) => {\n const msg = String(err?.message ?? err ?? '');\n if (msg.startsWith('VALIDATION_FAILED')) {\n return res.status(400).json({ code: 'VALIDATION_FAILED', error: msg.replace(/^VALIDATION_FAILED:\\s*/, '') });\n }\n if (msg.startsWith('RULE_NOT_FOUND')) {\n return res.status(404).json({ code: 'RULE_NOT_FOUND', error: msg.replace(/^RULE_NOT_FOUND:?\\s*/, '') });\n }\n logError(`[REST] sharing-rule ${defaultCode}:`, err);\n return res.status(500).json({ code: defaultCode, error: msg.slice(0, 500) });\n };\n\n // LIST\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/sharing/rules`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listRules({\n object: req.query?.object,\n activeOnly: req.query?.activeOnly === 'true' || req.query?.activeOnly === true,\n }, context ?? {});\n res.json({ data: rows });\n } catch (err: any) { handleError(err, res, 'RULE_LIST_FAILED'); }\n },\n metadata: { summary: 'List sharing rules', tags: ['sharing'] },\n });\n\n // CREATE / UPSERT\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/sharing/rules`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n const input = {\n name: body.name,\n label: body.label,\n description: body.description,\n object: body.object ?? body.object_name,\n criteria: body.criteria,\n recipientType: body.recipientType ?? body.recipient_type,\n recipientId: body.recipientId ?? body.recipient_id,\n accessLevel: body.accessLevel ?? body.access_level,\n active: body.active,\n };\n const row = await svc.defineRule(input, context ?? {});\n res.status(201).json(row);\n } catch (err: any) { handleError(err, res, 'RULE_DEFINE_FAILED'); }\n },\n metadata: { summary: 'Create or upsert a sharing rule', tags: ['sharing'] },\n });\n\n // GET\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/sharing/rules/:idOrName`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const row = await svc.getRule(req.params.idOrName, context ?? {});\n if (!row) return res.status(404).json({ code: 'RULE_NOT_FOUND' });\n res.json(row);\n } catch (err: any) { handleError(err, res, 'RULE_GET_FAILED'); }\n },\n metadata: { summary: 'Get a sharing rule by id or name', tags: ['sharing'] },\n });\n\n // DELETE\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/sharing/rules/:idOrName`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.deleteRule(req.params.idOrName, context ?? {});\n res.status(204).end();\n } catch (err: any) { handleError(err, res, 'RULE_DELETE_FAILED'); }\n },\n metadata: { summary: 'Delete a sharing rule and its materialised grants', tags: ['sharing'] },\n });\n\n // EVALUATE\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/sharing/rules/:idOrName/evaluate`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const result = await svc.evaluateRule(req.params.idOrName, context ?? {});\n res.json(result);\n } catch (err: any) { handleError(err, res, 'RULE_EVALUATE_FAILED'); }\n },\n metadata: { summary: 'Re-evaluate a sharing rule and reconcile grants', tags: ['sharing'] },\n });\n }\n\n /**\n * Register saved-report + scheduled-digest endpoints (M11.C16).\n *\n * Surfaces `IReportService` over HTTP so the UI can build,\n * run, and schedule reports without dropping to ObjectQL. Routes\n * live at the top of the API surface (alongside `/approvals` and\n * `/sharing`) — reports are a tenant-wide capability, not a record\n * on a specific CRUD object:\n *\n * GET {basePath}/reports?object=&ownerId=\n * POST {basePath}/reports\n * GET {basePath}/reports/:id\n * DELETE {basePath}/reports/:id\n * POST {basePath}/reports/:id/run\n * POST {basePath}/reports/:id/schedule\n * GET {basePath}/reports/:id/schedules\n * DELETE {basePath}/reports/schedules/:scheduleId\n *\n * All routes return 501 when `reportsServiceProvider` is unset so\n * a deployment without `@objectstack/plugin-reports` fails cleanly.\n */\n private registerReportsEndpoints(basePath: string): void {\n // Reports live at the top of the API surface (e.g. `/api/v1/reports`)\n // rather than under `/data/`, because a report is a first-class\n // capability whose definition is tenant-wide (not a record on a\n // particular object).\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.reportsServiceProvider) return undefined;\n try { return await this.reportsServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Reports service is not configured on this deployment',\n });\n const handleValidation = (res: any, err: any): boolean => {\n const msg = String(err?.message ?? err ?? '');\n if (msg.startsWith('VALIDATION_FAILED')) {\n res.status(400).json({\n code: 'VALIDATION_FAILED',\n error: msg.replace(/^VALIDATION_FAILED:\\s*/, ''),\n });\n return true;\n }\n if (msg.startsWith('REPORT_NOT_FOUND')) {\n res.status(404).json({ code: 'REPORT_NOT_FOUND', error: msg });\n return true;\n }\n return false;\n };\n\n // GET — list reports.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/reports`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const q = req.query ?? {};\n const rows = await svc.listReports({ object: q.object, ownerId: q.ownerId }, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List reports error:', error);\n res.status(500).json({ code: 'REPORTS_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List saved reports', tags: ['reports'] },\n });\n\n // POST — save (upsert) a report.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/reports`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n try {\n const row = await svc.saveReport(req.body ?? {}, context ?? {});\n res.status(201).json(row);\n } catch (err: any) {\n if (handleValidation(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Save report error:', error);\n res.status(500).json({ code: 'REPORT_SAVE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Create or update a saved report', tags: ['reports'] },\n });\n\n // GET — single report.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/reports/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const row = await svc.getReport(req.params.id, context ?? {});\n if (!row) {\n res.status(404).json({ code: 'REPORT_NOT_FOUND', error: `Report ${req.params.id} not found` });\n return;\n }\n res.json(row);\n } catch (error: any) {\n logError('[REST] Get report error:', error);\n res.status(500).json({ code: 'REPORT_GET_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Get a saved report by id', tags: ['reports'] },\n });\n\n // DELETE — drop report + cascade schedules.\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/reports/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.deleteReport(req.params.id, context ?? {});\n res.status(204).end();\n } catch (error: any) {\n logError('[REST] Delete report error:', error);\n res.status(500).json({ code: 'REPORT_DELETE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Delete a saved report (cascades schedules)', tags: ['reports'] },\n });\n\n // POST — execute a report by id.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/reports/:id/run`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n try {\n const result = await svc.run(req.params.id, context ?? {});\n res.json(result);\n } catch (err: any) {\n if (handleValidation(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Run report error:', error);\n res.status(500).json({ code: 'REPORT_RUN_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Execute a saved report and return rendered output', tags: ['reports'] },\n });\n\n // POST — schedule a report.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/reports/:id/schedule`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n try {\n const row = await svc.scheduleReport({\n reportId: req.params.id,\n recipients: body.recipients ?? [],\n name: body.name,\n intervalMinutes: body.intervalMinutes ?? body.interval_minutes,\n cronExpression: body.cronExpression ?? body.cron_expression,\n timezone: body.timezone,\n format: body.format,\n subjectTemplate: body.subjectTemplate ?? body.subject_template,\n ownerId: body.ownerId ?? body.owner_id,\n active: body.active,\n }, context ?? {});\n res.status(201).json(row);\n } catch (err: any) {\n if (handleValidation(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Schedule report error:', error);\n res.status(500).json({ code: 'REPORT_SCHEDULE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Create a recurring email schedule for a report', tags: ['reports'] },\n });\n\n // GET — list schedules for a report.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/reports/:id/schedules`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listSchedules({ reportId: req.params.id }, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List schedules error:', error);\n res.status(500).json({ code: 'SCHEDULES_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List schedules for a report', tags: ['reports'] },\n });\n\n // DELETE — drop a schedule.\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/reports/schedules/:scheduleId`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.unscheduleReport(req.params.scheduleId, context ?? {});\n res.status(204).end();\n } catch (error: any) {\n logError('[REST] Unschedule report error:', error);\n res.status(500).json({ code: 'SCHEDULE_DELETE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Delete a report schedule by id', tags: ['reports'] },\n });\n }\n\n /**\n * Register approval endpoints (ADR-0019: approval as a flow node).\n *\n * Approval is no longer a standalone process engine — a flow's Approval\n * node opens a request and suspends the run; a decision resumes it. There\n * are no process-authoring or submit routes anymore.\n *\n * Routes (all under {basePath}/approvals):\n * GET /requests — list (filters: status, object, recordId, approverId, submitterId)\n * GET /requests/:id — get request\n * POST /requests/:id/approve — record an approve decision (resumes the flow)\n * POST /requests/:id/reject — record a reject decision (resumes the flow)\n * GET /requests/:id/actions — audit trail\n *\n * Returns 501 when `approvalsServiceProvider` is unset so deployments\n * without `@objectstack/plugin-approvals` fail cleanly.\n */\n private registerApprovalsEndpoints(basePath: string): void {\n // Approval routes live at the top of the API surface (e.g.\n // `/api/v1/approvals/requests/:id/approve`). Approvals are a\n // cross-cutting capability — a request is not a record on a single\n // CRUD object, so anchoring it on `basePath` (instead of\n // `${basePath}/data`) keeps the URL semantics honest.\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.approvalsServiceProvider) return undefined;\n try { return await this.approvalsServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Approvals service is not configured on this deployment',\n });\n const handleApprovalError = (res: any, err: any): boolean => {\n const msg = String(err?.message ?? err ?? '');\n const mapping: Array<[RegExp, number, string]> = [\n [/^VALIDATION_FAILED/, 400, 'VALIDATION_FAILED'],\n [/^DUPLICATE_REQUEST/, 409, 'DUPLICATE_REQUEST'],\n [/^INVALID_STATE/, 409, 'INVALID_STATE'],\n [/^THROTTLED/, 429, 'THROTTLED'],\n [/^FORBIDDEN/, 403, 'FORBIDDEN'],\n [/^REQUEST_NOT_FOUND/, 404, 'REQUEST_NOT_FOUND'],\n ];\n for (const [re, status, code] of mapping) {\n if (re.test(msg)) {\n res.status(status).json({ code, error: msg.replace(/^[A-Z_]+:\\s*/, '') });\n return true;\n }\n }\n return false;\n };\n\n // ── Requests ──────────────────────────────────────────────\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/approvals/requests`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) {\n // No approvals plugin loaded — return empty list rather than 501\n // so Console badge polls don't spam the error log on deployments\n // that don't run an approvals workflow.\n res.json({ data: [] });\n return;\n }\n const q = req.query ?? {};\n // `approverId` accepts a single id, a comma-separated\n // list, or the param repeated (→ array). Normalise all\n // three to a string[] so the Console can resolve \"my\n // pending approvals\" across every identity (user id /\n // email / role:<r>) in ONE request rather than looping.\n const rawApprover = q.approverId ?? q.approver_id;\n const approverIds = (Array.isArray(rawApprover) ? rawApprover : (rawApprover != null ? [rawApprover] : []))\n .flatMap((s: any) => String(s).split(','))\n .map((s: string) => s.trim())\n .filter(Boolean);\n const limit = q.limit != null ? Number(q.limit) : undefined;\n const offset = q.offset != null ? Number(q.offset) : undefined;\n const listFilter = {\n object: q.object,\n recordId: q.recordId ?? q.record_id,\n status: q.status,\n approverId: approverIds.length ? approverIds : undefined,\n submitterId: q.submitterId ?? q.submitter_id,\n q: typeof q.q === 'string' ? q.q : undefined,\n limit: Number.isFinite(limit) ? limit : undefined,\n offset: Number.isFinite(offset) ? offset : undefined,\n };\n const rows = await svc.listRequests(listFilter, context ?? {});\n // `total` only when the caller pages — counting costs a\n // second query and unpaged callers don't need it.\n if (listFilter.limit != null && typeof svc.countRequests === 'function') {\n const total = await svc.countRequests(listFilter, context ?? {});\n res.json({ data: rows, total });\n return;\n }\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List approval requests error:', error);\n res.status(500).json({ code: 'APPROVAL_REQUEST_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List approval requests', tags: ['approvals'] },\n });\n\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/approvals/requests/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const row = await svc.getRequest(req.params.id, context ?? {});\n if (!row) {\n res.status(404).json({ code: 'REQUEST_NOT_FOUND', error: `Approval request '${req.params.id}' not found` });\n return;\n }\n res.json(row);\n } catch (error: any) {\n logError('[REST] Get approval request error:', error);\n res.status(500).json({ code: 'APPROVAL_REQUEST_GET_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Get an approval request by id', tags: ['approvals'] },\n });\n\n // Record a decision on a node-driven request. Both branches funnel\n // through the contract's `decide()`, which finalizes the request and\n // resumes the owning flow run down the matching `approve` / `reject`\n // edge.\n const decisionRoute = (decision: 'approve' | 'reject') => {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/approvals/requests/:id/${decision}`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n try {\n const out = await svc.decide(req.params.id, {\n decision,\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context ?? {});\n res.json(out);\n } catch (err: any) {\n if (handleApprovalError(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError(`[REST] ${decision} approval error:`, error);\n res.status(500).json({ code: `APPROVAL_${decision.toUpperCase()}_FAILED`, error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: `${decision[0].toUpperCase()}${decision.slice(1)} an approval request`, tags: ['approvals'] },\n });\n };\n decisionRoute('approve');\n decisionRoute('reject');\n\n // Recall — submitter withdraws a pending request. Mirrors the decision\n // routes' error mapping; the service enforces submitter-only access.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/approvals/requests/:id/recall`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc || typeof svc.recall !== 'function') return respond501(res);\n const body = req.body ?? {};\n try {\n const out = await svc.recall(req.params.id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context ?? {});\n res.json(out);\n } catch (err: any) {\n if (handleApprovalError(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] recall approval error:', error);\n res.status(500).json({ code: 'APPROVAL_RECALL_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Recall (withdraw) an approval request', tags: ['approvals'] },\n });\n\n // Thread interactions — reassign / remind / request-info / comment.\n // None of these move the flow; they update approver slots or the\n // audit thread. Registered generically: the service method enforces\n // the per-action permission (slot holder / submitter / participant).\n const threadRoute = (\n action: 'reassign' | 'remind' | 'request-info' | 'comment',\n invoke: (svc: any, id: string, body: any, context: any) => Promise<unknown>,\n ) => {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/approvals/requests/:id/${action}`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n try {\n const out = await invoke(svc, req.params.id, body, context ?? {});\n res.json(out);\n } catch (err: any) {\n if (handleApprovalError(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError(`[REST] ${action} approval error:`, error);\n res.status(500).json({ code: `APPROVAL_${action.toUpperCase().replace('-', '_')}_FAILED`, error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: `${action} on an approval request`, tags: ['approvals'] },\n });\n };\n threadRoute('reassign', (svc, id, body, context) => {\n if (typeof svc.reassign !== 'function') throw new Error('VALIDATION_FAILED: reassign is not supported');\n return svc.reassign(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n to: body.to, from: body.from, comment: body.comment,\n }, context);\n });\n threadRoute('remind', (svc, id, body, context) => {\n if (typeof svc.remind !== 'function') throw new Error('VALIDATION_FAILED: remind is not supported');\n return svc.remind(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context);\n });\n threadRoute('request-info', (svc, id, body, context) => {\n if (typeof svc.requestInfo !== 'function') throw new Error('VALIDATION_FAILED: request-info is not supported');\n return svc.requestInfo(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context);\n });\n threadRoute('comment', (svc, id, body, context) => {\n if (typeof svc.comment !== 'function') throw new Error('VALIDATION_FAILED: comment is not supported');\n return svc.comment(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context);\n });\n\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/approvals/requests/:id/actions`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listActions(req.params.id, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List approval actions error:', error);\n res.status(500).json({ code: 'APPROVAL_ACTIONS_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List actions (audit trail) for an approval request', tags: ['approvals'] },\n });\n }\n\n /**\n * Register batch operation endpoints\n */\n private registerBatchEndpoints(basePath: string): void {\n const { crud, batch } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const operations = batch.operations;\n\n // POST /batch — cross-object transactional batch (issue #1604).\n // Runs heterogeneous create/update/delete across objects in ONE engine\n // transaction (commit all or roll back all). Intra-batch references:\n // a field value of `{ $ref: <earlier op index> }` resolves to that op's\n // created id, so a child can reference its parent (master-detail).\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/batch`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const ql = this.objectQLProvider ? await this.objectQLProvider(environmentId) : undefined;\n if (!ql || typeof ql.transaction !== 'function') {\n res.status(501).json({ error: 'Transactional batch not supported by this runtime' });\n return;\n }\n const ops: any[] = Array.isArray(req.body?.operations) ? req.body.operations : [];\n const max = batch.maxBatchSize ?? 200;\n if (ops.length === 0) { res.json({ results: [] }); return; }\n if (ops.length > max) { res.status(400).json({ error: `Batch too large (max ${max})` }); return; }\n\n const resolveRefs = (data: any, out: any[]): any => {\n if (!data || typeof data !== 'object') return data;\n const result: any = Array.isArray(data) ? [] : {};\n for (const [k, v] of Object.entries(data)) {\n if (v && typeof v === 'object' && '$ref' in (v as any)) {\n const ref = out[(v as any).$ref];\n result[k] = (ref && (ref.id ?? ref._id)) ?? null;\n } else {\n result[k] = v;\n }\n }\n return result;\n };\n\n const results = await ql.transaction(async (trxCtx: any) => {\n const out: any[] = [];\n for (const op of ops) {\n const action = String(op?.action || 'create');\n const object = String(op?.object || '');\n if (!object) throw new Error('Each operation requires an `object`');\n const data = resolveRefs(op.data, out);\n if (action === 'create') {\n out.push(await ql.insert(object, data, { context: trxCtx }));\n } else if (action === 'update') {\n const id = op.id ?? data?.id;\n out.push(await ql.update(object, { ...data, id }, { context: trxCtx }));\n } else if (action === 'delete') {\n out.push(await ql.delete(object, { where: { id: op.id }, context: trxCtx }));\n } else {\n throw new Error(`Unknown batch action: ${action}`);\n }\n }\n return out;\n }, context);\n\n res.json({ results });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Cross-object transactional batch (atomic create/update/delete across objects)',\n tags: ['data', 'batch'],\n },\n });\n\n // POST /data/:object/batch - Generic batch endpoint\n if (batch.enableBatchEndpoint && this.protocol.batchData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/batch`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'bulk')) return;\n const result = await p.batchData!({\n object: req.params.object,\n request: req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Batch operations',\n tags: ['data', 'batch'],\n },\n });\n }\n\n // POST /data/:object/createMany - Bulk create\n if (operations.createMany && this.protocol.createManyData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/createMany`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'create')) return;\n const result = await p.createManyData!({\n object: req.params.object,\n records: req.body || [],\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.status(201).json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Create multiple records',\n tags: ['data', 'batch'],\n },\n });\n }\n\n // POST /data/:object/updateMany - Bulk update\n if (operations.updateMany && this.protocol.updateManyData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/updateMany`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'update')) return;\n const result = await p.updateManyData!({\n object: req.params.object,\n ...req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Update multiple records',\n tags: ['data', 'batch'],\n },\n });\n }\n\n // POST /data/:object/deleteMany - Bulk delete\n if (operations.deleteMany && this.protocol.deleteManyData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/deleteMany`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'delete')) return;\n const result = await p.deleteManyData!({\n object: req.params.object,\n ...req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Delete multiple records',\n tags: ['data', 'batch'],\n },\n });\n }\n }\n\n \n /**\n * Get the route manager\n */\n getRouteManager(): RouteManager {\n return this.routeManager;\n }\n \n /**\n * Get all registered routes\n */\n getRoutes() {\n return this.routeManager.getAll();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { RouteHandler, IHttpServer } from '@objectstack/core';\nimport * as System from '@objectstack/spec/system';\nimport * as Shared from '@objectstack/spec/shared';\nimport { z } from 'zod';\n\ntype RouteHandlerMetadata = System.RouteHandlerMetadata;\ntype HttpMethod = z.infer<typeof Shared.HttpMethod>;\n\n/**\n * Route Entry\n * Internal representation of registered routes\n */\nexport interface RouteEntry {\n method: HttpMethod;\n path: string;\n handler: RouteHandler;\n metadata?: RouteHandlerMetadata['metadata'];\n security?: RouteHandlerMetadata['security'];\n}\n\n/**\n * RouteManager\n * \n * Manages route registration and organization for HTTP servers.\n * Provides:\n * - Route registration with metadata\n * - Route lookup and querying\n * - Bulk route registration\n * - Route grouping by prefix\n * \n * @example\n * const manager = new RouteManager(server);\n * \n * // Register individual route\n * manager.register({\n * method: 'GET',\n * path: '/api/users/:id',\n * handler: getUserHandler,\n * metadata: {\n * summary: 'Get user by ID',\n * tags: ['users']\n * }\n * });\n * \n * // Register route group\n * manager.group('/api/users', (group) => {\n * group.get('/', listUsersHandler);\n * group.post('/', createUserHandler);\n * group.get('/:id', getUserHandler);\n * });\n */\nexport class RouteManager {\n private server: IHttpServer;\n private routes: Map<string, RouteEntry>;\n \n constructor(server: IHttpServer) {\n this.server = server;\n this.routes = new Map();\n }\n \n /**\n * Register a route\n * @param entry - Route entry with method, path, handler, and metadata\n */\n register(entry: Omit<RouteEntry, 'handler'> & { handler: RouteHandler | string }): void {\n // Validate handler type - string handlers not yet supported\n if (typeof entry.handler === 'string') {\n throw new Error(\n `String-based route handlers are not supported yet. ` +\n `Received handler identifier \"${entry.handler}\". ` +\n `Please provide a RouteHandler function instead.`\n );\n }\n \n const handler: RouteHandler = entry.handler;\n \n const routeEntry: RouteEntry = {\n method: entry.method,\n path: entry.path,\n handler,\n metadata: entry.metadata,\n security: entry.security,\n };\n \n const key = this.getRouteKey(entry.method, entry.path);\n this.routes.set(key, routeEntry);\n \n // Register with underlying server\n this.registerWithServer(routeEntry);\n }\n \n /**\n * Register multiple routes\n * @param entries - Array of route entries\n */\n registerMany(entries: Array<Omit<RouteEntry, 'handler'> & { handler: RouteHandler | string }>): void {\n entries.forEach(entry => this.register(entry));\n }\n \n /**\n * Unregister a route\n * @param method - HTTP method\n * @param path - Route path\n */\n unregister(method: HttpMethod, path: string): void {\n const key = this.getRouteKey(method, path);\n this.routes.delete(key);\n // Note: Most server frameworks don't support unregistering routes at runtime\n // This just removes it from our registry\n }\n \n /**\n * Get route by method and path\n * @param method - HTTP method\n * @param path - Route path\n */\n get(method: HttpMethod, path: string): RouteEntry | undefined {\n const key = this.getRouteKey(method, path);\n return this.routes.get(key);\n }\n \n /**\n * Get all routes\n */\n getAll(): RouteEntry[] {\n return Array.from(this.routes.values());\n }\n \n /**\n * Get routes by method\n * @param method - HTTP method\n */\n getByMethod(method: HttpMethod): RouteEntry[] {\n return this.getAll().filter(route => route.method === method);\n }\n \n /**\n * Get routes by path prefix\n * @param prefix - Path prefix\n */\n getByPrefix(prefix: string): RouteEntry[] {\n return this.getAll().filter(route => route.path.startsWith(prefix));\n }\n \n /**\n * Get routes by tag\n * @param tag - Tag name\n */\n getByTag(tag: string): RouteEntry[] {\n return this.getAll().filter(route => \n route.metadata?.tags?.includes(tag)\n );\n }\n \n /**\n * Create a route group with common prefix\n * @param prefix - Common path prefix\n * @param configure - Function to configure routes in the group\n */\n group(prefix: string, configure: (group: RouteGroupBuilder) => void): void {\n const builder = new RouteGroupBuilder(this, prefix);\n configure(builder);\n }\n \n /**\n * Get route count\n */\n count(): number {\n return this.routes.size;\n }\n \n /**\n * Clear all routes\n */\n clear(): void {\n this.routes.clear();\n }\n \n /**\n * Get route key for storage\n */\n private getRouteKey(method: HttpMethod, path: string): string {\n return `${method}:${path}`;\n }\n \n /**\n * Register route with underlying server\n */\n private registerWithServer(entry: RouteEntry): void {\n const { method, path, handler } = entry;\n \n switch (method) {\n case 'GET':\n this.server.get(path, handler);\n break;\n case 'POST':\n this.server.post(path, handler);\n break;\n case 'PUT':\n this.server.put(path, handler);\n break;\n case 'DELETE':\n this.server.delete(path, handler);\n break;\n case 'PATCH':\n this.server.patch(path, handler);\n break;\n default:\n throw new Error(`Unsupported HTTP method: ${method}`);\n }\n }\n}\n\n/**\n * RouteGroupBuilder\n * \n * Builder for creating route groups with common prefix\n */\nexport class RouteGroupBuilder {\n private manager: RouteManager;\n private prefix: string;\n \n constructor(manager: RouteManager, prefix: string) {\n this.manager = manager;\n this.prefix = prefix;\n }\n \n /**\n * Register GET route in group\n */\n get(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'GET',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register POST route in group\n */\n post(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'POST',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register PUT route in group\n */\n put(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'PUT',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register PATCH route in group\n */\n patch(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'PATCH',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register DELETE route in group\n */\n delete(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'DELETE',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Resolve full path with prefix\n */\n private resolvePath(path: string): string {\n // Normalize slashes\n const normalizedPrefix = this.prefix.endsWith('/') \n ? this.prefix.slice(0, -1) \n : this.prefix;\n const normalizedPath = path.startsWith('/') \n ? path \n : '/' + path;\n \n return normalizedPrefix + normalizedPath;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { IHttpServer } from '@objectstack/core';\nimport type { PackageService } from '@objectstack/service-package';\n\n/**\n * Options for package route registration.\n */\nexport interface PackageRoutesOptions {\n /**\n * Protocol service (ObjectStackProtocol) — provides access to in-memory\n * SchemaRegistry packages loaded via defineStack()/AppPlugin at boot time.\n */\n protocol?: { getMetaItems?(req: { type: string }): Promise<{ items: any[] }> };\n}\n\n/**\n * Register package management API routes\n *\n * Provides endpoints for publishing, retrieving, and managing packages.\n * Routes:\n * - POST /api/v1/packages - Publish a package\n * - GET /api/v1/packages - List all packages (merges registry + database)\n * - GET /api/v1/packages/:id - Get a specific package\n * - DELETE /api/v1/packages/:id - Delete a package\n */\nexport function registerPackageRoutes(\n server: IHttpServer,\n packageService: PackageService,\n basePath: string = '/api/v1',\n options: PackageRoutesOptions = {},\n) {\n const packagesPath = `${basePath}/packages`;\n\n // POST /api/v1/packages - Publish a package\n server.post(packagesPath, async (req, res) => {\n try {\n const { manifest, metadata } = req.body || {};\n\n if (!manifest || !metadata) {\n res.status(400).json({ error: 'Missing required fields: manifest, metadata' });\n return;\n }\n\n if (!manifest.id || !manifest.version) {\n res.status(400).json({ error: 'Invalid manifest: id and version are required' });\n return;\n }\n\n const result = await packageService.publish({ manifest, metadata });\n\n if (result.success) {\n res.json({\n success: true,\n message: `Published ${manifest.id}@${manifest.version}`,\n package: {\n id: manifest.id,\n version: manifest.version,\n },\n });\n return;\n }\n\n res.status(400).json({ success: false, error: result.error });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n // GET /api/v1/packages - List all packages (merges registry + database)\n server.get(packagesPath, async (_req, res) => {\n try {\n // Merge two sources:\n // 1. Registry packages (in-memory, loaded at boot via defineStack/AppPlugin)\n // 2. Database packages (published via POST /packages)\n const packagesMap = new Map<string, any>();\n\n // Registry packages (via protocol service → SchemaRegistry)\n if (options.protocol && typeof options.protocol.getMetaItems === 'function') {\n try {\n const result = await options.protocol.getMetaItems({ type: 'package' });\n if (result?.items) {\n for (const item of result.items) {\n const id = item.manifest?.id || item.id;\n if (id) {\n packagesMap.set(id, {\n ...item,\n source: 'registry',\n });\n }\n }\n }\n } catch {\n // Protocol unavailable — continue with database only\n }\n }\n\n // Database packages (published artifacts)\n try {\n const dbPackages = await packageService.list();\n for (const pkg of dbPackages) {\n const id = pkg.manifest?.id || pkg.id;\n if (id) {\n // Database entry takes precedence (has richer metadata from publish)\n packagesMap.set(id, {\n ...packagesMap.get(id),\n ...pkg,\n source: packagesMap.has(id) ? 'both' : 'database',\n });\n }\n }\n } catch {\n // Database query failed — continue with registry-only packages\n }\n\n const packages = Array.from(packagesMap.values());\n res.json({ packages, total: packages.length });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n // GET /api/v1/packages/:id - Get a specific package\n server.get(`${packagesPath}/:id`, async (req, res) => {\n try {\n const packageId = req.params.id;\n const version = req.query?.version || 'latest';\n\n // Try database first (richer data from publish)\n const pkg = await packageService.get(packageId, version);\n if (pkg) {\n res.json({ package: { ...pkg, source: 'database' } });\n return;\n }\n\n // Fall back to registry (in-memory loaded packages)\n if (options.protocol && typeof options.protocol.getMetaItems === 'function') {\n try {\n const result = await options.protocol.getMetaItems({ type: 'package' });\n const match = result?.items?.find((item: any) =>\n (item.manifest?.id || item.id) === packageId\n );\n if (match) {\n res.json({ package: { ...match, source: 'registry' } });\n return;\n }\n } catch {\n // Protocol unavailable\n }\n }\n\n res.status(404).json({ error: 'Package not found' });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n // DELETE /api/v1/packages/:id - Delete a package\n server.delete(`${packagesPath}/:id`, async (req, res) => {\n try {\n const packageId = req.params.id;\n const version = req.query?.version;\n\n const result = await packageService.delete(packageId, version);\n\n if (result.success) {\n res.json({\n success: true,\n message: `Deleted ${packageId}${version ? `@${version}` : ''}`,\n });\n return;\n }\n\n res.status(400).json({ success: false });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { PluginContext } from '@objectstack/core';\nimport type { IHttpServer } from '@objectstack/spec/contracts';\n\n/**\n * External Datasource Federation REST routes (ADR-0015 §6.2).\n *\n * Mounted under `/api/v1/datasources/:name/external/*` and served by the\n * `external-datasource` service. Every route degrades gracefully\n * (`503 external_service_unavailable`) when federation is not wired into the\n * host, so the routes are safe to register unconditionally.\n *\n * GET /datasources/:name/external/tables → listRemoteTables\n * POST /datasources/:name/external/tables/:remote/draft → generateObjectDraft\n * POST /datasources/:name/external/tables/:remote/import → importObject\n * POST /datasources/:name/external/refresh-catalog → refreshCatalog\n * POST /datasources/:name/external/validate → validateAll (this ds)\n *\n * NOTE: the datasource *lifecycle* routes (`/api/v1/datasources` —\n * list / test / create / update / remove, ADR-0015 Addendum) were extracted\n * into the private `@objectstack/datasource-admin` package, which registers\n * them via its own `registerDatasourceAdminRoutes`.\n */\nexport function registerExternalDatasourceRoutes(\n server: IHttpServer,\n ctx: PluginContext,\n basePath = '/api/v1',\n): void {\n const ext = `${basePath}/datasources/:name/external`;\n\n const externalService = (): any => {\n try {\n return ctx.getService<any>('external-datasource');\n } catch {\n return undefined;\n }\n };\n\n const unavailable = (res: any) =>\n res.status(503).json({ error: 'external_service_unavailable' });\n\n // List remote tables (optionally filtered by ?schema=).\n server.get(`${ext}/tables`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.listRemoteTables) return unavailable(res);\n const schema = typeof req.query?.schema === 'string' ? req.query.schema : undefined;\n const tables = await svc.listRemoteTables(req.params.name, { schema });\n res.json({ tables });\n });\n\n // Generate an Object draft (structured + *.object.ts source) from a table.\n server.post(`${ext}/tables/:remote/draft`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.generateObjectDraft) return unavailable(res);\n const draft = await svc.generateObjectDraft(\n req.params.name,\n req.params.remote,\n (req.body as Record<string, unknown>) ?? {},\n );\n res.json({ draft });\n });\n\n // Import a remote table as a live (runtime-origin) federated object so it's\n // immediately queryable — the \"Import as Object\" action (ADR-0015 Addendum).\n // 503 when the service is absent; 400 when import is refused (e.g. read-only\n // metadata store) or the remote table is missing.\n server.post(`${ext}/tables/:remote/import`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.importObject) return unavailable(res);\n try {\n const result = await svc.importObject(\n req.params.name,\n req.params.remote,\n (req.body as Record<string, unknown>) ?? {},\n );\n res.status(201).json({ object: result });\n } catch (err) {\n res.status(400).json({\n error: 'external_import_error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n });\n\n // Refresh and return the cached catalog snapshot.\n server.post(`${ext}/refresh-catalog`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.refreshCatalog) return unavailable(res);\n const catalog = await svc.refreshCatalog(req.params.name);\n res.json({ catalog });\n });\n\n // Validate the federated objects on this datasource.\n server.post(`${ext}/validate`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.validateAll) return unavailable(res);\n const report = await svc.validateAll();\n const results = (report.results ?? []).filter((r: any) => r.datasource === req.params.name);\n res.json({ ok: results.every((r: any) => r.ok), results });\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext, IHttpServer } from '@objectstack/core';\nimport { RestServer, RestKernelManager } from './rest-server.js';\nimport { ObjectStackProtocol, RestServerConfig } from '@objectstack/spec/api';\nimport { registerPackageRoutes } from './package-routes.js';\nimport { registerExternalDatasourceRoutes } from './external-datasource-routes.js';\nimport type { PackageService } from '@objectstack/service-package';\n\nexport interface RestApiPluginConfig {\n serverServiceName?: string;\n protocolServiceName?: string;\n /**\n * Optional override for the kernel-manager service name. When the service\n * is registered (by @objectstack/runtime's MultiProjectPlugin), scoped\n * routes resolve per-environment protocols at request time.\n */\n kernelManagerServiceName?: string;\n api?: RestServerConfig;\n}\n\n/**\n * REST API Plugin\n * \n * Responsibilities:\n * 1. Consumes 'http.server' (or configured service)\n * 2. Consumes 'protocol' (ObjectStackProtocol)\n * 3. Instantiates RestServer to auto-generate routes\n */\nexport function createRestApiPlugin(config: RestApiPluginConfig = {}): Plugin {\n return {\n name: 'com.objectstack.rest.api',\n version: '1.0.0',\n \n init: async (_ctx: PluginContext) => {\n // No service registration, this is a consumer plugin\n },\n \n start: async (ctx: PluginContext) => {\n const serverService = config.serverServiceName || 'http.server';\n const protocolService = config.protocolServiceName || 'protocol';\n \n let server: IHttpServer | undefined;\n let protocol: ObjectStackProtocol | undefined;\n\n try {\n server = ctx.getService<IHttpServer>(serverService);\n } catch (e) {\n // Ignore missing service\n }\n\n try {\n protocol = ctx.getService<ObjectStackProtocol>(protocolService);\n } catch (e) {\n // Ignore missing service\n }\n\n // Optional — only present when MultiProjectPlugin is mounted. When\n // available, RestServer will resolve a per-environment protocol at\n // request time for scoped (`/environments/:environmentId/...`) routes.\n let kernelManager: RestKernelManager | undefined;\n const kernelManagerService = config.kernelManagerServiceName || 'kernel-manager';\n try {\n kernelManager = ctx.getService<RestKernelManager>(kernelManagerService);\n } catch (e) {\n // Single-kernel deployment — fall back to the control protocol\n }\n\n // Optional — only present in runtime mode. When available,\n // RestServer will resolve hostname → environmentId on unscoped\n // routes so a remote runtime node can dispatch every request\n // to the matching per-environment kernel without requiring callers\n // to know the environmentId.\n let envRegistry: any;\n try {\n envRegistry = ctx.getService<any>('env-registry');\n } catch (e) {\n // Not running in runtime/multi-environment mode — fine.\n }\n\n // Optional default-project provider — registered by\n // `createSingleEnvironmentPlugin` in single-environment local mode.\n // Lets RestServer route bare `/api/v1/data/...` URLs into the\n // lone project's kernel.\n const defaultEnvironmentIdProvider = (): string | undefined => {\n try {\n const dp: any = ctx.getService('default-project');\n return dp?.environmentId;\n } catch { return undefined; }\n };\n\n // Auth service resolver — used by RestServer.resolveExecCtx in\n // single-kernel deployments where there is no kernelManager.\n // Multi-kernel paths look up auth via kernelManager.getOrCreate,\n // so this provider is the single-kernel fallback.\n const authServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('auth');\n } catch { return undefined; }\n };\n\n // ObjectQL resolver — single-kernel fallback so resolveExecCtx\n // can run sys_member / sys_user_permission_set lookups when\n // there is no kernelManager wired (e.g. `pnpm dev:crm`).\n const objectQLProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('objectql');\n } catch { return undefined; }\n };\n\n // Email service resolver — used by POST /email/send. Single-\n // kernel deployments resolve from the local kernel; multi-\n // tenant paths would resolve via kernelManager.getOrCreate.\n const emailServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('email');\n } catch { return undefined; }\n };\n\n // Sharing service resolver — used by /data/:object/:id/shares.\n const sharingServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('sharing');\n } catch { return undefined; }\n };\n\n // Reports service resolver — used by /reports/* routes.\n const reportsServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('reports');\n } catch { return undefined; }\n };\n\n // Approvals service resolver — used by /approvals/* routes.\n const approvalsServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('approvals');\n } catch { return undefined; }\n };\n\n // Sharing-rule service resolver — used by /sharing/rules/* routes.\n const sharingRulesServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('sharingRules');\n } catch { return undefined; }\n };\n\n // i18n service resolver — used to localize view / action / object\n // metadata. Single-kernel fallback so labels and select options\n // get translated even without a full multi-tenant kernelManager.\n const i18nServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('i18n');\n } catch { return undefined; }\n };\n\n // Analytics service resolver — used by /analytics/dataset/query\n // (ADR-0021 dataset preview/query). Returns undefined when no\n // analytics service is registered so the route fails cleanly (501).\n const analyticsServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('analytics');\n } catch { return undefined; }\n };\n\n if (!server) {\n ctx.logger.warn(`RestApiPlugin: HTTP Server service '${serverService}' not found. REST routes skipped.`);\n return;\n }\n \n if (!protocol) {\n ctx.logger.warn(`RestApiPlugin: Protocol service '${protocolService}' not found. REST routes skipped.`);\n return;\n }\n \n ctx.logger.info('Hydrating REST API from Protocol...');\n \n try {\n const restServer = new RestServer(server, protocol, config.api as any, kernelManager, envRegistry, defaultEnvironmentIdProvider, authServiceProvider, objectQLProvider, emailServiceProvider, sharingServiceProvider, reportsServiceProvider, approvalsServiceProvider, sharingRulesServiceProvider, i18nServiceProvider, analyticsServiceProvider);\n restServer.registerRoutes();\n\n ctx.logger.info('REST API successfully registered');\n } catch (err: any) {\n ctx.logger.error('Failed to register REST API routes', { error: err.message } as any);\n throw err;\n }\n\n const basePath = config.api?.api?.basePath || '/api';\n const version = config.api?.api?.version || 'v1';\n const versionedBase = `${basePath}/${version}`;\n const enableProjectScoping = config.api?.api?.enableProjectScoping ?? false;\n const projectResolution = config.api?.api?.projectResolution ?? 'auto';\n\n // Register package management routes if the service is available.\n try {\n const packageService = ctx.getService<PackageService>('package');\n if (packageService) {\n if (enableProjectScoping && projectResolution === 'required') {\n // Only register the scoped variant\n registerPackageRoutes(server, packageService, `${versionedBase}/environments/:environmentId`, {\n protocol,\n });\n } else {\n registerPackageRoutes(server, packageService, versionedBase, { protocol });\n if (enableProjectScoping) {\n registerPackageRoutes(server, packageService, `${versionedBase}/environments/:environmentId`, {\n protocol,\n });\n }\n }\n ctx.logger.info('Package management routes registered');\n }\n } catch (e) {\n // Package service not available, skip\n ctx.logger.debug('Package service not available, package routes skipped');\n }\n\n // External Datasource Federation routes (ADR-0015): catalog / draft /\n // import / validate. Registered unconditionally — they degrade\n // gracefully (503) when the `external-datasource` service is absent.\n // NOTE: the datasource *lifecycle* routes (ADR-0015 Addendum:\n // list / test / create / update / remove) moved to the private\n // `@objectstack/datasource-admin` package, which registers its own.\n try {\n registerExternalDatasourceRoutes(server, ctx, versionedBase);\n ctx.logger.info('Datasource federation routes registered');\n } catch (e: any) {\n ctx.logger.warn('Datasource federation routes registration failed', { error: e?.message });\n }\n }\n };\n}\n"],"mappings":"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","names":["row"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/rest-server.ts","../src/route-manager.ts","../src/package-routes.ts","../src/external-datasource-routes.ts","../src/rest-api-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n// REST Server\nexport { RestServer } from './rest-server.js';\n\n// Route Management\nexport { RouteManager, RouteGroupBuilder } from './route-manager.js';\nexport type { RouteEntry } from './route-manager.js';\n\n// REST API Plugin\nexport { createRestApiPlugin } from './rest-api-plugin.js';\nexport type { RestApiPluginConfig } from './rest-api-plugin.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { IHttpServer, resolveApiKeyPrincipal } from '@objectstack/core';\nimport { RouteManager } from './route-manager.js';\nimport { RestServerConfig, RestApiConfig, CrudEndpointsConfig, MetadataEndpointsConfig, BatchEndpointsConfig, RouteGenerationConfig } from '@objectstack/spec/api';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\n\n// Node-safe logger — avoids importing 'console' which is absent from ES2020 lib typings.\nconst logError = (...args: unknown[]) => (globalThis as any).console?.error(...args);\n\n/**\n * Metadata types whose user-facing labels are localized at the REST boundary\n * via `translateMetadataDocument`. Keep in sync with the type dispatch in\n * `@objectstack/spec/system`'s `translateMetadataDocument`.\n */\nconst TRANSLATABLE_META_TYPES = new Set(['view', 'action', 'object', 'app', 'dashboard']);\n\n/**\n * Detect the `getMetaItem` response envelope (`{ type, name, item, lock, … }`)\n * whose translatable metadata document is nested at `.item`. The cached read\n * path and `getMetaItems` element shape hand back the already-unwrapped\n * document instead, so translation helpers must distinguish the two: an\n * envelope carries a nested `item` object alongside its own `type`/`name`,\n * which a bare metadata document never does.\n */\nfunction isMetaEnvelope(value: any): boolean {\n return !!value\n && typeof value === 'object'\n && typeof value.type === 'string'\n && typeof value.name === 'string'\n && value.item != null\n && typeof value.item === 'object'\n && !Array.isArray(value.item);\n}\n\n/**\n * Map a data-layer error to a clean HTTP response. Unknown-object errors\n * (SQLite \"no such table\", PG \"relation does not exist\", protocol\n * \"object not found\", etc.) are surfaced as a 404 with `code: 'object_not_found'`\n * so clients can distinguish \"object isn't registered\" from real server\n * faults. Anything else becomes a 400 (bad request) preserving prior\n * behavior. Genuine 500s are still logged.\n *\n * `PermissionDeniedError` (thrown by `SecurityPlugin`) MUST be caught\n * before the unknown-object heuristic, otherwise its message —\n * \"[Security] Access denied: operation 'insert' on object 'sys_user' is\n * not permitted …\" — trips the `'<obj>' … not` substring check and\n * returns a misleading 404.\n */\nexport function mapDataError(error: any, object?: string): { status: number; body: Record<string, unknown> } {\n // Referential-integrity restrict on delete → 409 with the dependent count.\n // Surfaced FIRST so the structured fields survive the generic catch-alls.\n if (error?.code === 'DELETE_RESTRICTED') {\n return {\n status: 409,\n body: {\n error: error?.message ?? 'Cannot delete: dependent records exist',\n code: 'DELETE_RESTRICTED',\n ...(error?.dependentObject ? { dependentObject: error.dependentObject } : {}),\n ...(typeof error?.dependentCount === 'number' ? { dependentCount: error.dependentCount } : {}),\n ...(object ? { object } : {}),\n },\n };\n }\n // Optimistic-Concurrency-Control mismatch → 409 with current state.\n // Surfaced FIRST so the structured fields (`currentVersion`,\n // `currentRecord`) are preserved instead of being squashed into the\n // generic SQL-leak / catch-all paths below.\n if (error?.code === 'CONCURRENT_UPDATE' || error?.name === 'ConcurrentUpdateError') {\n return {\n status: 409,\n body: {\n error: error?.message ?? 'Record was modified by another user',\n code: 'CONCURRENT_UPDATE',\n ...(error?.currentVersion ? { currentVersion: error.currentVersion } : {}),\n ...(error?.currentRecord ? { currentRecord: error.currentRecord } : {}),\n ...(object ? { object } : {}),\n },\n };\n }\n // Validation failures → 400 with per-field envelope. Handled FIRST\n // because the validator throws a typed error before any SQL ever\n // runs, and we want callers to differentiate \"your payload was\n // invalid\" (fixable client-side) from generic 400s.\n if (error?.code === 'VALIDATION_FAILED' || error?.name === 'ValidationError') {\n return {\n status: 400,\n body: {\n error: error?.message ?? 'Validation failed',\n code: 'VALIDATION_FAILED',\n fields: Array.isArray(error?.fields) ? error.fields : [],\n ...(object ? { object } : {}),\n },\n };\n }\n // Short-circuit: explicit security denial → 403. Match by `code` /\n // `name` to avoid pulling a runtime dependency on plugin-security.\n if (\n error?.code === 'PERMISSION_DENIED' ||\n error?.name === 'PermissionDeniedError' ||\n (typeof error?.message === 'string' && error.message.startsWith('[Security] Access denied'))\n ) {\n return {\n status: 403,\n body: {\n error: error?.message ?? 'Permission denied',\n code: 'PERMISSION_DENIED',\n ...(object ? { object } : {}),\n },\n };\n }\n const raw = String(error?.message ?? error ?? '');\n const lower = raw.toLowerCase();\n\n // EnvironmentKernelFactory: project missing database_url/driver — typically\n // means provisioning is in flight or the project record was never\n // fully provisioned. 503 (with Retry-After implied) is more accurate\n // than the default 400/500: clients can poll until the project is\n // active.\n if (\n raw.includes('[EnvironmentKernelFactory]') &&\n (lower.includes('missing database_url') || lower.includes('not found'))\n ) {\n const isProvisioning = lower.includes(\"status='provisioning'\") || lower.includes(\"status='pending'\");\n const isFailed = lower.includes(\"status='failed'\");\n return {\n status: isProvisioning ? 503 : isFailed ? 502 : 404,\n body: {\n error: raw,\n code: isProvisioning\n ? 'PROJECT_PROVISIONING'\n : isFailed\n ? 'PROJECT_PROVISIONING_FAILED'\n : 'PROJECT_NOT_FOUND',\n },\n };\n }\n\n // Record-level not-found from ObjectQL (`getData` / `updateData` /\n // `deleteData`). These are normal client mistakes (stale UI link,\n // hand-typed id, deleted record) and should be a quiet 404 — not\n // a \"[REST] Unhandled error\" log entry that scares operators.\n if (\n error?.code === 'RECORD_NOT_FOUND' ||\n /^Record\\s+\\S+\\s+not found in\\s+\\S+/i.test(raw)\n ) {\n return {\n status: 404,\n body: {\n error: raw,\n code: 'RECORD_NOT_FOUND',\n ...(object ? { object } : {}),\n },\n };\n }\n\n // Schema-mismatch & required-field violations are CLIENT errors (a bad\n // payload the caller can fix), not server faults — so map them to a\n // structured 4xx BEFORE the unknown-object / SQL-leak branches, which\n // would otherwise bury them in a generic 404 or 500. Driver phrasing\n // varies by dialect; cover SQLite / Postgres / MySQL:\n // unknown column → SQLite \"table X has no column named c\" /\n // \"no such column: c\"; Postgres 'column \"c\" of\n // relation \"X\" does not exist'; MySQL \"Unknown\n // column 'c' in 'field list'\".\n // not-null → SQLite \"NOT NULL constraint failed: X.c\";\n // Postgres 'null value in column \"c\" ... violates\n // not-null constraint'; MySQL \"Column 'c' cannot\n // be null\".\n // NOTE: this is a last-resort safety net — the validation layer should\n // ideally reject these before they reach the driver (see follow-ups on\n // unknown-field rejection + provenance-aware required checks).\n const unknownColumn =\n /has no column named\\s+[\"'`]?([a-z0-9_]+)/i.exec(raw) ||\n /no such column:\\s*[\"'`]?([a-z0-9_.]+)/i.exec(raw) ||\n /unknown column\\s+[\"'`]([a-z0-9_]+)[\"'`]/i.exec(raw) ||\n /column\\s+[\"'`]([a-z0-9_]+)[\"'`]\\s+of relation\\s+\\S+\\s+does not exist/i.exec(raw);\n if (unknownColumn) {\n const field = unknownColumn[1]?.split('.').pop();\n return {\n status: 400,\n body: {\n error: field\n ? `Unknown field '${field}'${object ? ` on object '${object}'` : ''}`\n : 'Request references a field that does not exist',\n code: 'INVALID_FIELD',\n ...(field ? { field } : {}),\n ...(object ? { object } : {}),\n },\n };\n }\n\n const notNull =\n /not null constraint failed:\\s*\\S*?\\.([a-z0-9_]+)/i.exec(raw) ||\n /null value in column\\s+[\"'`]([a-z0-9_]+)[\"'`]/i.exec(raw) ||\n /column\\s+[\"'`]([a-z0-9_]+)[\"'`]\\s+cannot be null/i.exec(raw);\n if (notNull) {\n const field = notNull[1];\n return {\n status: 400,\n body: {\n error: `${field} is required`,\n code: 'VALIDATION_FAILED',\n fields: [{ field, code: 'required', message: `${field} is required` }],\n ...(object ? { object } : {}),\n },\n };\n }\n\n const looksLikeUnknownObject =\n lower.includes('no such table') ||\n lower.includes('relation') && lower.includes('does not exist') ||\n lower.includes('table not found') ||\n lower.includes('unknown object') ||\n lower.includes('object not found') ||\n lower.includes('no driver available') ||\n (object !== undefined && lower.includes(`'${object.toLowerCase()}'`) && lower.includes('not'));\n if (looksLikeUnknownObject) {\n return {\n status: 404,\n body: {\n error: object ? `Object '${object}' is not registered` : 'Object not found',\n code: 'object_not_found',\n object,\n },\n };\n }\n // Default: do NOT leak raw SQL or driver internals. If the message\n // looks like a SQL/driver dump, replace it with a generic envelope\n // and rely on server logs for the full diagnostic.\n const looksLikeSqlLeak =\n lower.includes('sqlite_') ||\n lower.includes('sqlstate') ||\n lower.startsWith('insert into ') ||\n lower.startsWith('update ') ||\n lower.startsWith('select ') ||\n lower.startsWith('delete from ') ||\n lower.includes('constraint failed') ||\n lower.includes('unique constraint') ||\n lower.includes('foreign key');\n if (looksLikeSqlLeak) {\n // Surface unique-constraint violations as a structured 409 so\n // the UI can map them to \"this value already exists\".\n if (lower.includes('unique constraint') || lower.includes('unique violation')) {\n return {\n status: 409,\n body: {\n error: 'A record with this value already exists',\n code: 'UNIQUE_VIOLATION',\n ...(object ? { object } : {}),\n },\n };\n }\n return {\n status: 500,\n body: { error: 'Internal data error', code: 'DATABASE_ERROR' },\n };\n }\n return { status: 400, body: { error: raw || 'Bad request' } };\n}\n\n/**\n * Centralized error responder for all REST handlers. Ensures raw driver\n * messages (SQLite/Postgres dumps, stack traces, unique-constraint\n * payloads with table names, etc.) never reach clients. Honors\n * structured errors that already carry an explicit `status` so callers\n * can surface domain-specific codes (e.g. 422 from a metadata save\n * validator), and routes everything else through `mapDataError` so the\n * security / validation / SQL-leak / unknown-object envelopes apply\n * uniformly across CRUD, batch, metadata, UI and discovery routes.\n */\nfunction sendError(res: any, error: any, object?: string): void {\n if (typeof error?.status === 'number' && error.status >= 400 && error.status < 600) {\n const safeMsg = typeof error.message === 'string' && error.message.length < 500\n ? error.message\n : 'Request failed';\n res.status(error.status).json({\n error: safeMsg,\n ...(error.code ? { code: error.code } : {}),\n ...(Array.isArray(error.issues) ? { issues: error.issues } : {}),\n });\n return;\n }\n const mapped = mapDataError(error, object);\n res.status(mapped.status).json(mapped.body);\n}\n\n/**\n * Whether a mapped data-error status represents an *expected* client/lifecycle\n * outcome (and therefore shouldn't be logged as \"[REST] Unhandled error\").\n * - 403 PERMISSION_DENIED is a normal RBAC denial\n * - 404 unknown object / project not found is a normal client mistake\n * - 502/503 mean the underlying project is provisioning or failed; the\n * handler will emit the response and the operator can inspect\n * sys_environment.metadata.provisioningError if needed.\n */\nfunction isExpectedDataStatus(status: number): boolean {\n return status === 403 || status === 404 || status === 409 || status === 502 || status === 503;\n}\n\n/**\n * Minimal RFC-4180-style CSV parser used by the bulk-import endpoint\n * (M10.9). Handles quoted fields (including embedded quotes via \"\" and\n * embedded commas/newlines) and both CRLF and LF line endings.\n *\n * The first non-empty line is treated as the header row. Header names\n * can be re-mapped to canonical field names via the optional `mapping`\n * argument (e.g. `{ \"First Name\": \"first_name\" }`); unmapped headers\n * pass through unchanged. Empty cells become empty strings.\n *\n * Kept dependency-free so REST stays runtime-portable (Hono / Express\n * adapters both consume this without pulling a CSV lib transitively).\n */\nfunction parseCsvToRows(csv: string, mapping: Record<string, string> = {}): Array<Record<string, any>> {\n const text = csv.replace(/^\\uFEFF/, ''); // strip BOM\n const cells: string[][] = [];\n let cur = '';\n let row: string[] = [];\n let inQuotes = false;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (inQuotes) {\n if (ch === '\"') {\n if (text[i + 1] === '\"') { cur += '\"'; i++; }\n else { inQuotes = false; }\n } else {\n cur += ch;\n }\n continue;\n }\n if (ch === '\"') { inQuotes = true; continue; }\n if (ch === ',') { row.push(cur); cur = ''; continue; }\n if (ch === '\\r') { continue; }\n if (ch === '\\n') {\n row.push(cur); cur = '';\n cells.push(row); row = [];\n continue;\n }\n cur += ch;\n }\n if (cur.length > 0 || row.length > 0) { row.push(cur); cells.push(row); }\n\n // Drop fully-empty trailing rows so a stray newline at EOF doesn't\n // produce a phantom empty record.\n while (cells.length > 0 && cells[cells.length - 1].every(c => c === '')) cells.pop();\n if (cells.length < 2) return [];\n\n const header = cells[0].map(h => h.trim());\n const fields = header.map(h => mapping[h] ?? h);\n const out: Array<Record<string, any>> = [];\n for (let r = 1; r < cells.length; r++) {\n const row = cells[r];\n const obj: Record<string, any> = {};\n for (let c = 0; c < fields.length; c++) {\n const key = fields[c];\n if (!key) continue;\n const raw = row[c] ?? '';\n obj[key] = raw;\n }\n out.push(obj);\n }\n return out;\n}\n\n/**\n * Escape a single value into an RFC-4180 CSV cell. Values containing\n * commas, quotes, CR, or LF are wrapped in double-quotes with embedded\n * quotes doubled. `null` / `undefined` become an empty cell. Objects and\n * arrays are serialised as compact JSON so nested data round-trips\n * without flattening surprises.\n */\nfunction formatCsvCell(value: any): string {\n if (value === null || value === undefined) return '';\n let s: string;\n if (typeof value === 'string') s = value;\n else if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') s = String(value);\n else if (value instanceof Date) s = value.toISOString();\n else { try { s = JSON.stringify(value); } catch { s = String(value); } }\n if (/[\",\\r\\n]/.test(s)) {\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n }\n return s;\n}\n\n/**\n * Serialise a list of rows to RFC-4180 CSV text. Caller supplies the\n * ordered list of field names; unknown fields produce empty cells.\n */\nfunction rowsToCsv(fields: string[], rows: Array<Record<string, any>>, includeHeader: boolean): string {\n const lines: string[] = [];\n if (includeHeader) lines.push(fields.map(formatCsvCell).join(','));\n for (const row of rows) {\n lines.push(fields.map(f => formatCsvCell(row?.[f])).join(','));\n }\n return lines.join('\\r\\n') + (lines.length > 0 ? '\\r\\n' : '');\n}\n\n/**\n * Structural subset of `KernelManager` that RestServer needs in order to\n * resolve a per-project protocol at request time. Typed locally to avoid\n * an @objectstack/runtime → @objectstack/rest → @objectstack/runtime\n * package cycle.\n */\nexport interface RestKernelManager {\n getOrCreate(environmentId: string): Promise<{\n getServiceAsync<T = unknown>(name: string): Promise<T>;\n }>;\n}\n\n/**\n * Normalized REST Server Configuration\n * All nested properties are required after normalization\n */\ntype NormalizedRestServerConfig = {\n api: {\n version: string;\n basePath: string;\n apiPath: string | undefined;\n enableCrud: boolean;\n enableMetadata: boolean;\n enableUi: boolean;\n enableBatch: boolean;\n enableDiscovery: boolean;\n enableOpenApi: boolean;\n enableSearch?: boolean;\n enableProjectScoping: boolean;\n projectResolution: 'required' | 'optional' | 'auto';\n requireAuth: boolean;\n documentation: RestApiConfig['documentation'];\n responseFormat: RestApiConfig['responseFormat'];\n };\n crud: {\n operations: {\n create: boolean;\n read: boolean;\n update: boolean;\n delete: boolean;\n list: boolean;\n };\n patterns: CrudEndpointsConfig['patterns'];\n dataPrefix: string;\n objectParamStyle: 'path' | 'query';\n };\n metadata: {\n prefix: string;\n enableCache: boolean;\n cacheTtl: number;\n endpoints: {\n types: boolean;\n items: boolean;\n item: boolean;\n schema: boolean;\n };\n };\n batch: {\n maxBatchSize: number;\n enableBatchEndpoint: boolean;\n operations: {\n createMany: boolean;\n updateMany: boolean;\n deleteMany: boolean;\n upsertMany: boolean;\n };\n defaultAtomic: boolean;\n };\n routes: {\n includeObjects: string[] | undefined;\n excludeObjects: string[] | undefined;\n nameTransform: 'none' | 'plural' | 'kebab-case' | 'camelCase';\n overrides: RouteGenerationConfig['overrides'];\n };\n};\n\n/**\n * RestServer\n * \n * Provides automatic REST API endpoint generation for ObjectStack.\n * Generates standard RESTful CRUD endpoints, metadata endpoints, and batch operations\n * based on the configured protocol provider.\n * \n * Features:\n * - Automatic CRUD endpoint generation (GET, POST, PUT, PATCH, DELETE)\n * - Metadata API endpoints (/meta)\n * - Batch operation endpoints (/batch, /createMany, /updateMany, /deleteMany)\n * - Discovery endpoint\n * - Configurable path prefixes and patterns\n * \n * @example\n * const restServer = new RestServer(httpServer, protocolProvider, {\n * api: {\n * version: 'v1',\n * basePath: '/api'\n * },\n * crud: {\n * dataPrefix: '/data'\n * }\n * });\n * \n * restServer.registerRoutes();\n */\n/**\n * Minimal env registry shape consumed by the REST server for hostname →\n * environmentId resolution and `X-Environment-Id` header validation on unscoped\n * routes. Mirrors the surface of `EnvironmentDriverRegistry` defined in\n * `@objectstack/service-cloud`.\n */\nexport interface RestEnvRegistry {\n resolveByHostname(hostname: string): Promise<{ environmentId: string } | null | undefined>;\n /**\n * Look up a project by id. Returns a truthy value (typically an\n * `IDataDriver`) when the project exists and is bound, `null` when\n * unknown. The REST server only uses the truthiness; it does not\n * touch the driver itself (the actual driver is loaded later via\n * `KernelManager.getOrCreate(environmentId)`).\n */\n resolveById?(environmentId: string): Promise<unknown | null>;\n}\n\nexport class RestServer {\n private protocol: ObjectStackProtocol;\n private config: NormalizedRestServerConfig;\n private routeManager: RouteManager;\n private kernelManager?: RestKernelManager;\n private envRegistry?: RestEnvRegistry;\n /**\n * Short-TTL cache for `hostname → environmentId` (P1-4). `resolveByHostname`\n * is a control-plane lookup (typically a DB query) that otherwise runs on\n * *every* unscoped request; caching it — including negative results, so\n * unknown hosts don't hammer the registry — removes that per-request cost.\n * The TTL is short so a newly-bound hostname becomes routable quickly.\n */\n private readonly hostnameCache = new Map<string, { value: { environmentId: string } | null; expiresAt: number }>();\n private readonly hostnameCacheTtlMs = 30_000;\n private defaultEnvironmentIdProvider?: () => string | undefined;\n private authServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private objectQLProvider?: (environmentId?: string) => Promise<any | undefined>;\n private emailServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private sharingServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private reportsServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private approvalsServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private sharingRulesServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private i18nServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private analyticsServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n private settingsServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n\n constructor(\n server: IHttpServer,\n protocol: ObjectStackProtocol,\n config: RestServerConfig = {},\n kernelManager?: RestKernelManager,\n envRegistry?: RestEnvRegistry,\n defaultEnvironmentIdProvider?: () => string | undefined,\n authServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n objectQLProvider?: (environmentId?: string) => Promise<any | undefined>,\n emailServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n sharingServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n reportsServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n approvalsServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n sharingRulesServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n i18nServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n analyticsServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n settingsServiceProvider?: (environmentId?: string) => Promise<any | undefined>,\n ) {\n this.protocol = protocol;\n this.config = this.normalizeConfig(config);\n this.routeManager = new RouteManager(server);\n this.kernelManager = kernelManager;\n this.envRegistry = envRegistry;\n this.defaultEnvironmentIdProvider = defaultEnvironmentIdProvider;\n this.authServiceProvider = authServiceProvider;\n this.objectQLProvider = objectQLProvider;\n this.emailServiceProvider = emailServiceProvider;\n this.sharingServiceProvider = sharingServiceProvider;\n this.reportsServiceProvider = reportsServiceProvider;\n this.approvalsServiceProvider = approvalsServiceProvider;\n this.sharingRulesServiceProvider = sharingRulesServiceProvider;\n this.i18nServiceProvider = i18nServiceProvider;\n this.analyticsServiceProvider = analyticsServiceProvider;\n this.settingsServiceProvider = settingsServiceProvider;\n }\n\n /**\n * Resolve the protocol for a given request. When `environmentId` is present\n * and a KernelManager is wired, fetch the per-project kernel's\n * `protocol` service so metadata / data / UI reads hit the project's\n * own registry and datastore.\n *\n * When `environmentId` is absent on an unscoped route and an `envRegistry`\n * is wired (runtime mode), the resolution chain is:\n * 1. Hostname → environmentId (`envRegistry.resolveByHostname`)\n * 2. `X-Environment-Id` header → environmentId (`envRegistry.resolveById`)\n * 3. Default-project fallback (`defaultEnvironmentIdProvider`, set by\n * `createSingleEnvironmentPlugin`)\n * 4. Control-plane protocol captured at boot.\n *\n * Special case: `environmentId === 'platform'` is a reserved virtual id used\n * by Studio to address the control plane through the regular project\n * URL shape (`/projects/platform/...`). It is NOT a row in the projects\n * table, so we must never call `KernelManager.getOrCreate('platform')`.\n * Instead, return the control-plane protocol directly. This lets Studio\n * (and any other client) speak a single, uniform URL family without\n * duplicating route logic for the platform surface.\n */\n /**\n * Cached wrapper around `envRegistry.resolveByHostname` (P1-4). Returns the\n * cached result while fresh; on a miss it queries the registry and caches the\n * outcome (positive *and* negative) for {@link hostnameCacheTtlMs}. Registry\n * errors are not cached so a transient control-plane blip self-heals on the\n * next request.\n */\n private async resolveHostnameCached(host: string): Promise<{ environmentId: string } | null | undefined> {\n const now = Date.now();\n const hit = this.hostnameCache.get(host);\n if (hit && hit.expiresAt > now) return hit.value;\n const result = (await this.envRegistry!.resolveByHostname(host)) ?? null;\n this.hostnameCache.set(host, { value: result, expiresAt: now + this.hostnameCacheTtlMs });\n return result;\n }\n\n /**\n * Resolve the environment a request targets: explicit id → tenant hostname\n * → `X-Environment-Id` header → single-project default. Returns undefined\n * for control-plane requests. Shared by every per-environment service\n * resolution (protocol, analytics, …) so they can never disagree about\n * which kernel a request belongs to.\n */\n private async resolveRequestEnvironmentId(environmentId?: string, req?: any): Promise<string | undefined> {\n if (environmentId) return environmentId;\n if (req && this.envRegistry && this.kernelManager) {\n const host = this.extractHostname(req);\n if (host) {\n try {\n const result = await this.resolveHostnameCached(host);\n if (result?.environmentId) return result.environmentId;\n } catch {\n // fall through to next strategy\n }\n }\n // 2. `X-Environment-Id` request header → environmentId. Lets clients\n // explicitly target a project when the URL is unscoped and\n // no hostname binding exists (e.g. a single shared origin\n // serving multiple compiled bundles via OS_PROJECT_ARTIFACTS).\n // We validate the id through the env registry to avoid\n // routing to a non-existent kernel.\n if (typeof this.envRegistry.resolveById === 'function') {\n const headerVal = this.extractProjectIdHeader(req);\n if (headerVal) {\n try {\n const driver = await this.envRegistry.resolveById(headerVal);\n if (driver) return headerVal;\n } catch {\n // fall through to default fallback\n }\n }\n }\n }\n // 3. Single-project default fallback. Registered by\n // `createSingleEnvironmentPlugin()` so bare `/api/v1/data/...` URLs\n // (no `/projects/<id>` prefix, no hostname mapping, no header)\n // resolve to the lone project's kernel rather than the control\n // plane.\n if (this.defaultEnvironmentIdProvider) {\n try {\n const def = this.defaultEnvironmentIdProvider();\n if (def) return def;\n } catch { /* fall through */ }\n }\n return undefined;\n }\n\n private async resolveProtocol(environmentId?: string, req?: any): Promise<ObjectStackProtocol> {\n if (environmentId === 'platform') return this.protocol;\n const envId = await this.resolveRequestEnvironmentId(environmentId, req);\n if (!envId || !this.kernelManager) return this.protocol;\n const kernel = await this.kernelManager.getOrCreate(envId);\n return kernel.getServiceAsync<ObjectStackProtocol>('protocol');\n }\n\n /**\n * Resolve the i18n service for the request's project (or control plane\n * when no project id is in scope). Returns `undefined` when no service is\n * registered, so callers can short-circuit and skip translation rather\n * than failing.\n *\n * Mirrors `resolveProtocol`'s lookup chain: explicit `environmentId` from the\n * route → kernel-managed `i18n` service. Control-plane / unscoped\n * requests intentionally return `undefined` because the platform kernel\n * does not own per-app translation bundles.\n */\n private async resolveI18nService(environmentId?: string, req?: any): Promise<any | undefined> {\n if (environmentId === 'platform') return undefined;\n // Mirror resolveProtocol's fallback chain so unscoped routes (single-\n // project dev servers, hostname-routed multi-tenants, X-Environment-Id\n // headers) can still pick up per-project translation bundles.\n if (!environmentId && req && this.envRegistry && this.kernelManager) {\n const host = this.extractHostname(req);\n if (host) {\n try {\n const result = await this.resolveHostnameCached(host);\n if (result?.environmentId) environmentId = result.environmentId;\n } catch { /* fall through */ }\n }\n if (!environmentId && typeof this.envRegistry.resolveById === 'function') {\n const headerVal = this.extractProjectIdHeader(req);\n if (headerVal) {\n try {\n const driver = await this.envRegistry.resolveById(headerVal);\n if (driver) environmentId = headerVal;\n } catch { /* fall through */ }\n }\n }\n }\n if (!environmentId && this.defaultEnvironmentIdProvider) {\n try {\n const def = this.defaultEnvironmentIdProvider();\n if (def) environmentId = def;\n } catch { /* fall through */ }\n }\n // Multi-tenant kernel lookup first; falls back to the single-kernel\n // provider supplied by RestApiPlugin in dev / standalone mode.\n if (environmentId && this.kernelManager) {\n try {\n const kernel = await this.kernelManager.getOrCreate(environmentId);\n const svc = await kernel.getServiceAsync<any>('i18n');\n if (svc) return svc;\n } catch { /* fall through */ }\n }\n if (this.i18nServiceProvider) {\n try {\n return await this.i18nServiceProvider(environmentId);\n } catch { return undefined; }\n }\n return undefined;\n }\n\n /**\n * Reject anonymous requests with HTTP 401 when `api.requireAuth` is set.\n * Returns `true` if the response was sent and the caller should stop\n * processing. Returns `false` to continue.\n *\n * The check is intentionally narrow: only `context?.userId` counts as\n * \"authenticated\". `isSystem` flags are never set on inbound HTTP\n * requests (they're internal-only), so they cannot bypass this gate.\n */\n private enforceAuth(req: any, res: any, context: any): boolean {\n if (!this.config.api.requireAuth) return false;\n if (context?.userId) return false;\n if (req?.method === 'OPTIONS') return false;\n res.status(401).json({\n error: 'unauthenticated',\n message: 'Authentication is required to access this endpoint.',\n });\n return true;\n }\n\n /**\n * Enforce object-level API exposure (ObjectSchema `enable.apiEnabled` /\n * `enable.apiMethods`) on the REST data surface — the *external* API boundary\n * only. Internal callers (hooks, flows, raw objectql) are unaffected, which is\n * the point: `apiEnabled` controls automatic API exposure, not data access.\n *\n * - `enable.apiEnabled === false` → object hidden from the API (404, so its\n * existence isn't revealed).\n * - `enable.apiMethods` (non-empty whitelist) → unlisted operations rejected (405).\n *\n * Default-allow: objects with no `enable` block (or `apiEnabled` unset/true and\n * no `apiMethods` whitelist) behave exactly as before — no regression. Unknown\n * objects fall through to the normal 404 path. A metadata-read failure does not\n * block (the data call itself needs the same metadata and will surface the\n * error). Returns `true` when the request was blocked (response already sent).\n *\n * See ADR-0049 (#1889): shipping a non-enforcing `apiEnabled` is false security.\n */\n private async enforceApiAccess(\n req: any,\n res: any,\n p: ObjectStackProtocol,\n environmentId: string | undefined,\n operation: string,\n ): Promise<boolean> {\n const objectName = req?.params?.object;\n if (!objectName) return false;\n let enable: any;\n try {\n const r: any = await (p as any).getMetaItems?.({\n type: 'object',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(r?.items) ? r.items : Array.isArray(r) ? r : [];\n const obj = items.find((o: any) => o?.name === objectName);\n if (!obj) return false; // unknown object → let the data path 404\n enable = obj.enable;\n } catch {\n return false; // metadata unavailable → don't block (data call needs it too)\n }\n if (!enable) return false;\n if (enable.apiEnabled === false) {\n res.status(404).json({\n error: `Object '${objectName}' is not exposed via the API`,\n code: 'OBJECT_API_DISABLED',\n object: objectName,\n });\n return true;\n }\n if (Array.isArray(enable.apiMethods) && enable.apiMethods.length > 0 && !enable.apiMethods.includes(operation)) {\n res.status(405).json({\n error: `API operation '${operation}' is not allowed on object '${objectName}'`,\n code: 'OBJECT_API_METHOD_NOT_ALLOWED',\n object: objectName,\n allowed: enable.apiMethods,\n });\n return true;\n }\n return false;\n }\n\n /**\n * Resolve the request's execution context (RBAC/RLS/FLS) by looking up\n * the better-auth session via the project's `auth` service. Returns\n * `undefined` for anonymous requests so callers can pass `context` as-is\n * to the protocol layer (the SecurityPlugin treats undefined as anon).\n */\n private async resolveExecCtx(environmentId: string | undefined, req: any): Promise<any | undefined> {\n try {\n // For multi-tenant hosts (objectos), incoming requests on unscoped\n // URLs like `/api/v1/data/:object` arrive with `environmentId === undefined`.\n // The route's protocol resolver already maps hostname → environmentId\n // (see resolveProtocol). We mirror that here so getSession() can\n // find the right per-project auth service. Without this, the\n // hostname-routed requests fall through to defaultEnvironmentIdProvider/\n // authServiceProvider (neither of which is wired in objectos) and\n // every authenticated user sees 401.\n if (!environmentId && req && this.envRegistry && this.kernelManager) {\n const host = this.extractHostname(req);\n if (host) {\n try {\n const result = await this.resolveHostnameCached(host);\n if (result?.environmentId) environmentId = result.environmentId;\n } catch { /* fall through */ }\n }\n if (!environmentId && typeof this.envRegistry.resolveById === 'function') {\n const headerVal = this.extractProjectIdHeader(req);\n if (headerVal) {\n try {\n const driver = await this.envRegistry.resolveById(headerVal);\n if (driver) environmentId = headerVal;\n } catch { /* fall through */ }\n }\n }\n }\n // Look up the auth service in the right kernel. For unscoped\n // single-environment apps the kernelManager will hand us the lone\n // tenant kernel; for multi-environment hosts we use the resolved\n // environmentId.\n let authService: any;\n let kernel: any;\n if (environmentId && environmentId !== 'platform' && this.kernelManager) {\n kernel = await this.kernelManager.getOrCreate(environmentId);\n authService = await kernel.getServiceAsync('auth').catch(() => undefined);\n }\n if (!authService && this.defaultEnvironmentIdProvider && this.kernelManager) {\n try {\n const def = this.defaultEnvironmentIdProvider();\n if (def) {\n kernel = await this.kernelManager.getOrCreate(def);\n authService = await kernel.getServiceAsync('auth').catch(() => undefined);\n }\n } catch { /* fall through */ }\n }\n // Single-kernel deployment fallback — no kernelManager, but\n // the plugin wired an `authServiceProvider` that hits the\n // local kernel directly.\n if (!authService && this.authServiceProvider) {\n authService = await this.authServiceProvider(environmentId).catch(() => undefined);\n }\n if (!authService) return undefined;\n // The auth service may be the AuthManager wrapper (which exposes\n // `getApi()`) or the raw better-auth instance (which exposes\n // `.api` directly). Normalize to the raw API object.\n let api: any = authService.api;\n if (!api && typeof authService.getApi === 'function') {\n api = await authService.getApi();\n }\n if (!api?.getSession) return undefined;\n\n // better-auth's `getSession` requires a Web `Headers` instance\n // (it calls `headers.get('cookie')`). Adapter req.headers may\n // already be one, or a plain object — normalize.\n const rawHeaders: any = req?.headers;\n let headers: any;\n if (rawHeaders && typeof rawHeaders.get === 'function') {\n headers = rawHeaders;\n } else if (rawHeaders && typeof rawHeaders === 'object') {\n headers = new (globalThis as any).Headers();\n for (const [k, v] of Object.entries(rawHeaders)) {\n if (Array.isArray(v)) v.forEach((x) => headers.append(k, String(x)));\n else if (v != null) headers.set(k, String(v));\n }\n } else {\n return undefined;\n }\n\n const permissions: string[] = [];\n const systemPermissions: string[] = [];\n const roles: string[] = [];\n\n // Resolve the data engine once — needed by the API-key verifier and\n // reused by the role/permission lookups below.\n let identityQl: any;\n if (kernel) identityQl = await kernel.getServiceAsync('objectql').catch(() => undefined);\n if (!identityQl && this.objectQLProvider) {\n identityQl = await this.objectQLProvider(environmentId).catch(() => undefined);\n }\n\n // ── Identity: API key (sys_api_key) takes precedence, then session.\n // Verified by the SAME `resolveApiKeyPrincipal` (@objectstack/core)\n // the dispatcher/MCP path uses, so REST + MCP never drift on how a\n // key authenticates. Anonymous (neither) → undefined → 401.\n let userId: string;\n let tenantId: string | undefined;\n const keyPrincipal = await resolveApiKeyPrincipal(identityQl, headers).catch(() => undefined);\n if (keyPrincipal) {\n userId = keyPrincipal.userId;\n tenantId = keyPrincipal.tenantId;\n for (const s of keyPrincipal.scopes) if (!permissions.includes(s)) permissions.push(s);\n } else {\n const session = await api.getSession({ headers });\n if (!session?.user?.id) return undefined;\n userId = session.user.id;\n tenantId = session.session?.activeOrganizationId ?? undefined;\n }\n // Look up the link tables to surface roles + permission set names.\n // Skipping this lookup would silently ignore admin/role grants —\n // including the platform-admin promotion seeded by\n // `bootstrapPlatformAdmin` — and force every authenticated user\n // through the `member_default` fallback path.\n try {\n let ql: any;\n if (kernel) {\n ql = await kernel.getServiceAsync('objectql').catch(() => undefined);\n }\n if (!ql && this.objectQLProvider) {\n ql = await this.objectQLProvider(environmentId).catch(() => undefined);\n }\n if (ql && typeof ql.find === 'function') {\n const sysOpts = { context: { isSystem: true } };\n const memberRows = await ql.find('sys_member', {\n where: tenantId ? { user_id: userId, organization_id: tenantId } : { user_id: userId },\n limit: 50,\n ...sysOpts,\n } as any).catch(() => []);\n for (const m of (memberRows ?? []) as any[]) {\n if (typeof m.role === 'string') {\n for (const r of m.role.split(',').map((s: string) => s.trim()).filter(Boolean)) {\n if (!roles.includes(r)) roles.push(r);\n }\n }\n }\n const upsRows = await ql.find('sys_user_permission_set', {\n where: { user_id: userId },\n limit: 100,\n ...sysOpts,\n } as any).catch(() => []);\n const psIds = new Set<string>();\n for (const r of (upsRows ?? []) as any[]) {\n const orgScope = r.organization_id ?? null;\n if (!orgScope || (tenantId && orgScope === tenantId)) {\n const pid = r.permission_set_id ?? r.permissionSetId;\n if (pid) psIds.add(pid);\n }\n }\n if (psIds.size > 0) {\n const psRows = await ql.find('sys_permission_set', {\n where: { id: { $in: Array.from(psIds) } },\n limit: 500,\n ...sysOpts,\n } as any).catch(() => []);\n for (const ps of (psRows ?? []) as any[]) {\n if (ps.name && !permissions.includes(ps.name)) permissions.push(ps.name);\n // System permissions may be stored as a JSON string\n // (driver-sql round-trips array columns as text).\n // Mirrors runtime/src/security/resolve-execution-context.ts.\n const rawSys = typeof ps.system_permissions === 'string'\n ? (() => { try { return JSON.parse(ps.system_permissions); } catch { return []; } })()\n : (ps.system_permissions ?? ps.systemPermissions);\n if (Array.isArray(rawSys)) {\n for (const sp of rawSys) {\n if (typeof sp === 'string' && !systemPermissions.includes(sp)) {\n systemPermissions.push(sp);\n }\n }\n }\n }\n }\n }\n } catch { /* fall through with empty perms */ }\n // Pre-resolve fellow-org user IDs so RLS can scope identity\n // tables (sys_user) to org collaborators. Cap at 1000. See\n // `@objectstack/runtime/security/resolve-execution-context.ts`\n // for the mirror implementation in the dispatcher path.\n let org_user_ids: string[] = [userId];\n if (tenantId) {\n try {\n let ql: any;\n if (kernel) {\n ql = await kernel.getServiceAsync('objectql').catch(() => undefined);\n }\n if (!ql && this.objectQLProvider) {\n ql = await this.objectQLProvider(environmentId).catch(() => undefined);\n }\n if (ql && typeof ql.find === 'function') {\n const sysOpts = { context: { isSystem: true } };\n const memberRows = await ql.find('sys_member', {\n where: { organization_id: tenantId },\n limit: 1000,\n ...sysOpts,\n } as any).catch(() => []);\n const ids = new Set<string>([userId]);\n for (const m of (memberRows ?? []) as any[]) {\n const uid = m.user_id ?? m.userId;\n if (typeof uid === 'string' && uid.length > 0) ids.add(uid);\n }\n org_user_ids = Array.from(ids);\n }\n } catch { /* fall back to self-only */ }\n }\n // Reference timezone + locale for date rendering and analytics date\n // bucketing (ADR-0053 Phase 2 / localization manifest #2006). Resolved\n // through the `settings` service so the 4-tier cascade — including the\n // env override `OS_LOCALIZATION_TIMEZONE` — is honoured; `sys_setting`\n // rows alone would miss the env/global tiers. Best-effort: any failure\n // leaves the engine's UTC default. Mirrors the dispatcher path's\n // `resolveLocalization` (runtime/security/resolve-execution-context.ts).\n let timezone: string | undefined;\n let locale: string | undefined;\n try {\n const settings = this.settingsServiceProvider\n ? await this.settingsServiceProvider(environmentId).catch(() => undefined)\n : undefined;\n if (settings && typeof settings.get === 'function') {\n const sctx = { tenantId, userId };\n const [tzRes, localeRes] = await Promise.all([\n settings.get('localization', 'timezone', sctx).catch(() => undefined),\n settings.get('localization', 'locale', sctx).catch(() => undefined),\n ]);\n const tzVal = tzRes?.value;\n const localeVal = localeRes?.value;\n if (typeof tzVal === 'string' && tzVal.trim()) timezone = tzVal.trim();\n if (typeof localeVal === 'string' && localeVal.trim()) locale = localeVal.trim();\n }\n } catch { /* best-effort — fall back to engine UTC default */ }\n return {\n userId,\n tenantId,\n roles,\n permissions,\n systemPermissions,\n isSystem: false,\n org_user_ids,\n ...(timezone ? { timezone } : {}),\n ...(locale ? { locale } : {}),\n } as any;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Filter an `App` metadata item by the current user's `systemPermissions`.\n *\n * - Drops the app entirely if its top-level `requiredPermissions` are not\n * a subset of the user's system permissions.\n * - Recursively strips child navigation entries (groups, items) whose\n * `requiredPermissions` are not satisfied. Empty groups collapse so\n * the sidebar doesn't render a label with no children.\n *\n * Returns `null` when the app should be hidden from the user. Returns a\n * shallow copy with a filtered `navigation` tree otherwise — the original\n * is never mutated so cached metadata stays clean.\n */\n private filterAppForUser(item: any, sysPerms: Set<string>): any | null {\n if (!item || typeof item !== 'object') return item;\n // ADR-0045: an unpublished app (`hidden: true`) is externally\n // unobservable — only builders (studio/setup access) receive it at all,\n // for direct-URL preview. The launcher's client-side hidden filter is a\n // listing courtesy; THIS is the visibility gate.\n if (item.hidden === true && !sysPerms.has('studio.access') && !sysPerms.has('setup.access')) {\n return null;\n }\n const reqApp = Array.isArray(item.requiredPermissions) ? item.requiredPermissions : [];\n if (reqApp.length > 0 && !reqApp.every((p: string) => sysPerms.has(p))) {\n return null;\n }\n const nav = Array.isArray(item.navigation) ? item.navigation : null;\n if (!nav) return item;\n\n const filterNav = (entries: any[]): any[] => {\n const out: any[] = [];\n for (const e of entries) {\n if (!e || typeof e !== 'object') continue;\n const req = Array.isArray(e.requiredPermissions) ? e.requiredPermissions : [];\n if (req.length > 0 && !req.every((p: string) => sysPerms.has(p))) continue;\n if (Array.isArray(e.children) && e.children.length > 0) {\n const kids = filterNav(e.children);\n // Drop empty groups so the sidebar doesn't render a label\n // with nothing under it (matches AppSidebar UX).\n if (e.type === 'group' && kids.length === 0) continue;\n out.push({ ...e, children: kids });\n } else {\n out.push(e);\n }\n }\n return out;\n };\n\n return { ...item, navigation: filterNav(nav) };\n }\n\n /**\n * Build a `TranslationBundle` (`Record<locale, TranslationData>`) from an\n * `II18nService` instance. Returns `undefined` when no locales are\n * registered so callers can avoid translation work.\n */\n private buildTranslationBundle(i18n: any): any | undefined {\n if (!i18n || typeof i18n.getLocales !== 'function' || typeof i18n.getTranslations !== 'function') {\n return undefined;\n }\n const locales: string[] = i18n.getLocales();\n if (!locales.length) return undefined;\n const bundle: Record<string, any> = {};\n for (const locale of locales) {\n const data = i18n.getTranslations(locale);\n if (data && typeof data === 'object') bundle[locale] = data;\n }\n return Object.keys(bundle).length ? bundle : undefined;\n }\n\n /**\n * Parse the highest-priority locale from an `Accept-Language` header.\n * Falls back to a `?locale=` query parameter, then to the i18n service's\n * default locale. Returns `undefined` when no preference is expressed\n * (callers will then return untranslated metadata).\n */\n private extractLocale(req: any, i18n?: any): string | undefined {\n const headers = req?.headers;\n let header: string | undefined;\n if (headers) {\n header = typeof headers.get === 'function'\n ? headers.get('accept-language') ?? undefined\n : headers['accept-language'] ?? headers['Accept-Language'];\n }\n if (typeof header === 'string' && header.length > 0) {\n const top = header.split(',')[0]?.split(';')[0]?.trim();\n if (top) return top;\n }\n const queryLocale = req?.query?.locale;\n if (typeof queryLocale === 'string' && queryLocale.length > 0) return queryLocale;\n if (i18n && typeof i18n.getDefaultLocale === 'function') {\n const def = i18n.getDefaultLocale();\n if (typeof def === 'string' && def.length > 0) return def;\n }\n return undefined;\n }\n\n /**\n * Translate a single metadata document (view or action) when an i18n\n * service is registered for the request's project and the requested\n * locale yields a match. Falls through unchanged for unsupported types\n * or missing translations.\n */\n private async translateMetaItem(req: any, type: string, environmentId: string | undefined, item: any, i18nService?: any): Promise<any> {\n if (!item || typeof item !== 'object') return item;\n if (!TRANSLATABLE_META_TYPES.has(type)) return item;\n // The cached read path resolves the i18n service up-front (to build a\n // locale-aware ETag) and passes it here so we don't repeat the\n // potentially registry-hitting lookup on every request.\n const i18n = i18nService !== undefined ? i18nService : await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n if (!bundle) return item;\n const locale = this.extractLocale(req, i18n);\n if (!locale) return item;\n const { translateMetadataDocument } = await import('@objectstack/spec/system');\n // `getMetaItem` returns an envelope `{ type, name, item, lock, ... }`\n // whose translatable document is nested at `.item`; the cached read\n // path hands us the already-unwrapped document. Translate whichever\n // shape we received — nav/field labels live on the inner doc, so\n // translating the envelope's top level (which has no `navigation`)\n // would leave the menu untranslated.\n if (isMetaEnvelope(item)) {\n return { ...item, item: translateMetadataDocument(type, item.item, bundle, { locale }) };\n }\n return translateMetadataDocument(type, item, bundle, { locale });\n }\n\n /**\n * Translate a list of metadata documents using `translateMetaItem`.\n */\n private async translateMetaItems(req: any, type: string, environmentId: string | undefined, items: any): Promise<any> {\n if (!TRANSLATABLE_META_TYPES.has(type)) return items;\n // `getMetaItems` may hand back a bare array or an `{ items: [...] }`\n // envelope. Unwrap so list responses are localized the same way the\n // single-item route is; a non-array, non-envelope value is returned\n // untouched.\n const arr: any[] | null = Array.isArray(items)\n ? items\n : (items && typeof items === 'object' && Array.isArray(items.items) ? items.items : null);\n if (!arr) return items;\n const i18n = await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n if (!bundle) return items;\n const locale = this.extractLocale(req, i18n);\n if (!locale) return items;\n const { translateMetadataDocument } = await import('@objectstack/spec/system');\n const translated = arr.map((item) =>\n isMetaEnvelope(item)\n ? { ...item, item: translateMetadataDocument(type, item.item, bundle, { locale }) }\n : translateMetadataDocument(type, item, bundle, { locale }),\n );\n return Array.isArray(items) ? translated : { ...items, items: translated };\n }\n\n /**\n * Translate the `entries` payload returned by `getMetaTypes()` — applies\n * the active locale to each entry's `label`, `description`, and the\n * nested `form` layout (section labels, field labels, helpText,\n * placeholders) via `metadataForms.<type>` translation namespace.\n *\n * No-ops when no i18n service / locale / matching bundle entry exists,\n * so this is safe to call unconditionally from the `/meta` handler.\n */\n private async translateMetaTypesResponse(req: any, environmentId: string | undefined, payload: any): Promise<any> {\n if (!payload || typeof payload !== 'object' || !Array.isArray(payload.entries)) return payload;\n const i18n = await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n if (!bundle) return payload;\n const locale = this.extractLocale(req, i18n);\n if (!locale) return payload;\n const {\n resolveMetadataTypeLabel,\n resolveMetadataTypeDescription,\n resolveMetadataFormLabels,\n } = await import('@objectstack/spec/system');\n const opts = { locale } as const;\n const entries = payload.entries.map((entry: any) => {\n if (!entry || typeof entry !== 'object' || typeof entry.type !== 'string') return entry;\n const next: any = { ...entry };\n next.label = resolveMetadataTypeLabel(bundle, entry.type, entry.label ?? entry.type, opts);\n const desc = resolveMetadataTypeDescription(bundle, entry.type, entry.description, opts);\n if (desc !== undefined) next.description = desc;\n if (entry.form) {\n next.form = resolveMetadataFormLabels(entry.form, entry.type, bundle, opts);\n }\n return next;\n });\n return { ...payload, entries };\n }\n\n /**\n * Pull the request hostname (without port) from a Node-style `req` or\n * a Fetch-style request wrapper. Returns undefined when no Host header\n * is available.\n */\n private extractHostname(req: any): string | undefined {\n const headers = req?.headers;\n let host: string | undefined;\n if (headers) {\n if (typeof headers.get === 'function') {\n host = headers.get('host') ?? undefined;\n } else {\n host = headers.host ?? headers.Host;\n }\n }\n if (!host && typeof req?.hostname === 'string') host = req.hostname;\n if (!host && typeof req?.url === 'string') {\n // Fetch-style requests expose the hostname via `req.url` even\n // when the (forbidden) `Host` header has been stripped by the\n // runtime. This branch keeps hostname-routing working when\n // tests build a `Request` object through `app.fetch(...)`.\n try {\n host = new (globalThis as any).URL(req.url).host;\n } catch { /* ignore */ }\n }\n if (!host) return undefined;\n return String(host).split(':')[0].toLowerCase();\n }\n\n /**\n * Pull the `X-Environment-Id` header from a Node- or Fetch-style request.\n * Header names are case-insensitive; we probe both casings to cover\n * adapters that don't normalize headers (e.g. raw Node http).\n */\n private extractProjectIdHeader(req: any): string | undefined {\n const headers = req?.headers;\n if (!headers) return undefined;\n let val: unknown;\n if (typeof headers.get === 'function') {\n val = headers.get('x-environment-id') ?? headers.get('X-Environment-Id');\n } else {\n val = headers['x-environment-id'] ?? headers['X-Environment-Id'];\n }\n if (Array.isArray(val)) val = val[0];\n if (typeof val !== 'string') return undefined;\n const trimmed = val.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n }\n \n /**\n * Normalize configuration with defaults\n */\n private normalizeConfig(config: RestServerConfig): NormalizedRestServerConfig {\n const api = (config.api ?? {}) as Partial<RestApiConfig>;\n const crud = (config.crud ?? {}) as Partial<CrudEndpointsConfig>;\n const metadata = (config.metadata ?? {}) as Partial<MetadataEndpointsConfig>;\n const batch = (config.batch ?? {}) as Partial<BatchEndpointsConfig>;\n const routes = (config.routes ?? {}) as Partial<RouteGenerationConfig>;\n \n return {\n api: {\n version: api.version ?? 'v1',\n basePath: api.basePath ?? '/api',\n apiPath: api.apiPath,\n enableCrud: api.enableCrud ?? true,\n enableMetadata: api.enableMetadata ?? true,\n enableUi: api.enableUi ?? true,\n enableBatch: api.enableBatch ?? true,\n enableDiscovery: api.enableDiscovery ?? true,\n enableOpenApi: (api as any).enableOpenApi ?? true,\n enableSearch: (api as any).enableSearch ?? true,\n enableProjectScoping: api.enableProjectScoping ?? false,\n projectResolution: api.projectResolution ?? 'auto',\n requireAuth: (api as any).requireAuth ?? false,\n documentation: api.documentation,\n responseFormat: api.responseFormat,\n },\n crud: {\n operations: crud.operations ?? {\n create: true,\n read: true,\n update: true,\n delete: true,\n list: true,\n },\n patterns: crud.patterns,\n dataPrefix: crud.dataPrefix ?? '/data',\n objectParamStyle: crud.objectParamStyle ?? 'path',\n },\n metadata: {\n prefix: metadata.prefix ?? '/meta',\n enableCache: metadata.enableCache ?? true,\n cacheTtl: metadata.cacheTtl ?? 3600,\n endpoints: metadata.endpoints ?? {\n types: true,\n items: true,\n item: true,\n schema: true,\n },\n },\n batch: {\n maxBatchSize: batch.maxBatchSize ?? 200,\n enableBatchEndpoint: batch.enableBatchEndpoint ?? true,\n operations: batch.operations ?? {\n createMany: true,\n updateMany: true,\n deleteMany: true,\n upsertMany: true,\n },\n defaultAtomic: batch.defaultAtomic ?? true,\n },\n routes: {\n includeObjects: routes.includeObjects,\n excludeObjects: routes.excludeObjects,\n nameTransform: routes.nameTransform ?? 'none',\n overrides: routes.overrides,\n },\n };\n }\n \n /**\n * Get the full API base path\n */\n private getApiBasePath(): string {\n const { api } = this.config;\n return api.apiPath ?? `${api.basePath}/${api.version}`;\n }\n\n /**\n * Get the project-scoped base path for a given unscoped base.\n * Example: `/api/v1` → `/api/v1/environments/:environmentId`.\n */\n private getScopedBasePath(basePath: string): string {\n return `${basePath}/environments/:environmentId`;\n }\n\n /**\n * Register all REST API routes\n *\n * When `enableProjectScoping` is true, routes are registered under\n * `/api/v1/environments/:environmentId/...`. The `projectResolution` strategy\n * controls whether unscoped legacy routes remain available:\n * - `required` → only scoped routes registered.\n * - `optional` / `auto` → both scoped and unscoped routes registered.\n */\n registerRoutes(): void {\n const basePath = this.getApiBasePath();\n const { enableProjectScoping, projectResolution } = this.config.api;\n\n const registerForBase = (bp: string) => {\n if (this.config.api.enableDiscovery) {\n this.registerDiscoveryEndpoints(bp);\n }\n if (this.config.api.enableOpenApi ?? true) {\n this.registerOpenApiEndpoints(bp);\n }\n if (this.config.api.enableMetadata) {\n this.registerMetadataEndpoints(bp);\n }\n if (this.config.api.enableUi) {\n this.registerUiEndpoints(bp);\n }\n if (this.config.api.enableSearch ?? true) {\n this.registerSearchEndpoints(bp);\n }\n this.registerEmailEndpoints(bp);\n // Public (anonymous) form endpoints — opt-in via FormView.sharing.\n // Registered BEFORE the greedy `/data/:object` matcher so the\n // `/forms/:slug` and `/forms/:slug/submit` paths can't be\n // shadowed by a literal object named \"forms\".\n this.registerFormEndpoints(bp);\n // Capability routes (sharing rules, reports, approvals) live at\n // the top of the API surface (`/api/v1/{capability}/...`) rather\n // than under `/data/`, so they don't collide with the greedy\n // CRUD `/:object` matcher and don't pretend to be records on a\n // single object.\n this.registerSharingEndpoints(bp);\n this.registerSharingRuleEndpoints(bp);\n this.registerReportsEndpoints(bp);\n this.registerApprovalsEndpoints(bp);\n this.registerAnalyticsEndpoints(bp);\n if (this.config.api.enableCrud) {\n this.registerCrudEndpoints(bp);\n }\n this.registerDataActionEndpoints(bp);\n if (this.config.api.enableBatch) {\n this.registerBatchEndpoints(bp);\n }\n };\n\n if (enableProjectScoping) {\n const scopedBase = this.getScopedBasePath(basePath);\n if (projectResolution === 'required') {\n // Strict: only scoped routes\n registerForBase(scopedBase);\n } else {\n // 'optional' | 'auto' — keep both so legacy callers keep working\n registerForBase(basePath);\n registerForBase(scopedBase);\n }\n } else {\n registerForBase(basePath);\n }\n }\n \n /**\n * Register discovery endpoints\n */\n private registerDiscoveryEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n const discoveryHandler = async (req: any, res: any) => {\n try {\n const discovery = await this.protocol.getDiscovery();\n\n // Override discovery information with actual server configuration\n discovery.version = this.config.api.version;\n\n // Substitute the resolved environmentId into the advertised routes so\n // clients can consume them verbatim (e.g. /api/v1/environments/abc/data).\n const realBase = isScoped\n ? basePath.replace(':environmentId', req.params?.environmentId ?? ':environmentId')\n : basePath;\n\n if (discovery.routes) {\n // Ensure routes match the actual mounted paths\n if (this.config.api.enableCrud) {\n discovery.routes.data = `${realBase}${this.config.crud.dataPrefix}`;\n }\n\n if (this.config.api.enableMetadata) {\n discovery.routes.metadata = `${realBase}${this.config.metadata.prefix}`;\n }\n\n if (this.config.api.enableUi) {\n discovery.routes.ui = `${realBase}/ui`;\n }\n\n // MCP (Streamable HTTP) is opt-in per env — advertise it\n // only when OS_MCP_SERVER_ENABLED=true so the objectui\n // Integrations page surfaces the connect card. The /mcp\n // route is mounted bare (not project-scoped), so point at\n // the unscoped base. This `/discovery` (served by\n // @objectstack/rest) is separate from the dispatcher's\n // getDiscoveryInfo — both must advertise `mcp`.\n const mcpEnabled =\n (globalThis as any)?.process?.env?.OS_MCP_SERVER_ENABLED === 'true';\n if (mcpEnabled) {\n const unscopedBase = isScoped\n ? basePath.replace(/\\/(environments|projects)\\/:environmentId$/, '')\n : basePath;\n (discovery.routes as any).mcp = `${unscopedBase}/mcp`;\n } else {\n delete (discovery.routes as any).mcp;\n }\n\n // Align auth route with the versioned base path if present.\n // Auth is a control-plane concern, so use the unscoped base.\n if (discovery.routes.auth) {\n const unscopedBase = isScoped\n ? basePath.replace(/\\/projects\\/:environmentId$/, '')\n : basePath;\n discovery.routes.auth = `${unscopedBase}/auth`;\n }\n }\n\n // Attach scoping metadata so clients can detect dual-mode routing.\n (discovery as any).scoping = {\n enabled: this.config.api.enableProjectScoping,\n resolution: this.config.api.projectResolution,\n scoped: isScoped,\n environmentId: isScoped ? req.params?.environmentId : undefined,\n };\n\n res.json(discovery);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n };\n\n // Register at basePath (e.g. /api/v1)\n this.routeManager.register({\n method: 'GET',\n path: basePath,\n handler: discoveryHandler,\n metadata: {\n summary: 'Get API discovery information',\n tags: ['discovery'],\n },\n });\n\n // Register at basePath/discovery (e.g. /api/v1/discovery)\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/discovery`,\n handler: discoveryHandler,\n metadata: {\n summary: 'Get API discovery information',\n tags: ['discovery'],\n },\n });\n }\n\n /**\n * Register OpenAPI 3.1 spec + interactive docs viewer.\n *\n * GET <basePath>/openapi.json → enriched OpenAPI document\n * GET <basePath>/docs → Scalar-rendered HTML (CDN, no dep)\n *\n * Enrichment at request time:\n * - servers[0].url — derived from the request's Host header\n * - paths — `{object}` placeholders expanded into\n * one concrete path per registered object\n * from the protocol's discovery metadata\n *\n * The base spec is loaded lazily from @objectstack/spec/openapi.json\n * (shipped pre-generated by spec's build pipeline) so we don't pay\n * the cost of regenerating on every request, and a missing or\n * malformed file degrades to a stub instead of crashing.\n */\n private registerOpenApiEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const openApiHandler = async (req: any, res: any) => {\n try {\n const spec = await this.loadOpenApiSpec();\n if (!spec) {\n res.status?.(503);\n res.json({\n error: 'openapi_unavailable',\n message: 'OpenAPI spec is not bundled with this runtime.',\n });\n return;\n }\n\n // Clone shallowly so per-request mutations (server URL,\n // expanded paths) don't bleed into the cached base spec.\n const enriched: any = { ...spec, servers: [...(spec.servers ?? [])] };\n\n // 1) Override servers[0] with the actual request origin so\n // \"Try it\" works straight from the docs viewer.\n const host = req.headers?.host ?? req.headers?.['host'];\n const proto = (req.headers?.['x-forwarded-proto'] as string)\n || (req.protocol as string)\n || 'http';\n if (host) {\n enriched.servers = [\n { url: `${proto}://${host}`, description: 'Current server' },\n ...(spec.servers ?? []),\n ];\n }\n\n // 2) Expand `{object}` path placeholders into concrete\n // routes for every registered data object. Falls back\n // silently if discovery isn't available.\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const protocol = await this.resolveProtocol(environmentId, req);\n const items = await protocol?.getMetaItems?.({ type: 'object' }).catch(() => null) as any;\n const objects: string[] = Array.isArray(items?.items)\n ? items.items.map((i: any) => i?.name).filter(Boolean)\n : Array.isArray(items)\n ? items.map((i: any) => i?.name).filter(Boolean)\n : [];\n if (objects.length > 0 && enriched.paths) {\n const expanded: Record<string, unknown> = {};\n for (const [p, def] of Object.entries(enriched.paths)) {\n if (p.includes('{object}')) {\n // Keep the template under x-template for tooling\n // that wants the generic shape, and emit one\n // concrete copy per registered object.\n expanded[p] = { ...(def as object), 'x-template': true };\n for (const obj of objects) {\n expanded[p.replace('{object}', obj)] = def;\n }\n } else {\n expanded[p] = def;\n }\n }\n enriched.paths = expanded;\n }\n } catch {\n // Enrichment is best-effort — never fail the spec serve.\n }\n\n // Surface the runtime version so consumers don't pin to\n // the spec package's compile-time version.\n if (enriched.info) {\n enriched.info = {\n ...enriched.info,\n version: this.config.api.version || enriched.info.version,\n };\n }\n\n res.json(enriched);\n } catch (error: any) {\n logError('[REST] openapi.json error:', error);\n sendError(res, error);\n }\n };\n\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/openapi.json`,\n handler: openApiHandler,\n metadata: {\n summary: 'OpenAPI 3.1 specification (machine-readable)',\n tags: ['openapi'],\n },\n });\n\n // Scalar HTML viewer — single inline page that loads the spec from\n // the sibling /openapi.json endpoint. No build-time bundling, no\n // server-side render cost.\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/docs`,\n handler: async (req: any, res: any) => {\n // Resolve the openapi.json URL relative to the current\n // request so the docs page works for any host / scoped\n // base path (e.g. /api/v1 vs /api/v1/environments/abc).\n const reqPath: string = req.path || req.url || `${basePath}/docs`;\n // Strip the trailing /docs to get the API base.\n const apiBase = reqPath.replace(/\\/docs\\/?$/, '');\n const specUrl = `${apiBase}/openapi.json`;\n const html = `<!doctype html>\n<html>\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>ObjectStack API Docs</title>\n</head>\n<body>\n<script id=\"api-reference\" data-url=\"${specUrl}\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n</body>\n</html>`;\n if (res.setHeader) res.setHeader('content-type', 'text/html; charset=utf-8');\n if (res.send) res.send(html);\n else if (res.body) res.body = html;\n else res.json?.(html);\n },\n metadata: {\n summary: 'Interactive API docs (Scalar viewer)',\n tags: ['openapi'],\n },\n });\n }\n\n /**\n * Lazily load the OpenAPI spec JSON shipped by @objectstack/spec.\n * Cached after first read. Resilient to missing files / parse errors\n * so a degraded environment still boots.\n */\n private _openApiSpecCache: any | null | undefined = undefined;\n private async loadOpenApiSpec(): Promise<any | null> {\n if (this._openApiSpecCache !== undefined) return this._openApiSpecCache;\n try {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore — node built-in, no @types/node in this package\n const mod: any = await import('module');\n const requireFn = mod.createRequire((import.meta as any).url);\n const pkgJsonPath: string = requireFn.resolve('@objectstack/spec/package.json');\n // @ts-ignore\n const pathMod: any = await import('path');\n // @ts-ignore\n const fsMod: any = await import('fs');\n const specPath = pathMod.join(pathMod.dirname(pkgJsonPath), 'json-schema', 'openapi.json');\n const raw = await fsMod.promises.readFile(specPath, 'utf-8');\n this._openApiSpecCache = JSON.parse(raw);\n return this._openApiSpecCache;\n } catch (err: any) {\n logError('[REST] Failed to load OpenAPI spec:', err?.message ?? err);\n this._openApiSpecCache = null;\n return null;\n }\n }\n \n /**\n * Register metadata endpoints\n */\n private registerMetadataEndpoints(basePath: string): void {\n const { metadata } = this.config;\n const metaPath = `${basePath}${metadata.prefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n // GET /meta - List all metadata types\n if (metadata.endpoints.types !== false) {\n this.routeManager.register({\n method: 'GET',\n path: metaPath,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const types = await p.getMetaTypes();\n const translated = await this.translateMetaTypesResponse(req, environmentId, types);\n res.header('Vary', 'Accept-Language');\n res.json(translated);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List all metadata types',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/diagnostics - Cross-type spec-validation sweep\n //\n // Returns every metadata entry that fails its registered Zod\n // schema, scoped to the environment (and optionally org /\n // package) of the request. Powers the Studio governance\n // dashboard and `os doctor`-style CLI checks.\n //\n // Registered BEFORE `/meta/:type` so the `diagnostics` segment\n // is not captured as a `:type` parameter.\n if (metadata.endpoints.items !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/diagnostics`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).getMetaDiagnostics !== 'function') {\n res.status(501).json({\n error: 'not_implemented',\n message: 'protocol.getMetaDiagnostics() is not available in this kernel',\n });\n return;\n }\n const severityParam = (req.query?.severity as string | undefined) ?? 'error';\n const severity = severityParam === 'warning' ? 'warning' : 'error';\n const result = await (p as any).getMetaDiagnostics({\n type: (req.query?.type as string | undefined) || undefined,\n severity,\n packageId: (req.query?.package as string | undefined) || undefined,\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List metadata entries that fail spec validation',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/_drafts - Pending DRAFT items (ADR-0033)\n //\n // Surfaces draft-state metadata that the active-only `/meta/:type`\n // list hides, so the console can show a \"pending changes\" view and\n // draft-aware package contents (a just-built app package no longer\n // looks empty). Optionally narrowed by `?packageId=` and/or `?type=`.\n //\n // Registered BEFORE `/meta/:type` so the `_drafts` segment is not\n // captured as a `:type` parameter.\n if (metadata.endpoints.items !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/_drafts`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).listDrafts !== 'function') {\n res.status(501).json({\n error: 'not_implemented',\n message: 'protocol.listDrafts() is not available in this kernel',\n });\n return;\n }\n const result = await (p as any).listDrafts({\n packageId: (req.query?.packageId as string | undefined) || undefined,\n type: (req.query?.type as string | undefined) || undefined,\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List pending draft metadata items',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/:type - List items of a type\n if (metadata.endpoints.items !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type`,\n handler: async (req: any, res: any) => {\n try {\n const packageId = req.query?.package || undefined;\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n // ADR-0033/0037 draft-overlay preview: `?preview=draft`\n // overlays pending drafts on the active list, exactly as\n // the runtime dispatcher's /metadata/:type route does —\n // the console's draft preview (Live Canvas) reads THIS\n // route, so dropping the flag here silently renders the\n // published-only world.\n const previewDrafts = typeof req.query?.preview === 'string'\n && req.query.preview.toLowerCase() === 'draft';\n const items = await p.getMetaItems({\n type: req.params.type,\n packageId,\n ...(previewDrafts ? { previewDrafts: true } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any);\n\n // RBAC-filter app metadata for authenticated users so\n // privileged apps (Studio, Setup, etc.) and gated nav\n // items are stripped before reaching the client. We\n // intentionally leave anonymous responses untouched —\n // the existing `requireAuth` gate (when enabled) blocks\n // them upstream; when disabled, the demo / public\n // surface keeps its prior behaviour.\n //\n // `getMetaItems` is typed as `{type, items[]}` but the\n // objectql implementation actually returns the raw\n // array. Handle both shapes defensively.\n let visible: any = items;\n if (req.params.type === 'app') {\n const raw = items as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (ctx?.userId) {\n const sysPerms = new Set<string>(\n Array.isArray(ctx.systemPermissions) ? ctx.systemPermissions : [],\n );\n const filtered = list\n .map((it: any) => this.filterAppForUser(it, sysPerms))\n .filter((it: any) => it != null);\n visible = Array.isArray(raw)\n ? filtered\n : { ...(raw as any), items: filtered };\n }\n }\n }\n\n // View switcher query: GET /meta/view?object=<object>\n // returns ONLY the independent ViewItems bound to that\n // object (the `package` layer of \"Object has-many\n // View\"), sorted for the switcher / left rail. The\n // aggregated container and other objects' views are\n // excluded. Runtime `shared` / `personal` views\n // (sys_view_definition) are merged client-side via the\n // generic data API.\n if (req.params.type === 'view' && req.query?.object) {\n const obj = String(req.query.object);\n const raw = visible as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const filtered = list\n .filter((v: any) => v && typeof v === 'object' && v.viewKind && v.object === obj)\n .sort((a: any, b: any) =>\n ((a.order ?? 0) as number) - ((b.order ?? 0) as number) ||\n String(a.name).localeCompare(String(b.name)));\n visible = Array.isArray(raw) ? filtered : { ...(raw as any), items: filtered };\n }\n }\n\n // ADR-0046 i18n: collapse each doc to the request\n // locale (localized label/description, `translations`\n // map dropped) before the content-strip step below.\n if (req.params.type === 'doc') {\n const locale = this.extractLocale(req);\n const { resolveDocLocale } = await import('@objectstack/spec/system');\n const raw = visible as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const localized = list.map((it: any) =>\n it && typeof it === 'object' ? resolveDocLocale(it as any, locale) : it);\n visible = Array.isArray(raw) ? localized : { ...(raw as any), items: localized };\n }\n }\n\n // ADR-0046: `doc` list responses omit `content` by\n // default — manuals are the one metadata payload that\n // grows unbounded, and the list surface only needs\n // name + label. `?include=content` opts back in; the\n // single-item GET /meta/doc/:name always returns the\n // full body.\n if (req.params.type === 'doc' && req.query?.include !== 'content') {\n const raw = visible as unknown;\n const list: any[] | null = Array.isArray(raw)\n ? (raw as any[])\n : (raw && typeof raw === 'object' && Array.isArray((raw as any).items))\n ? ((raw as any).items as any[])\n : null;\n if (list) {\n const slim = list.map((it: any) => {\n if (!it || typeof it !== 'object') return it;\n const { content: _content, ...rest } = it;\n return rest;\n });\n visible = Array.isArray(raw) ? slim : { ...(raw as any), items: slim };\n }\n }\n\n const translated = await this.translateMetaItems(req, req.params.type, environmentId, visible);\n res.header('Vary', 'Accept-Language');\n res.json(translated);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List metadata items of a type',\n tags: ['metadata'],\n },\n });\n }\n\n // GET /meta/:type/:name - Get specific item\n if (metadata.endpoints.item !== false) {\n // Phase 3a-references: /meta/:type/:name/references must be\n // registered BEFORE /meta/:type/:name so the more-specific\n // path wins under any first-match router strategy.\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/references`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).findReferencesToMeta !== 'function') {\n res.json({ references: [] });\n return;\n }\n const result = await (p as any).findReferencesToMeta({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List metadata items that reference this item',\n tags: ['metadata'],\n },\n });\n\n // ADR-0046 §6 — GET /meta/book/:name/tree\n // Resolve a book spine against the docs that exist *now* into a\n // rendered tree (membership is DERIVED, never stored — §6.2.1). An\n // unknown name is treated as a package id and resolved against the\n // implicit per-package book (§6.4). Anonymous requests only see a\n // book whose `audience` is `public` (§6.7 read-layer gating).\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/book/:name/tree`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const prot = await this.resolveProtocol(environmentId, req);\n const locale = this.extractLocale(req);\n const packageId = req.query?.package || undefined;\n const { resolveBookTree, deriveImplicitPackageBook, isPublicAudience, resolveDocLocale } =\n await import('@objectstack/spec/system');\n\n const norm = (raw: any): any[] =>\n Array.isArray(raw) ? raw : (raw && Array.isArray(raw.items) ? raw.items : []);\n\n const books = norm(await prot.getMetaItems({\n type: 'book',\n ...(packageId ? { packageId } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any));\n let book = books.find((b: any) => b && b.name === req.params.name);\n if (!book) {\n // Unknown name → the implicit per-package book (§6.4).\n book = deriveImplicitPackageBook(req.params.name, req.params.name);\n }\n\n // §6.7 — anonymous callers only get `public` books.\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (!ctx?.userId && !isPublicAudience((book as any).audience)) {\n sendError(res, { code: 'unauthorized', message: 'This documentation requires sign-in', status: 401 });\n return;\n }\n\n const docs = norm(await prot.getMetaItems({\n type: 'doc',\n ...(packageId ? { packageId } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any))\n .map((d: any) => (d && typeof d === 'object' ? resolveDocLocale(d, locale) : d))\n .map((d: any) => ({\n name: d.name,\n label: d.label,\n description: d.description,\n order: d.order,\n group: d.group,\n tags: d.tags,\n packageId: d._packageId,\n }));\n\n const tree = resolveBookTree(book as any, docs, (book as any)._packageId);\n res.json(tree);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Resolve a documentation book spine into its rendered tree (ADR-0046 §6)',\n tags: ['metadata'],\n },\n });\n\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n\n // Phase 3a-layered-get: opt-in 3-state view when client\n // asks for `?layers=true` (or any non-empty value).\n // Skips the cache path entirely — layered view is a\n // diagnostic endpoint, not on the hot read path.\n const wantLayered = req.query?.layers !== undefined && req.query?.layers !== '';\n if (wantLayered && typeof (p as any).getMetaItemLayered === 'function') {\n // ADR-0048 — thread `?package=` so the layered (Studio\n // editor) view is package-scoped; the editor passes the\n // edited item's owning package, not the studio app's.\n const layeredPackageId = req.query?.package || undefined;\n const layered = await (p as any).getMetaItemLayered({\n type: req.params.type,\n name: req.params.name,\n ...(layeredPackageId ? { packageId: layeredPackageId } : {}),\n ...(environmentId ? { environmentId } : {}),\n });\n res.json(layered);\n return;\n }\n\n // Check if cached version is available.\n // For `app` metadata we skip the cache path so the\n // per-user RBAC filter below can apply without\n // corrupting shared ETags across admin vs member\n // viewers of the same app schema. Drafts also\n // bypass cache: the cache is keyed on the\n // published checksum and drafts are out-of-band.\n const isAppType = req.params.type === 'app';\n const isDraftRead = typeof req.query?.state === 'string'\n && req.query.state.toLowerCase() === 'draft';\n // ADR-0033/0037 — `?preview=draft` overlays a pending\n // draft on the active item (draft wins, falls back to\n // active). Must also bypass the cache: ETags are keyed\n // on the published checksum, so a cached 304 would pin\n // the preview to the stale published world.\n const previewDrafts = typeof req.query?.preview === 'string'\n && req.query.preview.toLowerCase() === 'draft';\n // ADR-0048 — a `?package=` read is package-scoped\n // (prefer-local). The cached path keys ETags on\n // type+name only and does NOT thread `packageId` into\n // `getMetaItemCached`, so two installed packages shipping\n // the same type/name would share one cache entry and the\n // scope hint would be silently dropped. Bypass the cache\n // when a package scope is requested so the disambiguating\n // `getMetaItem(type, name, packageId)` path runs.\n const packageScoped = typeof req.query?.package === 'string'\n && req.query.package.length > 0;\n if (metadata.enableCache && p.getMetaItemCached && !isAppType && !isDraftRead && !previewDrafts && !packageScoped && req.params.type !== 'doc') {\n const cacheRequest = {\n ifNoneMatch: req.headers['if-none-match'] as string,\n ifModifiedSince: req.headers['if-modified-since'] as string,\n };\n\n // Resolve the response locale up-front and fold it\n // into the cache key. The body is translated below\n // (`translateMetaItem`) *after* this validator runs,\n // so without a locale-aware ETag a language switch\n // would return a stale-locale 304 (issue #1319).\n const cacheI18n = await this.resolveI18nService(environmentId, req);\n const cacheLocale = this.extractLocale(req, cacheI18n);\n\n const result = await p.getMetaItemCached({\n type: req.params.type,\n name: req.params.name,\n cacheRequest,\n ...(cacheLocale ? { locale: cacheLocale } : {}),\n ...(environmentId ? { environmentId } : {}),\n } as any);\n\n if (result.notModified) {\n res.status(304).send();\n return;\n }\n\n // Set cache headers\n if (result.etag) {\n const etagValue = result.etag.weak\n ? `W/\"${result.etag.value}\"`\n : `\"${result.etag.value}\"`;\n res.header('ETag', etagValue);\n }\n if (result.lastModified) {\n res.header('Last-Modified', new Date(result.lastModified).toUTCString());\n }\n if (result.cacheControl) {\n const directives = result.cacheControl.directives.join(', ');\n const maxAge = result.cacheControl.maxAge\n ? `, max-age=${result.cacheControl.maxAge}`\n : '';\n res.header('Cache-Control', directives + maxAge);\n }\n\n res.header('Vary', 'Accept-Language');\n res.json(await this.translateMetaItem(req, req.params.type, environmentId, result.data, cacheI18n));\n } else {\n // Non-cached version\n const packageId = req.query?.package || undefined;\n const stateParam = typeof req.query?.state === 'string'\n ? req.query.state.toLowerCase()\n : undefined;\n const item = await p.getMetaItem({\n type: req.params.type,\n name: req.params.name,\n packageId,\n ...(stateParam === 'draft' ? { state: 'draft' } : {}),\n ...(previewDrafts ? { previewDrafts: true } : {}),\n } as any);\n\n // Same per-user RBAC filtering as the list endpoint:\n // for `app` items, drop entirely (404) when the user\n // lacks the app's `requiredPermissions`, and strip\n // forbidden nav entries from the returned schema.\n let visible: any = item;\n if (isAppType && item) {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (ctx?.userId) {\n const sysPerms = new Set<string>(\n Array.isArray(ctx.systemPermissions) ? ctx.systemPermissions : [],\n );\n visible = this.filterAppForUser(item, sysPerms);\n if (visible == null) {\n res.status(404).json({\n error: 'not_found',\n message: 'Metadata item not found or access denied.',\n });\n return;\n }\n }\n }\n\n // ADR-0046 i18n: collapse the doc to the request\n // locale (label/description/content) and drop the\n // `translations` map so consumers get one body.\n if (req.params.type === 'doc' && visible) {\n const locale = this.extractLocale(req);\n const { resolveDocLocale } = await import('@objectstack/spec/system');\n visible = isMetaEnvelope(visible)\n ? { ...visible, item: resolveDocLocale(visible.item as any, locale) }\n : resolveDocLocale(visible as any, locale);\n }\n\n res.header('Vary', 'Accept-Language');\n res.json(await this.translateMetaItem(req, req.params.type, environmentId, visible));\n }\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Get specific metadata item',\n tags: ['metadata'],\n },\n });\n }\n\n // PUT /meta/:type/:name - Save metadata item\n // We always register this route, but return 501 if protocol doesn't support it\n // This makes it discoverable even if not implemented\n this.routeManager.register({\n method: 'PUT',\n path: `${metaPath}/:type/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!p.saveMetaItem) {\n res.status(501).json({ error: 'Save operation not supported by protocol implementation' });\n return;\n }\n\n // Accept both `{ ...itemFields }` (bare) and `{ metadata: {...} }`\n // / `{ item: {...} }` envelope shapes. Studio and direct API\n // callers historically use either; ADR-0005 settles on\n // unwrapping to a single payload before persistence.\n const body = req.body ?? {};\n const item = (body && typeof body === 'object' && 'metadata' in body)\n ? (body as any).metadata\n : (body && typeof body === 'object' && 'item' in body)\n ? (body as any).item\n : body;\n\n // Opt-in OCC under ADR-0008 PR-10d.3: callers (Studio,\n // CLI) may set `If-Match: <sha256:...>` to enforce that\n // the overlay row has not advanced since they last read\n // it. A `null`/empty body or no header preserves the\n // legacy last-write-wins behaviour.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const parentVersion = typeof ifMatchHeader === 'string'\n ? ifMatchHeader.replace(/^\"|\"$/g, '') // strip ETag-style quotes\n : undefined;\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n // Phase 3a-destructive: `?force=true` opts past the\n // destructive-change safety check. Accept any truthy\n // string ('true', '1', 'yes') for resilience.\n const forceRaw = req.query?.force;\n const force = typeof forceRaw === 'string'\n ? ['true', '1', 'yes', 'on'].includes(forceRaw.toLowerCase())\n : !!forceRaw;\n\n // Software-package binding (Studio package authoring).\n // `?package=<id>` binds the saved row to that package\n // (sys_metadata.package_id). 'all'/empty = env-local overlay.\n const packageRaw = req.query?.package;\n const packageId = typeof packageRaw === 'string' && packageRaw && packageRaw !== 'all'\n ? packageRaw\n : undefined;\n\n const result = await p.saveMetaItem({\n type: req.params.type,\n name: req.params.name,\n item,\n ...(environmentId ? { environmentId } : {}),\n ...(parentVersion !== undefined ? { parentVersion } : {}),\n ...(actor ? { actor } : {}),\n ...(force ? { force: true } : {}),\n ...(packageId ? { packageId } : {}),\n ...((typeof req.query?.mode === 'string'\n && req.query.mode.toLowerCase() === 'draft')\n ? { mode: 'draft' } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Save specific metadata item',\n tags: ['metadata'],\n },\n });\n\n // DELETE /meta/:type/:name - Reset metadata item to artifact default\n // Removes a customization overlay row from sys_metadata (ADR-0005).\n // Returns 200 even when no overlay existed (idempotent reset).\n this.routeManager.register({\n method: 'DELETE',\n path: `${metaPath}/:type/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).deleteMetaItem) {\n res.status(501).json({\n error: 'Reset operation not supported by protocol implementation',\n });\n return;\n }\n // Mirror saveMetaItem's OCC + actor plumbing (ADR-0008\n // PR-10d wiring): `If-Match` pins the expected current\n // version so concurrent edits get a 409 instead of a\n // silent reset; `X-Actor` (or req.user) flows into the\n // history tombstone row.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const parentVersion = typeof ifMatchHeader === 'string'\n ? ifMatchHeader.replace(/^\"|\"$/g, '')\n : undefined;\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n\n const stateParam = typeof req.query?.state === 'string'\n && req.query.state.toLowerCase() === 'draft'\n ? 'draft' as const\n : undefined;\n\n // `?dropStorage=true` also tears down the object's physical\n // table (object + active only). Used by the \"discard a\n // previewed object\" flow so a publish-to-preview leaves no\n // orphan table. Destructive — opt-in, defaults off.\n const dropStorage = req.query?.dropStorage === 'true' || req.query?.dropStorage === '1';\n\n const result = await (p as any).deleteMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(parentVersion !== undefined ? { parentVersion } : {}),\n ...(actor ? { actor } : {}),\n ...(stateParam ? { state: stateParam } : {}),\n ...(dropStorage ? { dropStorage: true } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Reset metadata item to artifact default (deletes customization overlay)',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:name/history — durable change-log for one item.\n // Returns the sys_metadata_history events that the Studio \"History\"\n // tab renders as an audit timeline. Overlay-only metadata types\n // (view/dashboard/report/email_template) return real events;\n // non-overlay types return `{ events: [] }` (the legacy raw-engine\n // path does not record history).\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/history`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).historyMetaItem) {\n res.status(501).json({\n error: 'History query not supported by protocol implementation',\n });\n return;\n }\n const sinceSeq = req.query?.sinceSeq !== undefined\n ? Number(req.query.sinceSeq)\n : undefined;\n const limit = req.query?.limit !== undefined\n ? Number(req.query.limit)\n : undefined;\n const result = await (p as any).historyMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(sinceSeq !== undefined && Number.isFinite(sinceSeq) ? { sinceSeq } : {}),\n ...(limit !== undefined && Number.isFinite(limit) ? { limit } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List durable history events for a metadata item',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:name/audit — ADR-0010 §3.6 / Phase 4.1.\n // Compliance trail for the metadata-protection layer: returns\n // recent sys_metadata_audit rows (save/publish/rollback/delete/\n // reset attempts, both allowed and denied) so Studio's \"审计\n // 日志 / Audit log\" tab can show who tried what and whether\n // a lock blocked it. Empty array on environments where the\n // table is not yet provisioned.\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/audit`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).auditMetaItem !== 'function') {\n res.json({ events: [] });\n return;\n }\n const limit = req.query?.limit !== undefined\n ? Number(req.query.limit)\n : undefined;\n const result = await (p as any).auditMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(limit !== undefined && Number.isFinite(limit) ? { limit } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'List protection-audit events for a metadata item',\n tags: ['metadata'],\n },\n });\n\n // POST /meta/:type/:name/publish — promote the pending draft\n // overlay to live. 404 [no_draft] when nothing to publish.\n this.routeManager.register({\n method: 'POST',\n path: `${metaPath}/:type/:name/publish`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).publishMetaItem) {\n res.status(501).json({\n error: 'Publish operation not supported by protocol implementation',\n });\n return;\n }\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n const body = (req.body && typeof req.body === 'object') ? req.body : {};\n const message = typeof body.message === 'string' ? body.message : undefined;\n const result = await (p as any).publishMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(actor ? { actor } : {}),\n ...(message ? { message } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Publish the pending draft overlay (promotes draft → active)',\n tags: ['metadata'],\n },\n });\n\n // POST /meta/:type/:name/rollback — restore a historical version\n // as the new live overlay. Body: { toVersion: <number>, message? }.\n this.routeManager.register({\n method: 'POST',\n path: `${metaPath}/:type/:name/rollback`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).rollbackMetaItem) {\n res.status(501).json({\n error: 'Rollback operation not supported by protocol implementation',\n });\n return;\n }\n const body = (req.body && typeof req.body === 'object') ? req.body : {};\n const toVersionRaw = body.toVersion ?? body.version ?? req.query?.toVersion;\n const toVersion = Number(toVersionRaw);\n if (!Number.isFinite(toVersion) || toVersion < 1) {\n res.status(400).json({\n error: `'toVersion' (positive integer) is required`,\n code: 'invalid_request',\n });\n return;\n }\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n const message = typeof body.message === 'string' ? body.message : undefined;\n const result = await (p as any).rollbackMetaItem({\n type: req.params.type,\n name: req.params.name,\n toVersion,\n ...(environmentId ? { environmentId } : {}),\n ...(actor ? { actor } : {}),\n ...(message ? { message } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Restore the body at the given history version as the new live row',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:name/diff?from=N&to=M — structural diff\n // between two historical versions (or one version vs current).\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:name/diff`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!(p as any).diffMetaItem) {\n res.status(501).json({\n error: 'Diff operation not supported by protocol implementation',\n });\n return;\n }\n const parseV = (raw: any): number | undefined => {\n if (raw === undefined || raw === null || raw === '') return undefined;\n const n = Number(raw);\n return Number.isFinite(n) ? n : undefined;\n };\n const fromVersion = parseV(req.query?.from ?? req.query?.fromVersion);\n const toVersion = parseV(req.query?.to ?? req.query?.toVersion);\n const result = await (p as any).diffMetaItem({\n type: req.params.type,\n name: req.params.name,\n ...(environmentId ? { environmentId } : {}),\n ...(fromVersion !== undefined ? { fromVersion } : {}),\n ...(toVersion !== undefined ? { toVersion } : {}),\n });\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Diff two metadata versions (from/to query params; omit for previous-vs-current)',\n tags: ['metadata'],\n },\n });\n\n // GET /meta/:type/:section/:name - Get specific item with compound name\n // Compound names express sub-resources of a type (e.g. a view of an\n // object, a flow under an automation). The protocol layer treats\n // `<section>/<name>` as a single opaque key.\n if (metadata.endpoints.item !== false) {\n this.routeManager.register({\n method: 'GET',\n path: `${metaPath}/:type/:section/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const compoundName = `${req.params.section}/${req.params.name}`;\n const packageId = req.query?.package || undefined;\n const item = await p.getMetaItem({\n type: req.params.type,\n name: compoundName,\n packageId,\n } as any);\n res.header('Vary', 'Accept-Language');\n res.json(await this.translateMetaItem(req, req.params.type, environmentId, item));\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Get specific metadata item by compound name',\n tags: ['metadata'],\n },\n });\n }\n\n // PUT /meta/:type/:section/:name - Save metadata item with compound name\n this.routeManager.register({\n method: 'PUT',\n path: `${metaPath}/:type/:section/:name`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (!p.saveMetaItem) {\n res.status(501).json({ error: 'Save operation not supported by protocol implementation' });\n return;\n }\n\n const compoundName = `${req.params.section}/${req.params.name}`;\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const parentVersion = typeof ifMatchHeader === 'string'\n ? ifMatchHeader.replace(/^\"|\"$/g, '')\n : undefined;\n const actorHeader = req.headers?.['x-actor'] ?? req.headers?.['X-Actor']\n ?? req.user?.id ?? req.userId;\n const actor = typeof actorHeader === 'string' ? actorHeader : undefined;\n\n const packageRaw = req.query?.package;\n const packageId = typeof packageRaw === 'string' && packageRaw && packageRaw !== 'all'\n ? packageRaw\n : undefined;\n\n const result = await p.saveMetaItem({\n type: req.params.type,\n name: compoundName,\n item: req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(parentVersion !== undefined ? { parentVersion } : {}),\n ...(actor ? { actor } : {}),\n ...(packageId ? { packageId } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Save specific metadata item by compound name',\n tags: ['metadata'],\n },\n });\n }\n\n /**\n * Register UI endpoints\n */\n private registerUiEndpoints(basePath: string): void {\n const uiPath = `${basePath}/ui`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n // GET /ui/view/:object/:type - Resolve view for object\n this.routeManager.register({\n method: 'GET',\n path: `${uiPath}/view/:object/:type`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n if (p.getUiView) {\n const view = await p.getUiView({\n object: req.params.object,\n type: req.params.type as any,\n ...(environmentId ? { environmentId } : {}),\n } as any);\n res.json(view);\n } else {\n res.status(501).json({ error: 'UI View resolution not supported by protocol implementation' });\n }\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Resolve UI View for object',\n tags: ['ui'],\n },\n });\n }\n \n /**\n * Register CRUD endpoints for data operations\n */\n private registerCrudEndpoints(basePath: string): void {\n const { crud } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const operations = crud.operations;\n\n // GET /data/:object - List/query records\n if (operations.list) {\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'list')) return;\n const result = await p.findData({\n object: req.params.object,\n query: req.query,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (mapped.status === 404 || mapped.status === 503 || mapped.status === 502) {\n res.status(mapped.status).json(mapped.body);\n } else {\n logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n }\n },\n metadata: {\n summary: 'Query records',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // GET /data/:object/:id - Get single record\n if (operations.read) {\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const { select, expand } = req.query || {};\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'get')) return;\n const result = await p.getData({\n object: req.params.object,\n id: req.params.id,\n ...(select != null ? { select } : {}),\n ...(expand != null ? { expand } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status === 400 ? 404 : mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Get record by ID',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // POST /data/:object - Create record\n if (operations.create) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'create')) return;\n const result = await p.createData({\n object: req.params.object,\n data: req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.status(201).json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Create record',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // POST /data/:object/query — Spec-shape advanced query (QueryAST in body).\n // Supports server-side aggregation via { groupBy, aggregations, where, ... }\n // per spec/data/query.zod.ts. Mirrors what `client.data.query()` posts.\n // Returns FindDataResponse = { object, records, total? }.\n if (operations.list) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/query`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'list')) return;\n const result = await p.findData({\n object: req.params.object,\n query: req.body || {},\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status)) logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Advanced query (QueryAST in body)',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // PATCH /data/:object/:id - Update record\n if (operations.update) {\n this.routeManager.register({\n method: 'PATCH',\n path: `${dataPath}/:object/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n // OCC: clients opt in by sending either the standard\n // `If-Match` header or an `expectedVersion` field in\n // the JSON body. Body wins when both are present\n // (lets callers override per-request without\n // touching headers). See ConcurrentUpdateError in\n // packages/objectql/src/protocol.ts.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const bodyVersion = (req.body && typeof req.body === 'object')\n ? (req.body as any).expectedVersion\n : undefined;\n const expectedVersion = bodyVersion ?? ifMatchHeader;\n // Strip the meta field out of the data payload so it\n // doesn't get written as a column.\n let data = req.body;\n if (data && typeof data === 'object' && 'expectedVersion' in (data as any)) {\n const { expectedVersion: _drop, ...rest } = data as any;\n data = rest;\n }\n if (await this.enforceApiAccess(req, res, p, environmentId, 'update')) return;\n const result = await p.updateData({\n object: req.params.object,\n id: req.params.id,\n data,\n ...(expectedVersion ? { expectedVersion: String(expectedVersion) } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Update record',\n tags: ['data', 'crud'],\n },\n });\n }\n\n // DELETE /data/:object/:id - Delete record\n if (operations.delete) {\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/:object/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n // OCC: same opt-in protocol as PATCH (`If-Match`\n // header or `expectedVersion` query string). DELETE\n // has no JSON body, so we only accept the header\n // and a query parameter.\n const ifMatchHeader = req.headers?.['if-match'] ?? req.headers?.['If-Match'];\n const queryVersion = (req.query && typeof req.query === 'object')\n ? (req.query as any).expectedVersion\n : undefined;\n const expectedVersion = queryVersion ?? ifMatchHeader;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'delete')) return;\n const result = await p.deleteData({\n object: req.params.object,\n id: req.params.id,\n ...(expectedVersion ? { expectedVersion: String(expectedVersion) } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error, req.params?.object);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== \"VALIDATION_FAILED\") logError(\"[REST] Unhandled error:\", error);\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Delete record',\n tags: ['data', 'crud'],\n },\n });\n }\n }\n \n /**\n * Register object-specific action endpoints that don't fit the\n * generic CRUD shape — domain operations where the protocol does its\n * own orchestration and we just need a thin HTTP route.\n *\n * POST {basePath}/data/:object/:id/clone — record clone (gated by\n * `enable.clone`). This is object-agnostic by design: it works for any\n * authored object regardless of namespace, unlike a hardcoded\n * per-object route would.\n */\n private registerDataActionEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n const { crud } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n\n // POST /data/:object/:id/clone — duplicate a record (gated by the\n // object's `enable.clone` capability, default on). Optional JSON body\n // `{ overrides?: {...} }` (or a bare field map) is applied on top of\n // the copied values, e.g. to set a new name or clear a unique field.\n // Distinct path segment (`/clone`) keeps it clear of the greedy\n // `/data/:object/:id` matchers.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/:id/clone`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'create')) return;\n const cloneData = (p as any).cloneData;\n if (typeof cloneData !== 'function') {\n res.status(501).json({ code: 'NOT_IMPLEMENTED', error: 'Clone not supported by this protocol' });\n return;\n }\n const body = req.body ?? {};\n // Accept both `{ overrides: {...} }` and a bare field map so\n // callers can POST overrides directly without nesting.\n const overrides = (body && typeof body === 'object' && 'overrides' in body)\n ? body.overrides\n : body;\n const result = await cloneData.call(p, {\n object: req.params.object,\n id: req.params.id,\n ...(overrides && typeof overrides === 'object' ? { overrides } : {}),\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n res.status(201).json(result);\n } catch (error: any) {\n // Clone's domain errors (CLONE_DISABLED/RECORD_NOT_FOUND)\n // carry an explicit `.status`; fall back to mapDataError for\n // driver/validation faults. Only log genuine server faults.\n const status = typeof error?.status === 'number'\n ? error.status\n : mapDataError(error, req.params?.object).status;\n if (!isExpectedDataStatus(status) && error?.code !== 'VALIDATION_FAILED') logError('[REST] Unhandled error:', error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Clone a record (gated by enable.clone)',\n tags: ['data', 'clone'],\n },\n });\n\n // POST /data/:object/import — bulk CSV/JSON ingestion (M10.9)\n //\n // Body shapes:\n // { format: 'csv', csv: '...header,row,...', dryRun?: boolean, mapping?: {<csvCol>:<field>} }\n // { format: 'json', rows: [...], dryRun?: boolean }\n //\n // Returns per-row outcome so a UI can present an import report.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/import`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const objectName = String(req.params.object || '');\n if (!objectName) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'object is required' });\n return;\n }\n if (await this.enforceApiAccess(req, res, p, environmentId, 'import')) return;\n const body = req.body ?? {};\n const dryRun = body.dryRun === true;\n const mapping: Record<string, string> = body.mapping ?? {};\n\n // Build rows[] from either explicit JSON array or CSV text.\n let rows: Array<Record<string, any>> = [];\n if (body.format === 'json' && Array.isArray(body.rows)) {\n rows = body.rows as Array<Record<string, any>>;\n } else if ((body.format === 'csv' || typeof body.csv === 'string') && typeof body.csv === 'string') {\n rows = parseCsvToRows(body.csv, mapping);\n } else if (Array.isArray(body)) {\n // Permissive: a bare JSON array at the top level.\n rows = body as Array<Record<string, any>>;\n } else {\n res.status(400).json({\n code: 'INVALID_REQUEST',\n error: 'Provide either format:\"csv\" with csv text or format:\"json\" with rows[]',\n });\n return;\n }\n\n const max = 5000;\n if (rows.length > max) {\n res.status(413).json({\n code: 'PAYLOAD_TOO_LARGE',\n error: `Import limit is ${max} rows per request (got ${rows.length})`,\n });\n return;\n }\n\n const results: Array<{ row: number; ok: boolean; id?: string; error?: string; code?: string }> = [];\n let okCount = 0;\n let errCount = 0;\n\n for (let i = 0; i < rows.length; i++) {\n const data = rows[i];\n try {\n if (dryRun) {\n // Validate via protocol's metadata layer when available, else\n // best-effort: treat any non-empty row as syntactically OK.\n const validate = (p as any).validate;\n if (typeof validate === 'function') {\n await validate.call(p, { object: objectName, data, context });\n }\n results.push({ row: i + 1, ok: true });\n okCount++;\n } else {\n const created = await (p as any).createData({ object: objectName, data, context });\n const id = (created as any)?.id ?? (created as any)?.record?.id;\n results.push({ row: i + 1, ok: true, id });\n okCount++;\n }\n } catch (err: any) {\n errCount++;\n const code = err?.code ?? 'IMPORT_ROW_FAILED';\n const message = typeof err?.message === 'string' ? err.message.slice(0, 300) : 'Row failed';\n results.push({ row: i + 1, ok: false, error: message, code });\n }\n }\n\n res.json({\n object: objectName,\n dryRun,\n total: rows.length,\n ok: okCount,\n errors: errCount,\n results,\n });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, String(req.params?.object || ''));\n }\n },\n metadata: {\n summary: 'Bulk-import rows into an object (CSV or JSON, with optional dry-run)',\n tags: ['data', 'import'],\n },\n });\n\n // GET /data/:object/export — streaming export (M10.21 / C.21)\n //\n // Query params:\n // format=csv|json (default: csv. json emits a JSON array.)\n // fields=a,b,c (default: derive from object schema; falls back to keys of the first row)\n // filter=<json> ($filter as URL-encoded JSON, same shape as list endpoint)\n // orderby=field:desc (optional ordering, mirrors $orderby semantics)\n // limit=<n> (default 10000, hard cap 50000)\n // page=<n> (driver chunk size, default 500, max 5000)\n //\n // Streams the response so 50k-row exports do not buffer in memory.\n // Filename suggests `${object}-${YYYY-MM-DD}.${ext}` for browsers.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object/export`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const objectName = String(req.params.object || '');\n if (!objectName) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'object is required' });\n return;\n }\n if (await this.enforceApiAccess(req, res, p, environmentId, 'export')) return;\n const q = req.query ?? {};\n const format = (String(q.format ?? 'csv')).toLowerCase() === 'json' ? 'json' : 'csv';\n const HARD_CAP = 50_000;\n const MAX_CHUNK = 5_000;\n const requestedLimit = q.limit != null ? Math.max(1, Number(q.limit) || 0) : 10_000;\n const limit = Math.min(requestedLimit, HARD_CAP);\n const chunkSize = Math.min(MAX_CHUNK, Math.max(50, q.page != null ? Number(q.page) || 500 : 500));\n\n let filter: any = undefined;\n if (typeof q.filter === 'string' && q.filter.length > 0) {\n try { filter = JSON.parse(q.filter); }\n catch {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'filter must be JSON' });\n return;\n }\n } else if (q.filter && typeof q.filter === 'object') {\n filter = q.filter;\n }\n\n let orderby: any = undefined;\n if (typeof q.orderby === 'string' && q.orderby.length > 0) {\n // Accept \"field:dir,field2:dir\" shorthand or a JSON object.\n if (q.orderby.startsWith('{') || q.orderby.startsWith('[')) {\n try { orderby = JSON.parse(q.orderby); } catch { /* leave undefined */ }\n } else {\n const obj: Record<string, 'asc' | 'desc'> = {};\n for (const part of q.orderby.split(',')) {\n const [field, dir] = part.split(':').map((s: string) => s.trim());\n if (field) obj[field] = dir?.toLowerCase() === 'desc' ? 'desc' : 'asc';\n }\n if (Object.keys(obj).length > 0) orderby = obj;\n }\n }\n\n // Resolve fields: explicit param > schema fields > derived from first row.\n let fields: string[] | undefined;\n if (typeof q.fields === 'string' && q.fields.length > 0) {\n fields = q.fields.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(q.fields)) {\n fields = q.fields.filter((s: any) => typeof s === 'string' && s.length > 0);\n }\n if (!fields || fields.length === 0) {\n try {\n const schema = await (p as any).getObjectSchema?.(objectName, environmentId);\n const schemaFields = schema?.fields;\n if (Array.isArray(schemaFields)) {\n fields = schemaFields.map((f: any) => f.name).filter((n: any) => typeof n === 'string');\n }\n } catch { /* fall back to first-row derivation */ }\n }\n\n // Prepare streaming response. Set headers BEFORE first write.\n const stamp = new Date().toISOString().slice(0, 10);\n const safeObj = objectName.replace(/[^A-Za-z0-9_.-]/g, '_');\n if (format === 'csv') {\n res.header('Content-Type', 'text/csv; charset=utf-8');\n res.header('Content-Disposition', `attachment; filename=\"${safeObj}-${stamp}.csv\"`);\n } else {\n res.header('Content-Type', 'application/json; charset=utf-8');\n res.header('Content-Disposition', `attachment; filename=\"${safeObj}-${stamp}.json\"`);\n }\n res.header('X-Export-Format', format);\n res.header('X-Export-Limit', String(limit));\n res.header('Cache-Control', 'no-store');\n\n let exported = 0;\n let firstChunk = true;\n let skip = 0;\n if (format === 'json') res.write('[');\n\n while (exported < limit) {\n const take = Math.min(chunkSize, limit - exported);\n const findArgs: any = {\n object: objectName,\n query: {\n ...(filter ? { $filter: filter } : {}),\n ...(orderby ? { $orderby: orderby } : {}),\n $top: take,\n $skip: skip,\n },\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n };\n const result: any = await (p as any).findData(findArgs);\n const rows: any[] = Array.isArray(result?.data) ? result.data\n : Array.isArray(result?.rows) ? result.rows\n : Array.isArray(result) ? result : [];\n\n if (rows.length === 0) break;\n\n if (format === 'csv') {\n // Derive fields from the first row if schema lookup failed.\n if ((!fields || fields.length === 0) && firstChunk) {\n fields = Object.keys(rows[0] ?? {});\n }\n const text = rowsToCsv(fields ?? [], rows, firstChunk);\n res.write(text);\n } else {\n for (let i = 0; i < rows.length; i++) {\n const prefix = (firstChunk && i === 0) ? '' : ',';\n res.write(prefix + JSON.stringify(rows[i]));\n }\n }\n firstChunk = false;\n exported += rows.length;\n skip += rows.length;\n if (rows.length < take) break;\n }\n if (format === 'json') res.write(']');\n res.end();\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n // Best-effort error envelope; if headers already sent the\n // client receives a truncated stream which signals failure.\n try { sendError(res, error, String(req.params?.object || '')); }\n catch { try { res.end(); } catch { /* swallow */ } }\n }\n },\n metadata: {\n summary: 'Streaming export of object rows (CSV or JSON)',\n tags: ['data', 'export'],\n },\n });\n }\n\n /**\n * Register global cross-object search endpoint (M10.5).\n * GET {basePath}/search?q=acme&objects=lead,account&limit=20&perObject=5\n */\n private registerSearchEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/search`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const searchAll = (p as any).searchAll;\n if (typeof searchAll !== 'function') {\n res.status(501).json({ code: 'NOT_IMPLEMENTED', message: 'Search not supported by this protocol' });\n return;\n }\n const q = String(req.query?.q ?? req.query?.query ?? '');\n const objectsParam = req.query?.objects;\n const objects = typeof objectsParam === 'string'\n ? objectsParam.split(',').map((s: string) => s.trim()).filter(Boolean)\n : Array.isArray(objectsParam) ? objectsParam : undefined;\n const result = await searchAll.call(p, {\n q,\n objects,\n limit: req.query?.limit ? Number(req.query.limit) : undefined,\n perObject: req.query?.perObject ? Number(req.query.perObject) : undefined,\n ...(context ? { context } : {}),\n });\n res.json(result);\n } catch (error: any) {\n const mapped = mapDataError(error);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== 'VALIDATION_FAILED') {\n logError('[REST] Unhandled error:', error);\n }\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Global cross-object search',\n tags: ['search'],\n },\n });\n }\n\n /**\n * Register email endpoints (M11.B1 / M10.7).\n *\n * POST {basePath}/email/send — send a transactional email via the\n * `IEmailService` provider registered by EmailServicePlugin. Returns\n * 501 when no provider is wired so deployments without email\n * configured fail cleanly.\n *\n * Request body:\n * {\n * to: \"a@b.com\" | [\"a@b.com\", { name, address }],\n * from?: ..., cc?: ..., bcc?: ..., replyTo?: ...,\n * subject: string,\n * text?: string, html?: string, // at least one required\n * attachments?: [{ filename, content, contentType?, cid? }],\n * headers?: { [name]: value },\n * relatedObject?: string, relatedId?: string,\n * }\n */\n private registerEmailEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/email/send`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n\n if (!this.emailServiceProvider) {\n res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Email service is not configured on this deployment',\n });\n return;\n }\n const emailService = await this.emailServiceProvider(environmentId).catch(() => undefined);\n if (!emailService || typeof emailService.send !== 'function') {\n res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Email service is not configured on this deployment',\n });\n return;\n }\n\n const body = req.body ?? {};\n if (!body || typeof body !== 'object') {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'JSON body required' });\n return;\n }\n // Stamp sentBy from the authenticated context when caller didn't supply one.\n const input = {\n ...body,\n ...(body.sentBy === undefined && (context as any)?.userId\n ? { sentBy: (context as any).userId }\n : {}),\n };\n\n try {\n const result = await emailService.send(input);\n if (result?.status === 'sent') {\n res.status(200).json(result);\n } else {\n // failed / queued — still surface to client with 200 so clients can branch on status.\n res.status(200).json(result);\n }\n } catch (err: any) {\n // Validation errors from normalizeMessage are surfaced as 400.\n const message = String(err?.message ?? err ?? 'send failed');\n if (message.startsWith('VALIDATION_FAILED')) {\n res.status(400).json({\n code: 'VALIDATION_FAILED',\n error: message.replace(/^VALIDATION_FAILED:\\s*/, ''),\n });\n return;\n }\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Email send unhandled error:', error);\n res.status(500).json({\n code: 'EMAIL_SEND_FAILED',\n error: String(error?.message ?? error ?? 'send failed').slice(0, 500),\n });\n }\n },\n metadata: {\n summary: 'Send a transactional email via the configured EmailService',\n tags: ['email'],\n },\n });\n }\n\n /**\n * Register public (anonymous) form endpoints.\n *\n * Public forms are opt-in: a `FormView` becomes accessible to anonymous\n * visitors only when `sharing.allowAnonymous === true` AND a\n * `sharing.publicLink` slug is configured. Two routes are registered:\n *\n * GET {basePath}/forms/:slug → resolved form spec\n * POST {basePath}/forms/:slug/submit → INSERT record (no auth required)\n *\n * Both routes bypass `enforceAuth` even when `requireAuth=true` on the\n * deployment (e.g. ObjectOS multi-tenant). Security is delegated to the\n * `guest_portal` permission set carried on the execution context — the\n * SecurityPlugin enforces INSERT-only access to the target object. If\n * the deployment hasn't registered a `guest_portal` profile, the\n * security middleware falls open with `permissions: []` (no userId),\n * matching the existing anonymous-access semantics; deployers must\n * keep `requireAuth=true` deployments paired with a `guest_portal`\n * profile (the CRM example does this) to enforce the INSERT-only\n * contract.\n *\n * The matched FormView's parent ViewSchema is found by scanning\n * `protocol.getMetaItems({ type: 'view' })`. For each entry we inspect\n * `form.sharing` and every entry in `formViews`; the first FormView\n * whose `sharing.publicLink` matches `/forms/:slug` (or just `:slug`)\n * wins. The response carries the matched form view under `form` and\n * the inferred target object, matching what the frontend's\n * `mapViewSpecToEmbeddableConfig` expects.\n */\n private registerFormEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const slugMatchesPublicLink = (publicLink: string | undefined, slug: string): boolean => {\n if (!publicLink || typeof publicLink !== 'string') return false;\n // Accept `/forms/:slug`, `forms/:slug`, or a bare slug.\n const normalized = publicLink.replace(/^\\/+/, '').replace(/^forms\\//, '');\n return normalized === slug;\n };\n\n const findPublicFormView = (views: any[], slug: string): { view: any; form: any; object: string } | null => {\n for (const view of views ?? []) {\n if (!view || typeof view !== 'object') continue;\n const candidates: Array<{ form: any; key?: string }> = [];\n // Authoring/nested shape (defineView): { form, formViews: { key: {...} } }.\n if (view.form && view.form.sharing) candidates.push({ form: view.form });\n const formViews = view.formViews;\n if (formViews && typeof formViews === 'object') {\n for (const [key, fv] of Object.entries(formViews)) {\n if (fv && typeof fv === 'object' && (fv as any).sharing) {\n candidates.push({ form: fv as any, key });\n }\n }\n }\n // Flattened registered shape (getMetaItems → one item per view:\n // { name, object, viewKind:'form', config:{ data, sections, sharing } }).\n // A form view carries its sharing under `config`; without this branch\n // public-form resolution silently fails for the standard view metadata.\n if (view.viewKind === 'form' && view.config && typeof view.config === 'object'\n && (view.config as any).sharing) {\n candidates.push({ form: view.config, key: view.name });\n }\n for (const c of candidates) {\n const sharing = c.form?.sharing;\n if (!sharing || sharing.allowAnonymous !== true) continue;\n if (!slugMatchesPublicLink(sharing.publicLink, slug)) continue;\n const objectName =\n c.form?.data?.object ??\n view?.list?.data?.object ??\n view?.form?.data?.object ??\n view?.object;\n if (!objectName) continue;\n return { view, form: c.form, object: objectName };\n }\n }\n return null;\n };\n\n const resolveFormBySlug = async (\n environmentId: string | undefined,\n req: any,\n slug: string,\n ): Promise<{ view: any; form: any; object: string } | null> => {\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).getMetaItems !== 'function') return null;\n const result: any = await (p as any).getMetaItems({\n type: 'view',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(result?.items)\n ? result.items\n : Array.isArray(result)\n ? result\n : [];\n return findPublicFormView(items, slug);\n };\n\n // GET /forms/:slug — resolve and return the public form spec\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/forms/:slug`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const slug = String(req.params?.slug ?? '').trim();\n if (!slug) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'slug is required' });\n return;\n }\n const match = await resolveFormBySlug(environmentId, req, slug);\n if (!match) {\n res.status(404).json({\n code: 'FORM_NOT_FOUND',\n error: `No public form configured at /forms/${slug}`,\n });\n return;\n }\n // Embed the target object's schema (limited to fields\n // referenced by the form) so anonymous front-ends can\n // render the form without a separate, auth-protected\n // meta lookup. The submit handler still enforces the\n // field whitelist server-side.\n let objectSchema: any = null;\n try {\n const p = await this.resolveProtocol(environmentId, req);\n if (typeof (p as any).getMetaItems === 'function') {\n const r: any = await (p as any).getMetaItems({\n type: 'object',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(r?.items) ? r.items : Array.isArray(r) ? r : [];\n const obj = items.find((o: any) => o?.name === match.object);\n if (obj && obj.fields && typeof obj.fields === 'object') {\n const allowed = new Set<string>();\n for (const sec of match.form?.sections ?? []) {\n for (const f of sec?.fields ?? []) {\n if (typeof f === 'string') allowed.add(f);\n else if (f?.field) allowed.add(f.field);\n }\n }\n const fields: Record<string, any> = {};\n for (const [name, def] of Object.entries(obj.fields)) {\n if (allowed.size === 0 || allowed.has(name)) {\n fields[name] = def;\n }\n }\n objectSchema = { name: obj.name, label: obj.label, fields };\n // Localize labels / help text / option labels so anonymous\n // clients render in the visitor's preferred language. The\n // form payload is otherwise un-translated (resolveFormBySlug\n // returns the raw view spec), so we hydrate the schema here.\n try {\n const i18n = await this.resolveI18nService(environmentId, req);\n const bundle = this.buildTranslationBundle(i18n);\n const locale = this.extractLocale(req, i18n);\n if (bundle && locale) {\n const { translateMetadataDocument } = await import('@objectstack/spec/system');\n objectSchema = translateMetadataDocument('object', objectSchema, bundle, { locale });\n }\n } catch (e: any) {\n logError('[REST] Public form schema translation failed:', e);\n }\n }\n }\n } catch (e: any) {\n logError('[REST] Public form schema load failed:', e);\n }\n // Anonymous public forms must NEVER include a lookup or\n // master-detail field unless the form designer has\n // explicitly opted-in via `publicPicker` on that field's\n // section entry (mirroring Airtable's \"Allow linking to\n // existing records\" toggle). Strip non-conforming\n // lookups defensively here so a stray spec mistake can\n // never expose unrestricted record search to the\n // internet — the related `/forms/:slug/lookup/:field`\n // endpoint also re-validates `publicPicker` server-side.\n const safeForm = (() => {\n if (!match.form || !Array.isArray(match.form.sections)) return match.form;\n const allow = (name: string, cfg: any): boolean => {\n const def = objectSchema?.fields?.[name];\n const t = def?.type;\n if (t !== 'lookup' && t !== 'master_detail') return true;\n return !!cfg?.publicPicker;\n };\n const sections = match.form.sections.map((sec: any) => {\n const fields = (sec?.fields ?? []).filter((f: any) => {\n const name = typeof f === 'string' ? f : f?.field;\n if (!name) return false;\n const cfg = typeof f === 'string' ? {} : f;\n return allow(name, cfg);\n });\n return { ...sec, fields };\n });\n return { ...match.form, sections };\n })();\n res.header('Vary', 'Accept-Language');\n res.json({\n slug,\n object: match.object,\n label: match.view?.label ?? match.form?.label,\n form: safeForm,\n objectSchema,\n });\n } catch (error: any) {\n logError('[REST] Public form resolve error:', error);\n res.status(500).json({\n code: 'FORM_RESOLVE_FAILED',\n error: String(error?.message ?? error ?? 'resolve failed').slice(0, 500),\n });\n }\n },\n metadata: {\n summary: 'Resolve a public form spec by slug (anonymous)',\n tags: ['forms', 'public'],\n },\n });\n\n // POST /forms/:slug/submit — INSERT a record on the target object\n // with the `guest_portal` permission set attached.\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/forms/:slug/submit`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const slug = String(req.params?.slug ?? '').trim();\n if (!slug) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'slug is required' });\n return;\n }\n const match = await resolveFormBySlug(environmentId, req, slug);\n if (!match) {\n res.status(404).json({\n code: 'FORM_NOT_FOUND',\n error: `No public form configured at /forms/${slug}`,\n });\n return;\n }\n\n // Only allow the fields declared on the matched FormView.\n // This prevents a public visitor from stuffing privileged\n // columns (owner_id, status, internal_notes, …) into the\n // row. Object hooks (`beforeInsert`) are still responsible\n // for stamping server-side defaults — see the CRM\n // `lead.hook.ts` / `case.hook.ts` for the canonical pattern.\n const allowedFields = new Set<string>();\n for (const section of match.form?.sections ?? []) {\n for (const f of section?.fields ?? []) {\n if (typeof f === 'string') allowedFields.add(f);\n else if (f?.field) allowedFields.add(f.field);\n }\n }\n const rawBody = (req.body && typeof req.body === 'object') ? req.body : {};\n const filteredData: Record<string, unknown> = {};\n if (allowedFields.size > 0) {\n for (const [k, v] of Object.entries(rawBody)) {\n if (allowedFields.has(k)) filteredData[k] = v;\n }\n } else {\n Object.assign(filteredData, rawBody);\n }\n\n // Anonymous execution context. Carries the `guest_portal`\n // permission set name so the SecurityPlugin resolves it\n // and enforces INSERT-only on the target object.\n // Leaving `userId` undefined keeps `ctx.user?.id` falsy\n // in object hooks (the canonical guest-detection check).\n const context: any = {\n permissions: ['guest_portal'],\n anonymous: true,\n };\n\n const p = await this.resolveProtocol(environmentId, req);\n const result = await p.createData({\n object: match.object,\n data: filteredData,\n ...(environmentId ? { environmentId } : {}),\n context,\n } as any);\n res.status(201).json(result);\n } catch (error: any) {\n const mapped = mapDataError(error);\n if (!isExpectedDataStatus(mapped.status) && mapped.body?.code !== 'VALIDATION_FAILED') {\n logError('[REST] Public form submit error:', error);\n }\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Submit an anonymous public form',\n tags: ['forms', 'public'],\n },\n });\n\n // GET /forms/:slug/lookup/:field — scoped picker for public-form\n // lookup widgets. Mirrors Airtable's per-form linked-record search:\n // the field MUST be declared in the form spec with an explicit\n // `publicPicker` block; otherwise the request is rejected with 403.\n // Records are projected to `publicPicker.displayFields`, capped at\n // `publicPicker.maxResults` (hard ceiling 50), and pre-filtered by\n // `publicPicker.filter`. Anonymous visitors can search but cannot\n // enumerate / paginate, so a leaked endpoint cannot exfiltrate the\n // table.\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/forms/:slug/lookup/:field`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const slug = String(req.params?.slug ?? '').trim();\n const fieldName = String(req.params?.field ?? '').trim();\n if (!slug || !fieldName) {\n res.status(400).json({ code: 'INVALID_REQUEST', error: 'slug and field are required' });\n return;\n }\n const match = await resolveFormBySlug(environmentId, req, slug);\n if (!match) {\n res.status(404).json({\n code: 'FORM_NOT_FOUND',\n error: `No public form configured at /forms/${slug}`,\n });\n return;\n }\n\n // Locate the field config and require an opt-in\n // `publicPicker` block. Without it the lookup is\n // considered private — return 403, not 404, so a\n // misconfigured form is loud rather than silent.\n let fieldCfg: any = null;\n for (const sec of match.form?.sections ?? []) {\n for (const f of sec?.fields ?? []) {\n const name = typeof f === 'string' ? f : f?.field;\n if (name === fieldName) {\n fieldCfg = typeof f === 'string' ? {} : f;\n break;\n }\n }\n if (fieldCfg) break;\n }\n const picker = fieldCfg?.publicPicker;\n if (!picker) {\n res.status(403).json({\n code: 'LOOKUP_NOT_PUBLIC',\n error: `Field \"${fieldName}\" is not enabled for public lookup on this form`,\n });\n return;\n }\n\n // Resolve the referenced object — prefer the explicit\n // `publicPicker.object` override, fall back to the\n // field def on the parent object.\n const p = await this.resolveProtocol(environmentId, req);\n let referenceTo: string | undefined = picker.object;\n if (!referenceTo && typeof (p as any).getMetaItems === 'function') {\n try {\n const r: any = await (p as any).getMetaItems({\n type: 'object',\n ...(environmentId ? { environmentId } : {}),\n });\n const items: any[] = Array.isArray(r?.items) ? r.items : Array.isArray(r) ? r : [];\n const obj = items.find((o: any) => o?.name === match.object);\n const def = obj?.fields?.[fieldName];\n referenceTo = def?.referenceTo ?? def?.target ?? def?.options?.objectName;\n } catch {/* ignore */}\n }\n if (!referenceTo) {\n res.status(500).json({\n code: 'LOOKUP_TARGET_MISSING',\n error: `Could not resolve referenced object for \"${fieldName}\"`,\n });\n return;\n }\n\n const displayFields: string[] = Array.isArray(picker.displayFields) && picker.displayFields.length > 0\n ? picker.displayFields.slice(0, 5)\n : ['name'];\n const hardCap = 50;\n const maxResults = Math.min(Math.max(1, Number(picker.maxResults) || 20), hardCap);\n const q = String(req.query?.q ?? '').trim().slice(0, 100);\n\n // Compose filters: form-defined static filter first,\n // then the search predicate over displayFields. The\n // search predicate uses `contains` on the first\n // display field so non-indexed columns still work.\n const filters: any[] = [];\n if (Array.isArray(picker.filter)) filters.push(...picker.filter);\n if (q) filters.push({ field: displayFields[0], operator: 'contains', value: q });\n\n const context: any = {\n permissions: ['guest_portal'],\n anonymous: true,\n };\n\n const result: any = await (p as any).findData({\n object: referenceTo,\n query: {\n limit: maxResults,\n offset: 0,\n filters,\n select: ['id', ...displayFields],\n sort: picker.sort ?? [{ field: displayFields[0], order: 'asc' }],\n },\n ...(environmentId ? { environmentId } : {}),\n context,\n } as any);\n\n // Project the response server-side too — never trust\n // that the driver respected `select`.\n const rows: any[] = Array.isArray(result?.data) ? result.data : Array.isArray(result?.items) ? result.items : [];\n const projected = rows.slice(0, maxResults).map((row: any) => {\n const out: any = { id: row?.id };\n for (const f of displayFields) {\n if (row && Object.prototype.hasOwnProperty.call(row, f)) out[f] = row[f];\n }\n return out;\n });\n res.json({\n data: projected,\n total: projected.length,\n truncated: rows.length >= maxResults,\n displayFields,\n });\n } catch (error: any) {\n const mapped = mapDataError(error);\n if (!isExpectedDataStatus(mapped.status)) {\n logError('[REST] Public form lookup error:', error);\n }\n res.status(mapped.status).json(mapped.body);\n }\n },\n metadata: {\n summary: 'Scoped lookup picker for a public form field (anonymous)',\n tags: ['forms', 'public'],\n },\n });\n }\n\n /**\n * Register record-level sharing endpoints (M11.C17).\n *\n * Surfaces `ISharingService` over HTTP so the UI can list, create\n * and revoke per-record grants without going through ObjectQL. The\n * three routes mirror the share-management drawer in Salesforce /\n * ServiceNow:\n *\n * GET {basePath}/data/:object/:id/shares\n * POST {basePath}/data/:object/:id/shares\n * DELETE {basePath}/data/:object/:id/shares/:shareId\n *\n * All three resolve via `sharingServiceProvider`; routes return 501\n * when no sharing service is configured so a deployment without the\n * `@objectstack/plugin-sharing` plugin fails cleanly.\n */\n /**\n * ADR-0021 — analytics dataset preview/query endpoint.\n *\n * POST {basePath}/analytics/dataset/query\n * body: { dataset?: <inline Dataset>, datasetName?: string, selection: DatasetSelection }\n *\n * Compiles the dataset (an inline draft for Studio preview, or a saved one\n * by name) and runs the selection through the analytics service's\n * `queryDataset`, threading the request ExecutionContext so tenant/RLS\n * scoping (ADR-0021 D-C) applies. Returns 501 when no analytics service\n * (or one without `queryDataset`) is configured, so a deployment without\n * `@objectstack/service-analytics` fails cleanly.\n */\n private registerAnalyticsEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n // Resolve the ENVIRONMENT's analytics service first — its strategy\n // bridges are bound to the env kernel's own data engine. The host\n // provider (whose 'data' is the host kernel's engine) is only a\n // fallback: serving a tenant's dataset query from the host engine\n // reads the WRONG database and silently aggregates over nothing\n // (the staging \"Total Spend: 0 on a populated table\" incident).\n const resolveService = async (environmentId?: string, req?: any) => {\n try {\n const envId = await this.resolveRequestEnvironmentId(environmentId, req);\n if (envId && envId !== 'platform' && this.kernelManager) {\n const kernel = await this.kernelManager.getOrCreate(envId);\n const svc = await kernel.getServiceAsync<any>('analytics').catch(() => undefined);\n if (svc) return svc;\n }\n } catch { /* fall back to the host service */ }\n if (!this.analyticsServiceProvider) return undefined;\n try { return await this.analyticsServiceProvider(environmentId); }\n catch { return undefined; }\n };\n\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/analytics/dataset/query`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n\n const svc = await resolveService(environmentId, req);\n if (!svc || typeof svc.queryDataset !== 'function') {\n return res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Analytics dataset query is not available on this deployment (no analytics service with queryDataset).',\n });\n }\n\n const body = req.body ?? {};\n const selection = body.selection;\n if (!selection || !Array.isArray(selection.measures) || selection.measures.length === 0) {\n return res.status(400).json({\n code: 'VALIDATION_FAILED',\n message: 'body.selection.measures must be a non-empty array of measure names.',\n });\n }\n\n // ADR-0037 P3 — draft data preview: the canvas / preview\n // pages pass the flag so (a) the dataset lookup sees\n // draft-overlaid definitions and (b) the selection runs\n // over the pending seed draft's rows when one exists.\n const previewDrafts = body.previewDrafts === true || req.query?.preview === 'draft';\n\n // Resolve the dataset definition: inline draft (Studio\n // preview) or a saved dataset by name.\n let dataset = body.dataset;\n if (!dataset && body.datasetName) {\n const p = await this.resolveProtocol(environmentId, req);\n const items = await (p as any).getMetaItems?.({ type: 'dataset', previewDrafts }).catch(() => null);\n const list = Array.isArray(items?.items) ? items.items : (Array.isArray(items) ? items : []);\n dataset = list.find((d: any) => d?.name === body.datasetName);\n if (!dataset) {\n return res.status(404).json({ code: 'NOT_FOUND', message: `Dataset \"${body.datasetName}\" not found.` });\n }\n }\n if (!dataset) {\n return res.status(400).json({ code: 'VALIDATION_FAILED', message: 'Provide body.dataset (inline) or body.datasetName.' });\n }\n\n // Validate against the spec schema so a malformed draft\n // yields a clean 400 instead of a runtime throw.\n try {\n const { DatasetSchema } = await import('@objectstack/spec/ui');\n dataset = (DatasetSchema as any).parse(dataset);\n } catch (verr: any) {\n return res.status(400).json({\n code: 'VALIDATION_FAILED',\n message: 'Invalid dataset definition.',\n detail: String(verr?.message ?? verr).slice(0, 1000),\n });\n }\n\n const result = await svc.queryDataset(\n dataset,\n selection,\n context ?? undefined,\n previewDrafts ? { previewDrafts: true } : undefined,\n );\n res.json(result);\n } catch (error: any) {\n const msg = String(error?.message ?? error ?? '');\n // Dataset-compiler D-C / unsupported-aggregate / read-scope\n // errors are client-side mistakes — surface as 400.\n if (/not declared in the dataset|not backed by a declared relationship|not supported by the v1 dataset runtime|read-scope-sql/.test(msg)) {\n return res.status(400).json({ code: 'DATASET_INVALID', message: msg.slice(0, 1000) });\n }\n logError('[REST] Analytics dataset query error:', error);\n res.status(500).json({ code: 'ANALYTICS_QUERY_FAILED', error: msg.slice(0, 500) });\n }\n },\n metadata: { summary: 'Run a semantic-layer dataset (preview/query)', tags: ['analytics'] },\n });\n }\n\n private registerSharingEndpoints(basePath: string): void {\n const { crud } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.sharingServiceProvider) return undefined;\n try { return await this.sharingServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Sharing service is not configured on this deployment',\n });\n\n // GET — list shares on a record.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/:object/:id/shares`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listShares(req.params.object, req.params.id, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List shares error:', error);\n res.status(500).json({ code: 'SHARES_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List per-record sharing grants', tags: ['sharing'] },\n });\n\n // POST — grant access.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/:id/shares`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n const input = {\n object: req.params.object,\n recordId: req.params.id,\n recipientType: body.recipientType ?? body.recipient_type,\n recipientId: body.recipientId ?? body.recipient_id,\n accessLevel: body.accessLevel ?? body.access_level,\n source: body.source,\n sourceId: body.sourceId ?? body.source_id,\n reason: body.reason,\n };\n try {\n const row = await svc.grant(input, context ?? {});\n res.status(201).json(row);\n } catch (err: any) {\n const msg = String(err?.message ?? err ?? '');\n if (msg.startsWith('VALIDATION_FAILED')) {\n res.status(400).json({\n code: 'VALIDATION_FAILED',\n error: msg.replace(/^VALIDATION_FAILED:\\s*/, ''),\n });\n return;\n }\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Grant share error:', error);\n res.status(500).json({ code: 'SHARE_GRANT_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Grant a per-record share to a principal', tags: ['sharing'] },\n });\n\n // DELETE — revoke a share by id.\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/:object/:id/shares/:shareId`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.revoke(req.params.shareId, context ?? {});\n res.status(204).end();\n } catch (error: any) {\n logError('[REST] Revoke share error:', error);\n res.status(500).json({ code: 'SHARE_REVOKE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Revoke a per-record share by id', tags: ['sharing'] },\n });\n }\n\n /**\n * Register sharing-rule endpoints (M10.17). Mirrors the existing\n * sharing endpoints but operates on `sys_sharing_rule` rows.\n *\n * GET {basePath}/sharing/rules?object=&activeOnly=\n * POST {basePath}/sharing/rules\n * GET {basePath}/sharing/rules/:idOrName\n * DELETE {basePath}/sharing/rules/:idOrName\n * POST {basePath}/sharing/rules/:idOrName/evaluate\n *\n * Returns 501 when no sharing-rule service is configured.\n */\n private registerSharingRuleEndpoints(basePath: string): void {\n // Sharing-rule routes live at the top of the API surface (e.g.\n // `/api/v1/sharing/rules`) — they administer rules across the whole\n // tenant rather than acting on a single CRUD object, so anchoring\n // them on `basePath` keeps them out of the `/data/:object` namespace\n // where greedy CRUD matchers would otherwise swallow them.\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.sharingRulesServiceProvider) return undefined;\n try { return await this.sharingRulesServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Sharing-rule service is not configured on this deployment',\n });\n const handleError = (err: any, res: any, defaultCode: string) => {\n const msg = String(err?.message ?? err ?? '');\n if (msg.startsWith('VALIDATION_FAILED')) {\n return res.status(400).json({ code: 'VALIDATION_FAILED', error: msg.replace(/^VALIDATION_FAILED:\\s*/, '') });\n }\n if (msg.startsWith('RULE_NOT_FOUND')) {\n return res.status(404).json({ code: 'RULE_NOT_FOUND', error: msg.replace(/^RULE_NOT_FOUND:?\\s*/, '') });\n }\n logError(`[REST] sharing-rule ${defaultCode}:`, err);\n return res.status(500).json({ code: defaultCode, error: msg.slice(0, 500) });\n };\n\n // LIST\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/sharing/rules`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listRules({\n object: req.query?.object,\n activeOnly: req.query?.activeOnly === 'true' || req.query?.activeOnly === true,\n }, context ?? {});\n res.json({ data: rows });\n } catch (err: any) { handleError(err, res, 'RULE_LIST_FAILED'); }\n },\n metadata: { summary: 'List sharing rules', tags: ['sharing'] },\n });\n\n // CREATE / UPSERT\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/sharing/rules`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n const input = {\n name: body.name,\n label: body.label,\n description: body.description,\n object: body.object ?? body.object_name,\n criteria: body.criteria,\n recipientType: body.recipientType ?? body.recipient_type,\n recipientId: body.recipientId ?? body.recipient_id,\n accessLevel: body.accessLevel ?? body.access_level,\n active: body.active,\n };\n const row = await svc.defineRule(input, context ?? {});\n res.status(201).json(row);\n } catch (err: any) { handleError(err, res, 'RULE_DEFINE_FAILED'); }\n },\n metadata: { summary: 'Create or upsert a sharing rule', tags: ['sharing'] },\n });\n\n // GET\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/sharing/rules/:idOrName`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const row = await svc.getRule(req.params.idOrName, context ?? {});\n if (!row) return res.status(404).json({ code: 'RULE_NOT_FOUND' });\n res.json(row);\n } catch (err: any) { handleError(err, res, 'RULE_GET_FAILED'); }\n },\n metadata: { summary: 'Get a sharing rule by id or name', tags: ['sharing'] },\n });\n\n // DELETE\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/sharing/rules/:idOrName`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.deleteRule(req.params.idOrName, context ?? {});\n res.status(204).end();\n } catch (err: any) { handleError(err, res, 'RULE_DELETE_FAILED'); }\n },\n metadata: { summary: 'Delete a sharing rule and its materialised grants', tags: ['sharing'] },\n });\n\n // EVALUATE\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/sharing/rules/:idOrName/evaluate`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const result = await svc.evaluateRule(req.params.idOrName, context ?? {});\n res.json(result);\n } catch (err: any) { handleError(err, res, 'RULE_EVALUATE_FAILED'); }\n },\n metadata: { summary: 'Re-evaluate a sharing rule and reconcile grants', tags: ['sharing'] },\n });\n }\n\n /**\n * Register saved-report + scheduled-digest endpoints (M11.C16).\n *\n * Surfaces `IReportService` over HTTP so the UI can build,\n * run, and schedule reports without dropping to ObjectQL. Routes\n * live at the top of the API surface (alongside `/approvals` and\n * `/sharing`) — reports are a tenant-wide capability, not a record\n * on a specific CRUD object:\n *\n * GET {basePath}/reports?object=&ownerId=\n * POST {basePath}/reports\n * GET {basePath}/reports/:id\n * DELETE {basePath}/reports/:id\n * POST {basePath}/reports/:id/run\n * POST {basePath}/reports/:id/schedule\n * GET {basePath}/reports/:id/schedules\n * DELETE {basePath}/reports/schedules/:scheduleId\n *\n * All routes return 501 when `reportsServiceProvider` is unset so\n * a deployment without `@objectstack/plugin-reports` fails cleanly.\n */\n private registerReportsEndpoints(basePath: string): void {\n // Reports live at the top of the API surface (e.g. `/api/v1/reports`)\n // rather than under `/data/`, because a report is a first-class\n // capability whose definition is tenant-wide (not a record on a\n // particular object).\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.reportsServiceProvider) return undefined;\n try { return await this.reportsServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Reports service is not configured on this deployment',\n });\n const handleValidation = (res: any, err: any): boolean => {\n const msg = String(err?.message ?? err ?? '');\n if (msg.startsWith('VALIDATION_FAILED')) {\n res.status(400).json({\n code: 'VALIDATION_FAILED',\n error: msg.replace(/^VALIDATION_FAILED:\\s*/, ''),\n });\n return true;\n }\n if (msg.startsWith('REPORT_NOT_FOUND')) {\n res.status(404).json({ code: 'REPORT_NOT_FOUND', error: msg });\n return true;\n }\n return false;\n };\n\n // GET — list reports.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/reports`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const q = req.query ?? {};\n const rows = await svc.listReports({ object: q.object, ownerId: q.ownerId }, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List reports error:', error);\n res.status(500).json({ code: 'REPORTS_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List saved reports', tags: ['reports'] },\n });\n\n // POST — save (upsert) a report.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/reports`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n try {\n const row = await svc.saveReport(req.body ?? {}, context ?? {});\n res.status(201).json(row);\n } catch (err: any) {\n if (handleValidation(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Save report error:', error);\n res.status(500).json({ code: 'REPORT_SAVE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Create or update a saved report', tags: ['reports'] },\n });\n\n // GET — single report.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/reports/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const row = await svc.getReport(req.params.id, context ?? {});\n if (!row) {\n res.status(404).json({ code: 'REPORT_NOT_FOUND', error: `Report ${req.params.id} not found` });\n return;\n }\n res.json(row);\n } catch (error: any) {\n logError('[REST] Get report error:', error);\n res.status(500).json({ code: 'REPORT_GET_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Get a saved report by id', tags: ['reports'] },\n });\n\n // DELETE — drop report + cascade schedules.\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/reports/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.deleteReport(req.params.id, context ?? {});\n res.status(204).end();\n } catch (error: any) {\n logError('[REST] Delete report error:', error);\n res.status(500).json({ code: 'REPORT_DELETE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Delete a saved report (cascades schedules)', tags: ['reports'] },\n });\n\n // POST — execute a report by id.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/reports/:id/run`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n try {\n const result = await svc.run(req.params.id, context ?? {});\n res.json(result);\n } catch (err: any) {\n if (handleValidation(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Run report error:', error);\n res.status(500).json({ code: 'REPORT_RUN_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Execute a saved report and return rendered output', tags: ['reports'] },\n });\n\n // POST — schedule a report.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/reports/:id/schedule`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n try {\n const row = await svc.scheduleReport({\n reportId: req.params.id,\n recipients: body.recipients ?? [],\n name: body.name,\n intervalMinutes: body.intervalMinutes ?? body.interval_minutes,\n cronExpression: body.cronExpression ?? body.cron_expression,\n timezone: body.timezone,\n format: body.format,\n subjectTemplate: body.subjectTemplate ?? body.subject_template,\n ownerId: body.ownerId ?? body.owner_id,\n active: body.active,\n }, context ?? {});\n res.status(201).json(row);\n } catch (err: any) {\n if (handleValidation(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] Schedule report error:', error);\n res.status(500).json({ code: 'REPORT_SCHEDULE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Create a recurring email schedule for a report', tags: ['reports'] },\n });\n\n // GET — list schedules for a report.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/reports/:id/schedules`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listSchedules({ reportId: req.params.id }, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List schedules error:', error);\n res.status(500).json({ code: 'SCHEDULES_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List schedules for a report', tags: ['reports'] },\n });\n\n // DELETE — drop a schedule.\n this.routeManager.register({\n method: 'DELETE',\n path: `${dataPath}/reports/schedules/:scheduleId`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n await svc.unscheduleReport(req.params.scheduleId, context ?? {});\n res.status(204).end();\n } catch (error: any) {\n logError('[REST] Unschedule report error:', error);\n res.status(500).json({ code: 'SCHEDULE_DELETE_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Delete a report schedule by id', tags: ['reports'] },\n });\n }\n\n /**\n * Register approval endpoints (ADR-0019: approval as a flow node).\n *\n * Approval is no longer a standalone process engine — a flow's Approval\n * node opens a request and suspends the run; a decision resumes it. There\n * are no process-authoring or submit routes anymore.\n *\n * Routes (all under {basePath}/approvals):\n * GET /requests — list (filters: status, object, recordId, approverId, submitterId)\n * GET /requests/:id — get request\n * POST /requests/:id/approve — record an approve decision (resumes the flow)\n * POST /requests/:id/reject — record a reject decision (resumes the flow)\n * GET /requests/:id/actions — audit trail\n *\n * Returns 501 when `approvalsServiceProvider` is unset so deployments\n * without `@objectstack/plugin-approvals` fail cleanly.\n */\n private registerApprovalsEndpoints(basePath: string): void {\n // Approval routes live at the top of the API surface (e.g.\n // `/api/v1/approvals/requests/:id/approve`). Approvals are a\n // cross-cutting capability — a request is not a record on a single\n // CRUD object, so anchoring it on `basePath` (instead of\n // `${basePath}/data`) keeps the URL semantics honest.\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.approvalsServiceProvider) return undefined;\n try { return await this.approvalsServiceProvider(environmentId); }\n catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Approvals service is not configured on this deployment',\n });\n const handleApprovalError = (res: any, err: any): boolean => {\n const msg = String(err?.message ?? err ?? '');\n const mapping: Array<[RegExp, number, string]> = [\n [/^VALIDATION_FAILED/, 400, 'VALIDATION_FAILED'],\n [/^DUPLICATE_REQUEST/, 409, 'DUPLICATE_REQUEST'],\n [/^INVALID_STATE/, 409, 'INVALID_STATE'],\n [/^THROTTLED/, 429, 'THROTTLED'],\n [/^FORBIDDEN/, 403, 'FORBIDDEN'],\n [/^REQUEST_NOT_FOUND/, 404, 'REQUEST_NOT_FOUND'],\n ];\n for (const [re, status, code] of mapping) {\n if (re.test(msg)) {\n res.status(status).json({ code, error: msg.replace(/^[A-Z_]+:\\s*/, '') });\n return true;\n }\n }\n return false;\n };\n\n // ── Requests ──────────────────────────────────────────────\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/approvals/requests`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) {\n // No approvals plugin loaded — return empty list rather than 501\n // so Console badge polls don't spam the error log on deployments\n // that don't run an approvals workflow.\n res.json({ data: [] });\n return;\n }\n const q = req.query ?? {};\n // `approverId` accepts a single id, a comma-separated\n // list, or the param repeated (→ array). Normalise all\n // three to a string[] so the Console can resolve \"my\n // pending approvals\" across every identity (user id /\n // email / role:<r>) in ONE request rather than looping.\n const rawApprover = q.approverId ?? q.approver_id;\n const approverIds = (Array.isArray(rawApprover) ? rawApprover : (rawApprover != null ? [rawApprover] : []))\n .flatMap((s: any) => String(s).split(','))\n .map((s: string) => s.trim())\n .filter(Boolean);\n const limit = q.limit != null ? Number(q.limit) : undefined;\n const offset = q.offset != null ? Number(q.offset) : undefined;\n const listFilter = {\n object: q.object,\n recordId: q.recordId ?? q.record_id,\n status: q.status,\n approverId: approverIds.length ? approverIds : undefined,\n submitterId: q.submitterId ?? q.submitter_id,\n q: typeof q.q === 'string' ? q.q : undefined,\n limit: Number.isFinite(limit) ? limit : undefined,\n offset: Number.isFinite(offset) ? offset : undefined,\n };\n const rows = await svc.listRequests(listFilter, context ?? {});\n // `total` only when the caller pages — counting costs a\n // second query and unpaged callers don't need it.\n if (listFilter.limit != null && typeof svc.countRequests === 'function') {\n const total = await svc.countRequests(listFilter, context ?? {});\n res.json({ data: rows, total });\n return;\n }\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List approval requests error:', error);\n res.status(500).json({ code: 'APPROVAL_REQUEST_LIST_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List approval requests', tags: ['approvals'] },\n });\n\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/approvals/requests/:id`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const row = await svc.getRequest(req.params.id, context ?? {});\n if (!row) {\n res.status(404).json({ code: 'REQUEST_NOT_FOUND', error: `Approval request '${req.params.id}' not found` });\n return;\n }\n res.json(row);\n } catch (error: any) {\n logError('[REST] Get approval request error:', error);\n res.status(500).json({ code: 'APPROVAL_REQUEST_GET_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Get an approval request by id', tags: ['approvals'] },\n });\n\n // Record a decision on a node-driven request. Both branches funnel\n // through the contract's `decide()`, which finalizes the request and\n // resumes the owning flow run down the matching `approve` / `reject`\n // edge.\n const decisionRoute = (decision: 'approve' | 'reject') => {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/approvals/requests/:id/${decision}`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n try {\n const out = await svc.decide(req.params.id, {\n decision,\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context ?? {});\n res.json(out);\n } catch (err: any) {\n if (handleApprovalError(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError(`[REST] ${decision} approval error:`, error);\n res.status(500).json({ code: `APPROVAL_${decision.toUpperCase()}_FAILED`, error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: `${decision[0].toUpperCase()}${decision.slice(1)} an approval request`, tags: ['approvals'] },\n });\n };\n decisionRoute('approve');\n decisionRoute('reject');\n\n // Recall — submitter withdraws a pending request. Mirrors the decision\n // routes' error mapping; the service enforces submitter-only access.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/approvals/requests/:id/recall`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc || typeof svc.recall !== 'function') return respond501(res);\n const body = req.body ?? {};\n try {\n const out = await svc.recall(req.params.id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context ?? {});\n res.json(out);\n } catch (err: any) {\n if (handleApprovalError(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError('[REST] recall approval error:', error);\n res.status(500).json({ code: 'APPROVAL_RECALL_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'Recall (withdraw) an approval request', tags: ['approvals'] },\n });\n\n // Thread interactions — reassign / remind / request-info / comment.\n // None of these move the flow; they update approver slots or the\n // audit thread. Registered generically: the service method enforces\n // the per-action permission (slot holder / submitter / participant).\n const threadRoute = (\n action: 'reassign' | 'remind' | 'request-info' | 'comment',\n invoke: (svc: any, id: string, body: any, context: any) => Promise<unknown>,\n ) => {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/approvals/requests/:id/${action}`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const body = req.body ?? {};\n try {\n const out = await invoke(svc, req.params.id, body, context ?? {});\n res.json(out);\n } catch (err: any) {\n if (handleApprovalError(res, err)) return;\n throw err;\n }\n } catch (error: any) {\n logError(`[REST] ${action} approval error:`, error);\n res.status(500).json({ code: `APPROVAL_${action.toUpperCase().replace('-', '_')}_FAILED`, error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: `${action} on an approval request`, tags: ['approvals'] },\n });\n };\n threadRoute('reassign', (svc, id, body, context) => {\n if (typeof svc.reassign !== 'function') throw new Error('VALIDATION_FAILED: reassign is not supported');\n return svc.reassign(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n to: body.to, from: body.from, comment: body.comment,\n }, context);\n });\n threadRoute('remind', (svc, id, body, context) => {\n if (typeof svc.remind !== 'function') throw new Error('VALIDATION_FAILED: remind is not supported');\n return svc.remind(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context);\n });\n threadRoute('request-info', (svc, id, body, context) => {\n if (typeof svc.requestInfo !== 'function') throw new Error('VALIDATION_FAILED: request-info is not supported');\n return svc.requestInfo(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context);\n });\n threadRoute('comment', (svc, id, body, context) => {\n if (typeof svc.comment !== 'function') throw new Error('VALIDATION_FAILED: comment is not supported');\n return svc.comment(id, {\n actorId: body.actorId ?? body.actor_id ?? context?.userId,\n comment: body.comment,\n }, context);\n });\n\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/approvals/requests/:id/actions`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const svc = await resolveService(environmentId);\n if (!svc) return respond501(res);\n const rows = await svc.listActions(req.params.id, context ?? {});\n res.json({ data: rows });\n } catch (error: any) {\n logError('[REST] List approval actions error:', error);\n res.status(500).json({ code: 'APPROVAL_ACTIONS_FAILED', error: String(error?.message ?? error).slice(0, 500) });\n }\n },\n metadata: { summary: 'List actions (audit trail) for an approval request', tags: ['approvals'] },\n });\n }\n\n /**\n * Register batch operation endpoints\n */\n private registerBatchEndpoints(basePath: string): void {\n const { crud, batch } = this.config;\n const dataPath = `${basePath}${crud.dataPrefix}`;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const operations = batch.operations;\n\n // POST /batch — cross-object transactional batch (issue #1604).\n // Runs heterogeneous create/update/delete across objects in ONE engine\n // transaction (commit all or roll back all). Intra-batch references:\n // a field value of `{ $ref: <earlier op index> }` resolves to that op's\n // created id, so a child can reference its parent (master-detail).\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/batch`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n const ql = this.objectQLProvider ? await this.objectQLProvider(environmentId) : undefined;\n if (!ql || typeof ql.transaction !== 'function') {\n res.status(501).json({ error: 'Transactional batch not supported by this runtime' });\n return;\n }\n const ops: any[] = Array.isArray(req.body?.operations) ? req.body.operations : [];\n const max = batch.maxBatchSize ?? 200;\n if (ops.length === 0) { res.json({ results: [] }); return; }\n if (ops.length > max) { res.status(400).json({ error: `Batch too large (max ${max})` }); return; }\n\n const resolveRefs = (data: any, out: any[]): any => {\n if (!data || typeof data !== 'object') return data;\n const result: any = Array.isArray(data) ? [] : {};\n for (const [k, v] of Object.entries(data)) {\n if (v && typeof v === 'object' && '$ref' in (v as any)) {\n const ref = out[(v as any).$ref];\n result[k] = (ref && (ref.id ?? ref._id)) ?? null;\n } else {\n result[k] = v;\n }\n }\n return result;\n };\n\n const results = await ql.transaction(async (trxCtx: any) => {\n const out: any[] = [];\n for (const op of ops) {\n const action = String(op?.action || 'create');\n const object = String(op?.object || '');\n if (!object) throw new Error('Each operation requires an `object`');\n const data = resolveRefs(op.data, out);\n if (action === 'create') {\n out.push(await ql.insert(object, data, { context: trxCtx }));\n } else if (action === 'update') {\n const id = op.id ?? data?.id;\n out.push(await ql.update(object, { ...data, id }, { context: trxCtx }));\n } else if (action === 'delete') {\n out.push(await ql.delete(object, { where: { id: op.id }, context: trxCtx }));\n } else {\n throw new Error(`Unknown batch action: ${action}`);\n }\n }\n return out;\n }, context);\n\n res.json({ results });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error);\n }\n },\n metadata: {\n summary: 'Cross-object transactional batch (atomic create/update/delete across objects)',\n tags: ['data', 'batch'],\n },\n });\n\n // POST /data/:object/batch - Generic batch endpoint\n if (batch.enableBatchEndpoint && this.protocol.batchData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/batch`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'bulk')) return;\n const result = await p.batchData!({\n object: req.params.object,\n request: req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Batch operations',\n tags: ['data', 'batch'],\n },\n });\n }\n\n // POST /data/:object/createMany - Bulk create\n if (operations.createMany && this.protocol.createManyData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/createMany`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'create')) return;\n const result = await p.createManyData!({\n object: req.params.object,\n records: req.body || [],\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.status(201).json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Create multiple records',\n tags: ['data', 'batch'],\n },\n });\n }\n\n // POST /data/:object/updateMany - Bulk update\n if (operations.updateMany && this.protocol.updateManyData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/updateMany`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'update')) return;\n const result = await p.updateManyData!({\n object: req.params.object,\n ...req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Update multiple records',\n tags: ['data', 'batch'],\n },\n });\n }\n\n // POST /data/:object/deleteMany - Bulk delete\n if (operations.deleteMany && this.protocol.deleteManyData) {\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/deleteMany`,\n handler: async (req: any, res: any) => {\n try {\n const environmentId = isScoped ? req.params?.environmentId : undefined;\n const p = await this.resolveProtocol(environmentId, req);\n const context = await this.resolveExecCtx(environmentId, req);\n if (this.enforceAuth(req, res, context)) return;\n if (await this.enforceApiAccess(req, res, p, environmentId, 'delete')) return;\n const result = await p.deleteManyData!({\n object: req.params.object,\n ...req.body,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n } as any);\n res.json(result);\n } catch (error: any) {\n logError(\"[REST] Unhandled error:\", error);\n sendError(res, error, req.params?.object);\n }\n },\n metadata: {\n summary: 'Delete multiple records',\n tags: ['data', 'batch'],\n },\n });\n }\n }\n\n \n /**\n * Get the route manager\n */\n getRouteManager(): RouteManager {\n return this.routeManager;\n }\n \n /**\n * Get all registered routes\n */\n getRoutes() {\n return this.routeManager.getAll();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { RouteHandler, IHttpServer } from '@objectstack/core';\nimport * as System from '@objectstack/spec/system';\nimport * as Shared from '@objectstack/spec/shared';\nimport { z } from 'zod';\n\ntype RouteHandlerMetadata = System.RouteHandlerMetadata;\ntype HttpMethod = z.infer<typeof Shared.HttpMethod>;\n\n/**\n * Route Entry\n * Internal representation of registered routes\n */\nexport interface RouteEntry {\n method: HttpMethod;\n path: string;\n handler: RouteHandler;\n metadata?: RouteHandlerMetadata['metadata'];\n security?: RouteHandlerMetadata['security'];\n}\n\n/**\n * RouteManager\n * \n * Manages route registration and organization for HTTP servers.\n * Provides:\n * - Route registration with metadata\n * - Route lookup and querying\n * - Bulk route registration\n * - Route grouping by prefix\n * \n * @example\n * const manager = new RouteManager(server);\n * \n * // Register individual route\n * manager.register({\n * method: 'GET',\n * path: '/api/users/:id',\n * handler: getUserHandler,\n * metadata: {\n * summary: 'Get user by ID',\n * tags: ['users']\n * }\n * });\n * \n * // Register route group\n * manager.group('/api/users', (group) => {\n * group.get('/', listUsersHandler);\n * group.post('/', createUserHandler);\n * group.get('/:id', getUserHandler);\n * });\n */\nexport class RouteManager {\n private server: IHttpServer;\n private routes: Map<string, RouteEntry>;\n \n constructor(server: IHttpServer) {\n this.server = server;\n this.routes = new Map();\n }\n \n /**\n * Register a route\n * @param entry - Route entry with method, path, handler, and metadata\n */\n register(entry: Omit<RouteEntry, 'handler'> & { handler: RouteHandler | string }): void {\n // Validate handler type - string handlers not yet supported\n if (typeof entry.handler === 'string') {\n throw new Error(\n `String-based route handlers are not supported yet. ` +\n `Received handler identifier \"${entry.handler}\". ` +\n `Please provide a RouteHandler function instead.`\n );\n }\n \n const handler: RouteHandler = entry.handler;\n \n const routeEntry: RouteEntry = {\n method: entry.method,\n path: entry.path,\n handler,\n metadata: entry.metadata,\n security: entry.security,\n };\n \n const key = this.getRouteKey(entry.method, entry.path);\n this.routes.set(key, routeEntry);\n \n // Register with underlying server\n this.registerWithServer(routeEntry);\n }\n \n /**\n * Register multiple routes\n * @param entries - Array of route entries\n */\n registerMany(entries: Array<Omit<RouteEntry, 'handler'> & { handler: RouteHandler | string }>): void {\n entries.forEach(entry => this.register(entry));\n }\n \n /**\n * Unregister a route\n * @param method - HTTP method\n * @param path - Route path\n */\n unregister(method: HttpMethod, path: string): void {\n const key = this.getRouteKey(method, path);\n this.routes.delete(key);\n // Note: Most server frameworks don't support unregistering routes at runtime\n // This just removes it from our registry\n }\n \n /**\n * Get route by method and path\n * @param method - HTTP method\n * @param path - Route path\n */\n get(method: HttpMethod, path: string): RouteEntry | undefined {\n const key = this.getRouteKey(method, path);\n return this.routes.get(key);\n }\n \n /**\n * Get all routes\n */\n getAll(): RouteEntry[] {\n return Array.from(this.routes.values());\n }\n \n /**\n * Get routes by method\n * @param method - HTTP method\n */\n getByMethod(method: HttpMethod): RouteEntry[] {\n return this.getAll().filter(route => route.method === method);\n }\n \n /**\n * Get routes by path prefix\n * @param prefix - Path prefix\n */\n getByPrefix(prefix: string): RouteEntry[] {\n return this.getAll().filter(route => route.path.startsWith(prefix));\n }\n \n /**\n * Get routes by tag\n * @param tag - Tag name\n */\n getByTag(tag: string): RouteEntry[] {\n return this.getAll().filter(route => \n route.metadata?.tags?.includes(tag)\n );\n }\n \n /**\n * Create a route group with common prefix\n * @param prefix - Common path prefix\n * @param configure - Function to configure routes in the group\n */\n group(prefix: string, configure: (group: RouteGroupBuilder) => void): void {\n const builder = new RouteGroupBuilder(this, prefix);\n configure(builder);\n }\n \n /**\n * Get route count\n */\n count(): number {\n return this.routes.size;\n }\n \n /**\n * Clear all routes\n */\n clear(): void {\n this.routes.clear();\n }\n \n /**\n * Get route key for storage\n */\n private getRouteKey(method: HttpMethod, path: string): string {\n return `${method}:${path}`;\n }\n \n /**\n * Register route with underlying server\n */\n private registerWithServer(entry: RouteEntry): void {\n const { method, path, handler } = entry;\n \n switch (method) {\n case 'GET':\n this.server.get(path, handler);\n break;\n case 'POST':\n this.server.post(path, handler);\n break;\n case 'PUT':\n this.server.put(path, handler);\n break;\n case 'DELETE':\n this.server.delete(path, handler);\n break;\n case 'PATCH':\n this.server.patch(path, handler);\n break;\n default:\n throw new Error(`Unsupported HTTP method: ${method}`);\n }\n }\n}\n\n/**\n * RouteGroupBuilder\n * \n * Builder for creating route groups with common prefix\n */\nexport class RouteGroupBuilder {\n private manager: RouteManager;\n private prefix: string;\n \n constructor(manager: RouteManager, prefix: string) {\n this.manager = manager;\n this.prefix = prefix;\n }\n \n /**\n * Register GET route in group\n */\n get(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'GET',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register POST route in group\n */\n post(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'POST',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register PUT route in group\n */\n put(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'PUT',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register PATCH route in group\n */\n patch(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'PATCH',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Register DELETE route in group\n */\n delete(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this {\n this.manager.register({\n method: 'DELETE',\n path: this.resolvePath(path),\n handler,\n metadata,\n });\n return this;\n }\n \n /**\n * Resolve full path with prefix\n */\n private resolvePath(path: string): string {\n // Normalize slashes\n const normalizedPrefix = this.prefix.endsWith('/') \n ? this.prefix.slice(0, -1) \n : this.prefix;\n const normalizedPath = path.startsWith('/') \n ? path \n : '/' + path;\n \n return normalizedPrefix + normalizedPath;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { IHttpServer } from '@objectstack/core';\nimport type { PackageService } from '@objectstack/service-package';\n\n/**\n * Options for package route registration.\n */\nexport interface PackageRoutesOptions {\n /**\n * Protocol service (ObjectStackProtocol) — provides access to in-memory\n * SchemaRegistry packages loaded via defineStack()/AppPlugin at boot time.\n */\n protocol?: { getMetaItems?(req: { type: string }): Promise<{ items: any[] }> };\n}\n\n/**\n * Register package management API routes\n *\n * Provides endpoints for publishing, retrieving, and managing packages.\n * Routes:\n * - POST /api/v1/packages - Publish a package\n * - GET /api/v1/packages - List all packages (merges registry + database)\n * - GET /api/v1/packages/:id - Get a specific package\n * - DELETE /api/v1/packages/:id - Delete a package\n */\nexport function registerPackageRoutes(\n server: IHttpServer,\n packageService: PackageService,\n basePath: string = '/api/v1',\n options: PackageRoutesOptions = {},\n) {\n const packagesPath = `${basePath}/packages`;\n\n // POST /api/v1/packages - Publish a package\n server.post(packagesPath, async (req, res) => {\n try {\n const { manifest, metadata } = req.body || {};\n\n if (!manifest || !metadata) {\n res.status(400).json({ error: 'Missing required fields: manifest, metadata' });\n return;\n }\n\n if (!manifest.id || !manifest.version) {\n res.status(400).json({ error: 'Invalid manifest: id and version are required' });\n return;\n }\n\n const result = await packageService.publish({ manifest, metadata });\n\n if (result.success) {\n res.json({\n success: true,\n message: `Published ${manifest.id}@${manifest.version}`,\n package: {\n id: manifest.id,\n version: manifest.version,\n },\n });\n return;\n }\n\n res.status(400).json({ success: false, error: result.error });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n // GET /api/v1/packages - List all packages (merges registry + database)\n server.get(packagesPath, async (_req, res) => {\n try {\n // Merge two sources:\n // 1. Registry packages (in-memory, loaded at boot via defineStack/AppPlugin)\n // 2. Database packages (published via POST /packages)\n const packagesMap = new Map<string, any>();\n\n // Registry packages (via protocol service → SchemaRegistry)\n if (options.protocol && typeof options.protocol.getMetaItems === 'function') {\n try {\n const result = await options.protocol.getMetaItems({ type: 'package' });\n if (result?.items) {\n for (const item of result.items) {\n const id = item.manifest?.id || item.id;\n if (id) {\n packagesMap.set(id, {\n ...item,\n source: 'registry',\n });\n }\n }\n }\n } catch {\n // Protocol unavailable — continue with database only\n }\n }\n\n // Database packages (published artifacts)\n try {\n const dbPackages = await packageService.list();\n for (const pkg of dbPackages) {\n const id = pkg.manifest?.id || pkg.id;\n if (id) {\n // Database entry takes precedence (has richer metadata from publish)\n packagesMap.set(id, {\n ...packagesMap.get(id),\n ...pkg,\n source: packagesMap.has(id) ? 'both' : 'database',\n });\n }\n }\n } catch {\n // Database query failed — continue with registry-only packages\n }\n\n const packages = Array.from(packagesMap.values());\n res.json({ packages, total: packages.length });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n // GET /api/v1/packages/:id - Get a specific package\n server.get(`${packagesPath}/:id`, async (req, res) => {\n try {\n const packageId = req.params.id;\n const version = req.query?.version || 'latest';\n\n // Try database first (richer data from publish)\n const pkg = await packageService.get(packageId, version);\n if (pkg) {\n res.json({ package: { ...pkg, source: 'database' } });\n return;\n }\n\n // Fall back to registry (in-memory loaded packages)\n if (options.protocol && typeof options.protocol.getMetaItems === 'function') {\n try {\n const result = await options.protocol.getMetaItems({ type: 'package' });\n const match = result?.items?.find((item: any) =>\n (item.manifest?.id || item.id) === packageId\n );\n if (match) {\n res.json({ package: { ...match, source: 'registry' } });\n return;\n }\n } catch {\n // Protocol unavailable\n }\n }\n\n res.status(404).json({ error: 'Package not found' });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n // DELETE /api/v1/packages/:id - Delete a package\n server.delete(`${packagesPath}/:id`, async (req, res) => {\n try {\n const packageId = req.params.id;\n const version = req.query?.version;\n\n const result = await packageService.delete(packageId, version);\n\n if (result.success) {\n res.json({\n success: true,\n message: `Deleted ${packageId}${version ? `@${version}` : ''}`,\n });\n return;\n }\n\n res.status(400).json({ success: false });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { PluginContext } from '@objectstack/core';\nimport type { IHttpServer } from '@objectstack/spec/contracts';\n\n/**\n * External Datasource Federation REST routes (ADR-0015 §6.2).\n *\n * Mounted under `/api/v1/datasources/:name/external/*` and served by the\n * `external-datasource` service. Every route degrades gracefully\n * (`503 external_service_unavailable`) when federation is not wired into the\n * host, so the routes are safe to register unconditionally.\n *\n * GET /datasources/:name/external/tables → listRemoteTables\n * POST /datasources/:name/external/tables/:remote/draft → generateObjectDraft\n * POST /datasources/:name/external/tables/:remote/import → importObject\n * POST /datasources/:name/external/refresh-catalog → refreshCatalog\n * POST /datasources/:name/external/validate → validateAll (this ds)\n *\n * NOTE: the datasource *lifecycle* routes (`/api/v1/datasources` —\n * list / test / create / update / remove, ADR-0015 Addendum) were extracted\n * into the private `@objectstack/datasource-admin` package, which registers\n * them via its own `registerDatasourceAdminRoutes`.\n */\nexport function registerExternalDatasourceRoutes(\n server: IHttpServer,\n ctx: PluginContext,\n basePath = '/api/v1',\n): void {\n const ext = `${basePath}/datasources/:name/external`;\n\n const externalService = (): any => {\n try {\n return ctx.getService<any>('external-datasource');\n } catch {\n return undefined;\n }\n };\n\n const unavailable = (res: any) =>\n res.status(503).json({ error: 'external_service_unavailable' });\n\n // List remote tables (optionally filtered by ?schema=).\n server.get(`${ext}/tables`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.listRemoteTables) return unavailable(res);\n const schema = typeof req.query?.schema === 'string' ? req.query.schema : undefined;\n const tables = await svc.listRemoteTables(req.params.name, { schema });\n res.json({ tables });\n });\n\n // Generate an Object draft (structured + *.object.ts source) from a table.\n server.post(`${ext}/tables/:remote/draft`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.generateObjectDraft) return unavailable(res);\n const draft = await svc.generateObjectDraft(\n req.params.name,\n req.params.remote,\n (req.body as Record<string, unknown>) ?? {},\n );\n res.json({ draft });\n });\n\n // Import a remote table as a live (runtime-origin) federated object so it's\n // immediately queryable — the \"Import as Object\" action (ADR-0015 Addendum).\n // 503 when the service is absent; 400 when import is refused (e.g. read-only\n // metadata store) or the remote table is missing.\n server.post(`${ext}/tables/:remote/import`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.importObject) return unavailable(res);\n try {\n const result = await svc.importObject(\n req.params.name,\n req.params.remote,\n (req.body as Record<string, unknown>) ?? {},\n );\n res.status(201).json({ object: result });\n } catch (err) {\n res.status(400).json({\n error: 'external_import_error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n });\n\n // Refresh and return the cached catalog snapshot.\n server.post(`${ext}/refresh-catalog`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.refreshCatalog) return unavailable(res);\n const catalog = await svc.refreshCatalog(req.params.name);\n res.json({ catalog });\n });\n\n // Validate the federated objects on this datasource.\n server.post(`${ext}/validate`, async (req: any, res: any) => {\n const svc = externalService();\n if (!svc?.validateAll) return unavailable(res);\n const report = await svc.validateAll();\n const results = (report.results ?? []).filter((r: any) => r.datasource === req.params.name);\n res.json({ ok: results.every((r: any) => r.ok), results });\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext, IHttpServer } from '@objectstack/core';\nimport { RestServer, RestKernelManager } from './rest-server.js';\nimport { ObjectStackProtocol, RestServerConfig } from '@objectstack/spec/api';\nimport { registerPackageRoutes } from './package-routes.js';\nimport { registerExternalDatasourceRoutes } from './external-datasource-routes.js';\nimport type { PackageService } from '@objectstack/service-package';\n\nexport interface RestApiPluginConfig {\n serverServiceName?: string;\n protocolServiceName?: string;\n /**\n * Optional override for the kernel-manager service name. When the service\n * is registered (by @objectstack/runtime's MultiProjectPlugin), scoped\n * routes resolve per-environment protocols at request time.\n */\n kernelManagerServiceName?: string;\n api?: RestServerConfig;\n}\n\n/**\n * REST API Plugin\n * \n * Responsibilities:\n * 1. Consumes 'http.server' (or configured service)\n * 2. Consumes 'protocol' (ObjectStackProtocol)\n * 3. Instantiates RestServer to auto-generate routes\n */\nexport function createRestApiPlugin(config: RestApiPluginConfig = {}): Plugin {\n return {\n name: 'com.objectstack.rest.api',\n version: '1.0.0',\n \n init: async (_ctx: PluginContext) => {\n // No service registration, this is a consumer plugin\n },\n \n start: async (ctx: PluginContext) => {\n const serverService = config.serverServiceName || 'http.server';\n const protocolService = config.protocolServiceName || 'protocol';\n \n let server: IHttpServer | undefined;\n let protocol: ObjectStackProtocol | undefined;\n\n try {\n server = ctx.getService<IHttpServer>(serverService);\n } catch (e) {\n // Ignore missing service\n }\n\n try {\n protocol = ctx.getService<ObjectStackProtocol>(protocolService);\n } catch (e) {\n // Ignore missing service\n }\n\n // Optional — only present when MultiProjectPlugin is mounted. When\n // available, RestServer will resolve a per-environment protocol at\n // request time for scoped (`/environments/:environmentId/...`) routes.\n let kernelManager: RestKernelManager | undefined;\n const kernelManagerService = config.kernelManagerServiceName || 'kernel-manager';\n try {\n kernelManager = ctx.getService<RestKernelManager>(kernelManagerService);\n } catch (e) {\n // Single-kernel deployment — fall back to the control protocol\n }\n\n // Optional — only present in runtime mode. When available,\n // RestServer will resolve hostname → environmentId on unscoped\n // routes so a remote runtime node can dispatch every request\n // to the matching per-environment kernel without requiring callers\n // to know the environmentId.\n let envRegistry: any;\n try {\n envRegistry = ctx.getService<any>('env-registry');\n } catch (e) {\n // Not running in runtime/multi-environment mode — fine.\n }\n\n // Optional default-project provider — registered by\n // `createSingleEnvironmentPlugin` in single-environment local mode.\n // Lets RestServer route bare `/api/v1/data/...` URLs into the\n // lone project's kernel.\n const defaultEnvironmentIdProvider = (): string | undefined => {\n try {\n const dp: any = ctx.getService('default-project');\n return dp?.environmentId;\n } catch { return undefined; }\n };\n\n // Auth service resolver — used by RestServer.resolveExecCtx in\n // single-kernel deployments where there is no kernelManager.\n // Multi-kernel paths look up auth via kernelManager.getOrCreate,\n // so this provider is the single-kernel fallback.\n const authServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('auth');\n } catch { return undefined; }\n };\n\n // ObjectQL resolver — single-kernel fallback so resolveExecCtx\n // can run sys_member / sys_user_permission_set lookups when\n // there is no kernelManager wired (e.g. `pnpm dev:crm`).\n const objectQLProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('objectql');\n } catch { return undefined; }\n };\n\n // Email service resolver — used by POST /email/send. Single-\n // kernel deployments resolve from the local kernel; multi-\n // tenant paths would resolve via kernelManager.getOrCreate.\n const emailServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('email');\n } catch { return undefined; }\n };\n\n // Sharing service resolver — used by /data/:object/:id/shares.\n const sharingServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('sharing');\n } catch { return undefined; }\n };\n\n // Reports service resolver — used by /reports/* routes.\n const reportsServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('reports');\n } catch { return undefined; }\n };\n\n // Approvals service resolver — used by /approvals/* routes.\n const approvalsServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('approvals');\n } catch { return undefined; }\n };\n\n // Sharing-rule service resolver — used by /sharing/rules/* routes.\n const sharingRulesServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('sharingRules');\n } catch { return undefined; }\n };\n\n // i18n service resolver — used to localize view / action / object\n // metadata. Single-kernel fallback so labels and select options\n // get translated even without a full multi-tenant kernelManager.\n const i18nServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('i18n');\n } catch { return undefined; }\n };\n\n // Analytics service resolver — used by /analytics/dataset/query\n // (ADR-0021 dataset preview/query). Returns undefined when no\n // analytics service is registered so the route fails cleanly (501).\n const analyticsServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('analytics');\n } catch { return undefined; }\n };\n\n // Settings service resolver — used by resolveExecCtx to resolve the\n // reference timezone/locale (localization manifest) through the 4-tier\n // cascade incl. the `OS_LOCALIZATION_TIMEZONE` env override. Returns\n // undefined when no settings service is registered (UTC default).\n const settingsServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('settings');\n } catch { return undefined; }\n };\n\n if (!server) {\n ctx.logger.warn(`RestApiPlugin: HTTP Server service '${serverService}' not found. REST routes skipped.`);\n return;\n }\n \n if (!protocol) {\n ctx.logger.warn(`RestApiPlugin: Protocol service '${protocolService}' not found. REST routes skipped.`);\n return;\n }\n \n ctx.logger.info('Hydrating REST API from Protocol...');\n \n try {\n const restServer = new RestServer(server, protocol, config.api as any, kernelManager, envRegistry, defaultEnvironmentIdProvider, authServiceProvider, objectQLProvider, emailServiceProvider, sharingServiceProvider, reportsServiceProvider, approvalsServiceProvider, sharingRulesServiceProvider, i18nServiceProvider, analyticsServiceProvider, settingsServiceProvider);\n restServer.registerRoutes();\n\n ctx.logger.info('REST API successfully registered');\n } catch (err: any) {\n ctx.logger.error('Failed to register REST API routes', { error: err.message } as any);\n throw err;\n }\n\n const basePath = config.api?.api?.basePath || '/api';\n const version = config.api?.api?.version || 'v1';\n const versionedBase = `${basePath}/${version}`;\n const enableProjectScoping = config.api?.api?.enableProjectScoping ?? false;\n const projectResolution = config.api?.api?.projectResolution ?? 'auto';\n\n // Register package management routes if the service is available.\n try {\n const packageService = ctx.getService<PackageService>('package');\n if (packageService) {\n if (enableProjectScoping && projectResolution === 'required') {\n // Only register the scoped variant\n registerPackageRoutes(server, packageService, `${versionedBase}/environments/:environmentId`, {\n protocol,\n });\n } else {\n registerPackageRoutes(server, packageService, versionedBase, { protocol });\n if (enableProjectScoping) {\n registerPackageRoutes(server, packageService, `${versionedBase}/environments/:environmentId`, {\n protocol,\n });\n }\n }\n ctx.logger.info('Package management routes registered');\n }\n } catch (e) {\n // Package service not available, skip\n ctx.logger.debug('Package service not available, package routes skipped');\n }\n\n // External Datasource Federation routes (ADR-0015): catalog / draft /\n // import / validate. Registered unconditionally — they degrade\n // gracefully (503) when the `external-datasource` service is absent.\n // NOTE: the datasource *lifecycle* routes (ADR-0015 Addendum:\n // list / test / create / update / remove) moved to the private\n // `@objectstack/datasource-admin` package, which registers its own.\n try {\n registerExternalDatasourceRoutes(server, ctx, versionedBase);\n ctx.logger.info('Datasource federation routes registered');\n } catch (e: any) {\n ctx.logger.warn('Datasource federation routes registration failed', { error: e?.message });\n }\n }\n };\n}\n"],"mappings":"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","names":["row"]}