@objectstack/rest 14.7.0 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rest-server.ts","../src/route-manager.ts","../src/export-format.ts","../src/import-coerce.ts","../src/import-runner.ts","../src/import-mapping.ts","../src/import-prepare.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\nimport { IHttpServer, resolveAuthzContext, resolveLocalizationContext, isAuthGateAllowlisted } from '@objectstack/core';\nimport { isMcpServerEnabled } from '@objectstack/types';\nimport { RouteManager } from './route-manager.js';\nimport { RestServerConfig, RestApiConfig, CrudEndpointsConfig, MetadataEndpointsConfig, BatchEndpointsConfig, RouteGenerationConfig } from '@objectstack/spec/api';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport {\n buildFieldMetaMap,\n referenceFieldNames,\n headerLabel,\n formatRowCells,\n formatRowForJson,\n cellFontColor,\n type ExportFieldMeta,\n} from './export-format.js';\nimport { runImport } from './import-runner.js';\nimport { prepareImportRequest, isMetaEnvelope } from './import-prepare.js';\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/**\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 // Capability gates (#2707 feeds / #2727 files): plugin-audit's engine\n // hooks reject sys_comment / sys_attachment inserts fail-closed when the\n // TARGET object's capability flag disallows them. 403 like\n // CLONE_DISABLED; surfaced by `code` because the generic data routes map\n // through here (they never reach sendError's `.status` passthrough).\n // `error.object` names the gated TARGET object (not the join table), so\n // prefer it.\n if (error?.code === 'FEEDS_DISABLED' || error?.code === 'FILES_DISABLED') {\n return {\n status: 403,\n body: {\n error: error?.message ?? 'This capability is disabled for the target object',\n code: error.code,\n ...(error?.object || object ? { object: error?.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 // The metadata required-check (`record-validator`) runs BEFORE the\n // driver, so a NOT NULL violation that reaches this far means metadata\n // did NOT consider the field required — i.e. the physical column has\n // drifted from metadata (#2186), not a genuine missing-required-field.\n // We keep the `VALIDATION_FAILED` / `required` envelope for back-compat\n // (form UIs key off it) but add an actionable `hint` so the message\n // stops being misleading.\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 hint:\n `If '${field}' is optional in your object metadata, the database column is still NOT NULL — ` +\n `the physical schema has drifted from metadata. Run 'os migrate' to reconcile ` +\n `(or reset the dev database).`,\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/** Platform object backing async import jobs (see sys-import-job.object.ts). */\nconst IMPORT_JOB_OBJECT = 'sys_import_job';\n/** Hard ceiling on rows per async import job (mirrors spec IMPORT_JOB_MAX_ROWS). */\nconst IMPORT_JOB_MAX_ROWS = 50_000;\n/** Cap on per-row results persisted on the job (failures first). */\nconst IMPORT_JOB_RESULTS_CAP = 500;\n/** Undo (logical rollback) is only recorded for jobs at or under this row\n * count — larger jobs skip the undo log to bound the stored before-snapshots. */\nconst IMPORT_JOB_UNDO_MAX_ROWS = 5_000;\n\n/** Generate a sortable-ish, collision-resistant import job id. */\nfunction newImportJobId(): string {\n return `imp_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Cap a results list to {@link IMPORT_JOB_RESULTS_CAP}, keeping failures first. */\nfunction capImportResults(results: Array<{ ok: boolean }>): { items: any[]; truncated: boolean } {\n if (results.length <= IMPORT_JOB_RESULTS_CAP) return { items: results, truncated: false };\n const failures = results.filter(r => !r.ok);\n const successes = results.filter(r => r.ok);\n const items = [...failures, ...successes].slice(0, IMPORT_JOB_RESULTS_CAP);\n return { items, truncated: true };\n}\n\n/** Parse the persisted undo log (json column may arrive as object or string). */\nfunction parseUndoLog(raw: any): { created: string[]; updated: Array<{ id: string; before: Record<string, any> }> } | undefined {\n if (!raw) return undefined;\n let v = raw;\n if (typeof v === 'string') { try { v = JSON.parse(v); } catch { return undefined; } }\n if (!v || typeof v !== 'object') return undefined;\n const created = Array.isArray(v.created) ? v.created.map(String) : [];\n const updated = Array.isArray(v.updated)\n ? v.updated.filter((u: any) => u && u.id != null).map((u: any) => ({ id: String(u.id), before: u.before ?? {} }))\n : [];\n return { created, updated };\n}\n\n/** True when a job can still be undone: it wrote data (undo log present with\n * entries), hasn't already been reverted, and finished in a terminal state. */\nfunction importJobUndoable(row: any): boolean {\n if (row?.reverted_at) return false;\n const status = String(row?.status ?? '');\n if (status !== 'succeeded' && status !== 'cancelled') return false;\n const log = parseUndoLog(row?.undo_log);\n return !!log && (log.created.length > 0 || log.updated.length > 0);\n}\n\n/** Map a persisted `sys_import_job` row to the ImportJobProgress DTO. */\nfunction importJobToProgress(row: any): Record<string, any> {\n const total = Number(row?.total_rows ?? 0);\n const processed = Number(row?.processed_rows ?? 0);\n return {\n undoable: importJobUndoable(row),\n ...(row?.reverted_at ? { revertedAt: String(row.reverted_at) } : {}),\n jobId: String(row?.id ?? ''),\n object: String(row?.object_name ?? ''),\n status: String(row?.status ?? 'pending'),\n dryRun: !!row?.dry_run,\n writeMode: String(row?.write_mode ?? 'insert'),\n total,\n processed,\n created: Number(row?.created_count ?? 0),\n updated: Number(row?.updated_count ?? 0),\n skipped: Number(row?.skipped_count ?? 0),\n errors: Number(row?.error_count ?? 0),\n percentComplete: total > 0 ? Math.min(100, Math.round((processed / total) * 100)) : (processed > 0 ? 100 : 0),\n ...(row?.error ? { error: String(row.error) } : {}),\n ...(row?.started_at ? { startedAt: String(row.started_at) } : {}),\n ...(row?.completed_at ? { completedAt: String(row.completed_at) } : {}),\n createdAt: String(row?.created_at ?? ''),\n };\n}\n\n/** Map a persisted `sys_import_job` row to the ImportJobSummary DTO (list). */\nfunction importJobToSummary(row: any): Record<string, any> {\n const p = importJobToProgress(row);\n return {\n jobId: p.jobId, object: p.object, status: p.status,\n total: p.total, processed: p.processed,\n created: p.created, updated: p.updated, skipped: p.skipped, errors: p.errors,\n createdAt: p.createdAt,\n undoable: p.undoable,\n ...(p.completedAt ? { completedAt: p.completedAt } : {}),\n ...(p.revertedAt ? { revertedAt: p.revertedAt } : {}),\n };\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 ordered\n * list of field names and a (possibly empty) field-metadata map. With metadata,\n * the header row uses field labels and cell values are formatted to readable\n * display values (lookup names, select labels, 是/否, formatted dates). With an\n * empty map the output is byte-identical to the raw, un-formatted behaviour.\n */\nfunction rowsToCsv(\n fields: string[],\n rows: Array<Record<string, any>>,\n includeHeader: boolean,\n metaMap: Map<string, ExportFieldMeta>,\n): string {\n const lines: string[] = [];\n if (includeHeader) lines.push(fields.map(f => formatCsvCell(headerLabel(f, metaMap))).join(','));\n for (const row of rows) {\n lines.push(formatRowCells(row, fields, metaMap).map(formatCsvCell).join(','));\n }\n return lines.join('\\r\\n') + (lines.length > 0 ? '\\r\\n' : '');\n}\n\n/**\n * Bridge exceljs' streaming workbook writer onto the chunked HTTP response.\n *\n * exceljs writes to a Node stream; we pipe a PassThrough's `data` events into\n * `res.write` (which the hono server encodes — strings via TextEncoder, binary\n * Buffers/Uint8Arrays enqueued verbatim) so the xlsx bytes stream straight to\n * the client without buffering the whole workbook in memory. `useStyles:false`\n * keeps the writer lean for large (20k+ row) exports.\n *\n * Returns the worksheet to append rows to and a `finalize()` that commits the\n * workbook and resolves once the last byte has been flushed and the response\n * ended. Dynamically imported so `node:stream` / `exceljs` stay out of the\n * module's static graph.\n */\nasync function createXlsxStream(res: any, useStyles = false): Promise<{\n ws: any;\n finalize: () => Promise<void>;\n}> {\n const { PassThrough } = await import('node:stream');\n const ExcelJS: any = (await import('exceljs')).default ?? (await import('exceljs'));\n\n const passthrough = new PassThrough();\n const done = new Promise<void>((resolve, reject) => {\n passthrough.on('data', (chunk: Buffer) => { res.write(chunk); });\n passthrough.on('end', () => { try { res.end(); } catch { /* swallow */ } resolve(); });\n passthrough.on('error', reject);\n });\n\n const wb = new ExcelJS.stream.xlsx.WorkbookWriter({ stream: passthrough, useStyles });\n const ws = wb.addWorksheet('Export');\n\n return {\n ws,\n finalize: async () => {\n await ws.commit();\n await wb.commit();\n await done;\n },\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 /**\n * Request-scoped memoization for `resolveExecCtx`. A single HTTP request\n * resolves the SAME execution context (identity + RBAC/RLS + localization)\n * many times — the data operation itself, app-nav RBAC filtering, dashboard\n * widget gating, the auth gate, etc. Each resolution is ~16 sequential\n * queries (the `resolveAuthzContext` aggregation plus localization), so a\n * request that resolves twice pays for duplicate authz and repeated\n * localization. Keyed by the per-request `req` object (a `WeakMap`, so the\n * entry is collected with the request — naturally request-scoped, no TTL,\n * no cross-request leak) and the input `environmentId`. We cache the\n * in-flight Promise so concurrent callers share one resolution.\n */\n private readonly execCtxMemo = new WeakMap<object, Map<string, Promise<any | undefined>>>();\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 /** [ADR-0090] `security` service resolver — used by the\n * /security/suggested-bindings (D5/D9) and /security/explain (D6)\n * routes (plugin-security). */\n private securityServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n /** Sync probe: is a kernel service registered? Single-env path for nav\n * capability gates (ADR-0057 D10) — resolveExecCtx sets no kernel in\n * single-kernel deployments, so this prevents the gate failing open. */\n private serviceExistsProvider?: (name: string) => boolean;\n /**\n * In-flight async import jobs the caller has asked to cancel. The worker\n * checks membership at each progress boundary and stops cooperatively. This\n * is process-local (single-node); the persisted `sys_import_job.status` is\n * the durable source of truth a restarted/other node reads.\n */\n private readonly cancelledImportJobs = new Set<string>();\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 serviceExistsProvider?: (name: string) => boolean,\n securityServiceProvider?: (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 this.serviceExistsProvider = serviceExistsProvider;\n this.securityServiceProvider = securityServiceProvider;\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 // ADR-0069 — authentication-policy gate (password expiry, enforced MFA).\n // Independent of `requireAuth`: a gated session (carrying `authGate`) is\n // blocked from protected resources, while the core allow-list keeps auth\n // + remediation reachable. Runs before the anonymous check.\n const gate = context?.authGate;\n if (gate && req?.method !== 'OPTIONS' && !isAuthGateAllowlisted(req?.path)) {\n res.status(403).json({ error: { code: gate.code, message: gate.message } });\n return true;\n }\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 // Request-scoped memoization — see `execCtxMemo`. The same `req` flows\n // unchanged through every handler call, so its identity keys the memo;\n // the input `environmentId` is part of the key because one host can route\n // multiple environments. Anonymous (`undefined`) resolutions are cached\n // too so repeat callers don't re-run getSession. Fall back to a direct\n // resolve when there is no object to key on.\n if (!req || typeof req !== 'object') return this.computeExecCtx(environmentId, req);\n const key = environmentId ?? '\\u0000default';\n let perReq = this.execCtxMemo.get(req);\n if (!perReq) { perReq = new Map(); this.execCtxMemo.set(req, perReq); }\n const cached = perReq.get(key);\n if (cached) return cached;\n const pending = this.computeExecCtx(environmentId, req);\n perReq.set(key, pending);\n return pending;\n }\n\n /**\n * [ADR-0046 §6.7] The audience-evaluation view of the caller for book/doc\n * gating. `permissionSets` resolves through the security service's\n * `resolvePermissionSetNames` — the SAME resolution as data-plane\n * enforcement (positions expanded, additive baseline), so the docs gate\n * can never drift from it. `permissionSets` stays undefined when the\n * service is absent or resolution fails; `audienceAllows` then DENIES\n * permission-set-gated audiences (fail closed, ADR-0049). Resolution is\n * skipped unless `needPermissionSets` — callers pass true only when a\n * `{ permissionSet }` audience is actually in play.\n */\n private async resolveAudienceCaller(\n environmentId: string | undefined,\n req: any,\n opts: { needPermissionSets: boolean },\n ): Promise<{ authenticated: boolean; permissionSets?: string[] }> {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n const authenticated = !!ctx?.userId;\n if (!authenticated || !opts.needPermissionSets || !this.securityServiceProvider) {\n return { authenticated };\n }\n try {\n const svc = await this.securityServiceProvider(environmentId);\n if (!svc || typeof svc.resolvePermissionSetNames !== 'function') return { authenticated };\n const names = await svc.resolvePermissionSetNames(ctx);\n return { authenticated, permissionSets: Array.isArray(names) ? names : [] };\n } catch {\n return { authenticated }; // unresolved holdings → gated audiences deny\n }\n }\n\n /** Whether any of these books carries a `{ permissionSet }` audience. */\n private static anyPermissionSetAudience(books: readonly any[]): boolean {\n return books.some(\n (b) => b && typeof b === 'object' && b.audience && typeof b.audience === 'object'\n && typeof b.audience.permissionSet === 'string',\n );\n }\n\n /** Coerce a getMetaItems result (array | {items}) into an array. */\n private static metaItemsArray(raw: unknown): any[] {\n if (Array.isArray(raw)) return raw;\n if (raw && typeof raw === 'object' && Array.isArray((raw as any).items)) return (raw as any).items;\n return [];\n }\n\n /** Fetch every book of the environment, shaped for the audience resolver. */\n private async fetchAudienceBooks(p: any, environmentId: string | undefined): Promise<any[]> {\n const raw = await p.getMetaItems({\n type: 'book',\n ...(environmentId ? { environmentId } : {}),\n } as any).catch(() => []);\n return RestServer.metaItemsArray(raw).map((b: any) =>\n b && typeof b === 'object' ? { ...b, packageId: b._packageId } : b,\n );\n }\n\n /** Heavy path behind `resolveExecCtx` — resolve identity + RBAC/RLS + localization. */\n private async computeExecCtx(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 // Resolve the data engine for this scope (shared by the resolver below).\n const ql: any = kernel\n ? await kernel.getServiceAsync('objectql').catch(() => undefined)\n : (this.objectQLProvider ? await this.objectQLProvider(environmentId).catch(() => undefined) : undefined);\n\n // Delegate ALL identity + role/permission/RLS aggregation to the SINGLE\n // shared resolver (`resolveAuthzContext`, @objectstack/core) — the same one\n // the runtime dispatcher uses, so the REST and dispatcher entry points can\n // never drift on authorization. (This path previously kept its own copy that\n // silently omitted sys_user_position / sys_position_permission_set / platform_admin /\n // ai_seat — see the resolver's module doc.)\n const getSession = async (h: any) => {\n try { return await api.getSession({ headers: h }); } catch { return undefined; }\n };\n const authz = await resolveAuthzContext({ ql, headers, getSession });\n if (!authz.userId) return undefined;\n\n const settings = this.settingsServiceProvider\n ? await this.settingsServiceProvider(environmentId).catch(() => undefined)\n : undefined;\n const localization = await resolveLocalizationContext({\n ql,\n settings,\n tenantId: authz.tenantId,\n userId: authz.userId,\n });\n\n // ADR-0069 — authentication-policy gate posture. Only when a gate\n // feature is active (cheap sync check) do we re-read the session for\n // its `user.authGate` (computed in customSession). enforceAuth() then\n // blocks protected resources for a gated user. Zero cost when off.\n let authGate: any;\n try {\n if (typeof authService.isAuthGateActive === 'function' && authService.isAuthGateActive()) {\n const gatedSession: any = await getSession(headers).catch(() => undefined);\n if (gatedSession?.user?.authGate) authGate = gatedSession.user.authGate;\n }\n } catch { /* gate is best-effort — never break context resolution */ }\n\n return {\n userId: authz.userId,\n tenantId: authz.tenantId,\n email: authz.email,\n positions: authz.positions,\n permissions: authz.permissions,\n systemPermissions: authz.systemPermissions,\n ...(authz.tabPermissions ? { tabPermissions: authz.tabPermissions } : {}),\n isSystem: false,\n org_user_ids: authz.org_user_ids,\n ...(authGate ? { authGate } : {}),\n ...(localization.timezone ? { timezone: localization.timezone } : {}),\n ...(localization.locale ? { locale: localization.locale } : {}),\n ...(localization.currency ? { currency: localization.currency } : {}),\n // Internal: resolved kernel so the nav-serving path can probe\n // requiresService capability gates (ADR-0057 D10). NOT an\n // authorization input — never read by RLS/permission logic.\n __kernel: kernel,\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>, serviceGate?: (name: string) => boolean): any | null {\n if (!item || typeof item !== 'object') return item;\n // getMetaItem returns an envelope { type, name, item: <app>, ... } while the\n // list path passes the raw app. Unwrap + re-wrap so gating runs on both —\n // filtering the envelope directly is a silent no-op (its .navigation is\n // undefined), which would bypass BOTH requiredPermissions and the ADR-0057\n // D10 requiresService gate.\n if (isMetaEnvelope(item)) {\n const body = this.filterAppForUser((item as any).item, sysPerms, serviceGate);\n return body == null ? null : { ...(item as any), item: body };\n }\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 // ADR-0057 D10 — capability gate: hide when the named kernel service is\n // absent. Fail-open when the gate can't be probed (serviceGate undefined).\n if (typeof item.requiresService === 'string' && serviceGate && serviceGate(item.requiresService) === false) {\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 (typeof e.requiresService === 'string' && serviceGate && serviceGate(e.requiresService) === false) 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 * ADR-0057 D10 (dashboards): strip dashboard widgets whose `requiresService`\n * capability gate names a kernel service that isn't registered — the same\n * \"server is the authoritative visibility gate\" rule already applied to app\n * nav entries (see {@link filterAppForUser}). Without this, a widget bound to\n * an optional service renders a dead tile in deployments where the service is\n * off (e.g. the Organizations KPI under multi-tenant `org-scoping`, which is\n * absent in a single-tenant runtime while its nav entry is correctly hidden).\n *\n * Fail-open when the gate can't be probed (serviceGate undefined). Never\n * mutates the original — returns a shallow copy only when a widget is dropped.\n */\n private filterDashboardForUser(item: any, serviceGate?: (name: string) => boolean): any {\n if (!item || typeof item !== 'object' || !serviceGate) return item;\n if (isMetaEnvelope(item)) {\n const body = this.filterDashboardForUser((item as any).item, serviceGate);\n return body === (item as any).item ? item : { ...(item as any), item: body };\n }\n if (!Array.isArray(item.widgets)) return item;\n const widgets = item.widgets.filter(\n (w: any) => !(w && typeof w.requiresService === 'string' && serviceGate(w.requiresService) === false),\n );\n return widgets.length === item.widgets.length ? item : { ...item, widgets };\n }\n\n /**\n * Probe which `requiresService` capability gates referenced anywhere in\n * `items` are actually registered in the runtime kernel. Returns `null`\n * when the kernel can't be probed — callers then SKIP service gating\n * (fail-open, matching the prior \"send everything, let the client hide\"\n * behaviour). ADR-0057 addendum D10.\n */\n private async resolveRegisteredServices(kernel: any, items: any[]): Promise<Set<string> | null> {\n // Prefer the per-request kernel (multi-env, resolved via kernelManager).\n // Fall back to the single-env service-existence provider — in single-kernel\n // deployments resolveExecCtx never sets a kernel, so without this the gate\n // would fail open (ADR-0057 D10).\n let probe: ((name: string) => Promise<boolean>) | null = null;\n if (kernel && typeof kernel.getServiceAsync === 'function') {\n probe = async (name) => { try { return (await kernel.getServiceAsync(name)) != null; } catch { return false; } };\n } else if (this.serviceExistsProvider) {\n const exists = this.serviceExistsProvider;\n probe = async (name) => { try { return exists(name) === true; } catch { return false; } };\n }\n if (!probe) return null;\n const wanted = new Set<string>();\n const walk = (e: any): void => {\n if (!e || typeof e !== 'object') return;\n if (isMetaEnvelope(e)) { walk((e as any).item); return; }\n if (typeof e.requiresService === 'string') wanted.add(e.requiresService);\n const kids = Array.isArray(e.navigation) ? e.navigation\n : Array.isArray(e.children) ? e.children\n // Dashboard widgets carry their own `requiresService` gate.\n : Array.isArray(e.widgets) ? e.widgets : null;\n if (kids) for (const k of kids) walk(k);\n };\n for (const it of items) walk(it);\n if (wanted.size === 0) return new Set();\n const registered = new Set<string>();\n for (const name of wanted) { if (await probe(name)) registered.add(name); }\n return registered;\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 ?? true, // secure-by-default (ADR-0056 D2; mirrors RestApiConfigSchema)\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 this.registerSecurityEndpoints(bp);\n this.registerSecurityExplainEndpoints(bp);\n // Data-action routes (e.g. GET /data/:object/export, POST\n // /data/:object/import) use static-literal action segments that\n // MUST be registered BEFORE the greedy GET /data/:object/:id\n // matcher in registerCrudEndpoints — the router is first-match-wins\n // with no specificity sorting (see route-manager.ts), so otherwise\n // a request to `.../export` is captured by `:id` and \"export\" is\n // treated as a record id (404 RECORD_NOT_FOUND). This mirrors the\n // /meta/:type/:name/references-before-/meta/:type/:name convention.\n // Safe in the other direction too: registerDataActionEndpoints has\n // no greedy 2-segment `:object/:id` routes (only literal actions and\n // deeper `:id/clone`, `:id/shares` paths), so it cannot shadow any\n // CRUD literal.\n this.registerDataActionEndpoints(bp);\n if (this.config.api.enableCrud) {\n this.registerCrudEndpoints(bp);\n }\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 a default-on core capability —\n // advertise it unless OS_MCP_SERVER_ENABLED=false opts the\n // env out, so the objectui Integrations page surfaces the\n // connect card. The /mcp route is mounted bare (not\n // project-scoped), so point at the unscoped base. This\n // `/discovery` (served by @objectstack/rest) is separate\n // from the dispatcher's getDiscoveryInfo — both must\n // advertise `mcp` (single source: isMcpServerEnabled).\n if (isMcpServerEnabled()) {\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 the metadata routes behind the SAME `requireAuth` gate the\n * `/data` routes use.\n *\n * `registerMetadataEndpoints` builds ~17 `/meta/*` routes but — unlike the\n * `/data` handlers — never calls {@link enforceAuth}: its handlers assumed\n * the `requireAuth` gate rejected anonymous callers \"upstream\", yet nothing\n * upstream covers `/meta`, so on a `requireAuth` deployment an anonymous\n * caller could read object / field schemas. On a tenant-less runtime host\n * those are SYSTEM-object schemas and the host is publicly reachable — a\n * real leak.\n *\n * Rather than add the gate to every handler (and have the next new route\n * forget it — the exact failure mode that caused this), wrap the route\n * registrar for the duration of registration so every meta route, present\n * and future, inherits it. The check is a no-op when `requireAuth` is off\n * (demo / single-tenant), so the previously-public metadata surface there\n * is unchanged; an authenticated user passes exactly as on `/data`.\n */\n private registerMetadataEndpoints(basePath: string): void {\n const realRouteManager = this.routeManager;\n const guardedRouteManager = {\n register: (entry: { handler: unknown; [k: string]: unknown }) => {\n const inner = entry.handler;\n if (typeof inner !== 'function') return realRouteManager.register(entry as any);\n return realRouteManager.register({\n ...entry,\n handler: async (req: any, res: any) => {\n // `req.params.environmentId` is present only on the\n // scoped `/environments/:id/meta/...` variant — mirrors\n // the `isScoped ? req.params.environmentId : undefined`\n // each `/data` handler derives.\n const environmentId = req?.params?.environmentId;\n const context = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (this.enforceAuth(req, res, context)) return;\n return (inner as (rq: any, rs: any) => unknown)(req, res);\n },\n } as any);\n },\n } as unknown as RouteManager;\n this.routeManager = guardedRouteManager;\n try {\n this.registerMetadataEndpointsInner(basePath);\n } finally {\n this.routeManager = realRouteManager;\n }\n }\n\n private registerMetadataEndpointsInner(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 registered = await this.resolveRegisteredServices((ctx as any).__kernel, list);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n const filtered = list\n .map((it: any) => this.filterAppForUser(it, sysPerms, serviceGate))\n .filter((it: any) => it != null);\n visible = Array.isArray(raw)\n ? filtered\n : { ...(raw as any), items: filtered };\n }\n }\n }\n\n // ADR-0057 D10: gate dashboard widgets by `requiresService`\n // the same way app nav entries are gated above.\n if (req.params.type === 'dashboard') {\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 ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n const registered = await this.resolveRegisteredServices((ctx as any)?.__kernel, list);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n if (serviceGate) {\n const filtered = list.map((it: any) => this.filterDashboardForUser(it, serviceGate));\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 §6.7 — book list is audience-filtered: anonymous\n // callers see only `public` books; `{ permissionSet }`-gated\n // books require the caller to hold the named set (resolved\n // through the security service; unresolvable → fail closed).\n if (req.params.type === 'book') {\n const raw = visible as unknown;\n const list = RestServer.metaItemsArray(raw);\n if (list.length > 0) {\n const { audienceAllows } = await import('@objectstack/spec/system');\n const caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience(list),\n });\n const filtered = list.filter((b: any) =>\n b && typeof b === 'object' && audienceAllows((b as any).audience, caller));\n visible = Array.isArray(raw) ? filtered : { ...(raw as any), items: filtered };\n }\n }\n\n // ADR-0046 §6.7 — doc list is audience-filtered by each\n // doc's EFFECTIVE audience (union over the books that\n // claim it; unclaimed docs default to `org`). Runs on the\n // raw items (before locale collapse) so `_packageId`\n // provenance is still present for membership scoping.\n if (req.params.type === 'doc') {\n const raw = visible as unknown;\n const list = RestServer.metaItemsArray(raw);\n if (list.length > 0) {\n const { audienceAllows, docAudienceAllows, resolveDocAudiences } =\n await import('@objectstack/spec/system');\n const books = await this.fetchAudienceBooks(p, environmentId);\n const caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience(books),\n });\n let filtered: any[];\n if (caller.authenticated && !RestServer.anyPermissionSetAudience(books)) {\n // Fast path: with no gated book anywhere, every\n // effective audience admits an authenticated caller.\n filtered = list;\n } else {\n const corpus = list\n .filter((d: any) => d && typeof d === 'object')\n .map((d: any) => ({\n name: d.name,\n group: d.group,\n tags: d.tags,\n order: d.order,\n packageId: d._packageId,\n }));\n const audiences = resolveDocAudiences(books as any, corpus);\n filtered = list.filter((d: any) => {\n if (!d || typeof d !== 'object') return false;\n const eff = audiences.get(d.name);\n return eff\n ? docAudienceAllows(eff, caller)\n : audienceAllows('org', caller);\n });\n }\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, audienceAllows, resolveDocAudiences, docAudienceAllows, 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 — the book's audience gates the whole tree:\n // anonymous → `public` only; `{ permissionSet }` →\n // the caller must hold the named set (fail closed\n // when holdings cannot be resolved, ADR-0049).\n const audienceBooks = books.map((b: any) =>\n b && typeof b === 'object' ? { ...b, packageId: b._packageId } : b);\n const caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience([book, ...audienceBooks]),\n });\n if (!audienceAllows((book as any).audience, caller)) {\n if (!caller.authenticated) {\n sendError(res, { code: 'unauthorized', message: 'This documentation requires sign-in', status: 401 });\n } else {\n sendError(res, { code: 'PERMISSION_DENIED', message: 'This documentation is limited to holders of a permission set you do not have', status: 403 });\n }\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\n // §6.7 — the tree's ENTRIES are additionally filtered by\n // each doc's effective audience (union over claiming\n // books, unclaimed → org), so an anonymous reader of a\n // public book never sees nav entries that would 401 on\n // fetch, and gated-only docs stay out of non-holders'\n // trees. The book gate above passed, so this only ever\n // narrows further for anonymous / non-holder callers.\n const gatedTreePossible = !caller.authenticated\n || RestServer.anyPermissionSetAudience(audienceBooks);\n if (gatedTreePossible) {\n const audiences = resolveDocAudiences(audienceBooks as any, docs);\n tree.groups = tree.groups\n .map((g: any) => ({\n ...g,\n entries: g.entries.filter((e: any) =>\n !e.doc || docAudienceAllows(audiences.get(e.doc), caller)),\n }))\n .filter((g: any) => g.entries.some((e: any) => e.doc || e.href));\n }\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 // `doc` and `book` bypass the shared cache: their §6.7\n // audience gate is per-caller, and a shared ETag would\n // leak gated content across viewers.\n if (metadata.enableCache && p.getMetaItemCached && !isAppType && !isDraftRead && !previewDrafts && !packageScoped && req.params.type !== 'doc' && req.params.type !== 'book') {\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 // `max-age` is a placeholder directive in the\n // array; its real value is appended from the\n // `maxAge` field. Strip the bare token before\n // joining so the two never collide into the\n // malformed `public, max-age, max-age=3600`.\n const parts: string[] = result.cacheControl.directives\n .filter((d: string) => d !== 'max-age');\n if (result.cacheControl.maxAge != null) {\n parts.push(`max-age=${result.cacheControl.maxAge}`);\n }\n res.header('Cache-Control', parts.join(', '));\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 const registered = await this.resolveRegisteredServices((ctx as any).__kernel, [item]);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n visible = this.filterAppForUser(item, sysPerms, serviceGate);\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-0057 D10: gate dashboard widgets by `requiresService`\n // (mirrors the app-nav gate above) so the console never\n // renders a tile bound to an absent optional service.\n if (req.params.type === 'dashboard' && visible) {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n const registered = await this.resolveRegisteredServices((ctx as any)?.__kernel, [visible]);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n if (serviceGate) visible = this.filterDashboardForUser(visible, serviceGate);\n }\n\n // ADR-0046 §6.7 — audience gate on single-item reads.\n // A `book` is gated by its own audience; a `doc` by its\n // EFFECTIVE audience (union over the books that claim\n // it, unclaimed → org). 401 for anonymous, 403 for an\n // authenticated non-holder; fail closed when holdings\n // cannot be resolved (ADR-0049).\n if ((req.params.type === 'book' || req.params.type === 'doc') && visible) {\n const { audienceAllows, docAudienceAllows, resolveDocAudiences } =\n await import('@objectstack/spec/system');\n const target = isMetaEnvelope(visible) ? (visible as any).item : visible;\n let caller: { authenticated: boolean; permissionSets?: string[] };\n let allowed: boolean;\n if (req.params.type === 'book') {\n caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience([target]),\n });\n allowed = audienceAllows(target?.audience, caller);\n } else {\n const books = await this.fetchAudienceBooks(p, environmentId);\n caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience(books),\n });\n if (caller.authenticated && !RestServer.anyPermissionSetAudience(books)) {\n allowed = true; // no gated book anywhere → org suffices\n } else {\n const corpus = RestServer.metaItemsArray(await p.getMetaItems({\n type: 'doc',\n ...(environmentId ? { environmentId } : {}),\n } as any).catch(() => []))\n .filter((d: any) => d && typeof d === 'object')\n .map((d: any) => ({\n name: d.name,\n group: d.group,\n tags: d.tags,\n order: d.order,\n packageId: d._packageId,\n }));\n const audiences = resolveDocAudiences(books as any, corpus);\n allowed = docAudienceAllows(audiences.get(target?.name), caller);\n }\n }\n if (!allowed) {\n if (!caller.authenticated) {\n sendError(res, { code: 'unauthorized', message: 'This documentation requires sign-in', status: 401 });\n } else {\n sendError(res, { code: 'PERMISSION_DENIED', message: 'This documentation is limited to holders of a permission set you do not have', status: 403 });\n }\n return;\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\n // Parse + validate the payload (shared with the async job route).\n // The synchronous path caps at 5k rows; larger files must use the\n // async import-job endpoint.\n const prep = await prepareImportRequest(body, { p, objectName, environmentId, maxRows: 5000 });\n if (!prep.ok) {\n if (prep.status === 413) prep.error += ' Use an async import job for larger files.';\n res.status(prep.status).json({ code: prep.code, error: prep.error });\n return;\n }\n const { rows, writeMode, dryRun } = prep.prepared;\n\n // Delegate the per-row coercion + upsert loop to the shared\n // runner (also used by the async import-job worker).\n const summary = await runImport({\n p, objectName, environmentId, context, ...prep.prepared,\n });\n\n res.json({\n object: objectName,\n dryRun,\n writeMode,\n total: rows.length,\n ok: summary.ok,\n errors: summary.errors,\n created: summary.created,\n updated: summary.updated,\n skipped: summary.skipped,\n results: summary.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 // ── Asynchronous import jobs (P1) ──────────────────────────────────\n //\n // For files too large for the synchronous route (up to 50k rows), the\n // client POSTs the whole payload once; the server persists a\n // `sys_import_job`, responds immediately with a jobId, then processes\n // the batch in the background — updating progress on the job row as it\n // streams. Callers poll progress/results and list history. These routes\n // are registered inside registerDataActionEndpoints (before the greedy\n // CRUD `:object/:id`), so the literal `import/jobs` segments win.\n\n // POST /data/:object/import/jobs — create an async import job.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/import/jobs`,\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\n const prep = await prepareImportRequest(req.body ?? {}, { p, objectName, environmentId, maxRows: IMPORT_JOB_MAX_ROWS });\n if (!prep.ok) {\n if (prep.status === 413) prep.error += ` This is the async import ceiling; split the file into batches of ${IMPORT_JOB_MAX_ROWS}.`;\n res.status(prep.status).json({ code: prep.code, error: prep.error });\n return;\n }\n const prepared = prep.prepared;\n\n const jobId = newImportJobId();\n const createdAt = new Date().toISOString();\n const createdBy = String((context as any)?.userId ?? (context as any)?.user?.id ?? '') || undefined;\n const jobRow: Record<string, any> = {\n id: jobId,\n object_name: objectName,\n status: 'pending',\n total_rows: prepared.rows.length,\n processed_rows: 0,\n created_count: 0,\n updated_count: 0,\n skipped_count: 0,\n error_count: 0,\n write_mode: prepared.writeMode,\n dry_run: prepared.dryRun,\n run_automations: prepared.runAutomations,\n created_at: createdAt,\n ...(createdBy ? { created_by: createdBy } : {}),\n };\n\n try {\n await (p as any).createData({ object: IMPORT_JOB_OBJECT, data: jobRow, context, ...(environmentId ? { environmentId } : {}) });\n } catch (err: any) {\n logError('[REST] Failed to persist import job:', err);\n res.status(500).json({ code: 'IMPORT_JOB_CREATE_FAILED', error: 'Could not create import job' });\n return;\n }\n\n // Respond immediately; process in the background.\n res.status(201).json({ jobId, object: objectName, status: 'pending', total: prepared.rows.length, createdAt });\n\n // Background worker. Fire-and-forget: it owns its own error\n // handling and persists terminal state to the job row.\n const patch = async (data: Record<string, any>) => {\n try {\n await (p as any).updateData({ object: IMPORT_JOB_OBJECT, id: jobId, data, context, ...(environmentId ? { environmentId } : {}) });\n } catch (err) {\n logError('[REST] import job progress write failed:', err);\n }\n };\n // Record undo instructions for small non-dry-run jobs so the\n // import can be logically rolled back later.\n const captureUndo = !prepared.dryRun && prepared.rows.length <= IMPORT_JOB_UNDO_MAX_ROWS;\n void (async () => {\n await patch({ status: 'running', started_at: new Date().toISOString() });\n try {\n const summary = await runImport({\n p, objectName, environmentId, context, ...prepared,\n captureUndo,\n progressEvery: 200,\n onProgress: (pr) => patch({\n processed_rows: pr.processed,\n created_count: pr.created,\n updated_count: pr.updated,\n skipped_count: pr.skipped,\n error_count: pr.errors,\n }),\n shouldCancel: () => this.cancelledImportJobs.has(jobId),\n });\n await patch({\n status: summary.cancelled ? 'cancelled' : 'succeeded',\n processed_rows: summary.processed,\n created_count: summary.created,\n updated_count: summary.updated,\n skipped_count: summary.skipped,\n error_count: summary.errors,\n results: capImportResults(summary.results),\n completed_at: new Date().toISOString(),\n ...(summary.undoLog ? { undo_log: summary.undoLog } : {}),\n });\n } catch (err: any) {\n await patch({\n status: 'failed',\n error: String(err?.message ?? err).slice(0, 1000),\n completed_at: new Date().toISOString(),\n });\n } finally {\n this.cancelledImportJobs.delete(jobId);\n }\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: 'Create an asynchronous import job (large files, up to 50k rows)',\n tags: ['data', 'import'],\n },\n });\n\n // Shared loader for the read routes: fetch one job row by id.\n const loadImportJob = async (p: any, jobId: string, environmentId?: string, context?: any): Promise<any | undefined> => {\n const r = await p.findData({\n object: IMPORT_JOB_OBJECT,\n query: { $filter: { id: jobId }, $top: 1 },\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n const rows = Array.isArray(r?.records) ? r.records\n : Array.isArray(r?.data) ? r.data\n : Array.isArray(r?.rows) ? r.rows\n : Array.isArray(r) ? r : [];\n return rows[0];\n };\n\n // POST /data/import/jobs/:jobId/cancel — request cancellation.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/import/jobs/:jobId/cancel`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n const status = String(row.status ?? '');\n if (status === 'pending' || status === 'running') {\n // Signal the in-process worker and mark the durable row.\n this.cancelledImportJobs.add(jobId);\n try {\n await (p as any).updateData({ object: IMPORT_JOB_OBJECT, id: jobId, data: { status: 'cancelled', completed_at: new Date().toISOString() }, context, ...(environmentId ? { environmentId } : {}) });\n } catch { /* worker will still stop via the in-memory flag */ }\n }\n res.json({ success: true });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Cancel an in-flight import job', tags: ['data', 'import'] },\n });\n\n // POST /data/import/jobs/:jobId/undo — logical rollback of a finished\n // job: delete the records it created and restore the fields it updated\n // to their pre-import values (from the captured undo log).\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/import/jobs/:jobId/undo`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n if (row.reverted_at) {\n res.status(409).json({ code: 'ALREADY_REVERTED', error: 'This import has already been undone' });\n return;\n }\n if (!importJobUndoable(row)) {\n res.status(422).json({ code: 'NOT_UNDOABLE', error: 'This import cannot be undone (too large, still running, or nothing was written)' });\n return;\n }\n const objectName = String(row.object_name ?? '');\n const log = parseUndoLog(row.undo_log)!;\n // Undo automations too: reversing writes shouldn't re-fire triggers.\n const writeCtx = { ...(context ?? {}), skipAutomations: true };\n let deleted = 0, restored = 0, failed = 0;\n\n // Delete created records first (they didn't exist before).\n for (const id of log.created) {\n try {\n await (p as any).deleteData({ object: objectName, id, context: writeCtx, ...(environmentId ? { environmentId } : {}) });\n deleted++;\n } catch { failed++; }\n }\n // Restore the touched fields on updated records.\n for (const u of log.updated) {\n try {\n await (p as any).updateData({ object: objectName, id: u.id, data: u.before, context: writeCtx, ...(environmentId ? { environmentId } : {}) });\n restored++;\n } catch { failed++; }\n }\n\n await (p as any).updateData({\n object: IMPORT_JOB_OBJECT, id: jobId,\n data: { reverted_at: new Date().toISOString() },\n context, ...(environmentId ? { environmentId } : {}),\n });\n res.json({ success: true, jobId, object: objectName, deleted, restored, failed });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Undo (logically roll back) a finished import job', tags: ['data', 'import'] },\n });\n\n // GET /data/import/jobs/:jobId/results — progress + capped per-row report.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/import/jobs/:jobId/results`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n const stored = row.results;\n const items = Array.isArray(stored?.items) ? stored.items : Array.isArray(stored) ? stored : [];\n res.json({ ...importJobToProgress(row), results: items, resultsTruncated: !!stored?.truncated });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Import job results (capped per-row report)', tags: ['data', 'import'] },\n });\n\n // GET /data/import/jobs/:jobId — live progress counters.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/import/jobs/:jobId`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n res.json(importJobToProgress(row));\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Import job progress', tags: ['data', 'import'] },\n });\n\n // GET /data/import/jobs — history list (newest first).\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/import/jobs`,\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 q = req.query ?? {};\n const filter: Record<string, any> = {};\n if (typeof q.object === 'string' && q.object) filter.object_name = q.object;\n if (typeof q.status === 'string' && q.status) filter.status = q.status;\n const limit = Math.min(200, Math.max(1, Number(q.limit) || 50));\n const offset = Math.max(0, Number(q.offset) || 0);\n const r = await (p as any).findData({\n object: IMPORT_JOB_OBJECT,\n query: { $filter: filter, $orderby: { created_at: 'desc' }, $top: limit, $skip: offset },\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n const rows = Array.isArray(r?.records) ? r.records\n : Array.isArray(r?.data) ? r.data\n : Array.isArray(r?.rows) ? r.rows\n : Array.isArray(r) ? r : [];\n res.json({ jobs: rows.map(importJobToSummary) });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'List import jobs (history)', tags: ['data', 'import'] },\n });\n\n // GET /data/:object/export — streaming export (M10.21 / C.21)\n //\n // Query params:\n // format=csv|json|xlsx (default: csv. json emits a JSON array, xlsx a workbook.)\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 // header=false (omit the header row for csv / xlsx; default true)\n // limit=<n> (default 10000, hard cap 50000)\n // page=<n> (driver chunk size, default 500, max 5000)\n //\n // Values are formatted for readability from the object schema: lookup /\n // user fields resolve to a name (via injected $expand), select fields to\n // their option label, booleans to 是/否, dates to YYYY-MM-DD. When the\n // schema is unavailable the raw stored values stream through unchanged.\n //\n // Streams the response so 50k-row exports do not buffer in memory; the\n // xlsx path pipes exceljs' streaming writer straight onto the response.\n // Filename suggests `${object}-${YYYY-MM-DD}.${ext}` for browsers.\n //\n // xlsx only: select / radio cells are coloured with their option's\n // `color` as the font colour (white cell background) when the effective\n // limit is <= 10000. Larger exports drop styling for performance and set\n // `X-Export-Styles: dropped` (else `applied`); csv / json are unaffected.\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 fmtRaw = String(q.format ?? 'csv').toLowerCase();\n const format: 'csv' | 'json' | 'xlsx' =\n fmtRaw === 'json' ? 'json' : fmtRaw === 'xlsx' ? 'xlsx' : 'csv';\n // Header row toggle (csv / xlsx). Default on; `header=false` omits it.\n const includeHeader = String(q.header ?? 'true').toLowerCase() !== 'false';\n const HARD_CAP = 50_000;\n const MAX_CHUNK = 5_000;\n // Styled xlsx (per-cell font colour from select options) is far\n // heavier than a bare value dump, so cap it well below HARD_CAP;\n // above this the export still succeeds, just without colours.\n const STYLE_ROW_CAP = 10_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 // Colour cells only for xlsx within the style cap; decided up\n // front (before streaming) since we can't know the true row\n // count until the stream drains.\n const styled = format === 'xlsx' && limit <= STYLE_ROW_CAP;\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\n // Field metadata drives readable formatting (lookup names, select\n // labels, 是/否, formatted dates) and the $expand that resolves\n // references. Best-effort: when the schema is unavailable the export\n // falls back to raw values, byte-identical to the un-formatted path.\n let metaMap = new Map<string, ExportFieldMeta>();\n try {\n // Field metadata comes from the same place `findData` resolves\n // the object: `getMetaItem` is registry-first (DB fallback), so\n // it returns the live `ObjectSchema` whose `fields` is an object\n // map. The read hands back an envelope `{ type, name, item }`;\n // the schema document lives at `.item` (a cached/bare read may\n // already be unwrapped). Legacy `getObjectSchema` is consulted\n // as a last resort so existing test doubles keep working.\n let schema: any = undefined;\n if (typeof (p as any).getMetaItem === 'function') {\n const res = await (p as any).getMetaItem({ type: 'object', name: objectName });\n schema = isMetaEnvelope(res) ? res.item : res;\n }\n if (!schema && typeof (p as any).getObjectSchema === 'function') {\n schema = await (p as any).getObjectSchema(objectName, environmentId);\n }\n // Localize field labels to the request locale (Accept-Language /\n // `?locale=`) the same way the metadata endpoints do, so the\n // export header row matches the UI column headers instead of\n // leaking the raw, untranslated `field.label` values.\n schema = await this.translateMetaItem(req, 'object', environmentId, schema);\n metaMap = buildFieldMetaMap(schema);\n if (!fields || fields.length === 0) {\n const names = [...metaMap.keys()];\n if (names.length > 0) fields = names;\n }\n } catch { /* fall back to first-row derivation + raw values */ }\n\n // Expand reference fields so lookup/user ids resolve to their record\n // (and thus a name). Batched $in inside findData — no N+1.\n const expandFields = referenceFieldNames(metaMap);\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 if (format === 'xlsx') {\n res.header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');\n res.header('Content-Disposition', `attachment; filename=\"${safeObj}-${stamp}.xlsx\"`);\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 // Signal whether select-option colours were applied. Only\n // meaningful for xlsx; 'dropped' means the limit exceeded the\n // style cap so the workbook is colourless but complete.\n if (format === 'xlsx') res.header('X-Export-Styles', styled ? 'applied' : 'dropped');\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 const xlsx = format === 'xlsx' ? await createXlsxStream(res, styled) : null;\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 ...(expandFields.length > 0 ? { $expand: expandFields.join(',') } : {}),\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 // `findData` returns `{ object, records, total, hasMore }`;\n // accept the legacy `data` / `rows` aliases and a bare array\n // so test doubles and alternate protocols keep working.\n const rows: any[] = Array.isArray(result?.records) ? result.records\n : 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 // 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\n if (format === 'csv') {\n const text = rowsToCsv(fields ?? [], rows, firstChunk && includeHeader, metaMap);\n res.write(text);\n } else if (format === 'xlsx') {\n if (firstChunk && includeHeader) {\n xlsx!.ws.addRow((fields ?? []).map((f) => headerLabel(f, metaMap))).commit();\n }\n const cols = fields ?? [];\n for (const row of rows) {\n const r = xlsx!.ws.addRow(formatRowCells(row, cols, metaMap));\n if (styled) {\n cols.forEach((f, i) => {\n const argb = cellFontColor(row?.[f], metaMap.get(f));\n if (argb) r.getCell(i + 1).font = { color: { argb } };\n });\n }\n r.commit();\n }\n } else {\n for (let i = 0; i < rows.length; i++) {\n const prefix = (firstChunk && i === 0) ? '' : ',';\n res.write(prefix + JSON.stringify(formatRowForJson(rows[i], metaMap)));\n }\n }\n firstChunk = false;\n exported += rows.length;\n skip += rows.length;\n if (rows.length < take) break;\n }\n if (format === 'json') {\n res.write(']');\n res.end();\n } else if (format === 'xlsx') {\n await xlsx!.finalize();\n } else {\n res.end();\n }\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, JSON, or XLSX)',\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 // `user` is a lookup specialized to sys_user — same risk as a\n // raw lookup: surfacing it on an anonymous public form would\n // expose unrestricted user search to the internet. Gate it\n // behind the same `publicPicker` opt-in.\n if (t !== 'lookup' && t !== 'master_detail' && t !== 'user') 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 // ADR-0056 (Option A): authorization DERIVED from the declared\n // form — a narrow create grant scoped to exactly this form's target\n // object. The SecurityPlugin honors `publicFormGrant` (create + the\n // immediate read-back, that object ONLY), so public forms work under\n // secure-by-default (requireAuth) WITHOUT a deployment-configured\n // `guest_portal`. `guest_portal` + `anonymous` are kept for back-compat\n // with object hooks (guest detection via falsy `ctx.user?.id`).\n const context: any = {\n publicFormGrant: { object: match.object },\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 /**\n * [ADR-0090 D6] Access-explanation endpoint — the REST face of the\n * explain engine (framework#2696).\n *\n * GET {basePath}/security/explain?object=…&operation=…&userId=…\n * POST {basePath}/security/explain body: { object, operation, userId? }\n *\n * Delegates to the security service's `explain(request, callerContext)`\n * (`SecurityPlugin.explainAccessForCaller`) — the same code paths the\n * enforcement middleware runs, so the report is explained by\n * construction. Caller authorization lives in the SERVICE, not here:\n * explaining ANOTHER user requires `manage_users` or a delegated\n * `adminScope` covering that user (D12); the service's\n * `PermissionDeniedError` maps to 403. The route itself only insists on\n * an authenticated caller (an access report is sensitive even about\n * oneself, and the anonymous `guest` posture is not this endpoint's\n * business) and returns 501 when no security service exposing `explain`\n * is mounted (a deployment without `@objectstack/plugin-security`).\n */\n private registerSecurityExplainEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n // Resolve the ENVIRONMENT's security service first (its resolver /\n // evaluator / RLS compiler are bound to the env kernel's own data\n // engine); the host provider is the single-kernel fallback.\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>('security').catch(() => undefined);\n if (svc) return svc;\n }\n } catch { /* fall back to the host service */ }\n if (!this.securityServiceProvider) return undefined;\n try { return await this.securityServiceProvider(environmentId); }\n catch { return undefined; }\n };\n\n const 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 if (!context?.userId) {\n // Even on requireAuth=false deployments the explain surface\n // stays authenticated-only — it is an admin diagnosis tool.\n return res.status(401).json({\n code: 'UNAUTHORIZED',\n message: 'The access-explanation endpoint requires an authenticated caller.',\n });\n }\n\n const svc = await resolveService(environmentId, req);\n if (!svc || typeof svc.explain !== 'function') {\n return res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Access explanation is not available on this deployment (no security service with explain).',\n });\n }\n\n // GET reads the request from the query string, POST from the\n // body — one contract (ExplainRequestSchema), two transports.\n const src = req.method === 'GET' ? (req.query ?? {}) : (req.body ?? {});\n const { ExplainRequestSchema } = await import('@objectstack/spec/security');\n const parsed = (ExplainRequestSchema as any).safeParse({\n object: src.object,\n operation: src.operation ?? 'read',\n ...(src.userId != null && src.userId !== '' ? { userId: src.userId } : {}),\n });\n if (!parsed.success) {\n return res.status(400).json({\n code: 'VALIDATION_FAILED',\n message: 'Invalid explain request — expected { object: string, operation: read|create|update|delete|transfer|restore|purge, userId?: string }.',\n detail: String(parsed.error?.message ?? '').slice(0, 1000),\n });\n }\n\n const decision = await svc.explain(parsed.data, context);\n res.json(decision);\n } catch (error: any) {\n const msg = String(error?.message ?? error ?? '');\n if (\n error?.code === 'PERMISSION_DENIED' ||\n error?.name === 'PermissionDeniedError' ||\n msg.startsWith('[Security] Access denied')\n ) {\n return res.status(403).json({ code: 'PERMISSION_DENIED', message: msg.slice(0, 1000) });\n }\n logError('[REST] Security explain error:', error);\n res.status(500).json({ code: 'EXPLAIN_FAILED', error: msg.slice(0, 500) });\n }\n };\n\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/security/explain`,\n handler,\n metadata: { summary: 'Explain why a principal can (or cannot) perform an operation on an object (ADR-0090 D6)', tags: ['security'] },\n });\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/security/explain`,\n handler,\n metadata: { summary: 'Explain why a principal can (or cannot) perform an operation on an object (ADR-0090 D6)', tags: ['security'] },\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 the security admin endpoints (ADR-0090 D5/D9) — suggested\n * audience bindings. A package permission set declaring `isDefault: true`\n * is an install-time SUGGESTION to bind it to the `everyone` position;\n * these routes surface pending suggestions and let a tenant admin resolve\n * them. The `security` service (plugin-security) does the real gating:\n * tenant-admin pre-check on all three, and confirm writes the binding\n * with the caller's execution context so the audience-anchor and\n * delegated-admin gates enforce it — never auto-bound, never system.\n *\n * GET {basePath}/security/suggested-bindings?status=&packageId=\n * POST {basePath}/security/suggested-bindings/:id/confirm\n * POST {basePath}/security/suggested-bindings/:id/dismiss\n *\n * Routes return 501 when the `security` service is not registered\n * (deployment without plugin-security). Typed service errors carry their\n * HTTP status (403 permission / 404 not found / 409 state).\n */\n private registerSecurityEndpoints(basePath: string): void {\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.securityServiceProvider) return undefined;\n try {\n const svc = await this.securityServiceProvider(environmentId);\n return svc && typeof svc.listAudienceBindingSuggestions === 'function' ? svc : undefined;\n } catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Security service is not configured on this deployment',\n });\n const handleError = (err: any, res: any, defaultCode: string) => {\n const status = typeof err?.statusCode === 'number' ? err.statusCode : 500;\n if (status !== 500) {\n return res.status(status).json({ code: err?.code ?? defaultCode, error: String(err?.message ?? err) });\n }\n logError(`[REST] suggested-bindings ${defaultCode}:`, err);\n return res.status(500).json({ code: defaultCode, error: String(err?.message ?? err).slice(0, 500) });\n };\n\n // LIST (reconciles against installed packages / declared sets first)\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/security/suggested-bindings`,\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.listAudienceBindingSuggestions(context ?? {}, {\n status: req.query?.status ? String(req.query.status) : undefined,\n packageId: req.query?.packageId ? String(req.query.packageId) : undefined,\n });\n res.json({ data: result });\n } catch (err: any) { handleError(err, res, 'SUGGESTION_LIST_FAILED'); }\n },\n metadata: { summary: 'List suggested audience bindings (ADR-0090 D5/D9)', tags: ['security'] },\n });\n\n // CONFIRM — creates the anchor binding as the caller (gated write)\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/security/suggested-bindings/:id/confirm`,\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.confirmAudienceBindingSuggestion(context ?? {}, String(req.params.id));\n res.json({ data: result });\n } catch (err: any) { handleError(err, res, 'SUGGESTION_CONFIRM_FAILED'); }\n },\n metadata: { summary: 'Confirm a suggested audience binding (creates the everyone/guest binding)', tags: ['security'] },\n });\n\n // DISMISS — records the admin's decline; nothing is bound\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/security/suggested-bindings/:id/dismiss`,\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.dismissAudienceBindingSuggestion(context ?? {}, String(req.params.id));\n res.json({ data: result });\n } catch (err: any) { handleError(err, res, 'SUGGESTION_DISMISS_FAILED'); }\n },\n metadata: { summary: 'Dismiss a suggested audience binding', tags: ['security'] },\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","/**\n * Type-aware value formatting for the streaming data export route\n * (`GET /data/:object/export`).\n *\n * The raw rows returned by `findData` carry *storage* values: lookup / user\n * fields hold ids (or, when `$expand`-ed, nested records), select fields hold\n * option codes, booleans hold true/false, dates hold ISO strings. None of those\n * read well in a spreadsheet. These helpers turn each value into a human\n * readable cell using the object's field metadata.\n *\n * Contract: when no field metadata is available (schema lookup failed or carried\n * no fields) every helper is a pass-through, so the export stays byte-for-byte\n * identical to the un-formatted behaviour.\n */\n\nexport interface ExportFieldMeta {\n name: string;\n type?: string;\n label?: string;\n options?: Array<{ label?: string; value?: unknown; color?: string }>;\n /** Target object for lookup / master_detail / user fields. */\n reference?: string;\n /** Field on the referenced record to show as its label. */\n displayField?: string;\n // The following four drive the import path's required-field pre-check\n // (import-runner.ts). They mirror the engine's insert-time validation\n // (objectql record-validator.ts) so a dry run can predict a NOT NULL /\n // required failure instead of green-lighting a row the real insert rejects.\n // Unused by the export path (formatting only reads type/options/reference).\n /** Field is required — a value (or default) must exist on insert. */\n required?: boolean;\n /** Engine-owned column the client never supplies (never required of import). */\n system?: boolean;\n /** Read-only column the client never supplies (never required of import). */\n readonly?: boolean;\n /** Field declares a `defaultValue` the engine applies on insert (satisfies required). */\n hasDefault?: boolean;\n}\n\n/** Field types whose stored value points at another record. */\nconst REFERENCE_TYPES = new Set(['lookup', 'master_detail', 'user', 'reference', 'tree']);\n\n/** Field types whose stored value maps to a static option label. */\nconst OPTION_TYPES = new Set(['select', 'radio']);\nconst MULTI_OPTION_TYPES = new Set(['multiselect', 'checkboxes', 'tags']);\n\n/**\n * Keys tried, in order, to derive a referenced record's display value when the\n * field carries no explicit `displayField`.\n */\nconst NAME_KEY_FALLBACKS = [\n 'name', 'title', 'label', 'full_name', 'fullName', 'display_name', 'username', 'email',\n];\n\n/**\n * Build a field-name → metadata map from an object schema (best-effort).\n *\n * Accepts both shapes `fields` appears in across the stack: the runtime\n * `ObjectSchema.fields` is a `Record<fieldName, FieldDefinition>` object map\n * (the form served by the engine registry / `getMetaItem`), while some callers\n * and fixtures hand back a plain `FieldDefinition[]` array. A field's name is\n * taken from its own `name`, falling back to the map key.\n */\nexport function buildFieldMetaMap(schema: unknown): Map<string, ExportFieldMeta> {\n const map = new Map<string, ExportFieldMeta>();\n const fields = (schema as { fields?: unknown })?.fields;\n\n // Normalize either shape to a list of [name, definition] entries.\n let entries: Array<[string, any]>;\n if (Array.isArray(fields)) {\n entries = fields\n .filter((f) => f && typeof f === 'object')\n .map((f) => [typeof f.name === 'string' ? f.name : '', f] as [string, any]);\n } else if (fields && typeof fields === 'object') {\n entries = Object.entries(fields as Record<string, any>).map(\n ([key, def]) => [\n def && typeof def === 'object' && typeof def.name === 'string' ? def.name : key,\n def,\n ] as [string, any],\n );\n } else {\n return map;\n }\n\n for (const [name, f] of entries) {\n if (!name || !f || typeof f !== 'object') continue;\n map.set(name, {\n name,\n type: typeof f.type === 'string' ? f.type : undefined,\n label: typeof f.label === 'string' ? f.label : undefined,\n options: Array.isArray(f.options) ? f.options : undefined,\n reference: typeof f.reference === 'string' ? f.reference : undefined,\n displayField: typeof f.displayField === 'string' ? f.displayField : undefined,\n required: f.required === true,\n system: f.system === true,\n readonly: f.readonly === true,\n // Mirror the engine's `applyFieldDefaults` gate (`f.defaultValue == null`\n // ⇒ no default): any non-null default — literal, expression object, or the\n // `current_user` token — counts as satisfying a required field.\n hasDefault: f.defaultValue != null,\n });\n }\n return map;\n}\n\n/**\n * Reference-typed field names that should be `$expand`-ed so their stored ids\n * resolve to the referenced record (and thus to a readable name).\n */\nexport function referenceFieldNames(metaMap: Map<string, ExportFieldMeta>): string[] {\n const out: string[] = [];\n for (const meta of metaMap.values()) {\n if (meta.type && REFERENCE_TYPES.has(meta.type) && meta.reference) out.push(meta.name);\n }\n return out;\n}\n\n/** Header label for a column: schema label when present, else the field name. */\nexport function headerLabel(field: string, metaMap: Map<string, ExportFieldMeta>): string {\n return metaMap.get(field)?.label || field;\n}\n\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\nfunction toDate(value: unknown): Date | null {\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n if (typeof value === 'number' || typeof value === 'string') {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n return null;\n}\n\n/** `YYYY-MM-DD` (date) or `YYYY-MM-DD HH:mm:ss` (datetime), in UTC. */\nfunction formatDate(value: unknown, withTime: boolean): unknown {\n const d = toDate(value);\n if (!d) return value;\n const ymd = `${d.getUTCFullYear()}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())}`;\n if (!withTime) return ymd;\n return `${ymd} ${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}:${pad2(d.getUTCSeconds())}`;\n}\n\nfunction optionLabel(value: unknown, options?: Array<{ label?: string; value?: unknown }>): unknown {\n if (!options) return value;\n const hit = options.find((o) => o && o.value === value);\n return hit?.label ?? value;\n}\n\n/**\n * Normalize a CSS-ish hex color to exceljs' 8-digit ARGB (`FFRRGGBB`, opaque).\n * Accepts `#RGB` / `#RRGGBB` with or without the leading `#`, any case.\n * Returns `undefined` for anything else (empty, named colors, rgb(), garbage)\n * so callers simply skip styling rather than emit an invalid workbook.\n */\nexport function toArgb(color: unknown): string | undefined {\n if (typeof color !== 'string') return undefined;\n const hex = color.trim().replace(/^#/, '');\n if (/^[0-9a-fA-F]{3}$/.test(hex)) {\n const [r, g, b] = hex;\n return `FF${r}${r}${g}${g}${b}${b}`.toUpperCase();\n }\n if (/^[0-9a-fA-F]{6}$/.test(hex)) return `FF${hex}`.toUpperCase();\n return undefined;\n}\n\n/**\n * Font color (exceljs ARGB) for one cell, driven by the matched select/radio\n * option's `color`. Returns `undefined` when the field is not option-typed, no\n * option matches, the option has no color, or the color is not a valid hex —\n * i.e. whenever the cell should stay unstyled.\n */\nexport function cellFontColor(value: unknown, meta?: ExportFieldMeta): string | undefined {\n if (value === null || value === undefined) return undefined;\n if (!meta || !meta.type || !OPTION_TYPES.has(meta.type) || !meta.options) return undefined;\n const hit = meta.options.find((o) => o && o.value === value);\n return toArgb(hit?.color);\n}\n\nfunction displayFromRecord(rec: Record<string, unknown>, displayField?: string): string {\n if (displayField && rec[displayField] != null) return String(rec[displayField]);\n for (const k of NAME_KEY_FALLBACKS) {\n const v = rec[k];\n if (v != null && typeof v !== 'object') return String(v);\n }\n if (rec.id != null) return String(rec.id);\n try { return JSON.stringify(rec); } catch { return String(rec); }\n}\n\nfunction formatReference(value: unknown, displayField?: string): unknown {\n const one = (v: unknown): unknown =>\n v && typeof v === 'object' ? displayFromRecord(v as Record<string, unknown>, displayField) : v;\n if (Array.isArray(value)) return value.map(one).join(', ');\n return one(value);\n}\n\n/** Format one storage value into a display value using its field metadata. */\nexport function formatCellValue(value: unknown, meta?: ExportFieldMeta): unknown {\n if (value === null || value === undefined) return value;\n if (!meta || !meta.type) return value;\n const t = meta.type;\n if (t === 'boolean' || t === 'toggle') {\n if (value === true || value === 'true' || value === 1) return '是';\n if (value === false || value === 'false' || value === 0) return '否';\n return value;\n }\n if (OPTION_TYPES.has(t)) return optionLabel(value, meta.options);\n if (MULTI_OPTION_TYPES.has(t)) {\n const arr = Array.isArray(value) ? value : [value];\n return arr.map((v) => optionLabel(v, meta.options)).join(', ');\n }\n if (t === 'date') return formatDate(value, false);\n if (t === 'datetime') return formatDate(value, true);\n if (REFERENCE_TYPES.has(t)) return formatReference(value, meta.displayField);\n return value;\n}\n\n/** Ordered display cells for one row — the CSV / XLSX column path. */\nexport function formatRowCells(\n row: Record<string, unknown>,\n fields: string[],\n metaMap: Map<string, ExportFieldMeta>,\n): unknown[] {\n return fields.map((f) => formatCellValue(row?.[f], metaMap.get(f)));\n}\n\n/**\n * Format a row for JSON output: readable values for known fields, every other\n * key left untouched. Returns the original object reference when nothing needs\n * formatting so the stream stays byte-identical to the un-formatted path.\n */\nexport function formatRowForJson(\n row: Record<string, unknown>,\n metaMap: Map<string, ExportFieldMeta>,\n): Record<string, unknown> {\n if (metaMap.size === 0 || !row || typeof row !== 'object') return row;\n let copy: Record<string, unknown> | null = null;\n for (const key of Object.keys(row)) {\n const meta = metaMap.get(key);\n if (!meta) continue;\n const formatted = formatCellValue(row[key], meta);\n if (formatted !== row[key]) {\n if (!copy) copy = { ...row };\n copy[key] = formatted;\n }\n }\n return copy ?? row;\n}\n","/**\n * Type-aware value *coercion* for the bulk-import route\n * (`POST /data/:object/import`).\n *\n * This is the inverse of `export-format.ts`. A spreadsheet / CSV cell arrives as\n * a raw string (or, for JSON payloads, an arbitrary primitive); the storage\n * layer, on the other hand, expects *storage* values — booleans as real\n * booleans, numbers as numbers, dates as ISO strings, select fields as their\n * option **code** (not the human label), and lookup / user fields as the\n * referenced record **id** (not its name). The engine deliberately does not\n * coerce for storage (see `record-validator.ts`, which coerces only to *check*\n * a value and then discards the coerced form), so import has to do it here.\n *\n * The accepted storage shapes below are dictated by what\n * `validateFieldValue` in `packages/objectql` will accept:\n * - number / currency / percent / rating / slider → a finite `number`\n * - boolean / toggle → a real `boolean`\n * - date / datetime → an ISO-8601 string\n * - time → `HH:MM` / `HH:MM:SS`\n * - select / radio → an option *value*\n * - multiselect / checkboxes / tags → an array of option values\n * - lookup / master_detail / user / reference → a record id (resolved async)\n *\n * Contract: when a field carries no usable metadata the value passes through\n * untouched, so an import stays byte-identical to the pre-coercion behaviour.\n */\n\nimport type { ExportFieldMeta } from './export-format.js';\n\n/** Field types whose stored value points at another record (id). */\nconst REFERENCE_TYPES = new Set(['lookup', 'master_detail', 'user', 'reference', 'tree']);\n/** Single-select option types (store one option value). */\nconst OPTION_TYPES = new Set(['select', 'radio']);\n/** Multi-select option types (store an array of option values). */\nconst MULTI_OPTION_TYPES = new Set(['multiselect', 'checkboxes', 'tags']);\n/** Numeric field types (store a finite number). */\nconst NUMBER_TYPES = new Set(['number', 'currency', 'percent', 'rating', 'slider']);\n/** Boolean field types (store a real boolean). */\nconst BOOL_TYPES = new Set(['boolean', 'toggle']);\n\n/**\n * Structured outcome of a reference lookup. `id` set → a single record matched.\n * `ambiguous` → the display value matched more than one record, so linking any\n * one of them would be a guess the importer refuses to make. `matchedField`\n * names the field the match came from (for diagnostics). An empty object means\n * nothing matched. A bare `string | undefined` is still accepted from legacy\n * resolvers and normalised to this shape.\n */\nexport interface RefMatch {\n id?: string;\n ambiguous?: boolean;\n matchedField?: string;\n}\n\n/**\n * Resolve a reference field's display value (a name / email / id typed by the\n * user) to the referenced record's id. Return `undefined` / `{}` when nothing\n * matches (caller surfaces \"not found\"), a bare id string / `{ id }` on a unique\n * hit, or `{ ambiguous: true }` when several records share the value. Legacy\n * resolvers that return `string | undefined` keep working. Implementations are\n * expected to cache — the same name shows up on many rows.\n */\nexport type RefResolver = (\n referenceObject: string,\n displayValue: string,\n meta: ExportFieldMeta,\n) => Promise<string | undefined | RefMatch>;\n\n/** Normalise a resolver result (legacy string or structured) to a RefMatch. */\nfunction normalizeRefMatch(result: string | undefined | RefMatch): RefMatch {\n if (result == null) return {};\n if (typeof result === 'string') return result ? { id: result } : {};\n return result;\n}\n\nexport interface CoerceContext {\n /** Trim leading/trailing whitespace from string-ish cells (default true). */\n trimWhitespace?: boolean;\n /** Extra strings (besides `''`) treated as null, e.g. `['N/A', 'null']`. */\n nullValues?: string[];\n /**\n * When a select/multiselect cell matches no known option, keep the raw value\n * instead of failing. Note: the engine still validates option membership, so\n * this only helps when the option is (or will be) present in the schema.\n */\n createMissingOptions?: boolean;\n /** Async reference resolver (name/email/id → record id). Optional. */\n resolveRef?: RefResolver;\n}\n\n/** A per-field coercion failure, shaped like the engine's validation errors. */\nexport interface FieldCoerceError {\n field: string;\n code: string;\n message: string;\n}\n\n// ── blank / null handling ──────────────────────────────────────────\n\nfunction isBlank(value: unknown, nullValues?: string[]): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value === 'string') {\n const s = value.trim();\n if (s === '') return true;\n if (nullValues && nullValues.some((nv) => nv === value || nv === s)) return true;\n }\n return false;\n}\n\n// ── boolean ────────────────────────────────────────────────────────\n\nconst BOOL_TRUE = new Set(['true', 't', 'yes', 'y', '1', 'on', '是', '对', '✓', '√']);\nconst BOOL_FALSE = new Set(['false', 'f', 'no', 'n', '0', 'off', '否', '错', '✗', '×']);\n\n/** Parse a spreadsheet cell into a boolean, or `undefined` if unrecognised. */\nexport function parseBooleanCell(raw: unknown): boolean | undefined {\n if (typeof raw === 'boolean') return raw;\n if (typeof raw === 'number') {\n if (raw === 1) return true;\n if (raw === 0) return false;\n return undefined;\n }\n const s = String(raw).trim().toLowerCase();\n if (BOOL_TRUE.has(s)) return true;\n if (BOOL_FALSE.has(s)) return false;\n return undefined;\n}\n\n// ── numbers ────────────────────────────────────────────────────────\n\n/**\n * Parse a numeric cell, tolerating the punctuation spreadsheets add: thousands\n * separators (`1,234`), a leading currency symbol (`$` `¥` `€` `£` `¥`), a\n * trailing percent sign (`25%` → `25`), and accounting-style parenthesised\n * negatives (`(1,234)` → `-1234`). Returns `undefined` when the residue is not\n * a finite number.\n */\nexport function parseNumberCell(raw: unknown): number | undefined {\n if (typeof raw === 'number') return Number.isFinite(raw) ? raw : undefined;\n let s = String(raw).trim();\n if (s === '') return undefined;\n let negative = false;\n if (/^\\(.*\\)$/.test(s)) { negative = true; s = s.slice(1, -1).trim(); }\n s = s.replace(/^[$¥€£¥]\\s*/, ''); // leading currency symbol\n s = s.replace(/%$/, '').trim(); // trailing percent\n s = s.replace(/,/g, ''); // thousands separators\n if (s === '' || !/^[+-]?\\d*\\.?\\d+(e[+-]?\\d+)?$/i.test(s)) return undefined;\n const n = Number(s);\n if (!Number.isFinite(n)) return undefined;\n return negative ? -n : n;\n}\n\n// ── dates ──────────────────────────────────────────────────────────\n\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\nconst TIME_OF_DAY = /^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$/;\n\n/**\n * Coerce a cell into the string shape the engine accepts for a date-ish field:\n * - `date` → `YYYY-MM-DD`\n * - `datetime` → full ISO-8601 (`toISOString`)\n * - `time` → `HH:MM` / `HH:MM:SS`\n * Returns `undefined` when the cell is not a recognisable date/time.\n *\n * Unambiguous `YYYY-MM-DD` / `YYYY/MM/DD` inputs are normalised directly to\n * avoid timezone drift; everything else falls back to `Date.parse` (which\n * covers ISO datetimes and locale-default `MM/DD/YYYY`).\n */\nexport function parseDateCell(raw: unknown, kind: 'date' | 'datetime' | 'time'): string | undefined {\n if (raw instanceof Date) {\n if (Number.isNaN(raw.getTime())) return undefined;\n if (kind === 'datetime') return raw.toISOString();\n if (kind === 'date') return `${raw.getUTCFullYear()}-${pad2(raw.getUTCMonth() + 1)}-${pad2(raw.getUTCDate())}`;\n return `${pad2(raw.getUTCHours())}:${pad2(raw.getUTCMinutes())}:${pad2(raw.getUTCSeconds())}`;\n }\n const s = String(raw).trim();\n if (s === '') return undefined;\n\n if (kind === 'time') {\n if (TIME_OF_DAY.test(s)) return s.length === 5 ? `${s}:00` : s;\n // A full datetime for a time field: take its clock component.\n const t = new Date(s);\n if (!Number.isNaN(t.getTime())) return `${pad2(t.getUTCHours())}:${pad2(t.getUTCMinutes())}:${pad2(t.getUTCSeconds())}`;\n return undefined;\n }\n\n // Fast path: bare calendar date, no timezone games.\n const ymd = s.match(/^(\\d{4})[-/](\\d{1,2})[-/](\\d{1,2})$/);\n if (ymd) {\n const y = Number(ymd[1]);\n const mo = Number(ymd[2]);\n const d = Number(ymd[3]);\n if (mo < 1 || mo > 12 || d < 1 || d > 31) return undefined;\n if (kind === 'date') return `${y}-${pad2(mo)}-${pad2(d)}`;\n return new Date(Date.UTC(y, mo - 1, d)).toISOString();\n }\n\n const parsed = new Date(s);\n if (Number.isNaN(parsed.getTime())) return undefined;\n if (kind === 'date') {\n return `${parsed.getUTCFullYear()}-${pad2(parsed.getUTCMonth() + 1)}-${pad2(parsed.getUTCDate())}`;\n }\n return parsed.toISOString();\n}\n\n// ── options (select / multiselect) ─────────────────────────────────\n\n/**\n * Match a cell against a field's options, accepting **either** the option value\n * (code) or its human label (case-insensitive). Returns the canonical option\n * value to store, or `undefined` on no match.\n */\nexport function matchOption(\n raw: unknown,\n options?: Array<{ label?: string; value?: unknown }>,\n): unknown | undefined {\n const s = String(raw).trim();\n if (!options || options.length === 0) return s; // no option list → accept as-is\n // Exact value match first (preserves the option's original value type).\n for (const o of options) {\n if (o && o.value !== undefined && String(o.value) === s) return o.value;\n }\n // Case-insensitive label match.\n const lower = s.toLowerCase();\n for (const o of options) {\n if (o && typeof o.label === 'string' && o.label.trim().toLowerCase() === lower) return o.value;\n }\n return undefined;\n}\n\n/** Split a multi-value cell on commas / semicolons / Chinese comma / newlines. */\nexport function splitMulti(raw: unknown): string[] {\n if (Array.isArray(raw)) return raw.map((v) => String(v).trim()).filter((v) => v !== '');\n return String(raw)\n .split(/[,;、\\n]/)\n .map((v) => v.trim())\n .filter((v) => v !== '');\n}\n\n// ── per-field orchestration ────────────────────────────────────────\n\n/**\n * Coerce one raw cell to its storage value using the field metadata. On success\n * returns `{ value }` (value may be `undefined`, meaning \"drop this key\"); on a\n * hard coercion failure returns `{ error }`.\n */\nexport async function coerceFieldValue(\n raw: unknown,\n meta: ExportFieldMeta | undefined,\n ctx: CoerceContext,\n): Promise<{ value?: unknown } | { error: FieldCoerceError }> {\n const trim = ctx.trimWhitespace !== false;\n const field = meta?.name ?? '';\n\n // Blank → leave the field unset so schema defaults / existing values win.\n if (isBlank(raw, ctx.nullValues)) return { value: undefined };\n\n const t = meta?.type;\n if (!t) return { value: trim && typeof raw === 'string' ? raw.trim() : raw };\n\n if (BOOL_TYPES.has(t)) {\n const b = parseBooleanCell(raw);\n if (b === undefined) return { error: { field, code: 'invalid_boolean', message: `${field}: \"${String(raw)}\" is not a boolean` } };\n return { value: b };\n }\n\n if (NUMBER_TYPES.has(t)) {\n const n = parseNumberCell(raw);\n if (n === undefined) return { error: { field, code: 'invalid_number', message: `${field}: \"${String(raw)}\" is not a number` } };\n return { value: n };\n }\n\n if (t === 'date' || t === 'datetime' || t === 'time') {\n const d = parseDateCell(raw, t);\n if (d === undefined) return { error: { field, code: 'invalid_date', message: `${field}: \"${String(raw)}\" is not a valid ${t}` } };\n return { value: d };\n }\n\n if (OPTION_TYPES.has(t)) {\n const v = matchOption(raw, meta?.options);\n if (v === undefined) {\n if (ctx.createMissingOptions) return { value: String(raw).trim() };\n return { error: { field, code: 'invalid_option', message: `${field}: \"${String(raw)}\" is not a known option` } };\n }\n return { value: v };\n }\n\n if (MULTI_OPTION_TYPES.has(t)) {\n const parts = splitMulti(raw);\n const out: unknown[] = [];\n for (const part of parts) {\n const v = matchOption(part, meta?.options);\n if (v === undefined) {\n if (ctx.createMissingOptions) { out.push(part); continue; }\n return { error: { field, code: 'invalid_option', message: `${field}: \"${part}\" is not a known option` } };\n }\n out.push(v);\n }\n return { value: out };\n }\n\n if (REFERENCE_TYPES.has(t)) {\n const display = String(raw).trim();\n // If it already looks resolved (an id was pasted) or we have no resolver /\n // no target object, store the raw value and let referential integrity be\n // enforced downstream.\n if (!ctx.resolveRef || !meta?.reference) return { value: display };\n const match = normalizeRefMatch(await ctx.resolveRef(meta.reference, display, meta));\n if (match.ambiguous) {\n return { error: { field, code: 'reference_ambiguous', message: `${field}: \"${display}\" matches more than one ${meta.reference} — use a unique value or the record id` } };\n }\n if (match.id === undefined) {\n return { error: { field, code: 'reference_not_found', message: `${field}: no ${meta.reference} matches \"${display}\"` } };\n }\n return { value: match.id };\n }\n\n // Everything else (text, email, phone, json, html, file, …): pass through,\n // trimming string cells so stray spreadsheet padding doesn't leak into storage.\n return { value: trim && typeof raw === 'string' ? raw.trim() : raw };\n}\n\n// ── required-field pre-check ───────────────────────────────────────\n\n/**\n * Engine-owned lifecycle columns the client never supplies. Mirrors\n * `record-validator.ts`'s `SKIP_FIELDS`, so the import's required pre-check and\n * the engine's insert-time required check agree on which fields the caller is\n * responsible for.\n */\nconst REQUIRED_CHECK_SKIP = new Set<string>([\n 'id', 'created_at', 'created_by', 'updated_at', 'updated_by',\n]);\n\nfunction isBlankValue(v: unknown): boolean {\n return v === undefined || v === null || (typeof v === 'string' && v.trim() === '');\n}\n\n/**\n * The first required field a would-be CREATE leaves unsatisfied, or `null` when\n * every required field has either a mapped value or a schema default.\n *\n * This mirrors the engine's insert-time required check (objectql\n * `record-validator.ts` + `applyFieldDefaults`) so the import's dry run predicts\n * the SAME verdict the real insert produces: a required (⇒ NOT NULL) field with\n * no default and no value fails both. Without it, dry run only reports coercion\n * errors and green-lights a row that then dies on `NOT NULL constraint failed`.\n *\n * Matches the engine's exemptions exactly — `system`/`readonly` columns, the\n * runtime-generated `autonumber`, a field carrying a `defaultValue`, and the\n * engine-owned lifecycle columns are never required of the importer. Applies to\n * CREATE only; an UPDATE touches just the supplied fields, so callers gate on\n * \"will create\" before calling.\n */\nexport function firstMissingRequiredField(\n data: Record<string, unknown>,\n metaMap: Map<string, ExportFieldMeta>,\n): string | null {\n for (const meta of metaMap.values()) {\n if (!meta.required) continue;\n if (meta.system || meta.readonly) continue;\n if (meta.hasDefault) continue;\n if (meta.type === 'autonumber') continue;\n if (REQUIRED_CHECK_SKIP.has(meta.name)) continue;\n if (isBlankValue(data[meta.name])) return meta.name;\n }\n return null;\n}\n\n/**\n * Coerce a whole raw row into a storage-ready record. Unknown columns (no\n * matching field metadata) pass through untouched so ad-hoc / schemaless\n * objects still import. Collects every field error rather than stopping at the\n * first, so a UI can show all problems in a row at once.\n */\nexport async function coerceRow(\n rawRow: Record<string, unknown>,\n metaMap: Map<string, ExportFieldMeta>,\n ctx: CoerceContext,\n): Promise<{ data: Record<string, unknown>; errors: FieldCoerceError[] }> {\n const data: Record<string, unknown> = {};\n const errors: FieldCoerceError[] = [];\n for (const [key, raw] of Object.entries(rawRow)) {\n const meta = metaMap.get(key);\n const res = await coerceFieldValue(raw, meta ? meta : undefined, ctx);\n if ('error' in res) {\n // Attribute the error to the column even when metadata was missing.\n errors.push({ ...res.error, field: res.error.field || key });\n continue;\n }\n if (res.value !== undefined) data[key] = res.value;\n }\n return { data, errors };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { coerceRow, firstMissingRequiredField, type RefResolver, type RefMatch } from './import-coerce.js';\nimport type { ExportFieldMeta } from './export-format.js';\nimport { bulkWrite, withTransientRetry, type BulkWriteRowResult } from '@objectstack/core';\n\n/**\n * import-runner — the shared row-processing core for bulk import.\n *\n * Both the synchronous `POST /data/:object/import` route and the asynchronous\n * import-job worker feed rows through {@link runImport}. Extracting the loop\n * keeps the two paths byte-for-byte identical in coercion, upsert matching, and\n * per-row reporting — the async worker only adds progress persistence and\n * cancellation on top.\n *\n * Rows resolved to a CREATE are batched through `p.createManyData` (the\n * engine's array-form `insert()` — one round-trip per batch, with transient\n * retry and per-row degradation on a logical/validation failure) instead of\n * one `p.createData` call per row — see framework#2678. A protocol that\n * doesn't implement `createManyData` falls back to the original per-row\n * `createData` path unchanged.\n */\n\nexport type ImportAction = 'created' | 'updated' | 'skipped' | 'failed';\n\nexport interface ImportRowResult {\n row: number;\n ok: boolean;\n action: ImportAction;\n id?: string;\n field?: string;\n error?: string;\n code?: string;\n}\n\n/** Running tallies handed to {@link RunImportOptions.onProgress}. */\nexport interface ImportProgress {\n processed: number;\n total: number;\n created: number;\n updated: number;\n skipped: number;\n errors: number;\n}\n\n/**\n * Records exactly what a non-dry-run import changed, so the job can be undone:\n * created records are deleted, and updated records have the touched fields\n * restored to their pre-import values. Only the fields the import wrote are\n * captured (keyed to `before`), keeping the log precise and bounded.\n */\nexport interface ImportUndoLog {\n /** Ids of records this import created (delete to undo). */\n created: string[];\n /** Per updated record: the touched fields' values *before* the import. */\n updated: Array<{ id: string; before: Record<string, any> }>;\n}\n\nexport interface ImportRunSummary extends ImportProgress {\n ok: number;\n results: ImportRowResult[];\n cancelled: boolean;\n /** Present only when `captureUndo` was set — the reversal instructions. */\n undoLog?: ImportUndoLog;\n}\n\n/** Minimal protocol surface the runner needs (find / create / update). */\nexport interface ImportProtocolLike {\n findData(args: any): Promise<any>;\n createData(args: any): Promise<any>;\n updateData(args: any): Promise<any>;\n /**\n * Optional bulk-create primitive. When present, `runImport` batches\n * CREATE-resolved rows through it instead of one `createData` call per\n * row — see framework#2678. Must resolve to `{ records: any[] }` with one\n * record per input row, in the same order.\n */\n createManyData?(args: { object: string; records: any[]; context?: any; environmentId?: string }): Promise<{ records: any[] }>;\n}\n\nexport interface RunImportOptions {\n /** Protocol/engine to read & write through. */\n p: ImportProtocolLike;\n objectName: string;\n environmentId?: string;\n /** Exec context threaded onto reads and (with automation toggle) writes. */\n context?: any;\n /** Already-mapped rows (source columns renamed to target fields). */\n rows: Array<Record<string, any>>;\n /** Field metadata for value coercion (name→id lookups, select codes, …). */\n metaMap: Map<string, ExportFieldMeta>;\n writeMode: 'insert' | 'update' | 'upsert';\n matchFields: string[];\n dryRun: boolean;\n runAutomations: boolean;\n trimWhitespace: boolean;\n nullValues?: string[];\n createMissingOptions: boolean;\n skipBlankMatchKey: boolean;\n /**\n * Progress callback, invoked every {@link RunImportOptions.progressEvery}\n * processed rows and once at the end. May be async; the runner awaits it so a\n * DB write of progress completes before the next chunk.\n */\n onProgress?: (p: ImportProgress) => void | Promise<void>;\n /**\n * Rows between onProgress calls (default 200). Also the flush boundary for\n * buffered creates — a batch never grows past this before being written,\n * so progress numbers stay accurate at every reported checkpoint.\n */\n progressEvery?: number;\n /**\n * Cooperative cancellation. Checked at each progress boundary; when it returns\n * truthy the runner stops and returns `cancelled: true` with partial results.\n */\n shouldCancel?: () => boolean | Promise<boolean>;\n /**\n * When true (and not a dry run), accumulate an {@link ImportUndoLog} so the\n * import can be reverted later. Callers gate this on row count to bound the\n * stored snapshot size.\n */\n captureUndo?: boolean;\n}\n\n/** Extracts a created/updated record's id regardless of which response shape the protocol returned. */\nfunction extractRecordId(rec: any): string | undefined {\n const id = rec?.id ?? rec?.record?.id;\n return id != null ? String(id) : undefined;\n}\n\nfunction toFailedResult(rowNo: number, err: unknown): ImportRowResult {\n const code = (err as any)?.code ?? 'IMPORT_ROW_FAILED';\n const message = typeof (err as any)?.message === 'string' ? (err as any).message.slice(0, 300) : 'Row failed';\n return { row: rowNo, ok: false, action: 'failed', error: message, code };\n}\n\n/** Upper bound on rows in one createManyData batch (framework#2678 suggests 100-500). */\nconst MAX_CREATE_BATCH_SIZE = 200;\n\nexport function runImport(opts: RunImportOptions): Promise<ImportRunSummary> {\n const {\n p, objectName, environmentId, context, rows, metaMap,\n writeMode, matchFields, dryRun, runAutomations,\n trimWhitespace, nullValues, createMissingOptions, skipBlankMatchKey,\n onProgress, shouldCancel, captureUndo,\n } = opts;\n const collectUndo = !!captureUndo && !dryRun;\n const undoLog: ImportUndoLog = { created: [], updated: [] };\n // Snapshot only the fields the import touched, so undo restores exactly what\n // changed. A field absent before the import is recorded as null → undo clears\n // it. Never captured on dry runs (nothing was written).\n const captureBefore = (before: Record<string, any>, written: Record<string, any>): Record<string, any> => {\n const snap: Record<string, any> = {};\n for (const k of Object.keys(written)) snap[k] = before[k] ?? null;\n return snap;\n };\n const progressEvery = Math.max(1, opts.progressEvery ?? 200);\n\n const findRows = (r: any): any[] =>\n Array.isArray(r?.records) ? r.records\n : Array.isArray(r?.data) ? r.data\n : Array.isArray(r?.rows) ? r.rows\n : Array.isArray(r) ? r : [];\n const findArgsBase = (query: any) => ({\n object: '',\n query,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n\n // Reference resolver: name/email/id → referenced record id. Cached per\n // (object, display) so a name repeated across rows costs one query.\n const refCache = new Map<string, RefMatch>();\n const resolveRef: RefResolver = async (referenceObject, display, meta) => {\n const cacheKey = `${referenceObject}::${display}`;\n const cached = refCache.get(cacheKey);\n if (cached) return cached;\n // Try an exact id first (authoritative + unique when the user pasted an id),\n // then the configured display field, then the usual human identifiers.\n // De-dupe so a field isn't queried twice. The first candidate field to match\n // wins; if that field matches >1 record we stop and report ambiguity rather\n // than silently linking the first.\n const candidates = [...new Set([\n 'id',\n ...(meta.displayField ? [meta.displayField] : []),\n 'name', 'title', 'label', 'full_name', 'email', 'username',\n ])];\n let match: RefMatch = {};\n for (const f of candidates) {\n try {\n const r = await p.findData({\n ...findArgsBase({ $filter: { [f]: display }, $top: 2 }),\n object: referenceObject,\n });\n const recs = findRows(r);\n if (recs.length === 0) continue;\n if (recs.length > 1) { match = { ambiguous: true, matchedField: f }; break; }\n if (recs[0]?.id != null) { match = { id: String(recs[0].id), matchedField: f }; break; }\n } catch { /* field absent on target object — try the next candidate */ }\n }\n refCache.set(cacheKey, match);\n return match;\n };\n\n // Locate an existing record for update/upsert by matchFields. Returns the\n // record, or a sentinel: 'blank' (a match field was empty), 'none' (no\n // match), 'ambiguous' (>1 match — too risky to update).\n const findExisting = async (\n data: Record<string, any>,\n ): Promise<Record<string, any> | 'blank' | 'none' | 'ambiguous'> => {\n const filter: Record<string, any> = {};\n for (const f of matchFields) {\n const v = data[f];\n if (v === undefined || v === null || v === '') return 'blank';\n filter[f] = v;\n }\n const r = await p.findData({ ...findArgsBase({ $filter: filter, $top: 2 }), object: objectName });\n const recs = findRows(r);\n if (recs.length === 0) return 'none';\n if (recs.length > 1) return 'ambiguous';\n return recs[0];\n };\n\n const writeCtx = { ...(context ?? {}), skipAutomations: !runAutomations };\n\n // Sparse-indexed by row position `i` (not push-only): CREATE rows are\n // resolved immediately but their write is deferred to a later batch flush,\n // so their result would otherwise land out of order relative to\n // immediately-written update/skip rows interleaved between them.\n const results: ImportRowResult[] = new Array(rows.length);\n let okCount = 0, errCount = 0, created = 0, updated = 0, skipped = 0;\n let cancelled = false;\n\n const snapshot = (processed: number): ImportProgress => ({\n processed, total: rows.length, created, updated, skipped, errors: errCount,\n });\n\n // CREATE rows are buffered here and flushed through `p.createManyData`\n // (one round-trip per batch) when the protocol supports it. A protocol\n // without `createManyData` never buffers — `canBulkCreate` is false and\n // creates fall back to the original inline per-row `createData` call.\n const canBulkCreate = typeof p.createManyData === 'function';\n const pendingCreates: Array<{ index: number; rowNo: number; data: Record<string, any> }> = [];\n const flushPendingCreates = async (): Promise<void> => {\n if (pendingCreates.length === 0) return;\n const batch = pendingCreates.splice(0, pendingCreates.length);\n const writeResults: BulkWriteRowResult[] = await bulkWrite(\n batch.map(b => b.data),\n {\n // Flush cadence follows progressEvery, but the write batch itself is\n // capped independently — a caller-supplied progressEvery far above\n // the issue's suggested 100-500 rows/batch must not translate into\n // one oversized multi-row INSERT statement.\n batchSize: Math.min(progressEvery, MAX_CREATE_BATCH_SIZE),\n writeBatch: (chunk) => p.createManyData!({\n object: objectName, records: chunk, context: writeCtx,\n ...(environmentId ? { environmentId } : {}),\n }).then(r => r.records),\n writeOne: (row) => p.createData({\n object: objectName, data: row, context: writeCtx,\n ...(environmentId ? { environmentId } : {}),\n }),\n },\n );\n for (const res of writeResults) {\n const { index, rowNo } = batch[res.index];\n if (res.ok) {\n const id = extractRecordId(res.record);\n okCount++; created++;\n if (collectUndo && id != null) undoLog.created.push(id);\n results[index] = { row: rowNo, ok: true, action: 'created', id };\n } else {\n errCount++;\n results[index] = toFailedResult(rowNo, res.error);\n }\n }\n };\n\n return (async () => {\n for (let i = 0; i < rows.length; i++) {\n const rowNo = i + 1;\n try {\n // 1. Coerce every cell to its storage value (+ resolve lookups).\n const { data, errors } = await coerceRow(rows[i], metaMap, {\n trimWhitespace, nullValues, createMissingOptions, resolveRef,\n });\n if (errors.length > 0) {\n const first = errors[0];\n errCount++;\n results[i] = { row: rowNo, ok: false, action: 'failed', field: first.field, code: first.code, error: first.message };\n } else {\n // 2. Decide create vs update vs skip.\n let existing: Record<string, any> | 'blank' | 'none' | 'ambiguous' = 'none';\n let handled = false;\n if (writeMode !== 'insert') {\n existing = await findExisting(data);\n if (existing === 'ambiguous') {\n errCount++;\n results[i] = { row: rowNo, ok: false, action: 'failed', code: 'AMBIGUOUS_MATCH', error: `matchFields matched more than one ${objectName} record` };\n handled = true;\n } else if (existing === 'blank' && (skipBlankMatchKey || writeMode === 'update')) {\n // Blank match key: skip when asked, else fall through to create.\n skipped++;\n results[i] = { row: rowNo, ok: true, action: 'skipped', code: 'BLANK_MATCH_KEY' };\n handled = true;\n }\n }\n\n if (!handled) {\n const willUpdate = existing && typeof existing === 'object';\n const willCreate = !willUpdate && (writeMode === 'insert' || writeMode === 'upsert');\n\n // Required-field pre-check (CREATE only). Give dry run the same\n // verdict the real insert produces — a required (⇒ NOT NULL) field\n // with no default and no value fails both — instead of reporting\n // success for a row that then dies on `NOT NULL constraint failed`.\n // Shared by both paths so they stay identical (and a real insert\n // gets a readable `<field> is required` instead of a raw driver\n // error). Skipped when automations run: a beforeInsert hook may\n // populate a required field, so we defer to the engine's own\n // validation rather than false-reject here.\n const requiredMiss =\n willCreate && !runAutomations ? firstMissingRequiredField(data, metaMap) : null;\n\n if (requiredMiss) {\n errCount++;\n results[i] = { row: rowNo, ok: false, action: 'failed', field: requiredMiss, code: 'required', error: `${requiredMiss} is required` };\n } else if (!willUpdate && !willCreate) {\n // update mode, no match → skip.\n skipped++;\n results[i] = { row: rowNo, ok: true, action: 'skipped', code: 'NO_MATCH' };\n } else if (dryRun) {\n okCount++;\n if (willUpdate) { updated++; results[i] = { row: rowNo, ok: true, action: 'updated', id: String((existing as any).id ?? '') || undefined }; }\n else { created++; results[i] = { row: rowNo, ok: true, action: 'created' }; }\n } else if (willUpdate) {\n const target = existing as Record<string, any>;\n const res2 = await withTransientRetry(() => p.updateData({ object: objectName, id: target.id, data, context: writeCtx, ...(environmentId ? { environmentId } : {}) }));\n const id = extractRecordId(res2) ?? String(target.id);\n okCount++; updated++;\n if (collectUndo && target.id != null) {\n undoLog.updated.push({ id: String(target.id), before: captureBefore(target, data) });\n }\n results[i] = { row: rowNo, ok: true, action: 'updated', id };\n } else if (canBulkCreate) {\n // Buffer — the actual write happens in a batched flush below.\n pendingCreates.push({ index: i, rowNo, data });\n } else {\n // No bulk-create primitive on this protocol: original inline path.\n const res2 = await p.createData({ object: objectName, data, context: writeCtx, ...(environmentId ? { environmentId } : {}) });\n const id = extractRecordId(res2);\n okCount++; created++;\n if (collectUndo && id != null) undoLog.created.push(id);\n results[i] = { row: rowNo, ok: true, action: 'created', id };\n }\n }\n }\n } catch (err: any) {\n errCount++;\n results[i] = toFailedResult(rowNo, err);\n }\n\n const processed = i + 1;\n if (processed % progressEvery === 0 || processed === rows.length) {\n // Flush before reporting/cancelling so counts and `processed` reflect\n // every row up to this checkpoint, not just decided-but-unwritten ones.\n await flushPendingCreates();\n if (onProgress) await onProgress(snapshot(processed));\n }\n if (shouldCancel && processed < rows.length && (processed % progressEvery === 0)) {\n if (await shouldCancel()) { cancelled = true; break; }\n }\n }\n\n await flushPendingCreates();\n const compacted = results.filter((r): r is ImportRowResult => r !== undefined);\n\n return {\n ...snapshot(compacted.length), ok: okCount, results: compacted, cancelled,\n ...(collectUndo ? { undoLog } : {}),\n };\n })();\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Named import mappings (#2611) — resolve a registered `mapping` artifact\n * (`defineMapping`, stack `mappings:`) by name and apply its `fieldMapping`\n * pipeline to parsed rows.\n *\n * Seam with the inline request `mapping`:\n * • inline = a plain `{ sourceColumn: targetField }` RENAME for one-off,\n * wizard-driven imports — unmapped columns pass through untouched.\n * • artifact = a reusable, governed ETL projection for recurring /\n * programmatic imports — the output row contains ONLY the mapped\n * targets (a strict projection; source files from external systems\n * routinely carry junk columns that must not leak into the write path).\n *\n * Transform support (Prime Directive #10 — implement or reject loudly):\n * none/constant/map/split/join — applied here.\n * lookup — the value is copied through; the import pipeline's built-in\n * reference resolution (metaMap) turns lookup names into record ids,\n * so a dedicated re-implementation here would be a second dialect.\n * javascript — REJECTED (400). No server-side sandbox is wired into the\n * import path yet; silently skipping a declared transform would corrupt\n * data. Tracked on framework#2611.\n */\n\nexport interface MappingArtifactLike {\n name: string;\n targetObject: string;\n sourceFormat?: 'csv' | 'json' | 'xml' | 'sql';\n fieldMapping: Array<{\n source: string | string[];\n target: string | string[];\n transform?: 'none' | 'constant' | 'lookup' | 'split' | 'join' | 'javascript' | 'map';\n params?: {\n value?: unknown;\n valueMap?: Record<string, unknown>;\n separator?: string;\n } & Record<string, unknown>;\n }>;\n mode?: 'insert' | 'update' | 'upsert';\n upsertKey?: string[];\n}\n\nexport type MappingFailure = { ok: false; status: number; code: string; error: string };\nexport type ResolveMappingResult = { ok: true; artifact: MappingArtifactLike } | MappingFailure;\n\n/** Unwrap `{ item }` meta envelopes returned by protocol getMetaItem. */\nfunction unwrapEnvelope(r: unknown): unknown {\n if (r && typeof r === 'object' && 'item' in (r as Record<string, unknown>)) {\n return (r as Record<string, unknown>).item;\n }\n return r;\n}\n\n/**\n * Resolve a named mapping artifact and check it against the request:\n * target object must match the URL object, and the artifact's declared\n * sourceFormat (when set) must match the payload format actually sent.\n */\nexport async function resolveNamedMapping(\n p: { getMetaItem?: (req: { type: string; name: string }) => Promise<unknown> },\n opts: { mappingName: string; objectName: string; detectedFormat: 'csv' | 'json' | 'xlsx' },\n): Promise<ResolveMappingResult> {\n const { mappingName, objectName, detectedFormat } = opts;\n if (typeof p?.getMetaItem !== 'function') {\n return { ok: false, status: 500, code: 'INTERNAL', error: 'Metadata protocol unavailable; cannot resolve mappingName' };\n }\n let artifact: MappingArtifactLike | undefined;\n try {\n artifact = unwrapEnvelope(await p.getMetaItem({ type: 'mapping', name: mappingName })) as MappingArtifactLike | undefined;\n } catch { /* treated as not found below */ }\n if (!artifact || typeof artifact !== 'object' || !Array.isArray(artifact.fieldMapping)) {\n return { ok: false, status: 404, code: 'MAPPING_NOT_FOUND', error: `No mapping artifact named \"${mappingName}\" is registered` };\n }\n if (artifact.targetObject !== objectName) {\n return {\n ok: false, status: 400, code: 'MAPPING_TARGET_MISMATCH',\n error: `Mapping \"${mappingName}\" targets object \"${artifact.targetObject}\", not \"${objectName}\"`,\n };\n }\n const declared = artifact.sourceFormat;\n if (declared === 'xml' || declared === 'sql') {\n return {\n ok: false, status: 400, code: 'MAPPING_FORMAT_UNSUPPORTED',\n error: `Mapping \"${mappingName}\" declares sourceFormat \"${declared}\", which the import endpoint does not accept (csv/json/xlsx)`,\n };\n }\n // xlsx rows are tabular like csv; a csv-declared mapping applies to both.\n const compatible = declared === undefined\n || (declared === 'json' && detectedFormat === 'json')\n || (declared === 'csv' && (detectedFormat === 'csv' || detectedFormat === 'xlsx'));\n if (!compatible) {\n return {\n ok: false, status: 400, code: 'MAPPING_FORMAT_MISMATCH',\n error: `Mapping \"${mappingName}\" declares sourceFormat \"${declared}\" but the payload is \"${detectedFormat}\"`,\n };\n }\n for (const entry of artifact.fieldMapping) {\n if (entry?.transform === 'javascript') {\n return {\n ok: false, status: 400, code: 'UNSUPPORTED_TRANSFORM',\n error: `Mapping \"${mappingName}\" uses transform \"javascript\", which the import path does not execute (no server-side sandbox; see framework#2611)`,\n };\n }\n }\n return { ok: true, artifact };\n}\n\nconst first = (v: string | string[]): string => (Array.isArray(v) ? v[0] : v);\n\n/**\n * Apply the artifact's fieldMapping pipeline to raw parsed rows (headers as\n * in the source file). Returns NEW rows containing only mapped targets.\n */\nexport function applyMappingToRows(\n rows: Array<Record<string, unknown>>,\n artifact: MappingArtifactLike,\n): { ok: true; rows: Array<Record<string, unknown>> } | MappingFailure {\n const out: Array<Record<string, unknown>> = [];\n for (const row of rows) {\n const mapped: Record<string, unknown> = {};\n for (const entry of artifact.fieldMapping) {\n const transform = entry.transform ?? 'none';\n const sep = entry.params?.separator ?? ' ';\n switch (transform) {\n case 'none':\n case 'lookup': { // lookup values resolve downstream via metaMap\n mapped[first(entry.target)] = row[first(entry.source)];\n break;\n }\n case 'constant': {\n mapped[first(entry.target)] = entry.params?.value;\n break;\n }\n case 'map': {\n const raw = row[first(entry.source)];\n const valueMap = entry.params?.valueMap ?? {};\n mapped[first(entry.target)] =\n typeof raw === 'string' && raw in valueMap ? valueMap[raw] : raw;\n break;\n }\n case 'split': {\n const raw = row[first(entry.source)];\n const targets = Array.isArray(entry.target) ? entry.target : [entry.target];\n const parts = typeof raw === 'string' ? raw.split(sep) : [];\n targets.forEach((t, i) => { mapped[t] = parts[i]?.trim(); });\n break;\n }\n case 'join': {\n const sources = Array.isArray(entry.source) ? entry.source : [entry.source];\n mapped[first(entry.target)] = sources\n .map((s) => row[s])\n .filter((v) => v !== undefined && v !== null && v !== '')\n .join(sep);\n break;\n }\n default:\n return {\n ok: false, status: 400, code: 'UNSUPPORTED_TRANSFORM',\n error: `Mapping \"${artifact.name}\" uses unknown transform \"${transform}\"`,\n };\n }\n }\n out.push(mapped);\n }\n return { ok: true, rows: out };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Bulk-import request parsing — extracted verbatim from rest-server.ts\n * (#2766 V2) so consumers outside the generic `/data/:object/import` routes\n * (the identity import endpoint in plugin-auth) can accept byte-identical\n * payloads (rows[]/csv/xlsxBase64, mapping in either shape, writeMode +\n * matchFields) without re-implementing the parsers.\n */\n\nimport {\n buildFieldMetaMap,\n type ExportFieldMeta,\n} from './export-format.js';\nimport { resolveNamedMapping, applyMappingToRows, type MappingArtifactLike } from './import-mapping.js';\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 */\nexport function 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 * 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 */\nexport function 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 * Flatten one ExcelJS cell value to the raw string the coercion layer expects.\n * ExcelJS hands back rich objects for formulas / hyperlinks / rich text / dates;\n * we reduce each to the human-visible text so a server-parsed xlsx yields the\n * same cells a CSV export would (dates → ISO, so parseDateCell can re-read them).\n */\nfunction xlsxCellToString(value: any): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') {\n // Formula cell → prefer its computed result.\n if ('result' in value && value.result !== undefined && value.result !== null) return xlsxCellToString(value.result);\n // Hyperlink cell → the visible text, not the target.\n if ('text' in value && typeof value.text === 'string') return value.text;\n if ('hyperlink' in value && typeof value.hyperlink === 'string') return value.hyperlink;\n // Rich text → concatenate runs.\n if (Array.isArray(value.richText)) return value.richText.map((r: any) => r?.text ?? '').join('');\n if ('error' in value && value.error) return String(value.error);\n }\n try { return String(value); } catch { return ''; }\n}\n\n/**\n * Parse an .xlsx workbook (raw bytes) into row objects, mirroring\n * {@link parseCsvToRows}: first non-empty row is the header, each subsequent row\n * becomes `{ header→cell }` with the optional `mapping` renaming columns. Reads\n * the named/indexed `sheet` when given, else the first worksheet. Dynamically\n * imports ExcelJS (already a dependency of the export path) so CSV/JSON imports\n * don't pay for it.\n */\nexport async function parseXlsxToRows(\n buffer: Buffer | ArrayBuffer,\n mapping: Record<string, string> = {},\n sheet?: string | number,\n): Promise<Array<Record<string, any>>> {\n const ExcelJS: any = (await import('exceljs')).default ?? (await import('exceljs'));\n const wb = new ExcelJS.Workbook();\n await wb.xlsx.load(buffer);\n const ws = sheet !== undefined ? wb.getWorksheet(sheet as any) : wb.worksheets[0];\n if (!ws) return [];\n\n const cells: string[][] = [];\n ws.eachRow({ includeEmpty: false }, (row: any) => {\n const values = row.values as any[]; // 1-based; index 0 is unused\n const line: string[] = [];\n for (let c = 1; c < values.length; c++) line.push(xlsxCellToString(values[c]));\n cells.push(line);\n });\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 line = 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 obj[key] = line[c] ?? '';\n }\n out.push(obj);\n }\n return out;\n}\n\n/** Everything the import runner needs, parsed & validated from a request body. */\nexport interface PreparedImport {\n rows: Array<Record<string, any>>;\n metaMap: Map<string, ExportFieldMeta>;\n writeMode: 'insert' | 'update' | 'upsert';\n matchFields: string[];\n dryRun: boolean;\n runAutomations: boolean;\n trimWhitespace: boolean;\n nullValues?: string[];\n createMissingOptions: boolean;\n skipBlankMatchKey: boolean;\n}\n\nexport type PrepareImportResult =\n | { ok: true; prepared: PreparedImport }\n | { ok: false; status: number; code: string; error: string };\n\n/**\n * Parse & validate a bulk-import request body into a {@link PreparedImport}.\n *\n * Shared by the synchronous `POST /data/:object/import` route and the async\n * import-job create route so both accept byte-identical payloads (writeMode +\n * matchFields, mapping in either shape, rows[]/csv/xlsxBase64) and resolve the\n * same field metadata. The only knob that differs is `maxRows` (5k sync vs\n * 50k async). Returns a discriminated result; the caller maps `!ok` to an HTTP\n * error using the returned status/code/error.\n */\nexport async function prepareImportRequest(\n body: any,\n opts: { p: any; objectName: string; environmentId?: string; maxRows: number },\n): Promise<PrepareImportResult> {\n const { p, objectName, environmentId, maxRows } = opts;\n const dryRun = body?.dryRun === true;\n\n let writeMode: 'insert' | 'update' | 'upsert' =\n body?.writeMode === 'update' || body?.writeMode === 'upsert' ? body.writeMode : 'insert';\n let matchFields: string[] = Array.isArray(body?.matchFields)\n ? body.matchFields.filter((f: any) => typeof f === 'string' && f.length > 0)\n : [];\n const runAutomations = body?.runAutomations === true;\n const trimWhitespace = body?.trimWhitespace !== false;\n const nullValues: string[] | undefined = Array.isArray(body?.nullValues)\n ? body.nullValues.filter((v: any) => typeof v === 'string')\n : undefined;\n const createMissingOptions = body?.createMissingOptions === true;\n const skipBlankMatchKey = body?.skipBlankMatchKey === true;\n\n // ── Named mapping artifact (#2611) ────────────────────────────────\n // `mappingName` references a registered `mapping` artifact\n // (defineMapping / stack `mappings:`) — the reusable, governed form for\n // recurring & programmatic imports. Mutually exclusive with the inline\n // `mapping` rename: one mapping source of truth per request.\n const mappingName: string | undefined =\n typeof body?.mappingName === 'string' && body.mappingName.length > 0 ? body.mappingName : undefined;\n const hasInlineMapping =\n (Array.isArray(body?.mapping) && body.mapping.length > 0) ||\n (!Array.isArray(body?.mapping) && body?.mapping && typeof body.mapping === 'object' && Object.keys(body.mapping).length > 0);\n if (mappingName && hasInlineMapping) {\n return { ok: false, status: 400, code: 'CONFLICTING_MAPPING', error: 'Provide either mappingName or an inline mapping, not both' };\n }\n let mappingArtifact: MappingArtifactLike | undefined;\n if (mappingName) {\n const detectedFormat: 'csv' | 'json' | 'xlsx' | undefined =\n (body?.format === 'json' && Array.isArray(body?.rows)) || Array.isArray(body) ? 'json'\n : typeof body?.csv === 'string' ? 'csv'\n : typeof body?.xlsxBase64 === 'string' ? 'xlsx'\n : undefined;\n if (!detectedFormat) {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: 'Provide format:\"csv\" with csv text, format:\"json\" with rows[], or format:\"xlsx\" with xlsxBase64' };\n }\n const resolved = await resolveNamedMapping(p, { mappingName, objectName, detectedFormat });\n if (!resolved.ok) return resolved;\n mappingArtifact = resolved.artifact;\n // Artifact-declared write semantics apply as DEFAULTS: an explicit\n // request writeMode/matchFields wins; absent ones fall back to the\n // artifact's mode/upsertKey.\n if (body?.writeMode === undefined && (mappingArtifact.mode === 'update' || mappingArtifact.mode === 'upsert')) {\n writeMode = mappingArtifact.mode;\n }\n if (matchFields.length === 0 && Array.isArray(mappingArtifact.upsertKey)) {\n matchFields = mappingArtifact.upsertKey.filter((f) => typeof f === 'string' && f.length > 0);\n }\n }\n\n if (writeMode !== 'insert' && matchFields.length === 0) {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: `writeMode \"${writeMode}\" requires a non-empty matchFields[]` };\n }\n\n // Normalize `mapping` to a `{ sourceColumn: targetField }` record. Accepts\n // either that compact form or a FieldMappingEntry[].\n const mapping: Record<string, string> = {};\n if (Array.isArray(body?.mapping)) {\n for (const e of body.mapping) {\n if (e && typeof e.sourceField === 'string' && typeof e.targetField === 'string') {\n mapping[e.sourceField] = e.targetField;\n }\n }\n } else if (body?.mapping && typeof body.mapping === 'object') {\n for (const [k, v] of Object.entries(body.mapping)) {\n if (typeof v === 'string') mapping[k] = v;\n }\n }\n const applyMapping = (row: Record<string, any>): Record<string, any> => {\n if (Object.keys(mapping).length === 0) return row;\n const out: Record<string, any> = {};\n for (const [k, val] of Object.entries(row)) out[mapping[k] ?? k] = val;\n return out;\n };\n\n // Build rows[] from JSON array, CSV text, or a base64 xlsx.\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>>).map(applyMapping);\n } else if ((body?.format === 'csv' || typeof body?.csv === 'string') && typeof body?.csv === 'string') {\n rows = parseCsvToRows(body.csv, mapping);\n } else if ((body?.format === 'xlsx' || typeof body?.xlsxBase64 === 'string') && typeof body?.xlsxBase64 === 'string') {\n // Native server-side xlsx parse — the client uploads raw workbook bytes\n // (base64) instead of pre-flattening to CSV.\n try {\n const buf = Buffer.from(body.xlsxBase64, 'base64');\n rows = await parseXlsxToRows(buf, mapping, body.sheet);\n } catch (e: any) {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: `Failed to parse xlsx: ${e?.message ?? String(e)}` };\n }\n } else if (Array.isArray(body)) {\n // Permissive: a bare JSON array at the top level.\n rows = (body as Array<Record<string, any>>).map(applyMapping);\n } else {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: 'Provide format:\"csv\" with csv text, format:\"json\" with rows[], or format:\"xlsx\" with xlsxBase64' };\n }\n\n if (rows.length > maxRows) {\n return { ok: false, status: 413, code: 'PAYLOAD_TOO_LARGE', error: `Import limit is ${maxRows} rows per request (got ${rows.length}).` };\n }\n\n // Apply the named mapping's fieldMapping pipeline (rename + transforms;\n // strict projection — only mapped targets reach the write path). Inline\n // `mapping` was empty in this branch, so rows still carry raw headers.\n if (mappingArtifact) {\n const applied = applyMappingToRows(rows, mappingArtifact);\n if (!applied.ok) return applied;\n rows = applied.rows;\n }\n\n // Resolve the object's field metadata so cells coerce to storage values\n // (booleans, numbers, dates→ISO, select label→code) and lookup names resolve\n // to record ids. Best-effort: a failed lookup leaves `metaMap` empty and\n // every value passes through untouched.\n let metaMap = new Map<string, ExportFieldMeta>();\n try {\n let schema: any = undefined;\n if (typeof p.getMetaItem === 'function') {\n const r = await p.getMetaItem({ type: 'object', name: objectName });\n schema = isMetaEnvelope(r) ? r.item : r;\n }\n if (!schema && typeof p.getObjectSchema === 'function') {\n schema = await p.getObjectSchema(objectName, environmentId);\n }\n metaMap = buildFieldMetaMap(schema);\n } catch { /* pass-through coercion */ }\n\n return {\n ok: true,\n prepared: {\n rows, metaMap, writeMode, matchFields, dryRun, runAutomations,\n trimWhitespace, nullValues, createMissingOptions, skipBlankMatchKey,\n },\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 * and (#2747) the full `deletePackage` uninstall semantics: package\n * metadata rows, the durable `sys_packages` record, and the registered\n * data-plane cleanups (e.g. plugin-security revoking the package's\n * permission sets and bindings).\n */\n protocol?: {\n getMetaItems?(req: { type: string }): Promise<{ items: any[] }>;\n deletePackage?(req: { packageId: string; actor?: string }): Promise<{\n success: boolean;\n deletedCount: number;\n failedCount: number;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n cleanups: Array<{ name: string; success: boolean; removed: number; error?: string }>;\n }>;\n };\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 // [#2747] A FULL uninstall (no version pin) goes through\n // protocol.deletePackage — one uninstall semantic, not three dialects:\n // it removes the package's metadata rows, drops the durable\n // sys_packages record, and runs the registered data-plane cleanups\n // (plugin-security revokes the package's permission sets/bindings —\n // no ghost grants). A version-scoped delete keeps the narrow durable\n // registry semantics, as does a deployment without the protocol.\n if (!version && typeof options.protocol?.deletePackage === 'function') {\n const result = await options.protocol.deletePackage({ packageId });\n // Zero metadata rows is still a successful uninstall (e.g. a\n // runtime-registered package that never published metadata) —\n // only per-item failures make it a failure.\n if (result.failedCount === 0) {\n res.json({\n success: true,\n message: `Deleted ${packageId}`,\n deletedCount: result.deletedCount,\n cleanups: result.cleanups,\n });\n return;\n }\n res.status(400).json({ success: false, failed: result.failed, cleanups: result.cleanups });\n return;\n }\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';\nimport { SysImportJob } from '@objectstack/platform-objects/audit';\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 // Register the async-import job object so its state/progress/history\n // is queryable in Studio and readable by the import-job routes.\n // The REST plugin owns the import feature, so it owns this object\n // (there is no separate import service). Mirrors JobServicePlugin.\n try {\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.rest.api',\n name: 'REST API',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n defaultDatasource: 'cloud',\n namespace: 'sys',\n objects: [SysImportJob],\n });\n } catch (err) {\n ctx.logger.warn('RestApiPlugin: manifest service unavailable; sys_import_job not registered', err as any);\n }\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 // Security service resolver — used by the ADR-0090 D5/D9\n // /security/suggested-bindings routes and the D6 /security/explain\n // route (plugin-security). Returns undefined when plugin-security\n // is not mounted so the routes fail cleanly (501).\n const securityServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('security');\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 // Single-env service-existence probe for nav capability gates\n // (ADR-0057 D10). Multi-env uses the per-request kernel instead.\n const serviceExistsProvider = (name: string): boolean => {\n try { return ctx.getService<any>(name) != null; } catch { return false; }\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, serviceExistsProvider, securityServiceProvider);\n restServer.registerRoutes();\n\n ctx.logger.info('REST API successfully registered');\n\n // ADR-0056 D2 (warn → enforce, ENFORCED): the global default is\n // secure-by-default — anonymous /data/* is denied unless the\n // deployment explicitly opts out. The warning remains for that\n // explicit opt-out so a fail-open posture is always visible.\n if ((config.api as any)?.api?.requireAuth === false) {\n ctx.logger.warn(\n '[security] anonymous access to the data API is ALLOWED (api.requireAuth=false, explicit opt-out) — ' +\n 'objects without OWD/RLS are world-readable. Remove the opt-out for secure-by-default and ' +\n 'expose public records via share-links / publicSharing / public forms (ADR-0056 D2).',\n );\n }\n // Misplaced-key guard: the effective key is `api.api.requireAuth`\n // (RestApiPluginConfig.api is the full RestServerConfig). A flat\n // `api.requireAuth` is silently ignored by normalizeConfig — under\n // the deny default that turns an INTENDED public deployment into a\n // 401 outage with no diagnostic, so name the mistake loudly.\n if ((config.api as any)?.requireAuth !== undefined) {\n ctx.logger.warn(\n '[security] `api.requireAuth` is set at the WRONG nesting level and has NO effect — ' +\n 'move it to `api.api.requireAuth` (RestServerConfig.api.requireAuth). ' +\n `The effective value this boot is ${(config.api as any)?.api?.requireAuth ?? true}.`,\n );\n }\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":["REFERENCE_TYPES","OPTION_TYPES","MULTI_OPTION_TYPES","pad2","first","row","res","result"]}
1
+ {"version":3,"sources":["../src/rest-server.ts","../src/route-manager.ts","../src/export-format.ts","../src/import-coerce.ts","../src/import-runner.ts","../src/import-mapping.ts","../src/import-prepare.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\nimport { IHttpServer, resolveAuthzContext, resolveLocalizationContext, isAuthGateAllowlisted } from '@objectstack/core';\nimport { isMcpServerEnabled } from '@objectstack/types';\nimport { RouteManager } from './route-manager.js';\nimport { RestServerConfig, RestApiConfig, CrudEndpointsConfig, MetadataEndpointsConfig, BatchEndpointsConfig, RouteGenerationConfig } from '@objectstack/spec/api';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport {\n buildFieldMetaMap,\n referenceFieldNames,\n headerLabel,\n formatRowCells,\n formatRowForJson,\n cellFontColor,\n exportContentDisposition,\n type ExportFieldMeta,\n} from './export-format.js';\nimport { runImport } from './import-runner.js';\nimport { prepareImportRequest, isMetaEnvelope } from './import-prepare.js';\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/**\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 // Capability gates (#2707 feeds / #2727 files): plugin-audit's engine\n // hooks reject sys_comment / sys_attachment inserts fail-closed when the\n // TARGET object's capability flag disallows them. 403 like\n // CLONE_DISABLED; surfaced by `code` because the generic data routes map\n // through here (they never reach sendError's `.status` passthrough).\n // `error.object` names the gated TARGET object (not the join table), so\n // prefer it.\n if (error?.code === 'FEEDS_DISABLED' || error?.code === 'FILES_DISABLED') {\n return {\n status: 403,\n body: {\n error: error?.message ?? 'This capability is disabled for the target object',\n code: error.code,\n ...(error?.object || object ? { object: error?.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 // Sandboxed hook/action bodies (QuickJS) throw SandboxError whose\n // `.message` carries a `<kind> '<name>' threw: <msg>` debug wrapper for\n // server logs, with the original business message preserved on\n // `.innerMessage` (see runtime/src/sandbox/quickjs-runner.ts). End users\n // must see only the business message — a hook's `throw new Error('删除被\n // 阻断…')` is a deliberate business rule, not a fault — the same unwrap\n // the custom-action route performs in http-dispatcher's handleAction.\n // The full wrapper still reaches server logs via the callers'\n // \"[REST] Unhandled error\" logging and the BodyRunner's own error log.\n // Deliberately NO `code` field: older @objectstack/client builds (still\n // bundled in deployed consoles) prepend any `code` to the human-readable\n // message, which would reintroduce the English noise this branch removes.\n if (typeof error?.innerMessage === 'string' && error.innerMessage) {\n return {\n status: 400,\n body: {\n error: error.innerMessage,\n ...(object ? { object } : {}),\n },\n };\n }\n\n const raw = String(error?.message ?? error ?? '');\n const lower = raw.toLowerCase();\n\n // Fallback for the same sandbox wrapper when the SandboxError instance\n // (and its `innerMessage`) was lost crossing a rethrow/serialization\n // boundary: strip the debug wrapper from the raw message. A leading\n // default `Error: ` name is dropped; non-default names (`TypeError: …`)\n // are kept — they signal a genuine script bug rather than a deliberately\n // thrown business rule, which is useful context.\n const sandboxWrapper = /^(?:hook|action) '[^']*' threw:\\s*(.+)$/s.exec(raw);\n if (sandboxWrapper) {\n const msg = sandboxWrapper[1].startsWith('Error: ')\n ? sandboxWrapper[1].slice('Error: '.length)\n : sandboxWrapper[1];\n return {\n status: 400,\n body: {\n error: msg,\n ...(object ? { object } : {}),\n },\n };\n }\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 // The metadata required-check (`record-validator`) runs BEFORE the\n // driver, so a NOT NULL violation that reaches this far means metadata\n // did NOT consider the field required — i.e. the physical column has\n // drifted from metadata (#2186), not a genuine missing-required-field.\n // We keep the `VALIDATION_FAILED` / `required` envelope for back-compat\n // (form UIs key off it) but add an actionable `hint` so the message\n // stops being misleading.\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 hint:\n `If '${field}' is optional in your object metadata, the database column is still NOT NULL — ` +\n `the physical schema has drifted from metadata. Run 'os migrate' to reconcile ` +\n `(or reset the dev database).`,\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/** Platform object backing async import jobs (see sys-import-job.object.ts). */\nconst IMPORT_JOB_OBJECT = 'sys_import_job';\n/** Hard ceiling on rows per async import job (mirrors spec IMPORT_JOB_MAX_ROWS). */\nconst IMPORT_JOB_MAX_ROWS = 50_000;\n/** Cap on per-row results persisted on the job (failures first). */\nconst IMPORT_JOB_RESULTS_CAP = 500;\n/** Undo (logical rollback) is only recorded for jobs at or under this row\n * count — larger jobs skip the undo log to bound the stored before-snapshots. */\nconst IMPORT_JOB_UNDO_MAX_ROWS = 5_000;\n\n/** Generate a sortable-ish, collision-resistant import job id. */\nfunction newImportJobId(): string {\n return `imp_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Cap a results list to {@link IMPORT_JOB_RESULTS_CAP}, keeping failures first. */\nfunction capImportResults(results: Array<{ ok: boolean }>): { items: any[]; truncated: boolean } {\n if (results.length <= IMPORT_JOB_RESULTS_CAP) return { items: results, truncated: false };\n const failures = results.filter(r => !r.ok);\n const successes = results.filter(r => r.ok);\n const items = [...failures, ...successes].slice(0, IMPORT_JOB_RESULTS_CAP);\n return { items, truncated: true };\n}\n\n/** Parse the persisted undo log (json column may arrive as object or string). */\nfunction parseUndoLog(raw: any): { created: string[]; updated: Array<{ id: string; before: Record<string, any> }> } | undefined {\n if (!raw) return undefined;\n let v = raw;\n if (typeof v === 'string') { try { v = JSON.parse(v); } catch { return undefined; } }\n if (!v || typeof v !== 'object') return undefined;\n const created = Array.isArray(v.created) ? v.created.map(String) : [];\n const updated = Array.isArray(v.updated)\n ? v.updated.filter((u: any) => u && u.id != null).map((u: any) => ({ id: String(u.id), before: u.before ?? {} }))\n : [];\n return { created, updated };\n}\n\n/** True when a job can still be undone: it wrote data (undo log present with\n * entries), hasn't already been reverted, and finished in a terminal state. */\nfunction importJobUndoable(row: any): boolean {\n if (row?.reverted_at) return false;\n const status = String(row?.status ?? '');\n if (status !== 'succeeded' && status !== 'cancelled') return false;\n const log = parseUndoLog(row?.undo_log);\n return !!log && (log.created.length > 0 || log.updated.length > 0);\n}\n\n/** Map a persisted `sys_import_job` row to the ImportJobProgress DTO. */\nfunction importJobToProgress(row: any): Record<string, any> {\n const total = Number(row?.total_rows ?? 0);\n const processed = Number(row?.processed_rows ?? 0);\n return {\n undoable: importJobUndoable(row),\n ...(row?.reverted_at ? { revertedAt: String(row.reverted_at) } : {}),\n jobId: String(row?.id ?? ''),\n object: String(row?.object_name ?? ''),\n status: String(row?.status ?? 'pending'),\n dryRun: !!row?.dry_run,\n writeMode: String(row?.write_mode ?? 'insert'),\n total,\n processed,\n created: Number(row?.created_count ?? 0),\n updated: Number(row?.updated_count ?? 0),\n skipped: Number(row?.skipped_count ?? 0),\n errors: Number(row?.error_count ?? 0),\n percentComplete: total > 0 ? Math.min(100, Math.round((processed / total) * 100)) : (processed > 0 ? 100 : 0),\n ...(row?.error ? { error: String(row.error) } : {}),\n ...(row?.started_at ? { startedAt: String(row.started_at) } : {}),\n ...(row?.completed_at ? { completedAt: String(row.completed_at) } : {}),\n createdAt: String(row?.created_at ?? ''),\n };\n}\n\n/** Map a persisted `sys_import_job` row to the ImportJobSummary DTO (list). */\nfunction importJobToSummary(row: any): Record<string, any> {\n const p = importJobToProgress(row);\n return {\n jobId: p.jobId, object: p.object, status: p.status,\n total: p.total, processed: p.processed,\n created: p.created, updated: p.updated, skipped: p.skipped, errors: p.errors,\n createdAt: p.createdAt,\n undoable: p.undoable,\n ...(p.completedAt ? { completedAt: p.completedAt } : {}),\n ...(p.revertedAt ? { revertedAt: p.revertedAt } : {}),\n };\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 ordered\n * list of field names and a (possibly empty) field-metadata map. With metadata,\n * the header row uses field labels and cell values are formatted to readable\n * display values (lookup names, select labels, 是/否, formatted dates). With an\n * empty map the output is byte-identical to the raw, un-formatted behaviour.\n */\nfunction rowsToCsv(\n fields: string[],\n rows: Array<Record<string, any>>,\n includeHeader: boolean,\n metaMap: Map<string, ExportFieldMeta>,\n): string {\n const lines: string[] = [];\n if (includeHeader) lines.push(fields.map(f => formatCsvCell(headerLabel(f, metaMap))).join(','));\n for (const row of rows) {\n lines.push(formatRowCells(row, fields, metaMap).map(formatCsvCell).join(','));\n }\n return lines.join('\\r\\n') + (lines.length > 0 ? '\\r\\n' : '');\n}\n\n/**\n * Bridge exceljs' streaming workbook writer onto the chunked HTTP response.\n *\n * exceljs writes to a Node stream; we pipe a PassThrough's `data` events into\n * `res.write` (which the hono server encodes — strings via TextEncoder, binary\n * Buffers/Uint8Arrays enqueued verbatim) so the xlsx bytes stream straight to\n * the client without buffering the whole workbook in memory. `useStyles:false`\n * keeps the writer lean for large (20k+ row) exports.\n *\n * Returns the worksheet to append rows to and a `finalize()` that commits the\n * workbook and resolves once the last byte has been flushed and the response\n * ended. Dynamically imported so `node:stream` / `exceljs` stay out of the\n * module's static graph.\n */\nasync function createXlsxStream(res: any, useStyles = false): Promise<{\n ws: any;\n finalize: () => Promise<void>;\n}> {\n const { PassThrough } = await import('node:stream');\n const ExcelJS: any = (await import('exceljs')).default ?? (await import('exceljs'));\n\n const passthrough = new PassThrough();\n const done = new Promise<void>((resolve, reject) => {\n passthrough.on('data', (chunk: Buffer) => { res.write(chunk); });\n passthrough.on('end', () => { try { res.end(); } catch { /* swallow */ } resolve(); });\n passthrough.on('error', reject);\n });\n\n const wb = new ExcelJS.stream.xlsx.WorkbookWriter({ stream: passthrough, useStyles });\n const ws = wb.addWorksheet('Export');\n\n return {\n ws,\n finalize: async () => {\n await ws.commit();\n await wb.commit();\n await done;\n },\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 /**\n * Request-scoped memoization for `resolveExecCtx`. A single HTTP request\n * resolves the SAME execution context (identity + RBAC/RLS + localization)\n * many times — the data operation itself, app-nav RBAC filtering, dashboard\n * widget gating, the auth gate, etc. Each resolution is ~16 sequential\n * queries (the `resolveAuthzContext` aggregation plus localization), so a\n * request that resolves twice pays for duplicate authz and repeated\n * localization. Keyed by the per-request `req` object (a `WeakMap`, so the\n * entry is collected with the request — naturally request-scoped, no TTL,\n * no cross-request leak) and the input `environmentId`. We cache the\n * in-flight Promise so concurrent callers share one resolution.\n */\n private readonly execCtxMemo = new WeakMap<object, Map<string, Promise<any | undefined>>>();\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 /** [ADR-0090] `security` service resolver — used by the\n * /security/suggested-bindings (D5/D9) and /security/explain (D6)\n * routes (plugin-security). */\n private securityServiceProvider?: (environmentId?: string) => Promise<any | undefined>;\n /** Sync probe: is a kernel service registered? Single-env path for nav\n * capability gates (ADR-0057 D10) — resolveExecCtx sets no kernel in\n * single-kernel deployments, so this prevents the gate failing open. */\n private serviceExistsProvider?: (name: string) => boolean;\n /**\n * In-flight async import jobs the caller has asked to cancel. The worker\n * checks membership at each progress boundary and stops cooperatively. This\n * is process-local (single-node); the persisted `sys_import_job.status` is\n * the durable source of truth a restarted/other node reads.\n */\n private readonly cancelledImportJobs = new Set<string>();\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 serviceExistsProvider?: (name: string) => boolean,\n securityServiceProvider?: (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 this.serviceExistsProvider = serviceExistsProvider;\n this.securityServiceProvider = securityServiceProvider;\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 // ADR-0069 — authentication-policy gate (password expiry, enforced MFA).\n // Independent of `requireAuth`: a gated session (carrying `authGate`) is\n // blocked from protected resources, while the core allow-list keeps auth\n // + remediation reachable. Runs before the anonymous check.\n const gate = context?.authGate;\n if (gate && req?.method !== 'OPTIONS' && !isAuthGateAllowlisted(req?.path)) {\n res.status(403).json({ error: { code: gate.code, message: gate.message } });\n return true;\n }\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 // Request-scoped memoization — see `execCtxMemo`. The same `req` flows\n // unchanged through every handler call, so its identity keys the memo;\n // the input `environmentId` is part of the key because one host can route\n // multiple environments. Anonymous (`undefined`) resolutions are cached\n // too so repeat callers don't re-run getSession. Fall back to a direct\n // resolve when there is no object to key on.\n if (!req || typeof req !== 'object') return this.computeExecCtx(environmentId, req);\n const key = environmentId ?? '\\u0000default';\n let perReq = this.execCtxMemo.get(req);\n if (!perReq) { perReq = new Map(); this.execCtxMemo.set(req, perReq); }\n const cached = perReq.get(key);\n if (cached) return cached;\n const pending = this.computeExecCtx(environmentId, req);\n perReq.set(key, pending);\n return pending;\n }\n\n /**\n * [ADR-0046 §6.7] The audience-evaluation view of the caller for book/doc\n * gating. `permissionSets` resolves through the security service's\n * `resolvePermissionSetNames` — the SAME resolution as data-plane\n * enforcement (positions expanded, additive baseline), so the docs gate\n * can never drift from it. `permissionSets` stays undefined when the\n * service is absent or resolution fails; `audienceAllows` then DENIES\n * permission-set-gated audiences (fail closed, ADR-0049). Resolution is\n * skipped unless `needPermissionSets` — callers pass true only when a\n * `{ permissionSet }` audience is actually in play.\n */\n private async resolveAudienceCaller(\n environmentId: string | undefined,\n req: any,\n opts: { needPermissionSets: boolean },\n ): Promise<{ authenticated: boolean; permissionSets?: string[] }> {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n const authenticated = !!ctx?.userId;\n if (!authenticated || !opts.needPermissionSets || !this.securityServiceProvider) {\n return { authenticated };\n }\n try {\n const svc = await this.securityServiceProvider(environmentId);\n if (!svc || typeof svc.resolvePermissionSetNames !== 'function') return { authenticated };\n const names = await svc.resolvePermissionSetNames(ctx);\n return { authenticated, permissionSets: Array.isArray(names) ? names : [] };\n } catch {\n return { authenticated }; // unresolved holdings → gated audiences deny\n }\n }\n\n /** Whether any of these books carries a `{ permissionSet }` audience. */\n private static anyPermissionSetAudience(books: readonly any[]): boolean {\n return books.some(\n (b) => b && typeof b === 'object' && b.audience && typeof b.audience === 'object'\n && typeof b.audience.permissionSet === 'string',\n );\n }\n\n /** Coerce a getMetaItems result (array | {items}) into an array. */\n private static metaItemsArray(raw: unknown): any[] {\n if (Array.isArray(raw)) return raw;\n if (raw && typeof raw === 'object' && Array.isArray((raw as any).items)) return (raw as any).items;\n return [];\n }\n\n /** Fetch every book of the environment, shaped for the audience resolver. */\n private async fetchAudienceBooks(p: any, environmentId: string | undefined): Promise<any[]> {\n const raw = await p.getMetaItems({\n type: 'book',\n ...(environmentId ? { environmentId } : {}),\n } as any).catch(() => []);\n return RestServer.metaItemsArray(raw).map((b: any) =>\n b && typeof b === 'object' ? { ...b, packageId: b._packageId } : b,\n );\n }\n\n /** Heavy path behind `resolveExecCtx` — resolve identity + RBAC/RLS + localization. */\n private async computeExecCtx(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 // Resolve the data engine for this scope (shared by the resolver below).\n const ql: any = kernel\n ? await kernel.getServiceAsync('objectql').catch(() => undefined)\n : (this.objectQLProvider ? await this.objectQLProvider(environmentId).catch(() => undefined) : undefined);\n\n // Delegate ALL identity + role/permission/RLS aggregation to the SINGLE\n // shared resolver (`resolveAuthzContext`, @objectstack/core) — the same one\n // the runtime dispatcher uses, so the REST and dispatcher entry points can\n // never drift on authorization. (This path previously kept its own copy that\n // silently omitted sys_user_position / sys_position_permission_set / platform_admin /\n // ai_seat — see the resolver's module doc.)\n const getSession = async (h: any) => {\n try { return await api.getSession({ headers: h }); } catch { return undefined; }\n };\n const authz = await resolveAuthzContext({ ql, headers, getSession });\n if (!authz.userId) return undefined;\n\n const settings = this.settingsServiceProvider\n ? await this.settingsServiceProvider(environmentId).catch(() => undefined)\n : undefined;\n const localization = await resolveLocalizationContext({\n ql,\n settings,\n tenantId: authz.tenantId,\n userId: authz.userId,\n });\n\n // ADR-0069 — authentication-policy gate posture. Only when a gate\n // feature is active (cheap sync check) do we re-read the session for\n // its `user.authGate` (computed in customSession). enforceAuth() then\n // blocks protected resources for a gated user. Zero cost when off.\n let authGate: any;\n try {\n if (typeof authService.isAuthGateActive === 'function' && authService.isAuthGateActive()) {\n const gatedSession: any = await getSession(headers).catch(() => undefined);\n if (gatedSession?.user?.authGate) authGate = gatedSession.user.authGate;\n }\n } catch { /* gate is best-effort — never break context resolution */ }\n\n return {\n userId: authz.userId,\n tenantId: authz.tenantId,\n email: authz.email,\n positions: authz.positions,\n permissions: authz.permissions,\n systemPermissions: authz.systemPermissions,\n ...(authz.tabPermissions ? { tabPermissions: authz.tabPermissions } : {}),\n isSystem: false,\n org_user_ids: authz.org_user_ids,\n ...(authGate ? { authGate } : {}),\n ...(localization.timezone ? { timezone: localization.timezone } : {}),\n ...(localization.locale ? { locale: localization.locale } : {}),\n ...(localization.currency ? { currency: localization.currency } : {}),\n // Internal: resolved kernel so the nav-serving path can probe\n // requiresService capability gates (ADR-0057 D10). NOT an\n // authorization input — never read by RLS/permission logic.\n __kernel: kernel,\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>, serviceGate?: (name: string) => boolean): any | null {\n if (!item || typeof item !== 'object') return item;\n // getMetaItem returns an envelope { type, name, item: <app>, ... } while the\n // list path passes the raw app. Unwrap + re-wrap so gating runs on both —\n // filtering the envelope directly is a silent no-op (its .navigation is\n // undefined), which would bypass BOTH requiredPermissions and the ADR-0057\n // D10 requiresService gate.\n if (isMetaEnvelope(item)) {\n const body = this.filterAppForUser((item as any).item, sysPerms, serviceGate);\n return body == null ? null : { ...(item as any), item: body };\n }\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 // ADR-0057 D10 — capability gate: hide when the named kernel service is\n // absent. Fail-open when the gate can't be probed (serviceGate undefined).\n if (typeof item.requiresService === 'string' && serviceGate && serviceGate(item.requiresService) === false) {\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 (typeof e.requiresService === 'string' && serviceGate && serviceGate(e.requiresService) === false) 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 * ADR-0057 D10 (dashboards): strip dashboard widgets whose `requiresService`\n * capability gate names a kernel service that isn't registered — the same\n * \"server is the authoritative visibility gate\" rule already applied to app\n * nav entries (see {@link filterAppForUser}). Without this, a widget bound to\n * an optional service renders a dead tile in deployments where the service is\n * off (e.g. the Organizations KPI under multi-tenant `org-scoping`, which is\n * absent in a single-tenant runtime while its nav entry is correctly hidden).\n *\n * Fail-open when the gate can't be probed (serviceGate undefined). Never\n * mutates the original — returns a shallow copy only when a widget is dropped.\n */\n private filterDashboardForUser(item: any, serviceGate?: (name: string) => boolean): any {\n if (!item || typeof item !== 'object' || !serviceGate) return item;\n if (isMetaEnvelope(item)) {\n const body = this.filterDashboardForUser((item as any).item, serviceGate);\n return body === (item as any).item ? item : { ...(item as any), item: body };\n }\n if (!Array.isArray(item.widgets)) return item;\n const widgets = item.widgets.filter(\n (w: any) => !(w && typeof w.requiresService === 'string' && serviceGate(w.requiresService) === false),\n );\n return widgets.length === item.widgets.length ? item : { ...item, widgets };\n }\n\n /**\n * Probe which `requiresService` capability gates referenced anywhere in\n * `items` are actually registered in the runtime kernel. Returns `null`\n * when the kernel can't be probed — callers then SKIP service gating\n * (fail-open, matching the prior \"send everything, let the client hide\"\n * behaviour). ADR-0057 addendum D10.\n */\n private async resolveRegisteredServices(kernel: any, items: any[]): Promise<Set<string> | null> {\n // Prefer the per-request kernel (multi-env, resolved via kernelManager).\n // Fall back to the single-env service-existence provider — in single-kernel\n // deployments resolveExecCtx never sets a kernel, so without this the gate\n // would fail open (ADR-0057 D10).\n let probe: ((name: string) => Promise<boolean>) | null = null;\n if (kernel && typeof kernel.getServiceAsync === 'function') {\n probe = async (name) => { try { return (await kernel.getServiceAsync(name)) != null; } catch { return false; } };\n } else if (this.serviceExistsProvider) {\n const exists = this.serviceExistsProvider;\n probe = async (name) => { try { return exists(name) === true; } catch { return false; } };\n }\n if (!probe) return null;\n const wanted = new Set<string>();\n const walk = (e: any): void => {\n if (!e || typeof e !== 'object') return;\n if (isMetaEnvelope(e)) { walk((e as any).item); return; }\n if (typeof e.requiresService === 'string') wanted.add(e.requiresService);\n const kids = Array.isArray(e.navigation) ? e.navigation\n : Array.isArray(e.children) ? e.children\n // Dashboard widgets carry their own `requiresService` gate.\n : Array.isArray(e.widgets) ? e.widgets : null;\n if (kids) for (const k of kids) walk(k);\n };\n for (const it of items) walk(it);\n if (wanted.size === 0) return new Set();\n const registered = new Set<string>();\n for (const name of wanted) { if (await probe(name)) registered.add(name); }\n return registered;\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 // A missing bundle is NOT a bail-out: `translateMetadataDocument`\n // still applies built-in fallbacks (e.g. the injected system-field\n // labels `owner_id`/`created_*`/`updated_*` on custom objects, which\n // ship no per-object translation entries).\n const bundle = this.buildTranslationBundle(i18n);\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 // Missing bundle ≠ bail-out — see `translateMetaItem`.\n const bundle = this.buildTranslationBundle(i18n);\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 ?? true, // secure-by-default (ADR-0056 D2; mirrors RestApiConfigSchema)\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 this.registerSecurityEndpoints(bp);\n this.registerSecurityExplainEndpoints(bp);\n // Data-action routes (e.g. GET /data/:object/export, POST\n // /data/:object/import) use static-literal action segments that\n // MUST be registered BEFORE the greedy GET /data/:object/:id\n // matcher in registerCrudEndpoints — the router is first-match-wins\n // with no specificity sorting (see route-manager.ts), so otherwise\n // a request to `.../export` is captured by `:id` and \"export\" is\n // treated as a record id (404 RECORD_NOT_FOUND). This mirrors the\n // /meta/:type/:name/references-before-/meta/:type/:name convention.\n // Safe in the other direction too: registerDataActionEndpoints has\n // no greedy 2-segment `:object/:id` routes (only literal actions and\n // deeper `:id/clone`, `:id/shares` paths), so it cannot shadow any\n // CRUD literal.\n this.registerDataActionEndpoints(bp);\n if (this.config.api.enableCrud) {\n this.registerCrudEndpoints(bp);\n }\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 a default-on core capability —\n // advertise it unless OS_MCP_SERVER_ENABLED=false opts the\n // env out, so the objectui Integrations page surfaces the\n // connect card. The /mcp route is mounted bare (not\n // project-scoped), so point at the unscoped base. This\n // `/discovery` (served by @objectstack/rest) is separate\n // from the dispatcher's getDiscoveryInfo — both must\n // advertise `mcp` (single source: isMcpServerEnabled).\n if (isMcpServerEnabled()) {\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 the metadata routes behind the SAME `requireAuth` gate the\n * `/data` routes use.\n *\n * `registerMetadataEndpoints` builds ~17 `/meta/*` routes but — unlike the\n * `/data` handlers — never calls {@link enforceAuth}: its handlers assumed\n * the `requireAuth` gate rejected anonymous callers \"upstream\", yet nothing\n * upstream covers `/meta`, so on a `requireAuth` deployment an anonymous\n * caller could read object / field schemas. On a tenant-less runtime host\n * those are SYSTEM-object schemas and the host is publicly reachable — a\n * real leak.\n *\n * Rather than add the gate to every handler (and have the next new route\n * forget it — the exact failure mode that caused this), wrap the route\n * registrar for the duration of registration so every meta route, present\n * and future, inherits it. The check is a no-op when `requireAuth` is off\n * (demo / single-tenant), so the previously-public metadata surface there\n * is unchanged; an authenticated user passes exactly as on `/data`.\n */\n private registerMetadataEndpoints(basePath: string): void {\n const realRouteManager = this.routeManager;\n const guardedRouteManager = {\n register: (entry: { handler: unknown; [k: string]: unknown }) => {\n const inner = entry.handler;\n if (typeof inner !== 'function') return realRouteManager.register(entry as any);\n return realRouteManager.register({\n ...entry,\n handler: async (req: any, res: any) => {\n // `req.params.environmentId` is present only on the\n // scoped `/environments/:id/meta/...` variant — mirrors\n // the `isScoped ? req.params.environmentId : undefined`\n // each `/data` handler derives.\n const environmentId = req?.params?.environmentId;\n const context = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n if (this.enforceAuth(req, res, context)) return;\n return (inner as (rq: any, rs: any) => unknown)(req, res);\n },\n } as any);\n },\n } as unknown as RouteManager;\n this.routeManager = guardedRouteManager;\n try {\n this.registerMetadataEndpointsInner(basePath);\n } finally {\n this.routeManager = realRouteManager;\n }\n }\n\n private registerMetadataEndpointsInner(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 registered = await this.resolveRegisteredServices((ctx as any).__kernel, list);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n const filtered = list\n .map((it: any) => this.filterAppForUser(it, sysPerms, serviceGate))\n .filter((it: any) => it != null);\n visible = Array.isArray(raw)\n ? filtered\n : { ...(raw as any), items: filtered };\n }\n }\n }\n\n // ADR-0057 D10: gate dashboard widgets by `requiresService`\n // the same way app nav entries are gated above.\n if (req.params.type === 'dashboard') {\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 ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n const registered = await this.resolveRegisteredServices((ctx as any)?.__kernel, list);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n if (serviceGate) {\n const filtered = list.map((it: any) => this.filterDashboardForUser(it, serviceGate));\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 §6.7 — book list is audience-filtered: anonymous\n // callers see only `public` books; `{ permissionSet }`-gated\n // books require the caller to hold the named set (resolved\n // through the security service; unresolvable → fail closed).\n if (req.params.type === 'book') {\n const raw = visible as unknown;\n const list = RestServer.metaItemsArray(raw);\n if (list.length > 0) {\n const { audienceAllows } = await import('@objectstack/spec/system');\n const caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience(list),\n });\n const filtered = list.filter((b: any) =>\n b && typeof b === 'object' && audienceAllows((b as any).audience, caller));\n visible = Array.isArray(raw) ? filtered : { ...(raw as any), items: filtered };\n }\n }\n\n // ADR-0046 §6.7 — doc list is audience-filtered by each\n // doc's EFFECTIVE audience (union over the books that\n // claim it; unclaimed docs default to `org`). Runs on the\n // raw items (before locale collapse) so `_packageId`\n // provenance is still present for membership scoping.\n if (req.params.type === 'doc') {\n const raw = visible as unknown;\n const list = RestServer.metaItemsArray(raw);\n if (list.length > 0) {\n const { audienceAllows, docAudienceAllows, resolveDocAudiences } =\n await import('@objectstack/spec/system');\n const books = await this.fetchAudienceBooks(p, environmentId);\n const caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience(books),\n });\n let filtered: any[];\n if (caller.authenticated && !RestServer.anyPermissionSetAudience(books)) {\n // Fast path: with no gated book anywhere, every\n // effective audience admits an authenticated caller.\n filtered = list;\n } else {\n const corpus = list\n .filter((d: any) => d && typeof d === 'object')\n .map((d: any) => ({\n name: d.name,\n group: d.group,\n tags: d.tags,\n order: d.order,\n packageId: d._packageId,\n }));\n const audiences = resolveDocAudiences(books as any, corpus);\n filtered = list.filter((d: any) => {\n if (!d || typeof d !== 'object') return false;\n const eff = audiences.get(d.name);\n return eff\n ? docAudienceAllows(eff, caller)\n : audienceAllows('org', caller);\n });\n }\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, audienceAllows, resolveDocAudiences, docAudienceAllows, 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 — the book's audience gates the whole tree:\n // anonymous → `public` only; `{ permissionSet }` →\n // the caller must hold the named set (fail closed\n // when holdings cannot be resolved, ADR-0049).\n const audienceBooks = books.map((b: any) =>\n b && typeof b === 'object' ? { ...b, packageId: b._packageId } : b);\n const caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience([book, ...audienceBooks]),\n });\n if (!audienceAllows((book as any).audience, caller)) {\n if (!caller.authenticated) {\n sendError(res, { code: 'unauthorized', message: 'This documentation requires sign-in', status: 401 });\n } else {\n sendError(res, { code: 'PERMISSION_DENIED', message: 'This documentation is limited to holders of a permission set you do not have', status: 403 });\n }\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\n // §6.7 — the tree's ENTRIES are additionally filtered by\n // each doc's effective audience (union over claiming\n // books, unclaimed → org), so an anonymous reader of a\n // public book never sees nav entries that would 401 on\n // fetch, and gated-only docs stay out of non-holders'\n // trees. The book gate above passed, so this only ever\n // narrows further for anonymous / non-holder callers.\n const gatedTreePossible = !caller.authenticated\n || RestServer.anyPermissionSetAudience(audienceBooks);\n if (gatedTreePossible) {\n const audiences = resolveDocAudiences(audienceBooks as any, docs);\n tree.groups = tree.groups\n .map((g: any) => ({\n ...g,\n entries: g.entries.filter((e: any) =>\n !e.doc || docAudienceAllows(audiences.get(e.doc), caller)),\n }))\n .filter((g: any) => g.entries.some((e: any) => e.doc || e.href));\n }\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 // `doc` and `book` bypass the shared cache: their §6.7\n // audience gate is per-caller, and a shared ETag would\n // leak gated content across viewers.\n if (metadata.enableCache && p.getMetaItemCached && !isAppType && !isDraftRead && !previewDrafts && !packageScoped && req.params.type !== 'doc' && req.params.type !== 'book') {\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 // `max-age` is a placeholder directive in the\n // array; its real value is appended from the\n // `maxAge` field. Strip the bare token before\n // joining so the two never collide into the\n // malformed `public, max-age, max-age=3600`.\n const parts: string[] = result.cacheControl.directives\n .filter((d: string) => d !== 'max-age');\n if (result.cacheControl.maxAge != null) {\n parts.push(`max-age=${result.cacheControl.maxAge}`);\n }\n res.header('Cache-Control', parts.join(', '));\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 const registered = await this.resolveRegisteredServices((ctx as any).__kernel, [item]);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n visible = this.filterAppForUser(item, sysPerms, serviceGate);\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-0057 D10: gate dashboard widgets by `requiresService`\n // (mirrors the app-nav gate above) so the console never\n // renders a tile bound to an absent optional service.\n if (req.params.type === 'dashboard' && visible) {\n const ctx = await this.resolveExecCtx(environmentId, req).catch(() => undefined);\n const registered = await this.resolveRegisteredServices((ctx as any)?.__kernel, [visible]);\n const serviceGate = registered ? (n: string) => registered.has(n) : undefined;\n if (serviceGate) visible = this.filterDashboardForUser(visible, serviceGate);\n }\n\n // ADR-0046 §6.7 — audience gate on single-item reads.\n // A `book` is gated by its own audience; a `doc` by its\n // EFFECTIVE audience (union over the books that claim\n // it, unclaimed → org). 401 for anonymous, 403 for an\n // authenticated non-holder; fail closed when holdings\n // cannot be resolved (ADR-0049).\n if ((req.params.type === 'book' || req.params.type === 'doc') && visible) {\n const { audienceAllows, docAudienceAllows, resolveDocAudiences } =\n await import('@objectstack/spec/system');\n const target = isMetaEnvelope(visible) ? (visible as any).item : visible;\n let caller: { authenticated: boolean; permissionSets?: string[] };\n let allowed: boolean;\n if (req.params.type === 'book') {\n caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience([target]),\n });\n allowed = audienceAllows(target?.audience, caller);\n } else {\n const books = await this.fetchAudienceBooks(p, environmentId);\n caller = await this.resolveAudienceCaller(environmentId, req, {\n needPermissionSets: RestServer.anyPermissionSetAudience(books),\n });\n if (caller.authenticated && !RestServer.anyPermissionSetAudience(books)) {\n allowed = true; // no gated book anywhere → org suffices\n } else {\n const corpus = RestServer.metaItemsArray(await p.getMetaItems({\n type: 'doc',\n ...(environmentId ? { environmentId } : {}),\n } as any).catch(() => []))\n .filter((d: any) => d && typeof d === 'object')\n .map((d: any) => ({\n name: d.name,\n group: d.group,\n tags: d.tags,\n order: d.order,\n packageId: d._packageId,\n }));\n const audiences = resolveDocAudiences(books as any, corpus);\n allowed = docAudienceAllows(audiences.get(target?.name), caller);\n }\n }\n if (!allowed) {\n if (!caller.authenticated) {\n sendError(res, { code: 'unauthorized', message: 'This documentation requires sign-in', status: 401 });\n } else {\n sendError(res, { code: 'PERMISSION_DENIED', message: 'This documentation is limited to holders of a permission set you do not have', status: 403 });\n }\n return;\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\n // Parse + validate the payload (shared with the async job route).\n // The synchronous path caps at 5k rows; larger files must use the\n // async import-job endpoint.\n const prep = await prepareImportRequest(body, {\n p, objectName, environmentId, maxRows: 5000,\n // Accept locale-translated option labels (what the localized\n // export / import template contain) as select-cell synonyms.\n localizeSchema: (schema: any) => this.translateMetaItem(req, 'object', environmentId, schema),\n });\n if (!prep.ok) {\n if (prep.status === 413) prep.error += ' Use an async import job for larger files.';\n res.status(prep.status).json({ code: prep.code, error: prep.error });\n return;\n }\n const { rows, writeMode, dryRun } = prep.prepared;\n\n // Delegate the per-row coercion + upsert loop to the shared\n // runner (also used by the async import-job worker).\n const summary = await runImport({\n p, objectName, environmentId, context, ...prep.prepared,\n });\n\n res.json({\n object: objectName,\n dryRun,\n writeMode,\n total: rows.length,\n ok: summary.ok,\n errors: summary.errors,\n created: summary.created,\n updated: summary.updated,\n skipped: summary.skipped,\n results: summary.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 // ── Asynchronous import jobs (P1) ──────────────────────────────────\n //\n // For files too large for the synchronous route (up to 50k rows), the\n // client POSTs the whole payload once; the server persists a\n // `sys_import_job`, responds immediately with a jobId, then processes\n // the batch in the background — updating progress on the job row as it\n // streams. Callers poll progress/results and list history. These routes\n // are registered inside registerDataActionEndpoints (before the greedy\n // CRUD `:object/:id`), so the literal `import/jobs` segments win.\n\n // POST /data/:object/import/jobs — create an async import job.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/:object/import/jobs`,\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\n const prep = await prepareImportRequest(req.body ?? {}, {\n p, objectName, environmentId, maxRows: IMPORT_JOB_MAX_ROWS,\n // Same round-trip i18n synonyms as the synchronous route.\n localizeSchema: (schema: any) => this.translateMetaItem(req, 'object', environmentId, schema),\n });\n if (!prep.ok) {\n if (prep.status === 413) prep.error += ` This is the async import ceiling; split the file into batches of ${IMPORT_JOB_MAX_ROWS}.`;\n res.status(prep.status).json({ code: prep.code, error: prep.error });\n return;\n }\n const prepared = prep.prepared;\n\n const jobId = newImportJobId();\n const createdAt = new Date().toISOString();\n const createdBy = String((context as any)?.userId ?? (context as any)?.user?.id ?? '') || undefined;\n const jobRow: Record<string, any> = {\n id: jobId,\n object_name: objectName,\n status: 'pending',\n total_rows: prepared.rows.length,\n processed_rows: 0,\n created_count: 0,\n updated_count: 0,\n skipped_count: 0,\n error_count: 0,\n write_mode: prepared.writeMode,\n dry_run: prepared.dryRun,\n run_automations: prepared.runAutomations,\n created_at: createdAt,\n ...(createdBy ? { created_by: createdBy } : {}),\n };\n\n try {\n await (p as any).createData({ object: IMPORT_JOB_OBJECT, data: jobRow, context, ...(environmentId ? { environmentId } : {}) });\n } catch (err: any) {\n logError('[REST] Failed to persist import job:', err);\n res.status(500).json({ code: 'IMPORT_JOB_CREATE_FAILED', error: 'Could not create import job' });\n return;\n }\n\n // Respond immediately; process in the background.\n res.status(201).json({ jobId, object: objectName, status: 'pending', total: prepared.rows.length, createdAt });\n\n // Background worker. Fire-and-forget: it owns its own error\n // handling and persists terminal state to the job row.\n const patch = async (data: Record<string, any>) => {\n try {\n await (p as any).updateData({ object: IMPORT_JOB_OBJECT, id: jobId, data, context, ...(environmentId ? { environmentId } : {}) });\n } catch (err) {\n logError('[REST] import job progress write failed:', err);\n }\n };\n // Record undo instructions for small non-dry-run jobs so the\n // import can be logically rolled back later.\n const captureUndo = !prepared.dryRun && prepared.rows.length <= IMPORT_JOB_UNDO_MAX_ROWS;\n void (async () => {\n await patch({ status: 'running', started_at: new Date().toISOString() });\n try {\n const summary = await runImport({\n p, objectName, environmentId, context, ...prepared,\n captureUndo,\n progressEvery: 200,\n onProgress: (pr) => patch({\n processed_rows: pr.processed,\n created_count: pr.created,\n updated_count: pr.updated,\n skipped_count: pr.skipped,\n error_count: pr.errors,\n }),\n shouldCancel: () => this.cancelledImportJobs.has(jobId),\n });\n await patch({\n status: summary.cancelled ? 'cancelled' : 'succeeded',\n processed_rows: summary.processed,\n created_count: summary.created,\n updated_count: summary.updated,\n skipped_count: summary.skipped,\n error_count: summary.errors,\n results: capImportResults(summary.results),\n completed_at: new Date().toISOString(),\n ...(summary.undoLog ? { undo_log: summary.undoLog } : {}),\n });\n } catch (err: any) {\n await patch({\n status: 'failed',\n error: String(err?.message ?? err).slice(0, 1000),\n completed_at: new Date().toISOString(),\n });\n } finally {\n this.cancelledImportJobs.delete(jobId);\n }\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: 'Create an asynchronous import job (large files, up to 50k rows)',\n tags: ['data', 'import'],\n },\n });\n\n // Shared loader for the read routes: fetch one job row by id.\n const loadImportJob = async (p: any, jobId: string, environmentId?: string, context?: any): Promise<any | undefined> => {\n const r = await p.findData({\n object: IMPORT_JOB_OBJECT,\n query: { $filter: { id: jobId }, $top: 1 },\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n const rows = Array.isArray(r?.records) ? r.records\n : Array.isArray(r?.data) ? r.data\n : Array.isArray(r?.rows) ? r.rows\n : Array.isArray(r) ? r : [];\n return rows[0];\n };\n\n // POST /data/import/jobs/:jobId/cancel — request cancellation.\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/import/jobs/:jobId/cancel`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n const status = String(row.status ?? '');\n if (status === 'pending' || status === 'running') {\n // Signal the in-process worker and mark the durable row.\n this.cancelledImportJobs.add(jobId);\n try {\n await (p as any).updateData({ object: IMPORT_JOB_OBJECT, id: jobId, data: { status: 'cancelled', completed_at: new Date().toISOString() }, context, ...(environmentId ? { environmentId } : {}) });\n } catch { /* worker will still stop via the in-memory flag */ }\n }\n res.json({ success: true });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Cancel an in-flight import job', tags: ['data', 'import'] },\n });\n\n // POST /data/import/jobs/:jobId/undo — logical rollback of a finished\n // job: delete the records it created and restore the fields it updated\n // to their pre-import values (from the captured undo log).\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/import/jobs/:jobId/undo`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n if (row.reverted_at) {\n res.status(409).json({ code: 'ALREADY_REVERTED', error: 'This import has already been undone' });\n return;\n }\n if (!importJobUndoable(row)) {\n res.status(422).json({ code: 'NOT_UNDOABLE', error: 'This import cannot be undone (too large, still running, or nothing was written)' });\n return;\n }\n const objectName = String(row.object_name ?? '');\n const log = parseUndoLog(row.undo_log)!;\n // Undo automations too: reversing writes shouldn't re-fire triggers.\n const writeCtx = { ...(context ?? {}), skipAutomations: true };\n let deleted = 0, restored = 0, failed = 0;\n\n // Delete created records first (they didn't exist before).\n for (const id of log.created) {\n try {\n await (p as any).deleteData({ object: objectName, id, context: writeCtx, ...(environmentId ? { environmentId } : {}) });\n deleted++;\n } catch { failed++; }\n }\n // Restore the touched fields on updated records.\n for (const u of log.updated) {\n try {\n await (p as any).updateData({ object: objectName, id: u.id, data: u.before, context: writeCtx, ...(environmentId ? { environmentId } : {}) });\n restored++;\n } catch { failed++; }\n }\n\n await (p as any).updateData({\n object: IMPORT_JOB_OBJECT, id: jobId,\n data: { reverted_at: new Date().toISOString() },\n context, ...(environmentId ? { environmentId } : {}),\n });\n res.json({ success: true, jobId, object: objectName, deleted, restored, failed });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Undo (logically roll back) a finished import job', tags: ['data', 'import'] },\n });\n\n // GET /data/import/jobs/:jobId/results — progress + capped per-row report.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/import/jobs/:jobId/results`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n const stored = row.results;\n const items = Array.isArray(stored?.items) ? stored.items : Array.isArray(stored) ? stored : [];\n res.json({ ...importJobToProgress(row), results: items, resultsTruncated: !!stored?.truncated });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Import job results (capped per-row report)', tags: ['data', 'import'] },\n });\n\n // GET /data/import/jobs/:jobId — live progress counters.\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/import/jobs/:jobId`,\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 jobId = String(req.params.jobId || '');\n const row = await loadImportJob(p, jobId, environmentId, context);\n if (!row) {\n res.status(404).json({ code: 'NOT_FOUND', error: `No import job ${jobId}` });\n return;\n }\n res.json(importJobToProgress(row));\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'Import job progress', tags: ['data', 'import'] },\n });\n\n // GET /data/import/jobs — history list (newest first).\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/import/jobs`,\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 q = req.query ?? {};\n const filter: Record<string, any> = {};\n if (typeof q.object === 'string' && q.object) filter.object_name = q.object;\n if (typeof q.status === 'string' && q.status) filter.status = q.status;\n const limit = Math.min(200, Math.max(1, Number(q.limit) || 50));\n const offset = Math.max(0, Number(q.offset) || 0);\n const r = await (p as any).findData({\n object: IMPORT_JOB_OBJECT,\n query: { $filter: filter, $orderby: { created_at: 'desc' }, $top: limit, $skip: offset },\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n const rows = Array.isArray(r?.records) ? r.records\n : Array.isArray(r?.data) ? r.data\n : Array.isArray(r?.rows) ? r.rows\n : Array.isArray(r) ? r : [];\n res.json({ jobs: rows.map(importJobToSummary) });\n } catch (error: any) {\n logError('[REST] Unhandled error:', error);\n sendError(res, error, '');\n }\n },\n metadata: { summary: 'List import jobs (history)', tags: ['data', 'import'] },\n });\n\n // GET /data/:object/export — streaming export (M10.21 / C.21)\n //\n // Query params:\n // format=csv|json|xlsx (default: csv. json emits a JSON array, xlsx a workbook.)\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 // header=false (omit the header row for csv / xlsx; default true)\n // limit=<n> (default 10000, hard cap 50000)\n // page=<n> (driver chunk size, default 500, max 5000)\n //\n // Values are formatted for readability from the object schema: lookup /\n // user fields resolve to a name (via injected $expand), select fields to\n // their option label, booleans to 是/否, dates to YYYY-MM-DD. When the\n // schema is unavailable the raw stored values stream through unchanged.\n //\n // Streams the response so 50k-row exports do not buffer in memory; the\n // xlsx path pipes exceljs' streaming writer straight onto the response.\n // Filename suggests `${objectLabel}-${YYYYMMDD}-${HHMMSS}.${ext}` for\n // browsers (localized label via RFC 5987 `filename*`, ASCII fallback\n // from the API name — see exportContentDisposition).\n //\n // xlsx only: select / radio cells are coloured with their option's\n // `color` as the font colour (white cell background) when the effective\n // limit is <= 10000. Larger exports drop styling for performance and set\n // `X-Export-Styles: dropped` (else `applied`); csv / json are unaffected.\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 fmtRaw = String(q.format ?? 'csv').toLowerCase();\n const format: 'csv' | 'json' | 'xlsx' =\n fmtRaw === 'json' ? 'json' : fmtRaw === 'xlsx' ? 'xlsx' : 'csv';\n // Header row toggle (csv / xlsx). Default on; `header=false` omits it.\n const includeHeader = String(q.header ?? 'true').toLowerCase() !== 'false';\n const HARD_CAP = 50_000;\n const MAX_CHUNK = 5_000;\n // Styled xlsx (per-cell font colour from select options) is far\n // heavier than a bare value dump, so cap it well below HARD_CAP;\n // above this the export still succeeds, just without colours.\n const STYLE_ROW_CAP = 10_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 // Colour cells only for xlsx within the style cap; decided up\n // front (before streaming) since we can't know the true row\n // count until the stream drains.\n const styled = format === 'xlsx' && limit <= STYLE_ROW_CAP;\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\n // Field metadata drives readable formatting (lookup names, select\n // labels, 是/否, formatted dates) and the $expand that resolves\n // references. Best-effort: when the schema is unavailable the export\n // falls back to raw values, byte-identical to the un-formatted path.\n let metaMap = new Map<string, ExportFieldMeta>();\n // Localized object display label (e.g. 合同) — drives the\n // suggested download filename below.\n let objectLabel: string | undefined;\n try {\n // Field metadata comes from the same place `findData` resolves\n // the object: `getMetaItem` is registry-first (DB fallback), so\n // it returns the live `ObjectSchema` whose `fields` is an object\n // map. The read hands back an envelope `{ type, name, item }`;\n // the schema document lives at `.item` (a cached/bare read may\n // already be unwrapped). Legacy `getObjectSchema` is consulted\n // as a last resort so existing test doubles keep working.\n let schema: any = undefined;\n if (typeof (p as any).getMetaItem === 'function') {\n const res = await (p as any).getMetaItem({ type: 'object', name: objectName });\n schema = isMetaEnvelope(res) ? res.item : res;\n }\n if (!schema && typeof (p as any).getObjectSchema === 'function') {\n schema = await (p as any).getObjectSchema(objectName, environmentId);\n }\n // Localize field labels to the request locale (Accept-Language /\n // `?locale=`) the same way the metadata endpoints do, so the\n // export header row matches the UI column headers instead of\n // leaking the raw, untranslated `field.label` values.\n schema = await this.translateMetaItem(req, 'object', environmentId, schema);\n if (typeof schema?.label === 'string' && schema.label.length > 0) {\n objectLabel = schema.label;\n }\n metaMap = buildFieldMetaMap(schema);\n if (!fields || fields.length === 0) {\n const names = [...metaMap.keys()];\n if (names.length > 0) fields = names;\n }\n } catch { /* fall back to first-row derivation + raw values */ }\n\n // Expand reference fields so lookup/user ids resolve to their record\n // (and thus a name). Batched $in inside findData — no N+1.\n const expandFields = referenceFieldNames(metaMap);\n\n // Prepare streaming response. Set headers BEFORE first write.\n if (format === 'csv') {\n res.header('Content-Type', 'text/csv; charset=utf-8');\n } else if (format === 'xlsx') {\n res.header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');\n } else {\n res.header('Content-Type', 'application/json; charset=utf-8');\n }\n res.header('Content-Disposition', exportContentDisposition(objectName, objectLabel, format));\n res.header('X-Export-Format', format);\n res.header('X-Export-Limit', String(limit));\n // Signal whether select-option colours were applied. Only\n // meaningful for xlsx; 'dropped' means the limit exceeded the\n // style cap so the workbook is colourless but complete.\n if (format === 'xlsx') res.header('X-Export-Styles', styled ? 'applied' : 'dropped');\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 const xlsx = format === 'xlsx' ? await createXlsxStream(res, styled) : null;\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 ...(expandFields.length > 0 ? { $expand: expandFields.join(',') } : {}),\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 // `findData` returns `{ object, records, total, hasMore }`;\n // accept the legacy `data` / `rows` aliases and a bare array\n // so test doubles and alternate protocols keep working.\n const rows: any[] = Array.isArray(result?.records) ? result.records\n : 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 // 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\n if (format === 'csv') {\n const text = rowsToCsv(fields ?? [], rows, firstChunk && includeHeader, metaMap);\n res.write(text);\n } else if (format === 'xlsx') {\n if (firstChunk && includeHeader) {\n xlsx!.ws.addRow((fields ?? []).map((f) => headerLabel(f, metaMap))).commit();\n }\n const cols = fields ?? [];\n for (const row of rows) {\n const r = xlsx!.ws.addRow(formatRowCells(row, cols, metaMap));\n if (styled) {\n cols.forEach((f, i) => {\n const argb = cellFontColor(row?.[f], metaMap.get(f));\n if (argb) r.getCell(i + 1).font = { color: { argb } };\n });\n }\n r.commit();\n }\n } else {\n for (let i = 0; i < rows.length; i++) {\n const prefix = (firstChunk && i === 0) ? '' : ',';\n res.write(prefix + JSON.stringify(formatRowForJson(rows[i], metaMap)));\n }\n }\n firstChunk = false;\n exported += rows.length;\n skip += rows.length;\n if (rows.length < take) break;\n }\n if (format === 'json') {\n res.write(']');\n res.end();\n } else if (format === 'xlsx') {\n await xlsx!.finalize();\n } else {\n res.end();\n }\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, JSON, or XLSX)',\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 // `user` is a lookup specialized to sys_user — same risk as a\n // raw lookup: surfacing it on an anonymous public form would\n // expose unrestricted user search to the internet. Gate it\n // behind the same `publicPicker` opt-in.\n if (t !== 'lookup' && t !== 'master_detail' && t !== 'user') 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 // ADR-0056 (Option A): authorization DERIVED from the declared\n // form — a narrow create grant scoped to exactly this form's target\n // object. The SecurityPlugin honors `publicFormGrant` (create + the\n // immediate read-back, that object ONLY), so public forms work under\n // secure-by-default (requireAuth) WITHOUT a deployment-configured\n // `guest_portal`. `guest_portal` + `anonymous` are kept for back-compat\n // with object hooks (guest detection via falsy `ctx.user?.id`).\n const context: any = {\n publicFormGrant: { object: match.object },\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 /**\n * [ADR-0090 D6] Access-explanation endpoint — the REST face of the\n * explain engine (framework#2696).\n *\n * GET {basePath}/security/explain?object=…&operation=…&userId=…\n * POST {basePath}/security/explain body: { object, operation, userId? }\n *\n * Delegates to the security service's `explain(request, callerContext)`\n * (`SecurityPlugin.explainAccessForCaller`) — the same code paths the\n * enforcement middleware runs, so the report is explained by\n * construction. Caller authorization lives in the SERVICE, not here:\n * explaining ANOTHER user requires `manage_users` or a delegated\n * `adminScope` covering that user (D12); the service's\n * `PermissionDeniedError` maps to 403. The route itself only insists on\n * an authenticated caller (an access report is sensitive even about\n * oneself, and the anonymous `guest` posture is not this endpoint's\n * business) and returns 501 when no security service exposing `explain`\n * is mounted (a deployment without `@objectstack/plugin-security`).\n */\n private registerSecurityExplainEndpoints(basePath: string): void {\n const isScoped = basePath.includes('/environments/:environmentId');\n // Resolve the ENVIRONMENT's security service first (its resolver /\n // evaluator / RLS compiler are bound to the env kernel's own data\n // engine); the host provider is the single-kernel fallback.\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>('security').catch(() => undefined);\n if (svc) return svc;\n }\n } catch { /* fall back to the host service */ }\n if (!this.securityServiceProvider) return undefined;\n try { return await this.securityServiceProvider(environmentId); }\n catch { return undefined; }\n };\n\n const 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 if (!context?.userId) {\n // Even on requireAuth=false deployments the explain surface\n // stays authenticated-only — it is an admin diagnosis tool.\n return res.status(401).json({\n code: 'UNAUTHORIZED',\n message: 'The access-explanation endpoint requires an authenticated caller.',\n });\n }\n\n const svc = await resolveService(environmentId, req);\n if (!svc || typeof svc.explain !== 'function') {\n return res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Access explanation is not available on this deployment (no security service with explain).',\n });\n }\n\n // GET reads the request from the query string, POST from the\n // body — one contract (ExplainRequestSchema), two transports.\n const src = req.method === 'GET' ? (req.query ?? {}) : (req.body ?? {});\n const { ExplainRequestSchema } = await import('@objectstack/spec/security');\n const parsed = (ExplainRequestSchema as any).safeParse({\n object: src.object,\n operation: src.operation ?? 'read',\n ...(src.userId != null && src.userId !== '' ? { userId: src.userId } : {}),\n // [C2 / ADR-0095] Optional record id — explains ONE concrete\n // row at record granularity; omitted stays object-level.\n ...(src.recordId != null && src.recordId !== '' ? { recordId: src.recordId } : {}),\n });\n if (!parsed.success) {\n return res.status(400).json({\n code: 'VALIDATION_FAILED',\n message: 'Invalid explain request — expected { object: string, operation: read|create|update|delete|transfer|restore|purge, userId?: string, recordId?: string }.',\n detail: String(parsed.error?.message ?? '').slice(0, 1000),\n });\n }\n\n const decision = await svc.explain(parsed.data, context);\n res.json(decision);\n } catch (error: any) {\n const msg = String(error?.message ?? error ?? '');\n if (\n error?.code === 'PERMISSION_DENIED' ||\n error?.name === 'PermissionDeniedError' ||\n msg.startsWith('[Security] Access denied')\n ) {\n return res.status(403).json({ code: 'PERMISSION_DENIED', message: msg.slice(0, 1000) });\n }\n logError('[REST] Security explain error:', error);\n res.status(500).json({ code: 'EXPLAIN_FAILED', error: msg.slice(0, 500) });\n }\n };\n\n this.routeManager.register({\n method: 'GET',\n path: `${basePath}/security/explain`,\n handler,\n metadata: { summary: 'Explain why a principal can (or cannot) perform an operation on an object (ADR-0090 D6)', tags: ['security'] },\n });\n this.routeManager.register({\n method: 'POST',\n path: `${basePath}/security/explain`,\n handler,\n metadata: { summary: 'Explain why a principal can (or cannot) perform an operation on an object (ADR-0090 D6)', tags: ['security'] },\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 the security admin endpoints (ADR-0090 D5/D9) — suggested\n * audience bindings. A package permission set declaring `isDefault: true`\n * is an install-time SUGGESTION to bind it to the `everyone` position;\n * these routes surface pending suggestions and let a tenant admin resolve\n * them. The `security` service (plugin-security) does the real gating:\n * tenant-admin pre-check on all three, and confirm writes the binding\n * with the caller's execution context so the audience-anchor and\n * delegated-admin gates enforce it — never auto-bound, never system.\n *\n * GET {basePath}/security/suggested-bindings?status=&packageId=\n * POST {basePath}/security/suggested-bindings/:id/confirm\n * POST {basePath}/security/suggested-bindings/:id/dismiss\n *\n * Routes return 501 when the `security` service is not registered\n * (deployment without plugin-security). Typed service errors carry their\n * HTTP status (403 permission / 404 not found / 409 state).\n */\n private registerSecurityEndpoints(basePath: string): void {\n const dataPath = basePath;\n const isScoped = basePath.includes('/environments/:environmentId');\n\n const resolveService = async (environmentId?: string) => {\n if (!this.securityServiceProvider) return undefined;\n try {\n const svc = await this.securityServiceProvider(environmentId);\n return svc && typeof svc.listAudienceBindingSuggestions === 'function' ? svc : undefined;\n } catch { return undefined; }\n };\n const respond501 = (res: any) => res.status(501).json({\n code: 'NOT_IMPLEMENTED',\n message: 'Security service is not configured on this deployment',\n });\n const handleError = (err: any, res: any, defaultCode: string) => {\n const status = typeof err?.statusCode === 'number' ? err.statusCode : 500;\n if (status !== 500) {\n return res.status(status).json({ code: err?.code ?? defaultCode, error: String(err?.message ?? err) });\n }\n logError(`[REST] suggested-bindings ${defaultCode}:`, err);\n return res.status(500).json({ code: defaultCode, error: String(err?.message ?? err).slice(0, 500) });\n };\n\n // LIST (reconciles against installed packages / declared sets first)\n this.routeManager.register({\n method: 'GET',\n path: `${dataPath}/security/suggested-bindings`,\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.listAudienceBindingSuggestions(context ?? {}, {\n status: req.query?.status ? String(req.query.status) : undefined,\n packageId: req.query?.packageId ? String(req.query.packageId) : undefined,\n });\n res.json({ data: result });\n } catch (err: any) { handleError(err, res, 'SUGGESTION_LIST_FAILED'); }\n },\n metadata: { summary: 'List suggested audience bindings (ADR-0090 D5/D9)', tags: ['security'] },\n });\n\n // CONFIRM — creates the anchor binding as the caller (gated write)\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/security/suggested-bindings/:id/confirm`,\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.confirmAudienceBindingSuggestion(context ?? {}, String(req.params.id));\n res.json({ data: result });\n } catch (err: any) { handleError(err, res, 'SUGGESTION_CONFIRM_FAILED'); }\n },\n metadata: { summary: 'Confirm a suggested audience binding (creates the everyone/guest binding)', tags: ['security'] },\n });\n\n // DISMISS — records the admin's decline; nothing is bound\n this.routeManager.register({\n method: 'POST',\n path: `${dataPath}/security/suggested-bindings/:id/dismiss`,\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.dismissAudienceBindingSuggestion(context ?? {}, String(req.params.id));\n res.json({ data: result });\n } catch (err: any) { handleError(err, res, 'SUGGESTION_DISMISS_FAILED'); }\n },\n metadata: { summary: 'Dismiss a suggested audience binding', tags: ['security'] },\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","/**\n * Type-aware value formatting for the streaming data export route\n * (`GET /data/:object/export`).\n *\n * The raw rows returned by `findData` carry *storage* values: lookup / user\n * fields hold ids (or, when `$expand`-ed, nested records), select fields hold\n * option codes, booleans hold true/false, dates hold ISO strings. None of those\n * read well in a spreadsheet. These helpers turn each value into a human\n * readable cell using the object's field metadata.\n *\n * Contract: when no field metadata is available (schema lookup failed or carried\n * no fields) every helper is a pass-through, so the export stays byte-for-byte\n * identical to the un-formatted behaviour.\n */\n\nexport interface ExportFieldMeta {\n name: string;\n type?: string;\n label?: string;\n options?: Array<{ label?: string; value?: unknown; color?: string }>;\n /** Target object for lookup / master_detail / user fields. */\n reference?: string;\n /** Field on the referenced record to show as its label. */\n displayField?: string;\n // The following four drive the import path's required-field pre-check\n // (import-runner.ts). They mirror the engine's insert-time validation\n // (objectql record-validator.ts) so a dry run can predict a NOT NULL /\n // required failure instead of green-lighting a row the real insert rejects.\n // Unused by the export path (formatting only reads type/options/reference).\n /** Field is required — a value (or default) must exist on insert. */\n required?: boolean;\n /** Engine-owned column the client never supplies (never required of import). */\n system?: boolean;\n /** Read-only column the client never supplies (never required of import). */\n readonly?: boolean;\n /** Field declares a `defaultValue` the engine applies on insert (satisfies required). */\n hasDefault?: boolean;\n}\n\n/**\n * Build the `Content-Disposition` header for an export download.\n *\n * The suggested filename is `<label>-<YYYYMMDD>-<HHMMSS>.<ext>` where the\n * label is the object's (locale-translated) display label — so a browser\n * saves e.g. `合同-20260714-153045.xlsx` instead of `contracts-2026-07-14.xlsx`.\n * Non-ASCII labels ride the RFC 5987/6266 `filename*` parameter; the plain\n * `filename` keeps an ASCII-safe fallback derived from the object API name\n * for clients that don't understand `filename*`.\n */\nexport function exportContentDisposition(\n objectName: string,\n label: string | undefined,\n ext: string,\n now: Date = new Date(),\n): string {\n const pad = (n: number) => String(n).padStart(2, '0');\n const stamp =\n `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}` +\n `-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;\n const asciiBase = objectName.replace(/[^A-Za-z0-9_.-]/g, '_') || 'export';\n // Keep unicode letters (CJK labels) but drop filesystem-hostile characters.\n // eslint-disable-next-line no-control-regex\n const utf8Base = String(label ?? '')\n .replace(/[\\\\/:*?\"<>|\\u0000-\\u001f]+/g, '_')\n .replace(/^[\\s._-]+|[\\s._-]+$/g, '')\n .slice(0, 80) || asciiBase;\n const asciiName = `${asciiBase}-${stamp}.${ext}`;\n const utf8Name = `${utf8Base}-${stamp}.${ext}`;\n // RFC 5987 pct-encoding: encodeURIComponent leaves `'()*` unescaped but\n // they are not attr-chars, so escape them explicitly.\n const encoded = encodeURIComponent(utf8Name)\n .replace(/['()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);\n return `attachment; filename=\"${asciiName}\"; filename*=UTF-8''${encoded}`;\n}\n\n/** Field types whose stored value points at another record. */\nconst REFERENCE_TYPES = new Set(['lookup', 'master_detail', 'user', 'reference', 'tree']);\n\n/** Field types whose stored value maps to a static option label. */\nconst OPTION_TYPES = new Set(['select', 'radio']);\nconst MULTI_OPTION_TYPES = new Set(['multiselect', 'checkboxes', 'tags']);\n\n/**\n * Keys tried, in order, to derive a referenced record's display value when the\n * field carries no explicit `displayField`.\n */\nconst NAME_KEY_FALLBACKS = [\n 'name', 'title', 'label', 'full_name', 'fullName', 'display_name', 'username', 'email',\n];\n\n/**\n * Build a field-name → metadata map from an object schema (best-effort).\n *\n * Accepts both shapes `fields` appears in across the stack: the runtime\n * `ObjectSchema.fields` is a `Record<fieldName, FieldDefinition>` object map\n * (the form served by the engine registry / `getMetaItem`), while some callers\n * and fixtures hand back a plain `FieldDefinition[]` array. A field's name is\n * taken from its own `name`, falling back to the map key.\n */\nexport function buildFieldMetaMap(schema: unknown): Map<string, ExportFieldMeta> {\n const map = new Map<string, ExportFieldMeta>();\n const fields = (schema as { fields?: unknown })?.fields;\n\n // Normalize either shape to a list of [name, definition] entries.\n let entries: Array<[string, any]>;\n if (Array.isArray(fields)) {\n entries = fields\n .filter((f) => f && typeof f === 'object')\n .map((f) => [typeof f.name === 'string' ? f.name : '', f] as [string, any]);\n } else if (fields && typeof fields === 'object') {\n entries = Object.entries(fields as Record<string, any>).map(\n ([key, def]) => [\n def && typeof def === 'object' && typeof def.name === 'string' ? def.name : key,\n def,\n ] as [string, any],\n );\n } else {\n return map;\n }\n\n for (const [name, f] of entries) {\n if (!name || !f || typeof f !== 'object') continue;\n map.set(name, {\n name,\n type: typeof f.type === 'string' ? f.type : undefined,\n label: typeof f.label === 'string' ? f.label : undefined,\n options: Array.isArray(f.options) ? f.options : undefined,\n reference: typeof f.reference === 'string' ? f.reference : undefined,\n displayField: typeof f.displayField === 'string' ? f.displayField : undefined,\n required: f.required === true,\n system: f.system === true,\n readonly: f.readonly === true,\n // Mirror the engine's `applyFieldDefaults` gate (`f.defaultValue == null`\n // ⇒ no default): any non-null default — literal, expression object, or the\n // `current_user` token — counts as satisfying a required field.\n hasDefault: f.defaultValue != null,\n });\n }\n return map;\n}\n\n/**\n * Reference-typed field names that should be `$expand`-ed so their stored ids\n * resolve to the referenced record (and thus to a readable name).\n */\nexport function referenceFieldNames(metaMap: Map<string, ExportFieldMeta>): string[] {\n const out: string[] = [];\n for (const meta of metaMap.values()) {\n if (meta.type && REFERENCE_TYPES.has(meta.type) && meta.reference) out.push(meta.name);\n }\n return out;\n}\n\n/** Header label for a column: schema label when present, else the field name. */\nexport function headerLabel(field: string, metaMap: Map<string, ExportFieldMeta>): string {\n return metaMap.get(field)?.label || field;\n}\n\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\nfunction toDate(value: unknown): Date | null {\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n if (typeof value === 'number' || typeof value === 'string') {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n return null;\n}\n\n/** `YYYY-MM-DD` (date) or `YYYY-MM-DD HH:mm:ss` (datetime), in UTC. */\nfunction formatDate(value: unknown, withTime: boolean): unknown {\n const d = toDate(value);\n if (!d) return value;\n const ymd = `${d.getUTCFullYear()}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())}`;\n if (!withTime) return ymd;\n return `${ymd} ${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}:${pad2(d.getUTCSeconds())}`;\n}\n\nfunction optionLabel(value: unknown, options?: Array<{ label?: string; value?: unknown }>): unknown {\n if (!options) return value;\n const hit = options.find((o) => o && o.value === value);\n return hit?.label ?? value;\n}\n\n/**\n * Normalize a CSS-ish hex color to exceljs' 8-digit ARGB (`FFRRGGBB`, opaque).\n * Accepts `#RGB` / `#RRGGBB` with or without the leading `#`, any case.\n * Returns `undefined` for anything else (empty, named colors, rgb(), garbage)\n * so callers simply skip styling rather than emit an invalid workbook.\n */\nexport function toArgb(color: unknown): string | undefined {\n if (typeof color !== 'string') return undefined;\n const hex = color.trim().replace(/^#/, '');\n if (/^[0-9a-fA-F]{3}$/.test(hex)) {\n const [r, g, b] = hex;\n return `FF${r}${r}${g}${g}${b}${b}`.toUpperCase();\n }\n if (/^[0-9a-fA-F]{6}$/.test(hex)) return `FF${hex}`.toUpperCase();\n return undefined;\n}\n\n/**\n * Font color (exceljs ARGB) for one cell, driven by the matched select/radio\n * option's `color`. Returns `undefined` when the field is not option-typed, no\n * option matches, the option has no color, or the color is not a valid hex —\n * i.e. whenever the cell should stay unstyled.\n */\nexport function cellFontColor(value: unknown, meta?: ExportFieldMeta): string | undefined {\n if (value === null || value === undefined) return undefined;\n if (!meta || !meta.type || !OPTION_TYPES.has(meta.type) || !meta.options) return undefined;\n const hit = meta.options.find((o) => o && o.value === value);\n return toArgb(hit?.color);\n}\n\nfunction displayFromRecord(rec: Record<string, unknown>, displayField?: string): string {\n if (displayField && rec[displayField] != null) return String(rec[displayField]);\n for (const k of NAME_KEY_FALLBACKS) {\n const v = rec[k];\n if (v != null && typeof v !== 'object') return String(v);\n }\n if (rec.id != null) return String(rec.id);\n try { return JSON.stringify(rec); } catch { return String(rec); }\n}\n\nfunction formatReference(value: unknown, displayField?: string): unknown {\n const one = (v: unknown): unknown =>\n v && typeof v === 'object' ? displayFromRecord(v as Record<string, unknown>, displayField) : v;\n if (Array.isArray(value)) return value.map(one).join(', ');\n return one(value);\n}\n\n/** Format one storage value into a display value using its field metadata. */\nexport function formatCellValue(value: unknown, meta?: ExportFieldMeta): unknown {\n if (value === null || value === undefined) return value;\n if (!meta || !meta.type) return value;\n const t = meta.type;\n if (t === 'boolean' || t === 'toggle') {\n if (value === true || value === 'true' || value === 1) return '是';\n if (value === false || value === 'false' || value === 0) return '否';\n return value;\n }\n if (OPTION_TYPES.has(t)) return optionLabel(value, meta.options);\n if (MULTI_OPTION_TYPES.has(t)) {\n const arr = Array.isArray(value) ? value : [value];\n return arr.map((v) => optionLabel(v, meta.options)).join(', ');\n }\n if (t === 'date') return formatDate(value, false);\n if (t === 'datetime') return formatDate(value, true);\n if (REFERENCE_TYPES.has(t)) return formatReference(value, meta.displayField);\n return value;\n}\n\n/** Ordered display cells for one row — the CSV / XLSX column path. */\nexport function formatRowCells(\n row: Record<string, unknown>,\n fields: string[],\n metaMap: Map<string, ExportFieldMeta>,\n): unknown[] {\n return fields.map((f) => formatCellValue(row?.[f], metaMap.get(f)));\n}\n\n/**\n * Format a row for JSON output: readable values for known fields, every other\n * key left untouched. Returns the original object reference when nothing needs\n * formatting so the stream stays byte-identical to the un-formatted path.\n */\nexport function formatRowForJson(\n row: Record<string, unknown>,\n metaMap: Map<string, ExportFieldMeta>,\n): Record<string, unknown> {\n if (metaMap.size === 0 || !row || typeof row !== 'object') return row;\n let copy: Record<string, unknown> | null = null;\n for (const key of Object.keys(row)) {\n const meta = metaMap.get(key);\n if (!meta) continue;\n const formatted = formatCellValue(row[key], meta);\n if (formatted !== row[key]) {\n if (!copy) copy = { ...row };\n copy[key] = formatted;\n }\n }\n return copy ?? row;\n}\n","/**\n * Type-aware value *coercion* for the bulk-import route\n * (`POST /data/:object/import`).\n *\n * This is the inverse of `export-format.ts`. A spreadsheet / CSV cell arrives as\n * a raw string (or, for JSON payloads, an arbitrary primitive); the storage\n * layer, on the other hand, expects *storage* values — booleans as real\n * booleans, numbers as numbers, dates as ISO strings, select fields as their\n * option **code** (not the human label), and lookup / user fields as the\n * referenced record **id** (not its name). The engine deliberately does not\n * coerce for storage (see `record-validator.ts`, which coerces only to *check*\n * a value and then discards the coerced form), so import has to do it here.\n *\n * The accepted storage shapes below are dictated by what\n * `validateFieldValue` in `packages/objectql` will accept:\n * - number / currency / percent / rating / slider → a finite `number`\n * - boolean / toggle → a real `boolean`\n * - date / datetime → an ISO-8601 string\n * - time → `HH:MM` / `HH:MM:SS`\n * - select / radio → an option *value*\n * - multiselect / checkboxes / tags → an array of option values\n * - lookup / master_detail / user / reference → a record id (resolved async)\n *\n * Contract: when a field carries no usable metadata the value passes through\n * untouched, so an import stays byte-identical to the pre-coercion behaviour.\n */\n\nimport type { ExportFieldMeta } from './export-format.js';\n\n/** Field types whose stored value points at another record (id). */\nconst REFERENCE_TYPES = new Set(['lookup', 'master_detail', 'user', 'reference', 'tree']);\n/** Single-select option types (store one option value). */\nconst OPTION_TYPES = new Set(['select', 'radio']);\n/** Multi-select option types (store an array of option values). */\nconst MULTI_OPTION_TYPES = new Set(['multiselect', 'checkboxes', 'tags']);\n/** Numeric field types (store a finite number). */\nconst NUMBER_TYPES = new Set(['number', 'currency', 'percent', 'rating', 'slider']);\n/** Boolean field types (store a real boolean). */\nconst BOOL_TYPES = new Set(['boolean', 'toggle']);\n\n/**\n * Structured outcome of a reference lookup. `id` set → a single record matched.\n * `ambiguous` → the display value matched more than one record, so linking any\n * one of them would be a guess the importer refuses to make. `matchedField`\n * names the field the match came from (for diagnostics). An empty object means\n * nothing matched. A bare `string | undefined` is still accepted from legacy\n * resolvers and normalised to this shape.\n */\nexport interface RefMatch {\n id?: string;\n ambiguous?: boolean;\n matchedField?: string;\n}\n\n/**\n * Resolve a reference field's display value (a name / email / id typed by the\n * user) to the referenced record's id. Return `undefined` / `{}` when nothing\n * matches (caller surfaces \"not found\"), a bare id string / `{ id }` on a unique\n * hit, or `{ ambiguous: true }` when several records share the value. Legacy\n * resolvers that return `string | undefined` keep working. Implementations are\n * expected to cache — the same name shows up on many rows.\n */\nexport type RefResolver = (\n referenceObject: string,\n displayValue: string,\n meta: ExportFieldMeta,\n) => Promise<string | undefined | RefMatch>;\n\n/** Normalise a resolver result (legacy string or structured) to a RefMatch. */\nfunction normalizeRefMatch(result: string | undefined | RefMatch): RefMatch {\n if (result == null) return {};\n if (typeof result === 'string') return result ? { id: result } : {};\n return result;\n}\n\nexport interface CoerceContext {\n /** Trim leading/trailing whitespace from string-ish cells (default true). */\n trimWhitespace?: boolean;\n /** Extra strings (besides `''`) treated as null, e.g. `['N/A', 'null']`. */\n nullValues?: string[];\n /**\n * When a select/multiselect cell matches no known option, keep the raw value\n * instead of failing. Note: the engine still validates option membership, so\n * this only helps when the option is (or will be) present in the schema.\n */\n createMissingOptions?: boolean;\n /** Async reference resolver (name/email/id → record id). Optional. */\n resolveRef?: RefResolver;\n}\n\n/** A per-field coercion failure, shaped like the engine's validation errors. */\nexport interface FieldCoerceError {\n field: string;\n code: string;\n message: string;\n}\n\n// ── blank / null handling ──────────────────────────────────────────\n\nfunction isBlank(value: unknown, nullValues?: string[]): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value === 'string') {\n const s = value.trim();\n if (s === '') return true;\n if (nullValues && nullValues.some((nv) => nv === value || nv === s)) return true;\n }\n return false;\n}\n\n// ── boolean ────────────────────────────────────────────────────────\n\nconst BOOL_TRUE = new Set(['true', 't', 'yes', 'y', '1', 'on', '是', '对', '✓', '√']);\nconst BOOL_FALSE = new Set(['false', 'f', 'no', 'n', '0', 'off', '否', '错', '✗', '×']);\n\n/** Parse a spreadsheet cell into a boolean, or `undefined` if unrecognised. */\nexport function parseBooleanCell(raw: unknown): boolean | undefined {\n if (typeof raw === 'boolean') return raw;\n if (typeof raw === 'number') {\n if (raw === 1) return true;\n if (raw === 0) return false;\n return undefined;\n }\n const s = String(raw).trim().toLowerCase();\n if (BOOL_TRUE.has(s)) return true;\n if (BOOL_FALSE.has(s)) return false;\n return undefined;\n}\n\n// ── numbers ────────────────────────────────────────────────────────\n\n/**\n * Parse a numeric cell, tolerating the punctuation spreadsheets add: thousands\n * separators (`1,234`), a leading currency symbol (`$` `¥` `€` `£` `¥`), a\n * trailing percent sign (`25%` → `25`), and accounting-style parenthesised\n * negatives (`(1,234)` → `-1234`). Returns `undefined` when the residue is not\n * a finite number.\n */\nexport function parseNumberCell(raw: unknown): number | undefined {\n if (typeof raw === 'number') return Number.isFinite(raw) ? raw : undefined;\n let s = String(raw).trim();\n if (s === '') return undefined;\n let negative = false;\n if (/^\\(.*\\)$/.test(s)) { negative = true; s = s.slice(1, -1).trim(); }\n s = s.replace(/^[$¥€£¥]\\s*/, ''); // leading currency symbol\n s = s.replace(/%$/, '').trim(); // trailing percent\n s = s.replace(/,/g, ''); // thousands separators\n if (s === '' || !/^[+-]?\\d*\\.?\\d+(e[+-]?\\d+)?$/i.test(s)) return undefined;\n const n = Number(s);\n if (!Number.isFinite(n)) return undefined;\n return negative ? -n : n;\n}\n\n// ── dates ──────────────────────────────────────────────────────────\n\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\nconst TIME_OF_DAY = /^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$/;\n\n/**\n * Coerce a cell into the string shape the engine accepts for a date-ish field:\n * - `date` → `YYYY-MM-DD`\n * - `datetime` → full ISO-8601 (`toISOString`)\n * - `time` → `HH:MM` / `HH:MM:SS`\n * Returns `undefined` when the cell is not a recognisable date/time.\n *\n * Unambiguous `YYYY-MM-DD` / `YYYY/MM/DD` inputs are normalised directly to\n * avoid timezone drift; everything else falls back to `Date.parse` (which\n * covers ISO datetimes and locale-default `MM/DD/YYYY`).\n */\nexport function parseDateCell(raw: unknown, kind: 'date' | 'datetime' | 'time'): string | undefined {\n if (raw instanceof Date) {\n if (Number.isNaN(raw.getTime())) return undefined;\n if (kind === 'datetime') return raw.toISOString();\n if (kind === 'date') return `${raw.getUTCFullYear()}-${pad2(raw.getUTCMonth() + 1)}-${pad2(raw.getUTCDate())}`;\n return `${pad2(raw.getUTCHours())}:${pad2(raw.getUTCMinutes())}:${pad2(raw.getUTCSeconds())}`;\n }\n const s = String(raw).trim();\n if (s === '') return undefined;\n\n if (kind === 'time') {\n if (TIME_OF_DAY.test(s)) return s.length === 5 ? `${s}:00` : s;\n // A full datetime for a time field: take its clock component.\n const t = new Date(s);\n if (!Number.isNaN(t.getTime())) return `${pad2(t.getUTCHours())}:${pad2(t.getUTCMinutes())}:${pad2(t.getUTCSeconds())}`;\n return undefined;\n }\n\n // Fast path: bare calendar date, no timezone games.\n const ymd = s.match(/^(\\d{4})[-/](\\d{1,2})[-/](\\d{1,2})$/);\n if (ymd) {\n const y = Number(ymd[1]);\n const mo = Number(ymd[2]);\n const d = Number(ymd[3]);\n if (mo < 1 || mo > 12 || d < 1 || d > 31) return undefined;\n if (kind === 'date') return `${y}-${pad2(mo)}-${pad2(d)}`;\n return new Date(Date.UTC(y, mo - 1, d)).toISOString();\n }\n\n const parsed = new Date(s);\n if (Number.isNaN(parsed.getTime())) return undefined;\n if (kind === 'date') {\n return `${parsed.getUTCFullYear()}-${pad2(parsed.getUTCMonth() + 1)}-${pad2(parsed.getUTCDate())}`;\n }\n return parsed.toISOString();\n}\n\n// ── options (select / multiselect) ─────────────────────────────────\n\n/**\n * Match a cell against a field's options, accepting **either** the option value\n * (code) or its human label (case-insensitive). Returns the canonical option\n * value to store, or `undefined` on no match.\n */\nexport function matchOption(\n raw: unknown,\n options?: Array<{ label?: string; value?: unknown }>,\n): unknown | undefined {\n const s = String(raw).trim();\n if (!options || options.length === 0) return s; // no option list → accept as-is\n // Exact value match first (preserves the option's original value type).\n for (const o of options) {\n if (o && o.value !== undefined && String(o.value) === s) return o.value;\n }\n // Case-insensitive label match.\n const lower = s.toLowerCase();\n for (const o of options) {\n if (o && typeof o.label === 'string' && o.label.trim().toLowerCase() === lower) return o.value;\n }\n return undefined;\n}\n\n/** Split a multi-value cell on commas / semicolons / Chinese comma / newlines. */\nexport function splitMulti(raw: unknown): string[] {\n if (Array.isArray(raw)) return raw.map((v) => String(v).trim()).filter((v) => v !== '');\n return String(raw)\n .split(/[,;、\\n]/)\n .map((v) => v.trim())\n .filter((v) => v !== '');\n}\n\n// ── per-field orchestration ────────────────────────────────────────\n\n/**\n * Coerce one raw cell to its storage value using the field metadata. On success\n * returns `{ value }` (value may be `undefined`, meaning \"drop this key\"); on a\n * hard coercion failure returns `{ error }`.\n */\nexport async function coerceFieldValue(\n raw: unknown,\n meta: ExportFieldMeta | undefined,\n ctx: CoerceContext,\n): Promise<{ value?: unknown } | { error: FieldCoerceError }> {\n const trim = ctx.trimWhitespace !== false;\n const field = meta?.name ?? '';\n\n // Blank → leave the field unset so schema defaults / existing values win.\n if (isBlank(raw, ctx.nullValues)) return { value: undefined };\n\n const t = meta?.type;\n if (!t) return { value: trim && typeof raw === 'string' ? raw.trim() : raw };\n\n if (BOOL_TYPES.has(t)) {\n const b = parseBooleanCell(raw);\n if (b === undefined) return { error: { field, code: 'invalid_boolean', message: `${field}: \"${String(raw)}\" is not a boolean` } };\n return { value: b };\n }\n\n if (NUMBER_TYPES.has(t)) {\n const n = parseNumberCell(raw);\n if (n === undefined) return { error: { field, code: 'invalid_number', message: `${field}: \"${String(raw)}\" is not a number` } };\n return { value: n };\n }\n\n if (t === 'date' || t === 'datetime' || t === 'time') {\n const d = parseDateCell(raw, t);\n if (d === undefined) return { error: { field, code: 'invalid_date', message: `${field}: \"${String(raw)}\" is not a valid ${t}` } };\n return { value: d };\n }\n\n if (OPTION_TYPES.has(t)) {\n const v = matchOption(raw, meta?.options);\n if (v === undefined) {\n if (ctx.createMissingOptions) return { value: String(raw).trim() };\n return { error: { field, code: 'invalid_option', message: `${field}: \"${String(raw)}\" is not a known option` } };\n }\n return { value: v };\n }\n\n if (MULTI_OPTION_TYPES.has(t)) {\n const parts = splitMulti(raw);\n const out: unknown[] = [];\n for (const part of parts) {\n const v = matchOption(part, meta?.options);\n if (v === undefined) {\n if (ctx.createMissingOptions) { out.push(part); continue; }\n return { error: { field, code: 'invalid_option', message: `${field}: \"${part}\" is not a known option` } };\n }\n out.push(v);\n }\n return { value: out };\n }\n\n if (REFERENCE_TYPES.has(t)) {\n const display = String(raw).trim();\n // If it already looks resolved (an id was pasted) or we have no resolver /\n // no target object, store the raw value and let referential integrity be\n // enforced downstream.\n if (!ctx.resolveRef || !meta?.reference) return { value: display };\n const match = normalizeRefMatch(await ctx.resolveRef(meta.reference, display, meta));\n if (match.ambiguous) {\n return { error: { field, code: 'reference_ambiguous', message: `${field}: \"${display}\" matches more than one ${meta.reference} — use a unique value or the record id` } };\n }\n if (match.id === undefined) {\n return { error: { field, code: 'reference_not_found', message: `${field}: no ${meta.reference} matches \"${display}\"` } };\n }\n return { value: match.id };\n }\n\n // Everything else (text, email, phone, json, html, file, …): pass through,\n // trimming string cells so stray spreadsheet padding doesn't leak into storage.\n return { value: trim && typeof raw === 'string' ? raw.trim() : raw };\n}\n\n// ── required-field pre-check ───────────────────────────────────────\n\n/**\n * Engine-owned lifecycle columns the client never supplies. Mirrors\n * `record-validator.ts`'s `SKIP_FIELDS`, so the import's required pre-check and\n * the engine's insert-time required check agree on which fields the caller is\n * responsible for.\n */\nconst REQUIRED_CHECK_SKIP = new Set<string>([\n 'id', 'created_at', 'created_by', 'updated_at', 'updated_by',\n]);\n\nfunction isBlankValue(v: unknown): boolean {\n return v === undefined || v === null || (typeof v === 'string' && v.trim() === '');\n}\n\n/**\n * The first required field a would-be CREATE leaves unsatisfied, or `null` when\n * every required field has either a mapped value or a schema default.\n *\n * This mirrors the engine's insert-time required check (objectql\n * `record-validator.ts` + `applyFieldDefaults`) so the import's dry run predicts\n * the SAME verdict the real insert produces: a required (⇒ NOT NULL) field with\n * no default and no value fails both. Without it, dry run only reports coercion\n * errors and green-lights a row that then dies on `NOT NULL constraint failed`.\n *\n * Matches the engine's exemptions exactly — `system`/`readonly` columns, the\n * runtime-generated `autonumber`, a field carrying a `defaultValue`, and the\n * engine-owned lifecycle columns are never required of the importer. Applies to\n * CREATE only; an UPDATE touches just the supplied fields, so callers gate on\n * \"will create\" before calling.\n */\nexport function firstMissingRequiredField(\n data: Record<string, unknown>,\n metaMap: Map<string, ExportFieldMeta>,\n): string | null {\n for (const meta of metaMap.values()) {\n if (!meta.required) continue;\n if (meta.system || meta.readonly) continue;\n if (meta.hasDefault) continue;\n if (meta.type === 'autonumber') continue;\n if (REQUIRED_CHECK_SKIP.has(meta.name)) continue;\n if (isBlankValue(data[meta.name])) return meta.name;\n }\n return null;\n}\n\n/**\n * Coerce a whole raw row into a storage-ready record. Unknown columns (no\n * matching field metadata) pass through untouched so ad-hoc / schemaless\n * objects still import. Collects every field error rather than stopping at the\n * first, so a UI can show all problems in a row at once.\n */\nexport async function coerceRow(\n rawRow: Record<string, unknown>,\n metaMap: Map<string, ExportFieldMeta>,\n ctx: CoerceContext,\n): Promise<{ data: Record<string, unknown>; errors: FieldCoerceError[] }> {\n const data: Record<string, unknown> = {};\n const errors: FieldCoerceError[] = [];\n for (const [key, raw] of Object.entries(rawRow)) {\n const meta = metaMap.get(key);\n const res = await coerceFieldValue(raw, meta ? meta : undefined, ctx);\n if ('error' in res) {\n // Attribute the error to the column even when metadata was missing.\n errors.push({ ...res.error, field: res.error.field || key });\n continue;\n }\n if (res.value !== undefined) data[key] = res.value;\n }\n return { data, errors };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { coerceRow, firstMissingRequiredField, type RefResolver, type RefMatch } from './import-coerce.js';\nimport type { ExportFieldMeta } from './export-format.js';\nimport { bulkWrite, withTransientRetry, type BulkWriteRowResult } from '@objectstack/core';\n\n/**\n * import-runner — the shared row-processing core for bulk import.\n *\n * Both the synchronous `POST /data/:object/import` route and the asynchronous\n * import-job worker feed rows through {@link runImport}. Extracting the loop\n * keeps the two paths byte-for-byte identical in coercion, upsert matching, and\n * per-row reporting — the async worker only adds progress persistence and\n * cancellation on top.\n *\n * Rows resolved to a CREATE are batched through `p.createManyData` (the\n * engine's array-form `insert()` — one round-trip per batch, with transient\n * retry and per-row degradation on a logical/validation failure) instead of\n * one `p.createData` call per row — see framework#2678. A protocol that\n * doesn't implement `createManyData` falls back to the original per-row\n * `createData` path unchanged.\n */\n\nexport type ImportAction = 'created' | 'updated' | 'skipped' | 'failed';\n\nexport interface ImportRowResult {\n row: number;\n ok: boolean;\n action: ImportAction;\n id?: string;\n field?: string;\n error?: string;\n code?: string;\n}\n\n/** Running tallies handed to {@link RunImportOptions.onProgress}. */\nexport interface ImportProgress {\n processed: number;\n total: number;\n created: number;\n updated: number;\n skipped: number;\n errors: number;\n}\n\n/**\n * Records exactly what a non-dry-run import changed, so the job can be undone:\n * created records are deleted, and updated records have the touched fields\n * restored to their pre-import values. Only the fields the import wrote are\n * captured (keyed to `before`), keeping the log precise and bounded.\n */\nexport interface ImportUndoLog {\n /** Ids of records this import created (delete to undo). */\n created: string[];\n /** Per updated record: the touched fields' values *before* the import. */\n updated: Array<{ id: string; before: Record<string, any> }>;\n}\n\nexport interface ImportRunSummary extends ImportProgress {\n ok: number;\n results: ImportRowResult[];\n cancelled: boolean;\n /** Present only when `captureUndo` was set — the reversal instructions. */\n undoLog?: ImportUndoLog;\n}\n\n/** Minimal protocol surface the runner needs (find / create / update). */\nexport interface ImportProtocolLike {\n findData(args: any): Promise<any>;\n createData(args: any): Promise<any>;\n updateData(args: any): Promise<any>;\n /**\n * Optional bulk-create primitive. When present, `runImport` batches\n * CREATE-resolved rows through it instead of one `createData` call per\n * row — see framework#2678. Must resolve to `{ records: any[] }` with one\n * record per input row, in the same order.\n */\n createManyData?(args: { object: string; records: any[]; context?: any; environmentId?: string }): Promise<{ records: any[] }>;\n}\n\nexport interface RunImportOptions {\n /** Protocol/engine to read & write through. */\n p: ImportProtocolLike;\n objectName: string;\n environmentId?: string;\n /** Exec context threaded onto reads and (with automation toggle) writes. */\n context?: any;\n /** Already-mapped rows (source columns renamed to target fields). */\n rows: Array<Record<string, any>>;\n /** Field metadata for value coercion (name→id lookups, select codes, …). */\n metaMap: Map<string, ExportFieldMeta>;\n writeMode: 'insert' | 'update' | 'upsert';\n matchFields: string[];\n dryRun: boolean;\n runAutomations: boolean;\n trimWhitespace: boolean;\n nullValues?: string[];\n createMissingOptions: boolean;\n skipBlankMatchKey: boolean;\n /**\n * Progress callback, invoked every {@link RunImportOptions.progressEvery}\n * processed rows and once at the end. May be async; the runner awaits it so a\n * DB write of progress completes before the next chunk.\n */\n onProgress?: (p: ImportProgress) => void | Promise<void>;\n /**\n * Rows between onProgress calls (default 200). Also the flush boundary for\n * buffered creates — a batch never grows past this before being written,\n * so progress numbers stay accurate at every reported checkpoint.\n */\n progressEvery?: number;\n /**\n * Cooperative cancellation. Checked at each progress boundary; when it returns\n * truthy the runner stops and returns `cancelled: true` with partial results.\n */\n shouldCancel?: () => boolean | Promise<boolean>;\n /**\n * When true (and not a dry run), accumulate an {@link ImportUndoLog} so the\n * import can be reverted later. Callers gate this on row count to bound the\n * stored snapshot size.\n */\n captureUndo?: boolean;\n}\n\n/** Extracts a created/updated record's id regardless of which response shape the protocol returned. */\nfunction extractRecordId(rec: any): string | undefined {\n const id = rec?.id ?? rec?.record?.id;\n return id != null ? String(id) : undefined;\n}\n\nfunction toFailedResult(rowNo: number, err: unknown): ImportRowResult {\n const code = (err as any)?.code ?? 'IMPORT_ROW_FAILED';\n const message = typeof (err as any)?.message === 'string' ? (err as any).message.slice(0, 300) : 'Row failed';\n return { row: rowNo, ok: false, action: 'failed', error: message, code };\n}\n\n/** Upper bound on rows in one createManyData batch (framework#2678 suggests 100-500). */\nconst MAX_CREATE_BATCH_SIZE = 200;\n\nexport function runImport(opts: RunImportOptions): Promise<ImportRunSummary> {\n const {\n p, objectName, environmentId, context, rows, metaMap,\n writeMode, matchFields, dryRun, runAutomations,\n trimWhitespace, nullValues, createMissingOptions, skipBlankMatchKey,\n onProgress, shouldCancel, captureUndo,\n } = opts;\n const collectUndo = !!captureUndo && !dryRun;\n const undoLog: ImportUndoLog = { created: [], updated: [] };\n // Snapshot only the fields the import touched, so undo restores exactly what\n // changed. A field absent before the import is recorded as null → undo clears\n // it. Never captured on dry runs (nothing was written).\n const captureBefore = (before: Record<string, any>, written: Record<string, any>): Record<string, any> => {\n const snap: Record<string, any> = {};\n for (const k of Object.keys(written)) snap[k] = before[k] ?? null;\n return snap;\n };\n const progressEvery = Math.max(1, opts.progressEvery ?? 200);\n\n const findRows = (r: any): any[] =>\n Array.isArray(r?.records) ? r.records\n : Array.isArray(r?.data) ? r.data\n : Array.isArray(r?.rows) ? r.rows\n : Array.isArray(r) ? r : [];\n const findArgsBase = (query: any) => ({\n object: '',\n query,\n ...(environmentId ? { environmentId } : {}),\n ...(context ? { context } : {}),\n });\n\n // Reference resolver: name/email/id → referenced record id. Cached per\n // (object, display) so a name repeated across rows costs one query.\n const refCache = new Map<string, RefMatch>();\n const resolveRef: RefResolver = async (referenceObject, display, meta) => {\n const cacheKey = `${referenceObject}::${display}`;\n const cached = refCache.get(cacheKey);\n if (cached) return cached;\n // Try an exact id first (authoritative + unique when the user pasted an id),\n // then the configured display field, then the usual human identifiers.\n // De-dupe so a field isn't queried twice. The first candidate field to match\n // wins; if that field matches >1 record we stop and report ambiguity rather\n // than silently linking the first.\n const candidates = [...new Set([\n 'id',\n ...(meta.displayField ? [meta.displayField] : []),\n 'name', 'title', 'label', 'full_name', 'email', 'username',\n ])];\n let match: RefMatch = {};\n for (const f of candidates) {\n try {\n const r = await p.findData({\n ...findArgsBase({ $filter: { [f]: display }, $top: 2 }),\n object: referenceObject,\n });\n const recs = findRows(r);\n if (recs.length === 0) continue;\n if (recs.length > 1) { match = { ambiguous: true, matchedField: f }; break; }\n if (recs[0]?.id != null) { match = { id: String(recs[0].id), matchedField: f }; break; }\n } catch { /* field absent on target object — try the next candidate */ }\n }\n refCache.set(cacheKey, match);\n return match;\n };\n\n // Locate an existing record for update/upsert by matchFields. Returns the\n // record, or a sentinel: 'blank' (a match field was empty), 'none' (no\n // match), 'ambiguous' (>1 match — too risky to update).\n const findExisting = async (\n data: Record<string, any>,\n ): Promise<Record<string, any> | 'blank' | 'none' | 'ambiguous'> => {\n const filter: Record<string, any> = {};\n for (const f of matchFields) {\n const v = data[f];\n if (v === undefined || v === null || v === '') return 'blank';\n filter[f] = v;\n }\n const r = await p.findData({ ...findArgsBase({ $filter: filter, $top: 2 }), object: objectName });\n const recs = findRows(r);\n if (recs.length === 0) return 'none';\n if (recs.length > 1) return 'ambiguous';\n return recs[0];\n };\n\n const writeCtx = { ...(context ?? {}), skipAutomations: !runAutomations };\n\n // Sparse-indexed by row position `i` (not push-only): CREATE rows are\n // resolved immediately but their write is deferred to a later batch flush,\n // so their result would otherwise land out of order relative to\n // immediately-written update/skip rows interleaved between them.\n const results: ImportRowResult[] = new Array(rows.length);\n let okCount = 0, errCount = 0, created = 0, updated = 0, skipped = 0;\n let cancelled = false;\n\n const snapshot = (processed: number): ImportProgress => ({\n processed, total: rows.length, created, updated, skipped, errors: errCount,\n });\n\n // CREATE rows are buffered here and flushed through `p.createManyData`\n // (one round-trip per batch) when the protocol supports it. A protocol\n // without `createManyData` never buffers — `canBulkCreate` is false and\n // creates fall back to the original inline per-row `createData` call.\n const canBulkCreate = typeof p.createManyData === 'function';\n const pendingCreates: Array<{ index: number; rowNo: number; data: Record<string, any> }> = [];\n const flushPendingCreates = async (): Promise<void> => {\n if (pendingCreates.length === 0) return;\n const batch = pendingCreates.splice(0, pendingCreates.length);\n const writeResults: BulkWriteRowResult[] = await bulkWrite(\n batch.map(b => b.data),\n {\n // Flush cadence follows progressEvery, but the write batch itself is\n // capped independently — a caller-supplied progressEvery far above\n // the issue's suggested 100-500 rows/batch must not translate into\n // one oversized multi-row INSERT statement.\n batchSize: Math.min(progressEvery, MAX_CREATE_BATCH_SIZE),\n writeBatch: (chunk) => p.createManyData!({\n object: objectName, records: chunk, context: writeCtx,\n ...(environmentId ? { environmentId } : {}),\n }).then(r => r.records),\n writeOne: (row) => p.createData({\n object: objectName, data: row, context: writeCtx,\n ...(environmentId ? { environmentId } : {}),\n }),\n },\n );\n for (const res of writeResults) {\n const { index, rowNo } = batch[res.index];\n if (res.ok) {\n const id = extractRecordId(res.record);\n okCount++; created++;\n if (collectUndo && id != null) undoLog.created.push(id);\n results[index] = { row: rowNo, ok: true, action: 'created', id };\n } else {\n errCount++;\n results[index] = toFailedResult(rowNo, res.error);\n }\n }\n };\n\n return (async () => {\n for (let i = 0; i < rows.length; i++) {\n const rowNo = i + 1;\n try {\n // 1. Coerce every cell to its storage value (+ resolve lookups).\n const { data, errors } = await coerceRow(rows[i], metaMap, {\n trimWhitespace, nullValues, createMissingOptions, resolveRef,\n });\n if (errors.length > 0) {\n const first = errors[0];\n errCount++;\n results[i] = { row: rowNo, ok: false, action: 'failed', field: first.field, code: first.code, error: first.message };\n } else {\n // 2. Decide create vs update vs skip.\n let existing: Record<string, any> | 'blank' | 'none' | 'ambiguous' = 'none';\n let handled = false;\n if (writeMode !== 'insert') {\n existing = await findExisting(data);\n if (existing === 'ambiguous') {\n errCount++;\n results[i] = { row: rowNo, ok: false, action: 'failed', code: 'AMBIGUOUS_MATCH', error: `matchFields matched more than one ${objectName} record` };\n handled = true;\n } else if (existing === 'blank' && (skipBlankMatchKey || writeMode === 'update')) {\n // Blank match key: skip when asked, else fall through to create.\n skipped++;\n results[i] = { row: rowNo, ok: true, action: 'skipped', code: 'BLANK_MATCH_KEY' };\n handled = true;\n }\n }\n\n if (!handled) {\n const willUpdate = existing && typeof existing === 'object';\n const willCreate = !willUpdate && (writeMode === 'insert' || writeMode === 'upsert');\n\n // Required-field pre-check (CREATE only). Give dry run the same\n // verdict the real insert produces — a required (⇒ NOT NULL) field\n // with no default and no value fails both — instead of reporting\n // success for a row that then dies on `NOT NULL constraint failed`.\n // Shared by both paths so they stay identical (and a real insert\n // gets a readable `<field> is required` instead of a raw driver\n // error). Skipped when automations run: a beforeInsert hook may\n // populate a required field, so we defer to the engine's own\n // validation rather than false-reject here.\n const requiredMiss =\n willCreate && !runAutomations ? firstMissingRequiredField(data, metaMap) : null;\n\n if (requiredMiss) {\n errCount++;\n results[i] = { row: rowNo, ok: false, action: 'failed', field: requiredMiss, code: 'required', error: `${requiredMiss} is required` };\n } else if (!willUpdate && !willCreate) {\n // update mode, no match → skip.\n skipped++;\n results[i] = { row: rowNo, ok: true, action: 'skipped', code: 'NO_MATCH' };\n } else if (dryRun) {\n okCount++;\n if (willUpdate) { updated++; results[i] = { row: rowNo, ok: true, action: 'updated', id: String((existing as any).id ?? '') || undefined }; }\n else { created++; results[i] = { row: rowNo, ok: true, action: 'created' }; }\n } else if (willUpdate) {\n const target = existing as Record<string, any>;\n const res2 = await withTransientRetry(() => p.updateData({ object: objectName, id: target.id, data, context: writeCtx, ...(environmentId ? { environmentId } : {}) }));\n const id = extractRecordId(res2) ?? String(target.id);\n okCount++; updated++;\n if (collectUndo && target.id != null) {\n undoLog.updated.push({ id: String(target.id), before: captureBefore(target, data) });\n }\n results[i] = { row: rowNo, ok: true, action: 'updated', id };\n } else if (canBulkCreate) {\n // Buffer — the actual write happens in a batched flush below.\n pendingCreates.push({ index: i, rowNo, data });\n } else {\n // No bulk-create primitive on this protocol: original inline path.\n const res2 = await p.createData({ object: objectName, data, context: writeCtx, ...(environmentId ? { environmentId } : {}) });\n const id = extractRecordId(res2);\n okCount++; created++;\n if (collectUndo && id != null) undoLog.created.push(id);\n results[i] = { row: rowNo, ok: true, action: 'created', id };\n }\n }\n }\n } catch (err: any) {\n errCount++;\n results[i] = toFailedResult(rowNo, err);\n }\n\n const processed = i + 1;\n if (processed % progressEvery === 0 || processed === rows.length) {\n // Flush before reporting/cancelling so counts and `processed` reflect\n // every row up to this checkpoint, not just decided-but-unwritten ones.\n await flushPendingCreates();\n if (onProgress) await onProgress(snapshot(processed));\n }\n if (shouldCancel && processed < rows.length && (processed % progressEvery === 0)) {\n if (await shouldCancel()) { cancelled = true; break; }\n }\n }\n\n await flushPendingCreates();\n const compacted = results.filter((r): r is ImportRowResult => r !== undefined);\n\n return {\n ...snapshot(compacted.length), ok: okCount, results: compacted, cancelled,\n ...(collectUndo ? { undoLog } : {}),\n };\n })();\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Named import mappings (#2611) — resolve a registered `mapping` artifact\n * (`defineMapping`, stack `mappings:`) by name and apply its `fieldMapping`\n * pipeline to parsed rows.\n *\n * Seam with the inline request `mapping`:\n * • inline = a plain `{ sourceColumn: targetField }` RENAME for one-off,\n * wizard-driven imports — unmapped columns pass through untouched.\n * • artifact = a reusable, governed ETL projection for recurring /\n * programmatic imports — the output row contains ONLY the mapped\n * targets (a strict projection; source files from external systems\n * routinely carry junk columns that must not leak into the write path).\n *\n * Transform support (Prime Directive #10 — implement or reject loudly):\n * none/constant/map/split/join — applied here.\n * lookup — the value is copied through; the import pipeline's built-in\n * reference resolution (metaMap) turns lookup names into record ids,\n * so a dedicated re-implementation here would be a second dialect.\n * javascript — REJECTED (400). No server-side sandbox is wired into the\n * import path yet; silently skipping a declared transform would corrupt\n * data. Tracked on framework#2611.\n */\n\nexport interface MappingArtifactLike {\n name: string;\n targetObject: string;\n sourceFormat?: 'csv' | 'json' | 'xml' | 'sql';\n fieldMapping: Array<{\n source: string | string[];\n target: string | string[];\n transform?: 'none' | 'constant' | 'lookup' | 'split' | 'join' | 'javascript' | 'map';\n params?: {\n value?: unknown;\n valueMap?: Record<string, unknown>;\n separator?: string;\n } & Record<string, unknown>;\n }>;\n mode?: 'insert' | 'update' | 'upsert';\n upsertKey?: string[];\n}\n\nexport type MappingFailure = { ok: false; status: number; code: string; error: string };\nexport type ResolveMappingResult = { ok: true; artifact: MappingArtifactLike } | MappingFailure;\n\n/** Unwrap `{ item }` meta envelopes returned by protocol getMetaItem. */\nfunction unwrapEnvelope(r: unknown): unknown {\n if (r && typeof r === 'object' && 'item' in (r as Record<string, unknown>)) {\n return (r as Record<string, unknown>).item;\n }\n return r;\n}\n\n/**\n * Resolve a named mapping artifact and check it against the request:\n * target object must match the URL object, and the artifact's declared\n * sourceFormat (when set) must match the payload format actually sent.\n */\nexport async function resolveNamedMapping(\n p: { getMetaItem?: (req: { type: string; name: string }) => Promise<unknown> },\n opts: { mappingName: string; objectName: string; detectedFormat: 'csv' | 'json' | 'xlsx' },\n): Promise<ResolveMappingResult> {\n const { mappingName, objectName, detectedFormat } = opts;\n if (typeof p?.getMetaItem !== 'function') {\n return { ok: false, status: 500, code: 'INTERNAL', error: 'Metadata protocol unavailable; cannot resolve mappingName' };\n }\n let artifact: MappingArtifactLike | undefined;\n try {\n artifact = unwrapEnvelope(await p.getMetaItem({ type: 'mapping', name: mappingName })) as MappingArtifactLike | undefined;\n } catch { /* treated as not found below */ }\n if (!artifact || typeof artifact !== 'object' || !Array.isArray(artifact.fieldMapping)) {\n return { ok: false, status: 404, code: 'MAPPING_NOT_FOUND', error: `No mapping artifact named \"${mappingName}\" is registered` };\n }\n if (artifact.targetObject !== objectName) {\n return {\n ok: false, status: 400, code: 'MAPPING_TARGET_MISMATCH',\n error: `Mapping \"${mappingName}\" targets object \"${artifact.targetObject}\", not \"${objectName}\"`,\n };\n }\n const declared = artifact.sourceFormat;\n if (declared === 'xml' || declared === 'sql') {\n return {\n ok: false, status: 400, code: 'MAPPING_FORMAT_UNSUPPORTED',\n error: `Mapping \"${mappingName}\" declares sourceFormat \"${declared}\", which the import endpoint does not accept (csv/json/xlsx)`,\n };\n }\n // xlsx rows are tabular like csv; a csv-declared mapping applies to both.\n const compatible = declared === undefined\n || (declared === 'json' && detectedFormat === 'json')\n || (declared === 'csv' && (detectedFormat === 'csv' || detectedFormat === 'xlsx'));\n if (!compatible) {\n return {\n ok: false, status: 400, code: 'MAPPING_FORMAT_MISMATCH',\n error: `Mapping \"${mappingName}\" declares sourceFormat \"${declared}\" but the payload is \"${detectedFormat}\"`,\n };\n }\n for (const entry of artifact.fieldMapping) {\n if (entry?.transform === 'javascript') {\n return {\n ok: false, status: 400, code: 'UNSUPPORTED_TRANSFORM',\n error: `Mapping \"${mappingName}\" uses transform \"javascript\", which the import path does not execute (no server-side sandbox; see framework#2611)`,\n };\n }\n }\n return { ok: true, artifact };\n}\n\nconst first = (v: string | string[]): string => (Array.isArray(v) ? v[0] : v);\n\n/**\n * Apply the artifact's fieldMapping pipeline to raw parsed rows (headers as\n * in the source file). Returns NEW rows containing only mapped targets.\n */\nexport function applyMappingToRows(\n rows: Array<Record<string, unknown>>,\n artifact: MappingArtifactLike,\n): { ok: true; rows: Array<Record<string, unknown>> } | MappingFailure {\n const out: Array<Record<string, unknown>> = [];\n for (const row of rows) {\n const mapped: Record<string, unknown> = {};\n for (const entry of artifact.fieldMapping) {\n const transform = entry.transform ?? 'none';\n const sep = entry.params?.separator ?? ' ';\n switch (transform) {\n case 'none':\n case 'lookup': { // lookup values resolve downstream via metaMap\n mapped[first(entry.target)] = row[first(entry.source)];\n break;\n }\n case 'constant': {\n mapped[first(entry.target)] = entry.params?.value;\n break;\n }\n case 'map': {\n const raw = row[first(entry.source)];\n const valueMap = entry.params?.valueMap ?? {};\n mapped[first(entry.target)] =\n typeof raw === 'string' && raw in valueMap ? valueMap[raw] : raw;\n break;\n }\n case 'split': {\n const raw = row[first(entry.source)];\n const targets = Array.isArray(entry.target) ? entry.target : [entry.target];\n const parts = typeof raw === 'string' ? raw.split(sep) : [];\n targets.forEach((t, i) => { mapped[t] = parts[i]?.trim(); });\n break;\n }\n case 'join': {\n const sources = Array.isArray(entry.source) ? entry.source : [entry.source];\n mapped[first(entry.target)] = sources\n .map((s) => row[s])\n .filter((v) => v !== undefined && v !== null && v !== '')\n .join(sep);\n break;\n }\n default:\n return {\n ok: false, status: 400, code: 'UNSUPPORTED_TRANSFORM',\n error: `Mapping \"${artifact.name}\" uses unknown transform \"${transform}\"`,\n };\n }\n }\n out.push(mapped);\n }\n return { ok: true, rows: out };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Bulk-import request parsing — extracted verbatim from rest-server.ts\n * (#2766 V2) so consumers outside the generic `/data/:object/import` routes\n * (the identity import endpoint in plugin-auth) can accept byte-identical\n * payloads (rows[]/csv/xlsxBase64, mapping in either shape, writeMode +\n * matchFields) without re-implementing the parsers.\n */\n\nimport {\n buildFieldMetaMap,\n type ExportFieldMeta,\n} from './export-format.js';\nimport { resolveNamedMapping, applyMappingToRows, type MappingArtifactLike } from './import-mapping.js';\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 */\nexport function 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 * 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 */\nexport function 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 * Flatten one ExcelJS cell value to the raw string the coercion layer expects.\n * ExcelJS hands back rich objects for formulas / hyperlinks / rich text / dates;\n * we reduce each to the human-visible text so a server-parsed xlsx yields the\n * same cells a CSV export would (dates → ISO, so parseDateCell can re-read them).\n */\nfunction xlsxCellToString(value: any): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') {\n // Formula cell → prefer its computed result.\n if ('result' in value && value.result !== undefined && value.result !== null) return xlsxCellToString(value.result);\n // Hyperlink cell → the visible text, not the target.\n if ('text' in value && typeof value.text === 'string') return value.text;\n if ('hyperlink' in value && typeof value.hyperlink === 'string') return value.hyperlink;\n // Rich text → concatenate runs.\n if (Array.isArray(value.richText)) return value.richText.map((r: any) => r?.text ?? '').join('');\n if ('error' in value && value.error) return String(value.error);\n }\n try { return String(value); } catch { return ''; }\n}\n\n/**\n * Parse an .xlsx workbook (raw bytes) into row objects, mirroring\n * {@link parseCsvToRows}: first non-empty row is the header, each subsequent row\n * becomes `{ header→cell }` with the optional `mapping` renaming columns. Reads\n * the named/indexed `sheet` when given, else the first worksheet. Dynamically\n * imports ExcelJS (already a dependency of the export path) so CSV/JSON imports\n * don't pay for it.\n */\nexport async function parseXlsxToRows(\n buffer: Buffer | ArrayBuffer,\n mapping: Record<string, string> = {},\n sheet?: string | number,\n): Promise<Array<Record<string, any>>> {\n const ExcelJS: any = (await import('exceljs')).default ?? (await import('exceljs'));\n const wb = new ExcelJS.Workbook();\n await wb.xlsx.load(buffer);\n const ws = sheet !== undefined ? wb.getWorksheet(sheet as any) : wb.worksheets[0];\n if (!ws) return [];\n\n const cells: string[][] = [];\n ws.eachRow({ includeEmpty: false }, (row: any) => {\n const values = row.values as any[]; // 1-based; index 0 is unused\n const line: string[] = [];\n for (let c = 1; c < values.length; c++) line.push(xlsxCellToString(values[c]));\n cells.push(line);\n });\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 line = 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 obj[key] = line[c] ?? '';\n }\n out.push(obj);\n }\n return out;\n}\n\n/** Everything the import runner needs, parsed & validated from a request body. */\nexport interface PreparedImport {\n rows: Array<Record<string, any>>;\n metaMap: Map<string, ExportFieldMeta>;\n writeMode: 'insert' | 'update' | 'upsert';\n matchFields: string[];\n dryRun: boolean;\n runAutomations: boolean;\n trimWhitespace: boolean;\n nullValues?: string[];\n createMissingOptions: boolean;\n skipBlankMatchKey: boolean;\n}\n\nexport type PrepareImportResult =\n | { ok: true; prepared: PreparedImport }\n | { ok: false; status: number; code: string; error: string };\n\n/**\n * Parse & validate a bulk-import request body into a {@link PreparedImport}.\n *\n * Shared by the synchronous `POST /data/:object/import` route and the async\n * import-job create route so both accept byte-identical payloads (writeMode +\n * matchFields, mapping in either shape, rows[]/csv/xlsxBase64) and resolve the\n * same field metadata. The only knob that differs is `maxRows` (5k sync vs\n * 50k async). Returns a discriminated result; the caller maps `!ok` to an HTTP\n * error using the returned status/code/error.\n */\n/**\n * Fold a locale-translated schema's option labels into the authored metaMap as\n * matching synonyms. The export route and the import-template both surface the\n * *translated* option label (e.g. 待规划 for `backlog`), so a re-imported file\n * carries those strings — but `matchOption` compares against the schema the\n * registry serves, which only knows the authored label. Appending each\n * translated label as an extra `{ label, value }` entry keeps the authored\n * label and code working while also accepting what the localized UI displays.\n */\nexport function mergeLocalizedOptionSynonyms(\n metaMap: Map<string, ExportFieldMeta>,\n localized: Map<string, ExportFieldMeta>,\n): void {\n for (const [name, meta] of metaMap) {\n const loc = localized.get(name);\n if (!meta.options?.length || !loc?.options?.length) continue;\n const known = new Set(\n meta.options\n .map((o) => (typeof o?.label === 'string' ? o.label.trim().toLowerCase() : ''))\n .filter(Boolean),\n );\n const synonyms = loc.options.filter(\n (o) =>\n o\n && typeof o.label === 'string'\n && o.label.trim().length > 0\n && o.value !== undefined\n && !known.has(o.label.trim().toLowerCase()),\n );\n if (synonyms.length > 0) {\n meta.options = [...meta.options, ...synonyms.map((o) => ({ label: o.label, value: o.value }))];\n }\n }\n}\n\nexport async function prepareImportRequest(\n body: any,\n opts: {\n p: any;\n objectName: string;\n environmentId?: string;\n maxRows: number;\n /**\n * Optional hook applying the request locale to a schema document (the\n * REST server passes `translateMetaItem` bound to the request). Used to\n * accept locale-translated option labels — the strings the localized\n * export / import template actually contain — as select-cell synonyms.\n */\n localizeSchema?: (schema: any) => Promise<any> | any;\n },\n): Promise<PrepareImportResult> {\n const { p, objectName, environmentId, maxRows, localizeSchema } = opts;\n const dryRun = body?.dryRun === true;\n\n let writeMode: 'insert' | 'update' | 'upsert' =\n body?.writeMode === 'update' || body?.writeMode === 'upsert' ? body.writeMode : 'insert';\n let matchFields: string[] = Array.isArray(body?.matchFields)\n ? body.matchFields.filter((f: any) => typeof f === 'string' && f.length > 0)\n : [];\n // Default ON: automations always ran historically (the engine ignored the\n // flag until #2922), so opt-out must be explicit — matches platform\n // convention (Salesforce runs triggers on import by default).\n const runAutomations = body?.runAutomations !== false;\n const trimWhitespace = body?.trimWhitespace !== false;\n const nullValues: string[] | undefined = Array.isArray(body?.nullValues)\n ? body.nullValues.filter((v: any) => typeof v === 'string')\n : undefined;\n const createMissingOptions = body?.createMissingOptions === true;\n const skipBlankMatchKey = body?.skipBlankMatchKey === true;\n\n // ── Named mapping artifact (#2611) ────────────────────────────────\n // `mappingName` references a registered `mapping` artifact\n // (defineMapping / stack `mappings:`) — the reusable, governed form for\n // recurring & programmatic imports. Mutually exclusive with the inline\n // `mapping` rename: one mapping source of truth per request.\n const mappingName: string | undefined =\n typeof body?.mappingName === 'string' && body.mappingName.length > 0 ? body.mappingName : undefined;\n const hasInlineMapping =\n (Array.isArray(body?.mapping) && body.mapping.length > 0) ||\n (!Array.isArray(body?.mapping) && body?.mapping && typeof body.mapping === 'object' && Object.keys(body.mapping).length > 0);\n if (mappingName && hasInlineMapping) {\n return { ok: false, status: 400, code: 'CONFLICTING_MAPPING', error: 'Provide either mappingName or an inline mapping, not both' };\n }\n let mappingArtifact: MappingArtifactLike | undefined;\n if (mappingName) {\n const detectedFormat: 'csv' | 'json' | 'xlsx' | undefined =\n (body?.format === 'json' && Array.isArray(body?.rows)) || Array.isArray(body) ? 'json'\n : typeof body?.csv === 'string' ? 'csv'\n : typeof body?.xlsxBase64 === 'string' ? 'xlsx'\n : undefined;\n if (!detectedFormat) {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: 'Provide format:\"csv\" with csv text, format:\"json\" with rows[], or format:\"xlsx\" with xlsxBase64' };\n }\n const resolved = await resolveNamedMapping(p, { mappingName, objectName, detectedFormat });\n if (!resolved.ok) return resolved;\n mappingArtifact = resolved.artifact;\n // Artifact-declared write semantics apply as DEFAULTS: an explicit\n // request writeMode/matchFields wins; absent ones fall back to the\n // artifact's mode/upsertKey.\n if (body?.writeMode === undefined && (mappingArtifact.mode === 'update' || mappingArtifact.mode === 'upsert')) {\n writeMode = mappingArtifact.mode;\n }\n if (matchFields.length === 0 && Array.isArray(mappingArtifact.upsertKey)) {\n matchFields = mappingArtifact.upsertKey.filter((f) => typeof f === 'string' && f.length > 0);\n }\n }\n\n if (writeMode !== 'insert' && matchFields.length === 0) {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: `writeMode \"${writeMode}\" requires a non-empty matchFields[]` };\n }\n\n // Normalize `mapping` to a `{ sourceColumn: targetField }` record. Accepts\n // either that compact form or a FieldMappingEntry[].\n const mapping: Record<string, string> = {};\n if (Array.isArray(body?.mapping)) {\n for (const e of body.mapping) {\n if (e && typeof e.sourceField === 'string' && typeof e.targetField === 'string') {\n mapping[e.sourceField] = e.targetField;\n }\n }\n } else if (body?.mapping && typeof body.mapping === 'object') {\n for (const [k, v] of Object.entries(body.mapping)) {\n if (typeof v === 'string') mapping[k] = v;\n }\n }\n const applyMapping = (row: Record<string, any>): Record<string, any> => {\n if (Object.keys(mapping).length === 0) return row;\n const out: Record<string, any> = {};\n for (const [k, val] of Object.entries(row)) out[mapping[k] ?? k] = val;\n return out;\n };\n\n // Build rows[] from JSON array, CSV text, or a base64 xlsx.\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>>).map(applyMapping);\n } else if ((body?.format === 'csv' || typeof body?.csv === 'string') && typeof body?.csv === 'string') {\n rows = parseCsvToRows(body.csv, mapping);\n } else if ((body?.format === 'xlsx' || typeof body?.xlsxBase64 === 'string') && typeof body?.xlsxBase64 === 'string') {\n // Native server-side xlsx parse — the client uploads raw workbook bytes\n // (base64) instead of pre-flattening to CSV.\n try {\n const buf = Buffer.from(body.xlsxBase64, 'base64');\n rows = await parseXlsxToRows(buf, mapping, body.sheet);\n } catch (e: any) {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: `Failed to parse xlsx: ${e?.message ?? String(e)}` };\n }\n } else if (Array.isArray(body)) {\n // Permissive: a bare JSON array at the top level.\n rows = (body as Array<Record<string, any>>).map(applyMapping);\n } else {\n return { ok: false, status: 400, code: 'INVALID_REQUEST', error: 'Provide format:\"csv\" with csv text, format:\"json\" with rows[], or format:\"xlsx\" with xlsxBase64' };\n }\n\n if (rows.length > maxRows) {\n return { ok: false, status: 413, code: 'PAYLOAD_TOO_LARGE', error: `Import limit is ${maxRows} rows per request (got ${rows.length}).` };\n }\n\n // Apply the named mapping's fieldMapping pipeline (rename + transforms;\n // strict projection — only mapped targets reach the write path). Inline\n // `mapping` was empty in this branch, so rows still carry raw headers.\n if (mappingArtifact) {\n const applied = applyMappingToRows(rows, mappingArtifact);\n if (!applied.ok) return applied;\n rows = applied.rows;\n }\n\n // Resolve the object's field metadata so cells coerce to storage values\n // (booleans, numbers, dates→ISO, select label→code) and lookup names resolve\n // to record ids. Best-effort: a failed lookup leaves `metaMap` empty and\n // every value passes through untouched.\n let metaMap = new Map<string, ExportFieldMeta>();\n try {\n let schema: any = undefined;\n if (typeof p.getMetaItem === 'function') {\n const r = await p.getMetaItem({ type: 'object', name: objectName });\n schema = isMetaEnvelope(r) ? r.item : r;\n }\n if (!schema && typeof p.getObjectSchema === 'function') {\n schema = await p.getObjectSchema(objectName, environmentId);\n }\n metaMap = buildFieldMetaMap(schema);\n // Round-trip i18n: also accept the locale-translated option labels the\n // localized export / import template display (merged as synonyms; the\n // authored label and option code keep working).\n if (schema && typeof localizeSchema === 'function') {\n try {\n const localized = await localizeSchema(schema);\n if (localized && localized !== schema) {\n mergeLocalizedOptionSynonyms(metaMap, buildFieldMetaMap(localized));\n }\n } catch { /* authored-only option matching */ }\n }\n } catch { /* pass-through coercion */ }\n\n return {\n ok: true,\n prepared: {\n rows, metaMap, writeMode, matchFields, dryRun, runAutomations,\n trimWhitespace, nullValues, createMissingOptions, skipBlankMatchKey,\n },\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 * and (#2747) the full `deletePackage` uninstall semantics: package\n * metadata rows, the durable `sys_packages` record, and the registered\n * data-plane cleanups (e.g. plugin-security revoking the package's\n * permission sets and bindings).\n */\n protocol?: {\n getMetaItems?(req: { type: string }): Promise<{ items: any[] }>;\n deletePackage?(req: { packageId: string; actor?: string }): Promise<{\n success: boolean;\n deletedCount: number;\n failedCount: number;\n failed: Array<{ type: string; name: string; error: string; code?: string }>;\n cleanups: Array<{ name: string; success: boolean; removed: number; error?: string }>;\n }>;\n };\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 // [#2747] A FULL uninstall (no version pin) goes through\n // protocol.deletePackage — one uninstall semantic, not three dialects:\n // it removes the package's metadata rows, drops the durable\n // sys_packages record, and runs the registered data-plane cleanups\n // (plugin-security revokes the package's permission sets/bindings —\n // no ghost grants). A version-scoped delete keeps the narrow durable\n // registry semantics, as does a deployment without the protocol.\n if (!version && typeof options.protocol?.deletePackage === 'function') {\n const result = await options.protocol.deletePackage({ packageId });\n // Zero metadata rows is still a successful uninstall (e.g. a\n // runtime-registered package that never published metadata) —\n // only per-item failures make it a failure.\n if (result.failedCount === 0) {\n res.json({\n success: true,\n message: `Deleted ${packageId}`,\n deletedCount: result.deletedCount,\n cleanups: result.cleanups,\n });\n return;\n }\n res.status(400).json({ success: false, failed: result.failed, cleanups: result.cleanups });\n return;\n }\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';\nimport { SysImportJob } from '@objectstack/platform-objects/audit';\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 // Register the async-import job object so its state/progress/history\n // is queryable in Studio and readable by the import-job routes.\n // The REST plugin owns the import feature, so it owns this object\n // (there is no separate import service). Mirrors JobServicePlugin.\n try {\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.rest.api',\n name: 'REST API',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n defaultDatasource: 'cloud',\n namespace: 'sys',\n objects: [SysImportJob],\n });\n } catch (err) {\n ctx.logger.warn('RestApiPlugin: manifest service unavailable; sys_import_job not registered', err as any);\n }\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 // Security service resolver — used by the ADR-0090 D5/D9\n // /security/suggested-bindings routes and the D6 /security/explain\n // route (plugin-security). Returns undefined when plugin-security\n // is not mounted so the routes fail cleanly (501).\n const securityServiceProvider = async (_environmentId?: string): Promise<any | undefined> => {\n try {\n return ctx.getService<any>('security');\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 // Single-env service-existence probe for nav capability gates\n // (ADR-0057 D10). Multi-env uses the per-request kernel instead.\n const serviceExistsProvider = (name: string): boolean => {\n try { return ctx.getService<any>(name) != null; } catch { return false; }\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, serviceExistsProvider, securityServiceProvider);\n restServer.registerRoutes();\n\n ctx.logger.info('REST API successfully registered');\n\n // ADR-0056 D2 (warn → enforce, ENFORCED): the global default is\n // secure-by-default — anonymous /data/* is denied unless the\n // deployment explicitly opts out. The warning remains for that\n // explicit opt-out so a fail-open posture is always visible.\n if ((config.api as any)?.api?.requireAuth === false) {\n ctx.logger.warn(\n '[security] anonymous access to the data API is ALLOWED (api.requireAuth=false, explicit opt-out) — ' +\n 'objects without OWD/RLS are world-readable. Remove the opt-out for secure-by-default and ' +\n 'expose public records via share-links / publicSharing / public forms (ADR-0056 D2).',\n );\n }\n // Misplaced-key guard: the effective key is `api.api.requireAuth`\n // (RestApiPluginConfig.api is the full RestServerConfig). A flat\n // `api.requireAuth` is silently ignored by normalizeConfig — under\n // the deny default that turns an INTENDED public deployment into a\n // 401 outage with no diagnostic, so name the mistake loudly.\n if ((config.api as any)?.requireAuth !== undefined) {\n ctx.logger.warn(\n '[security] `api.requireAuth` is set at the WRONG nesting level and has NO effect — ' +\n 'move it to `api.api.requireAuth` (RestServerConfig.api.requireAuth). ' +\n `The effective value this boot is ${(config.api as any)?.api?.requireAuth ?? true}.`,\n );\n }\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":["REFERENCE_TYPES","OPTION_TYPES","MULTI_OPTION_TYPES","pad2","first","row","res","result"]}