@happyvertical/smrt-reports 0.55.24 → 0.56.1

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.
Files changed (91) hide show
  1. package/AGENTS.md +26 -3
  2. package/README.md +11 -2
  3. package/dist/index.d.ts +4 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +476 -109
  6. package/dist/index.js.map +1 -1
  7. package/dist/manifest.json +174 -5
  8. package/dist/materialized-host.d.ts +72 -0
  9. package/dist/materialized-host.d.ts.map +1 -0
  10. package/dist/playground.d.ts +2 -0
  11. package/dist/playground.d.ts.map +1 -0
  12. package/dist/playground.js +154 -0
  13. package/dist/playground.js.map +1 -0
  14. package/dist/recipes.d.ts +55 -0
  15. package/dist/recipes.d.ts.map +1 -1
  16. package/dist/runtime-report.d.ts +9 -0
  17. package/dist/runtime-report.d.ts.map +1 -1
  18. package/dist/runtime-server.d.ts +77 -0
  19. package/dist/runtime-server.d.ts.map +1 -0
  20. package/dist/runtime-spec.d.ts +2 -1
  21. package/dist/runtime-spec.d.ts.map +1 -1
  22. package/dist/smrt-knowledge.json +203 -11
  23. package/dist/state.js +1 -1
  24. package/dist/state.js.map +1 -1
  25. package/dist/svelte/MaterializedReportTable.svelte +104 -0
  26. package/dist/svelte/MaterializedReportTable.svelte.d.ts +14 -0
  27. package/dist/svelte/MaterializedReportTable.svelte.d.ts.map +1 -0
  28. package/dist/svelte/ReportConfirmation.svelte +99 -0
  29. package/dist/svelte/ReportConfirmation.svelte.d.ts +15 -0
  30. package/dist/svelte/ReportConfirmation.svelte.d.ts.map +1 -0
  31. package/dist/svelte/ReportDetail.svelte +69 -0
  32. package/dist/svelte/ReportDetail.svelte.d.ts +11 -0
  33. package/dist/svelte/ReportDetail.svelte.d.ts.map +1 -0
  34. package/dist/svelte/ReportPicker.svelte +73 -0
  35. package/dist/svelte/ReportPicker.svelte.d.ts +16 -0
  36. package/dist/svelte/ReportPicker.svelte.d.ts.map +1 -0
  37. package/dist/svelte/ReportResult.svelte +69 -0
  38. package/dist/svelte/ReportResult.svelte.d.ts +10 -0
  39. package/dist/svelte/ReportResult.svelte.d.ts.map +1 -0
  40. package/dist/svelte/RuntimeReportChartWidget.svelte +20 -0
  41. package/dist/svelte/RuntimeReportChartWidget.svelte.d.ts +11 -0
  42. package/dist/svelte/RuntimeReportChartWidget.svelte.d.ts.map +1 -0
  43. package/dist/svelte/RuntimeReportDetailRoute.svelte +67 -0
  44. package/dist/svelte/RuntimeReportDetailRoute.svelte.d.ts +21 -0
  45. package/dist/svelte/RuntimeReportDetailRoute.svelte.d.ts.map +1 -0
  46. package/dist/svelte/RuntimeReportToolResult.svelte +26 -0
  47. package/dist/svelte/RuntimeReportToolResult.svelte.d.ts +8 -0
  48. package/dist/svelte/RuntimeReportToolResult.svelte.d.ts.map +1 -0
  49. package/dist/svelte/RuntimeReportWidgetOptions.svelte +58 -0
  50. package/dist/svelte/RuntimeReportWidgetOptions.svelte.d.ts +14 -0
  51. package/dist/svelte/RuntimeReportWidgetOptions.svelte.d.ts.map +1 -0
  52. package/dist/svelte/RuntimeReportsRoute.svelte +67 -0
  53. package/dist/svelte/RuntimeReportsRoute.svelte.d.ts +19 -0
  54. package/dist/svelte/RuntimeReportsRoute.svelte.d.ts.map +1 -0
  55. package/dist/svelte/SavedReports.svelte +114 -0
  56. package/dist/svelte/SavedReports.svelte.d.ts +11 -0
  57. package/dist/svelte/SavedReports.svelte.d.ts.map +1 -0
  58. package/dist/svelte/browser-client.d.ts +10 -0
  59. package/dist/svelte/browser-client.d.ts.map +1 -0
  60. package/dist/svelte/browser-client.js +16 -0
  61. package/dist/svelte/client.d.ts +15 -0
  62. package/dist/svelte/client.d.ts.map +1 -0
  63. package/dist/svelte/client.js +179 -0
  64. package/dist/svelte/index.d.ts +17 -0
  65. package/dist/svelte/index.d.ts.map +1 -0
  66. package/dist/svelte/index.js +14 -0
  67. package/dist/svelte/materialized.d.ts +19 -0
  68. package/dist/svelte/materialized.d.ts.map +1 -0
  69. package/dist/svelte/materialized.js +1 -0
  70. package/dist/svelte/messages.d.ts +72 -0
  71. package/dist/svelte/messages.d.ts.map +1 -0
  72. package/dist/svelte/messages.js +72 -0
  73. package/dist/svelte/playground.d.ts +132 -0
  74. package/dist/svelte/playground.d.ts.map +1 -0
  75. package/dist/svelte/playground.js +62 -0
  76. package/dist/svelte/preview-data.d.ts +7 -0
  77. package/dist/svelte/preview-data.d.ts.map +1 -0
  78. package/dist/svelte/preview-data.js +59 -0
  79. package/dist/svelte/result.d.ts +8 -0
  80. package/dist/svelte/result.d.ts.map +1 -0
  81. package/dist/svelte/result.js +99 -0
  82. package/dist/svelte/spec.d.ts +5 -0
  83. package/dist/svelte/spec.d.ts.map +1 -0
  84. package/dist/svelte/spec.js +282 -0
  85. package/dist/svelte/tool-result.d.ts +11 -0
  86. package/dist/svelte/tool-result.d.ts.map +1 -0
  87. package/dist/svelte/tool-result.js +19 -0
  88. package/dist/svelte/types.d.ts +38 -0
  89. package/dist/svelte/types.d.ts.map +1 -0
  90. package/dist/svelte/types.js +1 -0
  91. package/package.json +36 -12
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["suffix","children","filter","field"],"sources":["../src/lifecycle.ts","../src/adapter.ts","../src/recipes.ts","../src/report.ts","../src/runtime-spec.ts","../src/runtime-compiler.ts","../src/runtime-report.ts","../src/views.ts"],"sourcesContent":["import { ObjectRegistry, type SmrtObject } from '@happyvertical/smrt-core';\nimport type { DurableJobPayloadSigner } from '@happyvertical/smrt-jobs';\nimport { getTenantId, withSystemContext } from '@happyvertical/smrt-tenancy';\nimport {\n type DatabaseInterface,\n tableExists,\n validateColumnName,\n} from '@happyvertical/sql';\nimport type { ReportRefreshActionDescriptor } from './adapter.js';\nimport { buildReportDefinition } from './compiler.js';\nimport type { ReportRefreshExecutionAuthority } from './scheduler.js';\nimport { enqueueReportRefresh } from './scheduler.js';\nimport {\n assertReportTablesReady,\n REPORT_LOCKS_TABLE,\n REPORT_RUNS_TABLE,\n scopeKeyForTenant,\n} from './state.js';\nimport type {\n ReportRefreshMode,\n ReportRefreshResult,\n ReportRefreshTrigger,\n} from './types.js';\n\ntype ReportCtor = new (...args: any[]) => SmrtObject;\n\nfunction registeredReport(reportCtor: ReportCtor) {\n return (\n ObjectRegistry.getClassByConstructor(reportCtor) ??\n ObjectRegistry.getClass(reportCtor.name)\n );\n}\n\nexport type ReportLifecycleState =\n | 'current'\n | 'stale'\n | 'refreshing'\n | 'lock-skipped'\n | 'failed';\n\nexport interface ReportLifecycleRun {\n id: string;\n status: 'running' | 'success' | 'failed' | 'skipped';\n mode: ReportRefreshMode;\n trigger: ReportRefreshTrigger;\n startedAt?: string;\n completedAt?: string;\n rowCount: number;\n changedGroupCount: number;\n /** A failed run is safe to retry through the separately permissioned action. */\n mayRetry: boolean;\n}\n\n/**\n * Transport-neutral report lifecycle state. It deliberately never includes a\n * lock owner, a raw failure message, or tenant fanout identifiers.\n */\nexport interface ReportLifecycleSnapshot {\n version: 1;\n state: ReportLifecycleState;\n asOf?: string;\n refreshedAt?: string;\n /** Whether existing materialized rows can remain visible while work changes state. */\n hasUsableRows: boolean;\n mode: ReportRefreshMode;\n run?: ReportLifecycleRun;\n /** A stable, redacted failure signal; raw executor errors stay server-side. */\n failure?: {\n code: 'refresh_failed';\n retryable: true;\n };\n lock: {\n held: boolean;\n expiresAt?: string;\n };\n}\n\nexport interface ReportLifecycleOptions {\n db: DatabaseInterface;\n /** Test seam; production callers use the current clock. */\n now?: Date;\n}\n\nexport interface ReportRefreshJobHandle {\n jobId: string;\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';\n attempts: number;\n maxAttempts: number;\n /** Bounded polling guidance; this API does not create a second queue. */\n pollAfterMs: number;\n}\n\nexport interface ReportRefreshActionContext {\n phase: 'preview' | 'apply';\n reportClassName: string;\n /** The action always applies to the caller's already-bound tenant scope. */\n tenantScope: 'ambient';\n mode: ReportRefreshMode;\n requiredPermission: string;\n}\n\n/** Authority and audit stay with the application action host, not reports. */\nexport interface ReportRefreshActionHost {\n authorize(\n context: ReportRefreshActionContext,\n authority?: ReportRefreshExecutionAuthority,\n ): Promise<void> | void;\n audit(\n context: ReportRefreshActionContext,\n authority?: ReportRefreshExecutionAuthority,\n ): Promise<void> | void;\n /** Capture only a non-secret identity reference for worker-time reauthorization. */\n executionAuthority?(\n context: ReportRefreshActionContext,\n ): ReportRefreshExecutionAuthority | Promise<ReportRefreshExecutionAuthority>;\n /** Server-only signer shared with report worker processes. */\n jobIntegritySigner?(\n context: ReportRefreshActionContext,\n ): DurableJobPayloadSigner | Promise<DurableJobPayloadSigner>;\n}\n\nexport interface PreviewReportRefreshOptions extends ReportLifecycleOptions {\n host: ReportRefreshActionHost;\n mode?: ReportRefreshMode;\n /**\n * Pass `descriptor.refresh.action` when the adapter declares a custom\n * refresh permission, so the displayed and enforced action stay aligned.\n */\n refreshAction?: Pick<ReportRefreshActionDescriptor, 'requiredPermission'>;\n}\n\nexport interface ReportRefreshPreview {\n phase: 'preview';\n lifecycle: ReportLifecycleSnapshot;\n action: ReportRefreshActionContext;\n execution: 'background';\n}\n\nexport interface ApplyReportRefreshOptions extends PreviewReportRefreshOptions {\n jobIntegritySigner?: DurableJobPayloadSigner;\n queue?: string;\n priority?: number;\n timeout?: number;\n maxAttempts?: number;\n tenantJobCap?: number;\n}\n\nexport interface AppliedReportRefresh {\n phase: 'apply';\n job: ReportRefreshJobHandle;\n}\n\nexport interface ReportRefreshOutcome {\n state: 'current' | 'lock-skipped' | 'partial';\n rowCount: number;\n changedGroupCount: number;\n completedScopes: number;\n lockSkippedScopes: number;\n mode: ReportRefreshMode;\n refreshedAt: string;\n runId?: string;\n}\n\nfunction canonicalClassName(reportCtor: ReportCtor): string {\n const registered = registeredReport(reportCtor);\n return registered?.qualifiedName ?? registered?.name ?? reportCtor.name;\n}\n\nfunction reportTableName(reportCtor: ReportCtor): string {\n const reportClassName = canonicalClassName(reportCtor);\n const tableName = ObjectRegistry.getTableName(reportClassName);\n if (!tableName) {\n throw new Error(`No report table registered for ${reportCtor.name}`);\n }\n return validateColumnName(tableName);\n}\n\nasync function reportColumnName(\n reportClassName: string,\n fieldName: string,\n): Promise<string> {\n const fields = await ObjectRegistry.getAllFields(reportClassName);\n const direct = fields.get(fieldName) as\n | { columnName?: string; _meta?: { columnName?: string } }\n | undefined;\n return validateColumnName(\n direct?.columnName ??\n direct?._meta?.columnName ??\n fieldName.replace(/([A-Z])/g, '_$1').toLowerCase(),\n );\n}\n\nfunction toIso(value: unknown): string | undefined {\n if (!value) return undefined;\n const date = value instanceof Date ? value : new Date(String(value));\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString();\n}\n\nfunction latestIso(\n first: string | undefined,\n second: string | undefined,\n): string | undefined {\n if (!first) return second;\n if (!second) return first;\n return new Date(first).getTime() >= new Date(second).getTime()\n ? first\n : second;\n}\n\nfunction lifecycleTenantId(reportCtor: ReportCtor): string | null {\n return registeredReport(reportCtor)?.tenantScopedConfig\n ? (getTenantId() ?? null)\n : null;\n}\n\nfunction numberValue(value: unknown): number {\n const numeric = Number(value ?? 0);\n return Number.isFinite(numeric) ? numeric : 0;\n}\n\nfunction rowWhere(\n reportClassName: string,\n scopeKey: string,\n tenantId: string | null,\n): { sql: string; values: unknown[] } {\n if (tenantId) {\n return {\n sql: 'report_class = ? AND scope_key = ? AND tenant_id = ?',\n values: [reportClassName, scopeKey, tenantId],\n };\n }\n return {\n sql: 'report_class = ? AND scope_key = ? AND tenant_id IS NULL',\n values: [reportClassName, scopeKey],\n };\n}\n\nfunction runFromRow(\n row: Record<string, unknown> | undefined,\n): ReportLifecycleRun | undefined {\n if (!row || typeof row.id !== 'string') return undefined;\n const status = row.status;\n if (\n status !== 'running' &&\n status !== 'success' &&\n status !== 'failed' &&\n status !== 'skipped'\n ) {\n return undefined;\n }\n const mode: ReportRefreshMode =\n row.mode === 'incremental' ? 'incremental' : 'rebuild';\n const trigger: ReportRefreshTrigger =\n row.trigger === 'schedule' ||\n row.trigger === 'change' ||\n row.trigger === 'ttl' ||\n row.trigger === 'job'\n ? row.trigger\n : 'manual';\n return {\n id: row.id,\n status,\n mode,\n trigger,\n ...(toIso(row.started_at) ? { startedAt: toIso(row.started_at) } : {}),\n ...(toIso(row.completed_at)\n ? { completedAt: toIso(row.completed_at) }\n : {}),\n rowCount: numberValue(row.row_count),\n changedGroupCount: numberValue(row.changed_group_count),\n mayRetry: status === 'failed',\n };\n}\n\nfunction jobHandle(job: {\n id?: unknown;\n status: ReportRefreshJobHandle['status'];\n attempts: number;\n maxAttempts: number;\n}): ReportRefreshJobHandle {\n if (typeof job.id !== 'string' || job.id.length === 0) {\n throw new Error('Queued report refresh is missing its job id');\n }\n return {\n jobId: job.id,\n status: job.status,\n attempts: job.attempts,\n maxAttempts: job.maxAttempts,\n pollAfterMs: 1_000,\n };\n}\n\n/**\n * Read only the ambient tenant's report state. The caller cannot supply a\n * tenant selector, which prevents lifecycle lookup from becoming a tenant\n * enumeration surface.\n */\nexport async function getReportLifecycle(\n reportCtor: ReportCtor,\n options: ReportLifecycleOptions,\n): Promise<ReportLifecycleSnapshot> {\n await assertReportTablesReady(options.db, [\n REPORT_RUNS_TABLE,\n REPORT_LOCKS_TABLE,\n ]);\n\n const definition = await buildReportDefinition(reportCtor);\n const reportClassName = canonicalClassName(reportCtor);\n const tenantId = lifecycleTenantId(reportCtor);\n const scopeKey = scopeKeyForTenant(tenantId);\n const where = rowWhere(reportClassName, scopeKey, tenantId);\n const now = options.now ?? new Date();\n\n const [runResult, lockResult] = await Promise.all([\n options.db.query(\n `SELECT id, mode, trigger, status, started_at, completed_at, row_count, changed_group_count\n FROM ${REPORT_RUNS_TABLE}\n WHERE ${where.sql}\n ORDER BY started_at DESC, created_at DESC, id DESC\n LIMIT 1`,\n ...where.values,\n ),\n options.db.query(\n `SELECT expires_at\n FROM ${REPORT_LOCKS_TABLE}\n WHERE ${where.sql} AND expires_at > ?\n LIMIT 1`,\n ...where.values,\n now.toISOString(),\n ),\n ]);\n\n const tableName = reportTableName(reportCtor);\n if (!(await tableExists(options.db, tableName))) {\n throw new Error(\n `Report table '${tableName}' does not exist for ${reportClassName}`,\n );\n }\n const refreshedAtColumn = await reportColumnName(\n reportClassName,\n 'refreshedAt',\n );\n const registered = registeredReport(reportCtor);\n const configuredTenantField = registered?.tenantScopedConfig?.field;\n const tenantColumn = configuredTenantField\n ? await reportColumnName(reportClassName, configuredTenantField)\n : undefined;\n const materialized = tenantColumn\n ? await options.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${tableName} WHERE ${tenantColumn} ${tenantId ? '= ?' : 'IS NULL'}`,\n ...(tenantId ? [tenantId] : []),\n )\n : await options.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${tableName}`,\n );\n\n const run = runFromRow(\n runResult.rows[0] as Record<string, unknown> | undefined,\n );\n const refreshedAt = toIso(materialized.rows[0]?.refreshed_at);\n const completedAt = run?.status === 'success' ? run.completedAt : undefined;\n const asOf = latestIso(refreshedAt, completedAt);\n const ttlMs = definition.refresh?.ttl;\n const isStale =\n !asOf ||\n (ttlMs !== undefined && now.getTime() - new Date(asOf).getTime() > ttlMs);\n const lockExpiresAt = toIso(lockResult.rows[0]?.expires_at);\n const lockHeld = Boolean(lockExpiresAt);\n const state: ReportLifecycleState =\n run?.status === 'skipped'\n ? 'lock-skipped'\n : lockHeld\n ? 'refreshing'\n : run?.status === 'failed'\n ? 'failed'\n : run?.status === 'running'\n ? 'stale'\n : isStale\n ? 'stale'\n : 'current';\n\n return {\n version: 1,\n state,\n ...(asOf ? { asOf } : {}),\n ...(refreshedAt ? { refreshedAt } : {}),\n hasUsableRows: Boolean(refreshedAt),\n mode: run?.mode ?? definition.refresh?.mode ?? 'rebuild',\n ...(run ? { run } : {}),\n ...(run?.status === 'failed'\n ? { failure: { code: 'refresh_failed' as const, retryable: true } }\n : {}),\n lock: {\n held: lockHeld,\n ...(lockExpiresAt ? { expiresAt: lockExpiresAt } : {}),\n },\n };\n}\n\nfunction actionContext(\n reportCtor: ReportCtor,\n phase: ReportRefreshActionContext['phase'],\n mode: ReportRefreshMode,\n refreshAction:\n | Pick<ReportRefreshActionDescriptor, 'requiredPermission'>\n | undefined,\n): ReportRefreshActionContext {\n return {\n phase,\n reportClassName: canonicalClassName(reportCtor),\n tenantScope: 'ambient',\n mode,\n requiredPermission:\n refreshAction?.requiredPermission &&\n refreshAction.requiredPermission.trim().length > 0\n ? refreshAction.requiredPermission\n : 'reports.refresh',\n };\n}\n\nasync function actionMode(\n reportCtor: ReportCtor,\n requested: ReportRefreshMode | undefined,\n): Promise<ReportRefreshMode> {\n if (requested) return requested;\n const definition = await buildReportDefinition(reportCtor);\n return definition.refresh?.mode ?? 'rebuild';\n}\n\n/** Preview only declares a separately authorized and audited refresh request. */\nexport async function previewReportRefresh(\n reportCtor: ReportCtor,\n options: PreviewReportRefreshOptions,\n): Promise<ReportRefreshPreview> {\n const mode = await actionMode(reportCtor, options.mode);\n const action = actionContext(\n reportCtor,\n 'preview',\n mode,\n options.refreshAction,\n );\n await options.host.authorize(action);\n await options.host.audit(action);\n return {\n phase: 'preview',\n lifecycle: await getReportLifecycle(reportCtor, options),\n action,\n execution: 'background',\n };\n}\n\n/** Queue a manual refresh only after the action host authorizes and audits it. */\nexport async function applyReportRefresh(\n reportCtor: ReportCtor,\n options: ApplyReportRefreshOptions,\n): Promise<AppliedReportRefresh> {\n const mode = await actionMode(reportCtor, options.mode);\n const action = actionContext(\n reportCtor,\n 'apply',\n mode,\n options.refreshAction,\n );\n const executionAuthority = await options.host.executionAuthority?.(action);\n if (!executionAuthority) {\n throw new Error('Manual report refresh requires execution-time authority');\n }\n await options.host.authorize(action, executionAuthority);\n await options.host.audit(action, executionAuthority);\n const integritySigner =\n options.jobIntegritySigner ??\n (await options.host.jobIntegritySigner?.(action));\n if (!integritySigner) {\n throw new Error(\n 'Report refresh queue requires a durable job integrity signer',\n );\n }\n const tenantId = lifecycleTenantId(reportCtor);\n const enqueue = () =>\n enqueueReportRefresh({\n db: options.db,\n reportClass: canonicalClassName(reportCtor),\n mode,\n trigger: 'manual',\n tenantId,\n executionAuthority,\n queue: options.queue,\n priority: options.priority,\n timeout: options.timeout,\n maxAttempts: options.maxAttempts,\n tenantJobCap: options.tenantJobCap,\n integritySigner,\n });\n const job =\n tenantId === null && getTenantId()\n ? await withSystemContext(enqueue)\n : await enqueue();\n return { phase: 'apply', job: jobHandle(job) };\n}\n\n/** Normalize executor results without exposing the tenant identifiers in a fanout. */\nexport function reportRefreshOutcome(\n result: ReportRefreshResult,\n): ReportRefreshOutcome {\n const scopes = result.tenantResults ?? [result];\n const lockSkippedScopes = scopes.filter((scope) => scope.skipped).length;\n const completedScopes = scopes.length - lockSkippedScopes;\n return {\n state:\n scopes.length > 1 && lockSkippedScopes > 0\n ? 'partial'\n : lockSkippedScopes > 0\n ? 'lock-skipped'\n : 'current',\n rowCount: result.rowCount,\n changedGroupCount: result.changedGroupCount ?? 0,\n completedScopes,\n lockSkippedScopes,\n mode: result.mode,\n refreshedAt: result.refreshedAt.toISOString(),\n ...(result.runId ? { runId: result.runId } : {}),\n };\n}\n","import {\n createDataQueryFingerprint,\n DataQueryValidationError,\n normalizeDataQueryRequest,\n normalizeDataQueryResult,\n ObjectRegistry,\n type SmrtObject,\n} from '@happyvertical/smrt-core';\nimport { toSnakeCase } from '@happyvertical/smrt-core/utils';\nimport type {\n DataQueryCondition,\n DataQueryFieldDescriptor,\n DataQueryFilter,\n DataQueryFilterOperator,\n DataQueryFreshness,\n DataQueryRequest,\n DataQueryResult,\n DataQueryScalar,\n DataQuerySchema,\n} from '@happyvertical/smrt-types';\nimport { buildReportDefinition } from './compiler.js';\nimport {\n getReportLifecycle,\n type ReportLifecycleOptions,\n type ReportLifecycleSnapshot,\n} from './lifecycle.js';\nimport type {\n ReportAggregateFn,\n ReportDefinition,\n ReportFieldDefinition,\n ReportRefreshConfig,\n ReportTimeBucketUnit,\n} from './types.js';\n\n/** Presentation and policy metadata understood by the report adapter. */\nexport type ReportColumnSensitivity =\n | 'public'\n | 'personal'\n | 'sensitive'\n | 'secret';\n\nexport type ReportColumnCapability =\n | 'read'\n | 'project'\n | 'filter'\n | 'sort'\n | 'facet'\n | 'group'\n | 'aggregate';\n\nexport type ReportColumnKind = 'identity' | 'group' | 'bucket' | 'aggregate';\n\n/**\n * Source-query clause a field belongs to. The materialized read executor\n * applies both kinds through its tenant-scoped collection, but consumers use\n * this declaration to keep dimensions/periods (WHERE) distinct from measures\n * (HAVING) when constructing drilldowns, saved views, or a live query.\n */\nexport type ReportFilterScope = 'where' | 'having';\n\nexport interface ReportColumnDescriptor extends DataQueryFieldDescriptor {\n /** Stable output column id (never a property path). */\n id: string;\n fieldName: string;\n label: string;\n kind: ReportColumnKind;\n filterScope: ReportFilterScope;\n /** Capabilities available from this adapter revision. */\n capabilities: ReportColumnCapability[];\n format?: string;\n sensitivity?: ReportColumnSensitivity;\n sourceColumn?: string;\n bucket?: ReportTimeBucketUnit;\n aggregate?: ReportAggregateFn;\n distinct?: boolean;\n}\n\nexport interface ReportRefreshDescriptor {\n mode: 'rebuild' | 'incremental';\n /**\n * Whether the report configuration lets a registered SmrtReportCollection\n * synchronously refresh a stale read. Generic collection reads stay\n * read-only and report unknown freshness until the lifecycle adapter runs.\n */\n mayRefreshOnRead: boolean;\n ttlMs?: number;\n triggers: Array<'manual' | 'schedule' | 'change' | 'ttl' | 'job'>;\n /** Declared only; the lifecycle adapter owns authorization, audit, and run state. */\n action: ReportRefreshActionDescriptor;\n}\n\n/** A report-wide lifecycle action, never a mutation performed by this adapter. */\nexport interface ReportRefreshActionDescriptor {\n id: 'refresh';\n label: 'Refresh report';\n scope: 'surface';\n phases: Array<'preview' | 'apply'>;\n requiresPermission: true;\n requiredPermission: string;\n auditRequired: true;\n}\n\n/**\n * The report-owned, transport-neutral descriptor. Consumers can map `schema`\n * to the canonical data-query runtime and `columns` to their presentation\n * contract without importing smrt-ui or a report domain class.\n */\nexport interface ReportAdapterDescriptor {\n version: 1;\n resourceId: string;\n reportClassName: string;\n sourceClassName: string;\n tenantScoped: boolean;\n tenantField?: string;\n identityField: 'id';\n columns: ReportColumnDescriptor[];\n schema: DataQuerySchema;\n queryExecution: ReportQueryExecutionDescriptor;\n dataTable: ReportDataTableDescriptor;\n drilldown: ReportDrilldownDescriptor;\n refresh: ReportRefreshDescriptor;\n}\n\n/**\n * Delivery choices for the same bounded report query. They never add\n * authority: a host owns visible state and background-job execution.\n */\nexport type ReportQueryExecutionMode = 'visible' | 'background' | 'silent';\n\nexport interface ReportQueryExecutionDescriptor {\n modes: ReportQueryExecutionMode[];\n /** The caller may apply the returned rows to an already-authorized surface. */\n visible: { delivery: 'result' };\n /** A host queues the authority-free task and returns no materialized rows yet. */\n background: { delivery: 'queued'; requiresHost: true };\n /** The caller receives rows but the adapter makes no visible-surface change. */\n silent: { delivery: 'result'; mutatesVisibleSurface: false };\n}\n\n/**\n * The exact bounded request a background host may persist. Tenant, principal,\n * collection, database, and display state deliberately remain with that host.\n */\nexport interface ReportBackgroundQueryTask {\n version: 1;\n execution: 'background';\n resourceId: string;\n reportClassName: string;\n request: DataQueryRequest;\n inherits: Array<\n 'principal' | 'tenant' | 'report-definition' | 'field-policy'\n >;\n}\n\n/** Queuing a background query returns a handle, never rows from another scope. */\nexport interface ReportBackgroundQueryResult {\n version: 1;\n execution: 'background';\n status: 'queued';\n taskId: string;\n queryFingerprint: string;\n}\n\n/** One row value that can safely constrain a source-record drilldown. */\nexport interface ReportDrilldownFieldDescriptor {\n /** Stable report column id; never a display label. */\n id: string;\n /** Declared source field/column chosen by report metadata, not caller input. */\n sourceColumn: string;\n kind: 'group' | 'bucket';\n /** A bucket stays declarative so the source adapter preserves report timezone semantics. */\n bucket?: ReportTimeBucketUnit;\n}\n\n/**\n * Declarative source-query handoff for a report row. No client can supply a\n * principal, tenant, report definition, or arbitrary source field here.\n */\nexport interface ReportDrilldownDescriptor {\n id: 'drilldown';\n sourceClassName: string;\n fields: ReportDrilldownFieldDescriptor[];\n inherits: Array<\n 'principal' | 'tenant' | 'report-definition' | 'field-policy'\n >;\n}\n\nexport interface ReportDrilldownConstraint {\n id: string;\n sourceColumn: string;\n kind: 'group' | 'bucket';\n value: unknown;\n bucket?: ReportTimeBucketUnit;\n}\n\n/** A server adapter uses this authority-free handoff to execute a source drilldown. */\nexport interface ReportDrilldownQuery {\n version: 1;\n resourceId: string;\n reportClassName: string;\n sourceClassName: string;\n constraints: ReportDrilldownConstraint[];\n inherits: Array<\n 'principal' | 'tenant' | 'report-definition' | 'field-policy'\n >;\n}\n\n/** Structural DataTable view hints; deliberately not a smrt-ui dependency. */\nexport interface ReportDataTableHeaderPathSegment {\n /** Stable group identity within a header level. */\n id: string;\n /** Human-readable grouped-header label. */\n label: string;\n}\n\n/** Responsive metadata that maps directly to a consumer's table contract. */\nexport interface ReportDataTableColumnResponsive {\n /** Higher values make a column more important during responsive collapse. */\n priority?: number;\n /** Keep key dimensions reachable during responsive collapse. */\n keepVisible?: boolean;\n}\n\n/**\n * A rendering instruction for a raw materialized value. Formatting is never\n * applied to a query row, so sorting, export, and agent consumers retain it.\n */\nexport type ReportDataTableValueFormat =\n | 'text'\n | 'date'\n | 'datetime'\n | 'percentage'\n | 'count'\n | 'money'\n | 'number';\n\nexport type ReportDataTableColumnRole = 'data' | 'status' | 'action';\n\nexport interface ReportDataTableColumn {\n id: string;\n label: string;\n accessor: string;\n sortable: boolean;\n searchable: false;\n filterable: boolean;\n /** Group ancestry for consumers with multi-level table headers. */\n headerPath: ReportDataTableHeaderPathSegment[];\n /** Consumer-side display instruction; materialized rows remain raw. */\n valueFormat: ReportDataTableValueFormat;\n /** The default alignment for the formatted display value. */\n align: 'left' | 'right';\n /** Generic semantic role for status/action columns introduced by later slices. */\n role: ReportDataTableColumnRole;\n responsive: ReportDataTableColumnResponsive;\n}\n\nexport type ReportDataTableStructuralRowKind =\n | 'summary'\n | 'subtotal'\n | 'aggregate'\n | 'footer';\n\n/** Input supplied by a report consumer that computes a summary or subtotal. */\nexport interface ReportDataTableStructuralRowInput {\n id: string;\n kind: ReportDataTableStructuralRowKind;\n label: string;\n /** Raw values keyed by the adapter's stable column id. */\n values?: Readonly<Record<string, unknown>>;\n /** Column that renders this row's accessible row header. */\n labelColumnId?: string;\n}\n\n/**\n * Structural rows are intentionally separate from materialized data rows.\n * Consumers pass them to their DataTable's structural-row slot/prop, never its\n * selectable data collection.\n */\nexport interface ReportDataTableStructuralRow\n extends ReportDataTableStructuralRowInput {\n selection: 'excluded';\n actions: 'excluded';\n}\n\n/** Per-column presentation overrides owned by the consuming report surface. */\nexport interface ReportDataTableColumnOverride {\n label?: string;\n headerPath?: readonly ReportDataTableHeaderPathSegment[];\n valueFormat?: ReportDataTableValueFormat;\n align?: 'left' | 'right';\n role?: ReportDataTableColumnRole;\n responsive?: ReportDataTableColumnResponsive;\n}\n\nexport interface ReportDataTablePresentationOptions {\n /** Overrides are keyed by stable adapter column id, not display labels. */\n columns?: Readonly<Record<string, ReportDataTableColumnOverride>>;\n /** Summary/subtotal rows remain structural rather than materialized data rows. */\n structuralRows?: readonly ReportDataTableStructuralRowInput[];\n}\n\nexport interface ReportDataTableDescriptor {\n rowKey: 'id';\n manualPagination: true;\n manualSorting: true;\n enableFiltering: true;\n enableSearch: false;\n columns: ReportDataTableColumn[];\n structuralRows: ReportDataTableStructuralRow[];\n}\n\nexport interface ReportAdapterOptions {\n /** Scope used only to make a stable resource id; it is not authority. */\n tenantScope?: 'current' | 'global' | 'tenant';\n /** Permission that a lifecycle action host must require before refresh. */\n refreshPermission?: string;\n /** Consumer-owned presentational preferences; they never affect query rows. */\n dataTable?: ReportDataTablePresentationOptions;\n}\n\ninterface ReportQueryCommonOptions {\n /** Injected collection seam for tests and application-owned adapters. */\n collection?: {\n list(\n options: Record<string, unknown>,\n ): Promise<Array<Record<string, unknown>>>;\n count(options?: Record<string, unknown>): Promise<number>;\n facets?(options: Record<string, unknown>): Promise<\n Array<{\n field: string;\n values: Array<{\n value: string | number | boolean | null;\n count: number;\n }>;\n }>\n >;\n };\n db?: import('@happyvertical/sql').DatabaseInterface;\n /**\n * Consumer-owned descriptor preferences. They contribute to the stable\n * resource identity and must match the catalog used to select this report.\n */\n adapter?: ReportAdapterOptions;\n /**\n * Opt in to a tenant-safe lifecycle snapshot alongside this materialized\n * read. It never makes a generic read mutate.\n */\n lifecycle?: Omit<ReportLifecycleOptions, 'db'>;\n}\n\n/** Visible is the default; silent has identical data authority but no UI intent. */\nexport interface ReportQueryOptions extends ReportQueryCommonOptions {\n execution?: 'visible' | 'silent';\n}\n\n/** Background execution is possible only through an application-owned queue host. */\nexport interface ReportBackgroundQueryOptions extends ReportQueryCommonOptions {\n execution: 'background';\n enqueueBackgroundQuery(\n task: ReportBackgroundQueryTask,\n ): Promise<{ taskId: string }>;\n}\n\n/** Lifecycle context attached only when a caller explicitly opts in. */\nexport interface ReportMaterializedReadLifecycle {\n snapshot: ReportLifecycleSnapshot;\n /** Whether this collection read appears to have completed a TTL refresh. */\n read: 'current' | 'stale' | 'refresh-triggered';\n}\n\nexport interface ReportDataQueryResult extends DataQueryResult {\n /** Delivery intent only; the adapter never mutates a visible surface. */\n execution: 'visible' | 'silent';\n reportLifecycle?: ReportMaterializedReadLifecycle;\n}\n\ntype RegistryField = {\n type?: string;\n transient?: boolean;\n description?: string;\n sensitive?: boolean;\n readPermission?: string;\n format?: unknown;\n sensitivity?: unknown;\n _meta?: Record<string, unknown>;\n};\nconst SENSITIVITIES = new Set<ReportColumnSensitivity>([\n 'public',\n 'personal',\n 'sensitive',\n 'secret',\n]);\n\nfunction registeredClass(\n ctor: new (...args: any[]) => SmrtObject,\n): ReturnType<typeof ObjectRegistry.getClassByConstructor> {\n return (\n ObjectRegistry.getClassByConstructor(ctor) ??\n ObjectRegistry.getClass(ctor.name)\n );\n}\n\nfunction fieldPolicy(field: RegistryField | undefined): {\n sensitive: boolean;\n readPermission?: string;\n} {\n const meta = field?._meta ?? {};\n const sensitivity = [field?.sensitivity, meta.sensitivity].find(\n (value): value is string => typeof value === 'string',\n );\n return {\n sensitive:\n field?.sensitive === true ||\n meta.sensitive === true ||\n sensitivity === 'sensitive' ||\n sensitivity === 'secret',\n readPermission:\n typeof field?.readPermission === 'string'\n ? field.readPermission\n : typeof meta.readPermission === 'string'\n ? meta.readPermission\n : undefined,\n };\n}\n\nfunction descriptorMetadata(field: RegistryField | undefined): {\n format?: string;\n sensitivity?: ReportColumnSensitivity;\n} {\n const metadata = field?._meta ?? {};\n const format = [field?.format, metadata.format].find(\n (value): value is string => typeof value === 'string' && value.length > 0,\n );\n const rawSensitivity = [field?.sensitivity, metadata.sensitivity].find(\n (value): value is string =>\n typeof value === 'string' &&\n SENSITIVITIES.has(value as ReportColumnSensitivity),\n );\n return {\n ...(format ? { format } : {}),\n ...(rawSensitivity\n ? { sensitivity: rawSensitivity as ReportColumnSensitivity }\n : {}),\n };\n}\n\nfunction labelFor(fieldName: string): string {\n return fieldName\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .replace(/^./, (value) => value.toUpperCase());\n}\n\nfunction queryType(type: string | undefined): DataQueryFieldDescriptor['type'] {\n switch (type) {\n case 'integer':\n case 'decimal':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'datetime';\n case 'json':\n return 'json';\n default:\n return 'string';\n }\n}\n\nfunction configuredTenantField(configured?: string): string | undefined {\n return configured ? toSnakeCase(configured) : undefined;\n}\n\nfunction isColumnBackedField(field: RegistryField | undefined): boolean {\n if (!field) return false;\n if (field.transient === true || field._meta?.transient === true) return false;\n return !['meta', 'oneToMany', 'manyToMany'].includes(field.type ?? '');\n}\n\nfunction reportColumn(\n field: ReportFieldDefinition,\n registryField: RegistryField | undefined,\n): ReportColumnDescriptor | undefined {\n const policy = fieldPolicy(registryField);\n // A descriptor is an exposure boundary. Without a principal/permission\n // context, sensitive, permission-gated, and non-column fields fail closed.\n if (\n policy.sensitive ||\n policy.readPermission ||\n !isColumnBackedField(registryField)\n ) {\n return undefined;\n }\n\n const id = field.columnName ?? toSnakeCase(field.fieldName);\n const report = field.report;\n if (!report) return undefined;\n const type = queryType(field.type ?? registryField?.type);\n const filterOperators = filterOperatorsFor(type);\n const base: ReportColumnDescriptor = {\n id,\n fieldName: field.fieldName,\n label: registryField?.description || labelFor(field.fieldName),\n kind: report.kind,\n filterScope: report.kind === 'aggregate' ? 'having' : 'where',\n type,\n projectable: true,\n sortable: true,\n facetable: report.kind !== 'aggregate',\n ...(filterOperators ? { filterOperators } : {}),\n capabilities: [\n 'project',\n 'read',\n ...(filterOperators ? (['filter'] as const) : []),\n 'sort',\n ...(report.kind !== 'aggregate' ? (['facet'] as const) : []),\n ...(report.kind === 'aggregate'\n ? (['aggregate'] as const)\n : report.kind === 'group'\n ? (['group'] as const)\n : []),\n ],\n ...(report.kind === 'group'\n ? { sourceColumn: toSnakeCase(report.sourceColumn ?? field.fieldName) }\n : {}),\n ...(report.kind === 'bucket'\n ? { bucket: report.unit, sourceColumn: toSnakeCase(report.sourceColumn) }\n : {}),\n ...(report.kind === 'aggregate'\n ? {\n aggregate: report.fn,\n ...(report.column\n ? { sourceColumn: toSnakeCase(report.column) }\n : {}),\n ...(report.distinct === undefined\n ? {}\n : { distinct: report.distinct }),\n }\n : {}),\n ...descriptorMetadata(registryField),\n };\n return base;\n}\n\nfunction identityColumn(): ReportColumnDescriptor {\n return {\n id: 'id',\n fieldName: 'id',\n label: 'ID',\n kind: 'identity',\n filterScope: 'where',\n type: 'string',\n projectable: true,\n sortable: true,\n facetable: false,\n filterOperators: filterOperatorsFor('string'),\n capabilities: ['project', 'read', 'filter', 'sort'],\n };\n}\n\nfunction toQueryField(\n column: ReportColumnDescriptor,\n): DataQueryFieldDescriptor {\n return {\n id: column.id,\n type: column.type,\n ...(column.projectable === undefined\n ? {}\n : { projectable: column.projectable }),\n sortable: column.sortable === true,\n facetable: column.facetable === true,\n ...(column.filterOperators === undefined\n ? {}\n : { filterOperators: [...column.filterOperators] }),\n };\n}\n\nfunction filterOperatorsFor(\n type: DataQueryFieldDescriptor['type'],\n): DataQueryFilterOperator[] | undefined {\n switch (type) {\n case 'string':\n return ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', 'like'];\n case 'number':\n case 'datetime':\n return ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn'];\n case 'boolean':\n return ['eq', 'ne', 'in', 'notIn'];\n case 'json':\n return undefined;\n }\n}\n\nfunction refreshDescriptor(\n refresh?: ReportRefreshConfig,\n refreshPermission = 'reports.refresh',\n): ReportRefreshDescriptor {\n const config = refresh ?? {};\n const triggers = new Set<ReportRefreshDescriptor['triggers'][number]>([\n 'manual',\n ]);\n if (!config.manual) {\n const hasSchedule = Boolean(config.schedule || config.fullRebuildSchedule);\n const hasChangeTrigger = Boolean(config.onChange?.length);\n if (hasSchedule) triggers.add('schedule');\n if (hasChangeTrigger) triggers.add('change');\n if (config.ttl !== undefined && config.ttl > 0) triggers.add('ttl');\n // Scheduler and on-change refreshes enqueue a durable job in either mode;\n // incremental mode alone is not itself a trigger.\n if (hasSchedule || hasChangeTrigger) triggers.add('job');\n }\n return {\n mode: config.mode ?? 'rebuild',\n mayRefreshOnRead:\n config.ttl !== undefined && config.ttl > 0 && !config.manual,\n ...(config.ttl === undefined ? {} : { ttlMs: config.ttl }),\n triggers: [...triggers],\n action: {\n id: 'refresh',\n label: 'Refresh report',\n scope: 'surface',\n phases: ['preview', 'apply'],\n requiresPermission: true,\n requiredPermission:\n refreshPermission.trim().length > 0\n ? refreshPermission\n : 'reports.refresh',\n auditRequired: true,\n },\n };\n}\n\nfunction resourceId(\n definition: ReportDefinition,\n scope: ReportAdapterOptions['tenantScope'],\n): string {\n return `${definition.reportClassName}#${scope ?? 'current'}`;\n}\n\nconst VALUE_FORMAT_ALIASES: Readonly<\n Record<string, ReportDataTableValueFormat>\n> = {\n text: 'text',\n date: 'date',\n datetime: 'datetime',\n 'date-time': 'datetime',\n percentage: 'percentage',\n percent: 'percentage',\n count: 'count',\n money: 'money',\n currency: 'money',\n number: 'number',\n decimal: 'number',\n integer: 'number',\n};\n\nconst VALUE_FORMATS = new Set<ReportDataTableValueFormat>(\n Object.values(VALUE_FORMAT_ALIASES),\n);\nconst COLUMN_ROLES = new Set<ReportDataTableColumnRole>([\n 'data',\n 'status',\n 'action',\n]);\nconst STRUCTURAL_ROW_KINDS = new Set<ReportDataTableStructuralRowKind>([\n 'summary',\n 'subtotal',\n 'aggregate',\n 'footer',\n]);\n\nfunction valueFormat(\n column: ReportColumnDescriptor,\n): ReportDataTableValueFormat {\n const configured = column.format?.trim().toLowerCase();\n if (configured && Object.hasOwn(VALUE_FORMAT_ALIASES, configured)) {\n return VALUE_FORMAT_ALIASES[configured];\n }\n if (column.kind === 'bucket') {\n return column.bucket === 'minute' || column.bucket === 'hour'\n ? 'datetime'\n : 'date';\n }\n if (column.kind === 'aggregate' && column.aggregate === 'count') {\n return 'count';\n }\n if (column.type === 'datetime') return 'datetime';\n if (column.type === 'number') return 'number';\n return 'text';\n}\n\nfunction headerPath(\n column: ReportColumnDescriptor,\n): ReportDataTableHeaderPathSegment[] {\n if (column.kind === 'aggregate') {\n return [\n { id: 'measures', label: 'Measures' },\n {\n id: `aggregate:${column.aggregate ?? 'value'}`,\n label: labelFor(column.aggregate ?? 'value'),\n },\n ];\n }\n if (column.kind === 'bucket') {\n return [\n { id: 'dimensions', label: 'Dimensions' },\n { id: 'time', label: 'Time' },\n ];\n }\n if (column.kind === 'group') {\n return [\n { id: 'dimensions', label: 'Dimensions' },\n { id: 'groups', label: 'Groups' },\n ];\n }\n return [{ id: 'dimensions', label: 'Dimensions' }];\n}\n\nfunction responsive(\n column: ReportColumnDescriptor,\n): ReportDataTableColumnResponsive {\n if (column.kind === 'group' || column.kind === 'bucket') {\n return { priority: 100, keepVisible: true };\n }\n if (column.kind === 'identity') return { priority: 80 };\n return { priority: 20 };\n}\n\nfunction assertHeaderPath(\n columnId: string,\n path: readonly ReportDataTableHeaderPathSegment[],\n): ReportDataTableHeaderPathSegment[] {\n if (!Array.isArray(path)) {\n throw new TypeError(\n `Report DataTable headerPath for ${columnId} must be an array`,\n );\n }\n return path.map((segment) => {\n if (\n !segment ||\n typeof segment.id !== 'string' ||\n segment.id.trim().length === 0 ||\n typeof segment.label !== 'string' ||\n segment.label.trim().length === 0\n ) {\n throw new TypeError(\n `Report DataTable headerPath entries for ${columnId} require non-empty id and label`,\n );\n }\n return { id: segment.id, label: segment.label };\n });\n}\n\nfunction dataTableColumn(\n column: ReportColumnDescriptor,\n override?: ReportDataTableColumnOverride,\n): ReportDataTableColumn {\n const format = override?.valueFormat ?? valueFormat(column);\n const path = override?.headerPath ?? headerPath(column);\n if (!VALUE_FORMATS.has(format)) {\n throw new TypeError(\n `Report DataTable valueFormat for ${column.id} is not supported: ${String(format)}`,\n );\n }\n if (override?.role !== undefined && !COLUMN_ROLES.has(override.role)) {\n throw new TypeError(\n `Report DataTable role for ${column.id} is not supported: ${String(override.role)}`,\n );\n }\n if (\n override?.label !== undefined &&\n (typeof override.label !== 'string' || override.label.trim().length === 0)\n ) {\n throw new TypeError(\n `Report DataTable label for ${column.id} must not be empty`,\n );\n }\n if (\n override?.align !== undefined &&\n override.align !== 'left' &&\n override.align !== 'right'\n ) {\n throw new TypeError(\n `Report DataTable align for ${column.id} is not supported: ${String(override.align)}`,\n );\n }\n if (\n override?.responsive?.priority !== undefined &&\n (!Number.isFinite(override.responsive.priority) ||\n override.responsive.priority < 0)\n ) {\n throw new TypeError(\n `Report DataTable responsive priority for ${column.id} must be a non-negative finite number`,\n );\n }\n if (\n override?.responsive?.keepVisible !== undefined &&\n typeof override.responsive.keepVisible !== 'boolean'\n ) {\n throw new TypeError(\n `Report DataTable keepVisible for ${column.id} must be a boolean`,\n );\n }\n return {\n id: column.id,\n label: override?.label ?? column.label,\n accessor: column.id,\n sortable: column.sortable === true,\n searchable: false,\n filterable: column.filterOperators !== undefined,\n headerPath: assertHeaderPath(column.id, path),\n valueFormat: format,\n align:\n override?.align ??\n (['count', 'money', 'number', 'percentage'].includes(format)\n ? 'right'\n : 'left'),\n role: override?.role ?? 'data',\n responsive: { ...responsive(column), ...override?.responsive },\n };\n}\n\nfunction structuralRows(\n columnIds: ReadonlySet<string>,\n rows: readonly ReportDataTableStructuralRowInput[] = [],\n): ReportDataTableStructuralRow[] {\n const ids = new Set<string>();\n return rows.map((row) => {\n if (\n !row ||\n typeof row.id !== 'string' ||\n row.id.trim().length === 0 ||\n typeof row.label !== 'string' ||\n row.label.trim().length === 0\n ) {\n throw new TypeError(\n 'Report structural rows require non-empty id and label values',\n );\n }\n if (ids.has(row.id)) {\n throw new TypeError(`Report structural row id must be unique: ${row.id}`);\n }\n if (!STRUCTURAL_ROW_KINDS.has(row.kind)) {\n throw new TypeError(\n `Report structural row kind is not supported: ${String(row.kind)}`,\n );\n }\n if (row.labelColumnId !== undefined) {\n if (\n typeof row.labelColumnId !== 'string' ||\n row.labelColumnId.trim().length === 0 ||\n !columnIds.has(row.labelColumnId)\n ) {\n throw new TypeError(\n `Report structural row labelColumnId must name an adapter column: ${String(row.labelColumnId)}`,\n );\n }\n }\n if (\n row.values !== undefined &&\n (typeof row.values !== 'object' ||\n row.values === null ||\n Array.isArray(row.values))\n ) {\n throw new TypeError('Report structural row values must be an object');\n }\n if (\n row.values &&\n Object.keys(row.values).some((columnId) => !columnIds.has(columnId))\n ) {\n throw new TypeError(\n 'Report structural row values must use adapter column ids',\n );\n }\n ids.add(row.id);\n return {\n id: row.id,\n kind: row.kind,\n label: row.label,\n ...(row.values !== undefined\n ? {\n values: jsonSafeValue(row.values) as Record<string, unknown>,\n }\n : {}),\n ...(row.labelColumnId !== undefined\n ? { labelColumnId: row.labelColumnId }\n : {}),\n selection: 'excluded' as const,\n actions: 'excluded' as const,\n };\n });\n}\n\nfunction drilldownDescriptor(\n columns: readonly ReportColumnDescriptor[],\n sourceClassName: string,\n): ReportDrilldownDescriptor {\n return {\n id: 'drilldown',\n sourceClassName,\n fields: columns\n .filter(\n (\n column,\n ): column is ReportColumnDescriptor & {\n kind: 'group' | 'bucket';\n sourceColumn: string;\n } =>\n (column.kind === 'group' || column.kind === 'bucket') &&\n typeof column.sourceColumn === 'string',\n )\n .map((column) => ({\n id: column.id,\n sourceColumn: column.sourceColumn,\n kind: column.kind,\n ...(column.kind === 'bucket' && column.bucket\n ? { bucket: column.bucket }\n : {}),\n })),\n inherits: ['principal', 'tenant', 'report-definition', 'field-policy'],\n };\n}\n\nexport async function buildReportAdapterDescriptor(\n reportCtor: new (...args: any[]) => SmrtObject,\n options: ReportAdapterOptions = {},\n): Promise<ReportAdapterDescriptor> {\n const definition = await buildReportDefinition(reportCtor);\n const registered = registeredClass(reportCtor);\n const fields = (await ObjectRegistry.getAllFields(\n definition.reportClassName,\n )) as Map<string, RegistryField>;\n // A tenant-looking field is not an isolation boundary. Only registered\n // tenant scoping installs the collection interceptor used by the executor.\n const tenantField = configuredTenantField(\n registered?.tenantScopedConfig?.field,\n );\n const columns = [\n identityColumn(),\n ...definition.fields\n .map((field) => reportColumn(field, fields.get(field.fieldName)))\n .filter((field): field is ReportColumnDescriptor => Boolean(field)),\n ].sort((left, right) => left.id.localeCompare(right.id));\n const schema: DataQuerySchema = {\n version: 1,\n identityField: 'id',\n fields: columns.map(toQueryField),\n defaultSort: [{ field: 'id', direction: 'asc' }],\n supports: { cursorPagination: false, consistency: false, facets: true },\n };\n const dataTable: ReportDataTableDescriptor = {\n rowKey: 'id',\n manualPagination: true,\n manualSorting: true,\n enableFiltering: true,\n enableSearch: false,\n columns: columns.map((column) =>\n dataTableColumn(column, options.dataTable?.columns?.[column.id]),\n ),\n structuralRows: structuralRows(\n new Set(columns.map((column) => column.id)),\n options.dataTable?.structuralRows,\n ),\n };\n return {\n version: 1,\n resourceId: resourceId(definition, options.tenantScope),\n reportClassName: definition.reportClassName,\n sourceClassName: definition.sourceClassName,\n tenantScoped: Boolean(registered?.tenantScopedConfig),\n ...(tenantField ? { tenantField } : {}),\n identityField: 'id',\n columns,\n schema,\n queryExecution: {\n modes: ['visible', 'background', 'silent'],\n visible: { delivery: 'result' },\n background: { delivery: 'queued', requiresHost: true },\n silent: { delivery: 'result', mutatesVisibleSurface: false },\n },\n dataTable,\n drilldown: drilldownDescriptor(columns, definition.sourceClassName),\n refresh: refreshDescriptor(definition.refresh, options.refreshPermission),\n };\n}\n\nfunction publicFieldMap(\n descriptor: ReportAdapterDescriptor,\n): Map<string, string> {\n return new Map(\n descriptor.columns.map((column) => [column.id, column.fieldName]),\n );\n}\n\n/**\n * Bind a materialized report row to its declared source dimensions. This is a\n * query handoff, not an executor: an authenticated source adapter must apply\n * the inherited principal, tenant, definition, and field policy before it\n * reads source records.\n */\nexport async function buildReportDrilldownQuery(\n reportCtor: new (...args: any[]) => SmrtObject,\n row: Readonly<Record<string, unknown>>,\n options: ReportAdapterOptions = {},\n): Promise<ReportDrilldownQuery> {\n const descriptor = await buildReportAdapterDescriptor(reportCtor, options);\n const constraints = descriptor.drilldown.fields.map((field) => {\n if (!Object.hasOwn(row, field.id)) {\n throw new DataQueryValidationError(\n `Report drilldown row is missing grouping field: ${field.id}`,\n 'DATA_QUERY_RESULT_INVALID',\n );\n }\n return {\n id: field.id,\n sourceColumn: field.sourceColumn,\n kind: field.kind,\n value: jsonSafeValue(row[field.id]),\n ...(field.bucket ? { bucket: field.bucket } : {}),\n };\n });\n return {\n version: 1,\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n sourceClassName: descriptor.drilldown.sourceClassName,\n constraints,\n inherits: [...descriptor.drilldown.inherits],\n };\n}\n\ntype MaterializedWhere = Array<Array<Record<string, unknown>>>;\n\n/** Keep OR expansion bounded before it reaches the database collection. */\nconst MAX_REPORT_FILTER_OR_GROUPS = 128;\n\nfunction reportFilterError(message: string): never {\n throw new DataQueryValidationError(message, 'DATA_QUERY_UNSUPPORTED');\n}\n\nfunction crossProductWhere(\n left: MaterializedWhere,\n right: MaterializedWhere,\n): MaterializedWhere {\n if (left.length * right.length > MAX_REPORT_FILTER_OR_GROUPS) {\n return reportFilterError(\n `Report filter expands beyond ${MAX_REPORT_FILTER_OR_GROUPS} OR groups`,\n );\n }\n return left.flatMap((leftGroup) =>\n right.map((rightGroup) => [...leftGroup, ...rightGroup]),\n );\n}\n\nfunction inverseOperator(\n operator: DataQueryFilterOperator,\n): DataQueryFilterOperator {\n switch (operator) {\n case 'eq':\n return 'ne';\n case 'ne':\n return 'eq';\n case 'gt':\n return 'lte';\n case 'gte':\n return 'lt';\n case 'lt':\n return 'gte';\n case 'lte':\n return 'gt';\n case 'in':\n return 'notIn';\n case 'notIn':\n return 'in';\n case 'like':\n return reportFilterError(\n 'Report filters do not support negating a LIKE predicate',\n );\n }\n}\n\nfunction collectionCondition(\n field: string,\n operator: DataQueryFilterOperator,\n value: DataQueryCondition['value'],\n): MaterializedWhere {\n const keyFor = (suffix: string) => (suffix ? `${field} ${suffix}` : field);\n const scalar = (key: string, scalarValue: unknown): MaterializedWhere => [\n [{ [key]: scalarValue }],\n ];\n\n if (operator === 'in') {\n const values = value as Array<string | number | boolean | null>;\n const nonNull = values.filter((entry) => entry !== null);\n if (nonNull.length === 0) return scalar(field, null);\n if (nonNull.length === values.length) return scalar(keyFor('in'), nonNull);\n // SQL IN does not match NULL. Model the user-visible union explicitly.\n return [[{ [field]: null }], [{ [keyFor('in')]: nonNull }]];\n }\n\n if (operator === 'notIn') {\n const values = value as Array<string | number | boolean | null>;\n // `buildWhere()` does not have a `NOT IN` primitive. A bounded AND of\n // inequality predicates has the same null-safe semantics and remains fully\n // validated by the collection.\n return [values.map((entry) => ({ [keyFor('!=')]: entry }))];\n }\n\n const suffix: Record<\n Exclude<DataQueryFilterOperator, 'in' | 'notIn'>,\n string\n > = {\n eq: '',\n ne: '!=',\n gt: '>',\n gte: '>=',\n lt: '<',\n lte: '<=',\n like: 'like',\n };\n return scalar(keyFor(suffix[operator]), value);\n}\n\nfunction materializedWhereForFilter(\n filter: DataQueryFilter,\n fields: Map<string, string>,\n negate = false,\n): MaterializedWhere {\n if (filter.kind === 'condition') {\n const field = fields.get(filter.field);\n if (!field) {\n return reportFilterError(\n `Report filter field is not declared: ${filter.field}`,\n );\n }\n return collectionCondition(\n field,\n negate ? inverseOperator(filter.operator) : filter.operator,\n filter.value,\n );\n }\n\n if (filter.kind === 'not') {\n return materializedWhereForFilter(filter.filter, fields, !negate);\n }\n\n const combineWithAnd =\n (filter.kind === 'all' && !negate) || (filter.kind === 'any' && negate);\n if (combineWithAnd) {\n return filter.filters.reduce<MaterializedWhere>(\n (combined, child) =>\n crossProductWhere(\n combined,\n materializedWhereForFilter(child, fields, negate),\n ),\n [[]],\n );\n }\n\n const groups = filter.filters.flatMap((child) =>\n materializedWhereForFilter(child, fields, negate),\n );\n if (groups.length > MAX_REPORT_FILTER_OR_GROUPS) {\n return reportFilterError(\n `Report filter expands beyond ${MAX_REPORT_FILTER_OR_GROUPS} OR groups`,\n );\n }\n return groups;\n}\n\n/**\n * Converts a normalized report filter to collection-owned, parameterized\n * predicates. The returned DNF form gives each OR branch a complete AND\n * clause, so tenant interception can add its tenant predicate to every branch.\n */\nfunction materializedWhere(\n filter: DataQueryFilter | undefined,\n fields: Map<string, string>,\n): MaterializedWhere | undefined {\n return filter ? materializedWhereForFilter(filter, fields) : undefined;\n}\n\nfunction filterScopeForColumn(\n column: ReportColumnDescriptor,\n): ReportFilterScope {\n return column.filterScope;\n}\n\n/**\n * Split the declared filter language by report semantics for consumers that\n * construct a live source query. Mixed AND expressions are represented as two\n * independent clauses; mixed OR/NOT expressions are rejected because moving\n * either half across WHERE/HAVING would change their meaning.\n */\nexport function splitReportFilterScopes(\n descriptor: ReportAdapterDescriptor,\n filter: DataQueryFilter | undefined,\n): { where?: DataQueryFilter; having?: DataQueryFilter } {\n if (!filter) return {};\n const columns = new Map(\n descriptor.columns.map((column) => [column.id, column]),\n );\n const combineAll = (\n filters: DataQueryFilter[],\n ): DataQueryFilter | undefined => {\n const flattened = filters.flatMap((candidate) =>\n candidate.kind === 'all' ? candidate.filters : [candidate],\n );\n return flattened.length === 0\n ? undefined\n : flattened.length === 1\n ? flattened[0]\n : { kind: 'all', filters: flattened };\n };\n const split = (\n candidate: DataQueryFilter,\n ): { where?: DataQueryFilter; having?: DataQueryFilter } => {\n if (candidate.kind === 'condition') {\n const column = columns.get(candidate.field);\n if (!column) {\n reportFilterError(\n `Report filter field is not declared: ${candidate.field}`,\n );\n }\n return filterScopeForColumn(column) === 'where'\n ? { where: candidate }\n : { having: candidate };\n }\n\n if (candidate.kind === 'all') {\n const children = candidate.filters.map(split);\n const where = combineAll(\n children.flatMap((child) => (child.where ? [child.where] : [])),\n );\n const having = combineAll(\n children.flatMap((child) => (child.having ? [child.having] : [])),\n );\n return {\n ...(where ? { where } : {}),\n ...(having ? { having } : {}),\n };\n }\n\n const children =\n candidate.kind === 'not'\n ? [split(candidate.filter)]\n : candidate.filters.map(split);\n const scopes = new Set(\n children.flatMap((child) => [\n ...(child.where ? (['where'] as const) : []),\n ...(child.having ? (['having'] as const) : []),\n ]),\n );\n if (scopes.size !== 1) {\n reportFilterError(\n 'Report WHERE and HAVING filters cannot be mixed inside one OR or NOT expression',\n );\n }\n const scope = scopes.has('where') ? 'where' : 'having';\n const filters = children.flatMap((child) => {\n const filter = scope === 'where' ? child.where : child.having;\n return filter ? [filter] : [];\n });\n if (candidate.kind === 'not') {\n const [filter] = filters;\n if (!filter) {\n reportFilterError('Report NOT expressions must contain one filter');\n }\n return scope === 'where'\n ? { where: { kind: 'not', filter } }\n : { having: { kind: 'not', filter } };\n }\n return scope === 'where'\n ? { where: { kind: 'any', filters } }\n : { having: { kind: 'any', filters } };\n };\n\n return split(filter);\n}\n\nconst DATE_ONLY_VALUE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * `YYYY-MM-DD[T ]HH:MM[:SS[.fff]]` with no zone designator — the shape SQLite's\n * `CURRENT_TIMESTAMP` / `datetime('now')` persist. SQLite writes those in UTC,\n * but `new Date('2026-09-17 12:00:00')` reads the space-separated form as\n * *local* time, so the zone is appended explicitly instead of inferred.\n */\nconst NAIVE_TIMESTAMP_VALUE =\n /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?$/;\n\n/** ISO-8601/RFC 3339 instant in UTC, or `null` for an unrepresentable date. */\nfunction instantOrNull(value: Date): string | null {\n return Number.isNaN(value.getTime()) ? null : value.toISOString();\n}\n\nfunction epochToInstant(value: number): string | null {\n if (!Number.isFinite(value)) return null;\n return instantOrNull(new Date(value));\n}\n\n/**\n * Serialize one temporal row value to an RFC 3339 instant in UTC (#2934).\n *\n * `SmrtCollection.list()` hydrates a `datetime` field into a `Date`, and a raw\n * driver row can hand back the stored string or an epoch number instead. The\n * shared result validator only accepts JSON scalars, and normalizes a\n * `datetime` descriptor's value through `normalizedInstant`, so every one of\n * those forms has to reach it as an instant string.\n *\n * An unparseable string is returned unchanged on purpose: the shared validator\n * owns that error, and its message names the field and the RFC 3339 contract.\n */\nfunction temporalToInstant(value: unknown): unknown {\n if (value instanceof Date) return instantOrNull(value);\n if (typeof value === 'number') return epochToInstant(value);\n if (typeof value === 'bigint') {\n // An epoch outside the safe-integer range would round on the way through\n // `Number`, producing a WRONG instant. For a temporal value a missing one\n // is safer than a silently shifted one.\n const numeric = Number(value);\n return Number.isSafeInteger(numeric) ? epochToInstant(numeric) : null;\n }\n if (typeof value !== 'string') return value;\n const text = value.trim();\n if (text.length === 0) return null;\n if (DATE_ONLY_VALUE.test(text)) return `${text}T00:00:00.000Z`;\n if (NAIVE_TIMESTAMP_VALUE.test(text)) {\n return epochToInstant(Date.parse(`${text.replace(' ', 'T')}Z`)) ?? value;\n }\n const parsed = Date.parse(text);\n if (!Number.isFinite(parsed)) return value;\n return epochToInstant(parsed) ?? value;\n}\n\nfunction jsonSafeValue(\n value: unknown,\n ancestors = new WeakSet<object>(),\n): unknown {\n if (value instanceof Date) return instantOrNull(value);\n if (typeof value === 'bigint') {\n const numeric = Number(value);\n if (!Number.isSafeInteger(numeric)) {\n throw new RangeError(\n 'Materialized bigint values must be safely representable as numbers',\n );\n }\n return numeric;\n }\n if (value && typeof value === 'object') {\n if (ancestors.has(value)) {\n throw new TypeError('Values must not contain circular references');\n }\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n return value.map((entry) => jsonSafeValue(entry, ancestors));\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [\n key,\n jsonSafeValue(entry, ancestors),\n ]),\n );\n } finally {\n ancestors.delete(value);\n }\n }\n return value;\n}\n\n/** Normalize hydrated values according to the public descriptor (#2934). */\nfunction toDeclaredValue(\n value: unknown,\n descriptor: DataQueryFieldDescriptor,\n shortened: Set<string>,\n): unknown {\n const cap = (text: string): string => {\n if (text.length <= 4096) return text;\n shortened.add(descriptor.id);\n // Keep a UTF-16 surrogate pair together at the scalar length boundary.\n const last = text.charCodeAt(4095);\n const next = text.charCodeAt(4096);\n const splitsPair =\n last >= 0xd800 && last <= 0xdbff && next >= 0xdc00 && next <= 0xdfff;\n return text.slice(0, splitsPair ? 4095 : 4096);\n };\n // Identity is authoritative: reject unsupported values instead of rewriting it.\n if (descriptor.id === 'id') return value;\n if (value === undefined || value === null) return null;\n if (descriptor.type === 'datetime') return temporalToInstant(value);\n if (descriptor.type === 'json') return jsonSafeValue(value);\n if (typeof value === 'object' && !(value instanceof Date)) {\n try {\n const rendered = JSON.stringify(jsonSafeValue(value));\n return rendered === undefined ? null : cap(rendered);\n } catch (error) {\n if (error instanceof RangeError) throw error;\n return null;\n }\n }\n if (descriptor.type === 'boolean' && typeof value === 'number')\n return value !== 0;\n if (typeof value === 'string') return cap(value);\n return jsonSafeValue(value);\n}\n\nfunction mapMaterializedRow(\n row: Record<string, unknown>,\n projection: readonly string[],\n fieldMap: Map<string, string>,\n schema: DataQuerySchema,\n shortened: Set<string>,\n): Record<string, unknown> {\n const mapped: Record<string, unknown> = {};\n for (const id of projection) {\n const sourceField = fieldMap.get(id) ?? id;\n const descriptor = schema.fields.find((field) => field.id === id);\n if (sourceField in row && descriptor)\n mapped[id] = toDeclaredValue(row[sourceField], descriptor, shortened);\n }\n return mapped;\n}\n\nfunction queryFreshness(\n lifecycle: ReportLifecycleSnapshot,\n): DataQueryFreshness {\n switch (lifecycle.state) {\n case 'current':\n return {\n state: 'fresh',\n ...(lifecycle.asOf ? { asOf: lifecycle.asOf } : {}),\n };\n case 'stale':\n case 'lock-skipped':\n case 'failed':\n return {\n state: 'stale',\n ...(lifecycle.asOf ? { asOf: lifecycle.asOf } : {}),\n };\n case 'refreshing':\n return lifecycle.hasUsableRows\n ? {\n state: 'stale',\n ...(lifecycle.asOf ? { asOf: lifecycle.asOf } : {}),\n }\n : { state: 'unknown' };\n }\n}\n\n/**\n * Execute bounded materialized report reads through the canonical query\n * envelope. Every predicate is an adapter-declared field/operator pair; the\n * collection converts it to parameterized SQL and applies tenant interceptors\n * to list, count, and facet reads alike.\n */\nexport function queryReportMaterializedRows(\n reportCtor: new (...args: any[]) => SmrtObject,\n input: unknown,\n options: ReportBackgroundQueryOptions,\n): Promise<ReportBackgroundQueryResult>;\nexport function queryReportMaterializedRows(\n reportCtor: new (...args: any[]) => SmrtObject,\n input: unknown,\n options?: ReportQueryOptions,\n): Promise<ReportDataQueryResult>;\nexport async function queryReportMaterializedRows(\n reportCtor: new (...args: any[]) => SmrtObject,\n input: unknown,\n options: ReportQueryOptions | ReportBackgroundQueryOptions = {},\n): Promise<ReportDataQueryResult | ReportBackgroundQueryResult> {\n const descriptor = await buildReportAdapterDescriptor(\n reportCtor,\n options.adapter,\n );\n const request = normalizeDataQueryRequest(input, descriptor.schema);\n // Validate the semantic split even though materialized-row reads execute the\n // complete predicate against one persisted table. It prevents an adapter\n // consumer from silently treating a mixed source WHERE/HAVING expression as\n // either side of the aggregate boundary.\n splitReportFilterScopes(descriptor, request.filter);\n const queryFingerprint = createDataQueryFingerprint(\n request,\n descriptor.schema,\n );\n if (options.execution === 'background') {\n const queued = await options.enqueueBackgroundQuery({\n version: 1,\n execution: 'background',\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n request,\n inherits: ['principal', 'tenant', 'report-definition', 'field-policy'],\n });\n if (typeof queued.taskId !== 'string' || queued.taskId.length === 0) {\n throw new Error('Background report query hosts must return a task id');\n }\n return {\n version: 1,\n execution: 'background',\n status: 'queued',\n taskId: queued.taskId,\n queryFingerprint,\n };\n }\n const execution = options.execution ?? 'visible';\n const lifecycleDb = options.db;\n if (options.lifecycle && !lifecycleDb) {\n throw new Error('Report lifecycle disclosure requires a database handle');\n }\n const lifecycleOptions =\n options.lifecycle && lifecycleDb\n ? { db: lifecycleDb, ...options.lifecycle }\n : undefined;\n const lifecycleBefore = lifecycleOptions\n ? await getReportLifecycle(reportCtor, lifecycleOptions)\n : undefined;\n const fieldMap = publicFieldMap(descriptor);\n const where = materializedWhere(request.filter, fieldMap);\n const collection: NonNullable<ReportQueryOptions['collection']> =\n options.collection ??\n ((await ObjectRegistry.getCollection(descriptor.reportClassName, {\n db: options.db,\n })) as unknown as NonNullable<ReportQueryOptions['collection']>);\n const shortened = new Set<string>();\n let rows: Record<string, unknown>[] = [];\n let page: DataQueryResult['page'];\n let total: number;\n let facets: DataQueryResult['facets'];\n if (request.mode === 'rows') {\n const projection = request.projection ?? [descriptor.identityField];\n const select = projection.map((id) => fieldMap.get(id) ?? id);\n const offset = request.page?.kind === 'offset' ? request.page.offset : 0;\n const limit = request.page?.limit ?? 50;\n const orderBy = request.sort?.map(\n ({ field, direction }) =>\n `${fieldMap.get(field) ?? field} ${direction.toUpperCase()}`,\n );\n const materialized = await collection.list({\n select,\n offset,\n limit,\n orderBy: orderBy?.length === 1 ? orderBy[0] : orderBy,\n ...(where === undefined ? {} : { where }),\n });\n rows = materialized.map((row) =>\n mapMaterializedRow(\n row,\n projection,\n fieldMap,\n descriptor.schema,\n shortened,\n ),\n );\n rows.forEach((row) => {\n if (typeof row.id !== 'string' || row.id.length === 0) {\n throw new Error(\n 'Materialized report rows require a non-empty string id',\n );\n }\n });\n // SmrtReportCollection performs an eligible TTL refresh from list(). Count\n // must follow that operation so total/hasMore describe the same snapshot.\n total = await collection.count(where === undefined ? undefined : { where });\n page = {\n kind: 'offset',\n offset,\n limit,\n hasMore: offset + rows.length < total,\n };\n } else {\n // Count-only reads still enter SmrtReportCollection's list lifecycle to\n // refresh an eligible stale report before calculating its exact total.\n await collection.list({\n select: ['id'],\n offset: 0,\n limit: 1,\n orderBy: 'id ASC',\n ...(where === undefined ? {} : { where }),\n });\n total = await collection.count(where === undefined ? undefined : { where });\n if (request.mode === 'facets') {\n if (!collection.facets) {\n throw new Error(\n 'Report materialized facet reads require a collection facets() implementation',\n );\n }\n const requested = request.facets ?? [];\n const sourceFacets = await collection.facets({\n fields: requested.map((facet) => ({\n field: fieldMap.get(facet.field) ?? facet.field,\n limit: facet.limit,\n })),\n ...(where === undefined ? {} : { where }),\n });\n const byField = new Map(\n sourceFacets.map((facet) => [facet.field, facet]),\n );\n facets = requested.map((facet) => {\n const sourceField = fieldMap.get(facet.field) ?? facet.field;\n const values = byField.get(sourceField)?.values ?? [];\n const field = descriptor.schema.fields.find(\n (field) => field.id === facet.field,\n );\n if (!field) throw new Error('Unknown report facet field');\n return {\n field: facet.field,\n values: values.map((value) => ({\n value: toDeclaredValue(\n value.value,\n field,\n shortened,\n ) as DataQueryScalar,\n count: value.count,\n })),\n // The collection deliberately bounds this database grouping query;\n // an exactly-full page may have more values, so report conservatively.\n truncated: values.length >= facet.limit,\n };\n });\n }\n }\n const result = {\n version: 1 as const,\n requestId: request.requestId,\n queryFingerprint,\n identityField: descriptor.identityField,\n rows,\n ...(page ? { page } : {}),\n total: { kind: 'exact' as const, value: total },\n ...(facets === undefined ? {} : { facets }),\n freshness: { state: 'unknown' as const },\n warnings: shortened.size\n ? ['Values exceeding the scalar result limit were shortened.']\n : [],\n truncated: shortened.size > 0,\n };\n const normalized = normalizeDataQueryResult(\n result,\n request,\n descriptor.schema,\n );\n if (!lifecycleBefore || !lifecycleOptions) {\n return { ...normalized, execution };\n }\n\n const lifecycleAfter = await getReportLifecycle(reportCtor, lifecycleOptions);\n return {\n ...normalized,\n execution,\n freshness: queryFreshness(lifecycleAfter),\n reportLifecycle: {\n snapshot: lifecycleAfter,\n read:\n lifecycleBefore.state !== 'current' &&\n lifecycleAfter.state === 'current'\n ? 'refresh-triggered'\n : lifecycleAfter.state === 'current'\n ? 'current'\n : 'stale',\n },\n };\n}\n\n/** Read the already-materialized primary key; never use a display/page index. */\nexport function reportMaterializedRowKey(row: Record<string, unknown>): string {\n const id = row.id;\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error('Materialized report rows require a non-empty string id');\n }\n return id;\n}\n","/**\n * Declared recipes for smrt-reports (#3719): user-facing units of\n * functionality an app or agent can pick instead of the whole package.\n * The scanner reads these statics into the `recipes` array of `manifest.json`\n * and `smrt-knowledge.json`; nothing here runs at that point.\n *\n * `reports.materialized` brings the refresh bookkeeping tables a declared\n * (`@report`) report needs. The report classes themselves belong to the app, so\n * they are not listed here. It declares no surfaces: this package ships no\n * Svelte components, and the assistant reaches declared reports through the\n * `reports.query` tools in `@happyvertical/smrt-agents`.\n *\n * @packageDocumentation\n */\n\nimport { SmrtRecipe } from '@happyvertical/smrt-core';\nimport {\n SmrtPrincipalReportRefreshTask,\n SmrtReportRefreshTask,\n} from './scheduler.js';\nimport {\n SmrtReportLock,\n SmrtReportRun,\n SmrtReportSchedule,\n SmrtReportWatermark,\n} from './state.js';\n\n/** Reports: totals and trends kept ready to read, refreshed on a schedule. */\nexport class MaterializedReportsRecipe extends SmrtRecipe {\n static id = 'reports.materialized';\n static help = './materialized.recipe.md';\n static label = 'Reports';\n static summary =\n 'Keep totals and trends ready to read, refreshed on a schedule and open to the assistant.';\n static synonyms = [\n 'reports',\n 'totals',\n 'summaries',\n 'rollups',\n 'kpis',\n 'trends',\n 'dashboards',\n ];\n // Refresh bookkeeping only. Every table is internal (`_smrt_` prefix, no REST\n // or MCP surface), so there is no `nav`; the app's own `@report` classes bring\n // their own rows and views.\n static models = [\n SmrtReportRun,\n SmrtReportWatermark,\n SmrtReportLock,\n SmrtReportSchedule,\n SmrtReportRefreshTask,\n SmrtPrincipalReportRefreshTask,\n ];\n // Aggregation runs as SQL against the app database, and scheduled refreshes\n // are queued through smrt-jobs; neither can run in a browser.\n static runtime = 'server' as const;\n}\n","import {\n ObjectRegistry,\n SmrtCollection,\n type SmrtListOptions,\n SmrtObject,\n type SmrtObjectOptions,\n type SmrtSelectedRow,\n type SmrtSelectField,\n type SmrtStiReadScope,\n} from '@happyvertical/smrt-core';\nimport { toSnakeCase } from '@happyvertical/smrt-core/utils';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { validateColumnName } from '@happyvertical/sql';\nimport { buildReportDefinition } from './compiler.js';\nimport { refreshReport } from './refresh.js';\nimport type { ReportRefreshOptions, ReportRefreshResult } from './types.js';\n\ntype RegistryField = {\n columnName?: string;\n _meta?: {\n columnName?: string;\n __tenancy?: { isTenantIdField?: boolean };\n };\n};\n\nfunction registryColumnName(fieldName: string, field?: RegistryField): string {\n return validateColumnName(\n field?.columnName ?? field?._meta?.columnName ?? toSnakeCase(fieldName),\n );\n}\n\nfunction findFieldColumn(\n fields: Map<string, RegistryField>,\n fieldName: string,\n): string {\n const direct = fields.get(fieldName);\n if (direct) return registryColumnName(fieldName, direct);\n const requestedColumn = toSnakeCase(fieldName);\n for (const [name, field] of fields.entries()) {\n if (toSnakeCase(name) === requestedColumn) {\n return registryColumnName(name, field);\n }\n }\n return validateColumnName(requestedColumn);\n}\n\nfunction findTenantColumn(\n fields: Map<string, RegistryField>,\n configuredField?: string,\n): string | null {\n if (configuredField) {\n return registryColumnName(configuredField, fields.get(configuredField));\n }\n for (const [fieldName, field] of fields.entries()) {\n if (fieldName === 'tenantId' || field?._meta?.__tenancy?.isTenantIdField) {\n return registryColumnName(fieldName, field);\n }\n }\n return null;\n}\n\nexport class SmrtReport extends SmrtObject {\n static readonly _isReportBase = true as const;\n\n refreshedAt: Date | null = null;\n\n constructor(options: SmrtObjectOptions = {}) {\n super(options);\n if (options.refreshedAt !== undefined) {\n this.refreshedAt =\n options.refreshedAt instanceof Date\n ? options.refreshedAt\n : options.refreshedAt\n ? new Date(options.refreshedAt)\n : null;\n }\n }\n\n isStale(ttlMs?: number): boolean {\n if (!this.refreshedAt) return true;\n if (ttlMs === undefined) return false;\n return Date.now() - this.refreshedAt.getTime() > ttlMs;\n }\n\n async refresh(\n options: Omit<ReportRefreshOptions, 'db'> = {},\n ): Promise<ReportRefreshResult> {\n const result = await refreshReport(this.constructor as typeof SmrtReport, {\n ...options,\n db: this.db,\n });\n this.refreshedAt = result.refreshedAt;\n return result;\n }\n}\n\nexport class SmrtReportCollection<\n ModelType extends SmrtReport,\n> extends SmrtCollection<ModelType> {\n private async refreshIfStale(): Promise<void> {\n const reportCtor = this.getItemClass();\n const definition = await buildReportDefinition(reportCtor);\n const refresh = definition.refresh;\n if (!refresh?.ttl || refresh.manual) return;\n\n const registered =\n ObjectRegistry.getClassByConstructor(reportCtor) ??\n ObjectRegistry.getClass(reportCtor.name);\n const reportClass =\n registered?.qualifiedName ?? registered?.name ?? reportCtor.name;\n const tableName = ObjectRegistry.getTableName(reportClass);\n if (!tableName) return;\n\n const fields = (await ObjectRegistry.getAllFields(reportClass)) as Map<\n string,\n RegistryField\n >;\n const safeTableName = validateColumnName(tableName);\n const refreshedAtColumn = findFieldColumn(fields, 'refreshedAt');\n const tenantColumn = findTenantColumn(\n fields,\n registered?.tenantScopedConfig?.field,\n );\n const tenantId = getTenantId() ?? null;\n const result = tenantColumn\n ? await this.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${safeTableName} WHERE ${tenantColumn} ${tenantId ? '= ?' : 'IS NULL'}`,\n ...(tenantId ? [tenantId] : []),\n )\n : await this.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${safeTableName}`,\n );\n const refreshedAt = result.rows[0]?.refreshed_at\n ? new Date(result.rows[0].refreshed_at as string)\n : null;\n const stale =\n !refreshedAt || Date.now() - refreshedAt.getTime() > refresh.ttl;\n if (!stale) return;\n\n await refreshReport(reportCtor, {\n db: this.db,\n mode: refresh.mode ?? 'rebuild',\n trigger: 'ttl',\n tenantId,\n });\n }\n\n async refresh(\n options: Omit<ReportRefreshOptions, 'db'> = {},\n ): Promise<ReportRefreshResult> {\n return refreshReport(this.getItemClass(), {\n ...options,\n db: this.db,\n });\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<ModelType>[],\n >(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<Record<string, unknown>[]>;\n override async list<\n const Select extends readonly SmrtSelectField<ModelType>[],\n >(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<ModelType, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<ModelType[]>;\n override async list(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<ModelType[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<ModelType>, 'select'> & { select?: undefined })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<ModelType> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<ModelType> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n await this.refreshIfStale();\n return super.list(options);\n }\n\n override async get(\n filter: Parameters<SmrtCollection<ModelType>['get']>[0],\n options: Parameters<SmrtCollection<ModelType>['get']>[1] = {},\n ): Promise<ModelType | null> {\n await this.refreshIfStale();\n return super.get(filter, options);\n }\n}\n","/**\n * Declarative runtime report specification (#3711).\n *\n * A runtime report is DATA, never code: a closed, versioned structure that a\n * user (or the assistant on a user's behalf) can propose at runtime. The spec\n * grammar deliberately has no free-form SQL, no expression language, no raw\n * identifiers and no join syntax. Every name in it is later resolved against\n * the ObjectRegistry field policy by `compileRuntimeReportSpec()`; this module\n * only enforces the STRUCTURE (shape, bounds, alias hygiene) and normalizes\n * defaults so equal specs hash equally.\n *\n * The parser accepts no authority. Nothing in a spec names a tenant, a\n * principal, a permission, a table, a column alias that is not a plain\n * identifier, or an SQL fragment.\n */\n\nimport { createHash } from 'node:crypto';\n\nexport const RUNTIME_REPORT_SPEC_VERSION = 1 as const;\n\nexport const RUNTIME_REPORT_LIMITS = Object.freeze({\n maxTitleLength: 120,\n maxDescriptionLength: 500,\n maxDimensions: 4,\n maxMeasures: 6,\n maxFilters: 12,\n maxHaving: 4,\n maxSort: 3,\n maxInValues: 100,\n maxStringValueLength: 256,\n defaultRowLimit: 100,\n maxRowLimit: 1000,\n maxAliasLength: 40,\n maxFieldNameLength: 64,\n maxSourceIdLength: 120,\n});\n\nexport const RUNTIME_REPORT_BUCKETS = [\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n 'quarter',\n 'year',\n] as const;\nexport type RuntimeReportBucket = (typeof RUNTIME_REPORT_BUCKETS)[number];\n\nexport const RUNTIME_REPORT_MEASURE_FNS = [\n 'count',\n 'countDistinct',\n 'sum',\n 'avg',\n 'min',\n 'max',\n] as const;\nexport type RuntimeReportMeasureFn =\n (typeof RUNTIME_REPORT_MEASURE_FNS)[number];\n\nexport const RUNTIME_REPORT_FILTER_OPS = [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'contains',\n 'isNull',\n 'isNotNull',\n] as const;\nexport type RuntimeReportFilterOp = (typeof RUNTIME_REPORT_FILTER_OPS)[number];\n\nexport const RUNTIME_REPORT_HAVING_OPS = [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n] as const;\nexport type RuntimeReportHavingOp = (typeof RUNTIME_REPORT_HAVING_OPS)[number];\n\nexport const RUNTIME_REPORT_CHART_TYPES = [\n 'table',\n 'bar',\n 'line',\n 'pie',\n 'stat',\n] as const;\nexport type RuntimeReportChartType =\n (typeof RUNTIME_REPORT_CHART_TYPES)[number];\n\nexport type RuntimeReportScalar = string | number | boolean;\n\nexport interface RuntimeReportDimension {\n /** Source field name as declared on the model (for example `issuedAt`). */\n field: string;\n /** Output column alias. Defaults to the snake_case field (plus bucket). */\n as: string;\n /** Time bucket; only valid on datetime fields. */\n bucket?: RuntimeReportBucket;\n}\n\nexport interface RuntimeReportMeasure {\n fn: RuntimeReportMeasureFn;\n /** Source field; omitted only for a plain row `count`. */\n field?: string;\n as: string;\n}\n\nexport interface RuntimeReportFilter {\n field: string;\n op: RuntimeReportFilterOp;\n /** Scalar, or a bounded array for `in`/`notIn`; absent for null tests. */\n value?: RuntimeReportScalar | RuntimeReportScalar[];\n}\n\nexport interface RuntimeReportHaving {\n /** A measure alias declared by this spec. */\n measure: string;\n op: RuntimeReportHavingOp;\n value: number;\n}\n\nexport interface RuntimeReportSort {\n /** A dimension or measure alias declared by this spec. */\n by: string;\n direction: 'asc' | 'desc';\n}\n\nexport interface RuntimeReportChart {\n type: RuntimeReportChartType;\n /** Dimension alias for the category/x axis. */\n x?: string;\n /** Measure aliases for the value/y axis. */\n y?: string[];\n}\n\nexport interface RuntimeReportSpec {\n version: typeof RUNTIME_REPORT_SPEC_VERSION;\n title: string;\n description?: string;\n /** A server-owned source id; resolved against an allow-list at compile. */\n source: string;\n dimensions: RuntimeReportDimension[];\n measures: RuntimeReportMeasure[];\n filters: RuntimeReportFilter[];\n having: RuntimeReportHaving[];\n sort: RuntimeReportSort[];\n limit: number;\n chart: RuntimeReportChart;\n}\n\nexport type RuntimeReportErrorCode =\n | 'invalid_spec'\n | 'unknown_source'\n | 'unknown_field'\n | 'invalid_operation'\n | 'invalid_value'\n | 'tenant_required'\n | 'confirmation_required'\n | 'unsupported_source'\n | 'invalid_result';\n\n/**\n * Raised for any spec or compile rejection. The message is safe to hand back\n * to a model so it can repair the spec; it never echoes restricted-field\n * metadata (a hidden field is reported exactly like an absent one).\n */\nexport class RuntimeReportError extends Error {\n readonly code: RuntimeReportErrorCode;\n readonly path: string;\n /**\n * HTTP-style status so tool loops classify it: 4xx input problems are\n * repairable by the caller, `tenant_required` and `confirmation_required`\n * are denials, results that cannot be represented are server errors.\n */\n readonly status: number;\n\n constructor(code: RuntimeReportErrorCode, path: string, message: string) {\n super(path ? `${path}: ${message}` : message);\n this.name = 'RuntimeReportError';\n this.code = code;\n this.path = path;\n this.status =\n code === 'tenant_required' || code === 'confirmation_required'\n ? 403\n : code === 'invalid_result'\n ? 500\n : 422;\n }\n}\n\nfunction fail(path: string, message: string): never {\n throw new RuntimeReportError('invalid_spec', path, message);\n}\n\n/** Output aliases that would be reserved words in at least one SQL dialect. */\nconst RESERVED_ALIASES: ReadonlySet<string> = new Set([\n 'all',\n 'and',\n 'as',\n 'asc',\n 'between',\n 'by',\n 'case',\n 'cast',\n 'check',\n 'column',\n 'constraint',\n 'create',\n 'cross',\n 'default',\n 'delete',\n 'desc',\n 'distinct',\n 'drop',\n 'else',\n 'end',\n 'except',\n 'exists',\n 'false',\n 'for',\n 'foreign',\n 'from',\n 'full',\n 'group',\n 'having',\n 'in',\n 'inner',\n 'insert',\n 'intersect',\n 'into',\n 'is',\n 'join',\n 'left',\n 'like',\n 'limit',\n 'natural',\n 'not',\n 'null',\n 'offset',\n 'on',\n 'or',\n 'order',\n 'outer',\n 'primary',\n 'references',\n 'right',\n 'select',\n 'set',\n 'table',\n 'then',\n 'to',\n 'true',\n 'union',\n 'unique',\n 'update',\n 'user',\n 'using',\n 'values',\n 'when',\n 'where',\n 'with',\n]);\n\nconst ALIAS_PATTERN = /^[a-z][a-z0-9_]*$/;\nconst FIELD_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/;\nconst SOURCE_PATTERN = /^[A-Za-z@][A-Za-z0-9_@./:-]*$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype ||\n Object.getPrototypeOf(value) === null)\n );\n}\n\nfunction strictObject(\n value: unknown,\n path: string,\n allowed: readonly string[],\n): Record<string, unknown> {\n if (!isRecord(value)) fail(path, 'must be an object');\n for (const key of Object.keys(value)) {\n if (!allowed.includes(key)) fail(`${path}.${key}`, 'is not a known key');\n }\n return value;\n}\n\nfunction strictArray(\n value: unknown,\n path: string,\n max: number,\n min = 0,\n): unknown[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) fail(path, 'must be an array');\n if (value.length > max) fail(path, `must have at most ${max} entries`);\n if (value.length < min) fail(path, `must have at least ${min} entries`);\n return value;\n}\n\nfunction text(\n value: unknown,\n path: string,\n max: number,\n options: { optional?: boolean } = {},\n): string {\n if (typeof value !== 'string') {\n if (options.optional && value === undefined) return '';\n fail(path, 'must be a string');\n }\n const trimmed = value.trim();\n if (trimmed.length === 0 && !options.optional) {\n fail(path, 'must not be empty');\n }\n if (trimmed.length > max) fail(path, `must be at most ${max} characters`);\n // Titles/descriptions are echoed into UIs and prompts: keep them printable.\n // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional guard\n if (/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/.test(trimmed)) {\n fail(path, 'must not contain control characters');\n }\n return trimmed;\n}\n\nfunction oneOf<T extends string>(\n value: unknown,\n path: string,\n allowed: readonly T[],\n): T {\n if (typeof value !== 'string' || !allowed.includes(value as T)) {\n fail(path, `must be one of: ${allowed.join(', ')}`);\n }\n return value as T;\n}\n\nfunction fieldName(value: unknown, path: string): string {\n if (typeof value !== 'string') fail(path, 'must be a string');\n if (\n value.length === 0 ||\n value.length > RUNTIME_REPORT_LIMITS.maxFieldNameLength ||\n !FIELD_PATTERN.test(value)\n ) {\n fail(path, 'must be a plain field name (letters, digits, underscore)');\n }\n return value;\n}\n\nfunction alias(value: unknown, path: string): string {\n if (typeof value !== 'string') fail(path, 'must be a string');\n if (\n value.length === 0 ||\n value.length > RUNTIME_REPORT_LIMITS.maxAliasLength ||\n !ALIAS_PATTERN.test(value)\n ) {\n fail(\n path,\n `must be a lowercase identifier of at most ${RUNTIME_REPORT_LIMITS.maxAliasLength} characters (a-z, 0-9, underscore)`,\n );\n }\n if (RESERVED_ALIASES.has(value)) fail(path, `'${value}' is a reserved word`);\n return value;\n}\n\nfunction scalar(value: unknown, path: string): RuntimeReportScalar {\n if (typeof value === 'string') {\n if (value.length > RUNTIME_REPORT_LIMITS.maxStringValueLength) {\n fail(\n path,\n `must be at most ${RUNTIME_REPORT_LIMITS.maxStringValueLength} characters`,\n );\n }\n if (value.includes('\\u0000')) fail(path, 'must not contain NUL');\n return value;\n }\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) fail(path, 'must be a finite number');\n return value;\n }\n if (typeof value === 'boolean') return value;\n return fail(path, 'must be a string, number or boolean');\n}\n\nfunction snake(name: string): string {\n return name\n .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n .toLowerCase();\n}\n\nfunction parseDimension(value: unknown, path: string): RuntimeReportDimension {\n const raw = strictObject(value, path, ['field', 'as', 'bucket']);\n const field = fieldName(raw.field, `${path}.field`);\n const bucket =\n raw.bucket === undefined\n ? undefined\n : oneOf(raw.bucket, `${path}.bucket`, RUNTIME_REPORT_BUCKETS);\n const as =\n raw.as === undefined\n ? alias(bucket ? `${snake(field)}_${bucket}` : snake(field), `${path}.as`)\n : alias(raw.as, `${path}.as`);\n return { field, as, ...(bucket ? { bucket } : {}) };\n}\n\nfunction parseMeasure(value: unknown, path: string): RuntimeReportMeasure {\n const raw = strictObject(value, path, ['fn', 'field', 'as']);\n const fn = oneOf(raw.fn, `${path}.fn`, RUNTIME_REPORT_MEASURE_FNS);\n const field =\n raw.field === undefined ? undefined : fieldName(raw.field, `${path}.field`);\n if (!field && fn !== 'count') fail(`${path}.field`, `is required for ${fn}`);\n const as =\n raw.as === undefined\n ? alias(\n field ? `${snake(fn)}_${snake(field)}` : 'row_count',\n `${path}.as`,\n )\n : alias(raw.as, `${path}.as`);\n return { fn, ...(field ? { field } : {}), as };\n}\n\nfunction parseFilter(value: unknown, path: string): RuntimeReportFilter {\n const raw = strictObject(value, path, ['field', 'op', 'value']);\n const field = fieldName(raw.field, `${path}.field`);\n const op = oneOf(raw.op, `${path}.op`, RUNTIME_REPORT_FILTER_OPS);\n if (op === 'isNull' || op === 'isNotNull') {\n if (raw.value !== undefined)\n fail(`${path}.value`, `must be omitted for ${op}`);\n return { field, op };\n }\n if (raw.value === undefined) fail(`${path}.value`, `is required for ${op}`);\n if (op === 'in' || op === 'notIn') {\n const values = strictArray(\n raw.value,\n `${path}.value`,\n RUNTIME_REPORT_LIMITS.maxInValues,\n 1,\n ).map((entry, index) => scalar(entry, `${path}.value[${index}]`));\n return { field, op, value: values };\n }\n if (Array.isArray(raw.value))\n fail(`${path}.value`, `must be a scalar for ${op}`);\n const parsed = scalar(raw.value, `${path}.value`);\n if (op === 'contains' && typeof parsed !== 'string') {\n fail(`${path}.value`, 'must be a string for contains');\n }\n return { field, op, value: parsed };\n}\n\nfunction parseHaving(value: unknown, path: string): RuntimeReportHaving {\n const raw = strictObject(value, path, ['measure', 'op', 'value']);\n const measure = alias(raw.measure, `${path}.measure`);\n const op = oneOf(raw.op, `${path}.op`, RUNTIME_REPORT_HAVING_OPS);\n if (typeof raw.value !== 'number' || !Number.isFinite(raw.value)) {\n fail(`${path}.value`, 'must be a finite number');\n }\n return { measure, op, value: raw.value };\n}\n\nfunction parseSort(value: unknown, path: string): RuntimeReportSort {\n const raw = strictObject(value, path, ['by', 'direction']);\n const by = alias(raw.by, `${path}.by`);\n const direction =\n raw.direction === undefined\n ? 'asc'\n : oneOf(raw.direction, `${path}.direction`, ['asc', 'desc'] as const);\n return { by, direction };\n}\n\n/**\n * Parse and normalize an untrusted spec (an object, or its JSON string form).\n *\n * Structural only: aliases are unique and well-formed, sort/having/chart refer\n * to aliases the spec itself declares, and every bound is enforced. Field,\n * source, permission and type checks happen at compile time because they\n * depend on the registry and the live principal.\n */\nexport function parseRuntimeReportSpec(input: unknown): RuntimeReportSpec {\n let candidate = input;\n if (typeof input === 'string') {\n if (input.length > 64 * 1024) fail('', 'spec JSON is too large');\n try {\n candidate = JSON.parse(input);\n } catch {\n fail('', 'spec is not valid JSON');\n }\n }\n const raw = strictObject(candidate, 'spec', [\n 'version',\n 'title',\n 'description',\n 'source',\n 'dimensions',\n 'measures',\n 'filters',\n 'having',\n 'sort',\n 'limit',\n 'chart',\n ]);\n if (\n raw.version !== undefined &&\n raw.version !== RUNTIME_REPORT_SPEC_VERSION\n ) {\n fail(\n 'spec.version',\n `unsupported version (expected ${RUNTIME_REPORT_SPEC_VERSION})`,\n );\n }\n const title = text(\n raw.title,\n 'spec.title',\n RUNTIME_REPORT_LIMITS.maxTitleLength,\n );\n const description = text(\n raw.description,\n 'spec.description',\n RUNTIME_REPORT_LIMITS.maxDescriptionLength,\n { optional: true },\n );\n if (\n typeof raw.source !== 'string' ||\n raw.source.length === 0 ||\n raw.source.length > RUNTIME_REPORT_LIMITS.maxSourceIdLength ||\n !SOURCE_PATTERN.test(raw.source)\n ) {\n fail('spec.source', 'must be a source id');\n }\n\n const dimensions = strictArray(\n raw.dimensions,\n 'spec.dimensions',\n RUNTIME_REPORT_LIMITS.maxDimensions,\n ).map((entry, index) => parseDimension(entry, `spec.dimensions[${index}]`));\n const measures = strictArray(\n raw.measures,\n 'spec.measures',\n RUNTIME_REPORT_LIMITS.maxMeasures,\n 1,\n ).map((entry, index) => parseMeasure(entry, `spec.measures[${index}]`));\n const filters = strictArray(\n raw.filters,\n 'spec.filters',\n RUNTIME_REPORT_LIMITS.maxFilters,\n ).map((entry, index) => parseFilter(entry, `spec.filters[${index}]`));\n const having = strictArray(\n raw.having,\n 'spec.having',\n RUNTIME_REPORT_LIMITS.maxHaving,\n ).map((entry, index) => parseHaving(entry, `spec.having[${index}]`));\n const sort = strictArray(\n raw.sort,\n 'spec.sort',\n RUNTIME_REPORT_LIMITS.maxSort,\n ).map((entry, index) => parseSort(entry, `spec.sort[${index}]`));\n\n const dimensionAliases = new Set<string>();\n const measureAliases = new Set<string>();\n const seen = new Set<string>();\n for (const [index, dimension] of dimensions.entries()) {\n if (seen.has(dimension.as)) {\n fail(`spec.dimensions[${index}].as`, `duplicate alias '${dimension.as}'`);\n }\n seen.add(dimension.as);\n dimensionAliases.add(dimension.as);\n }\n for (const [index, measure] of measures.entries()) {\n if (seen.has(measure.as)) {\n fail(`spec.measures[${index}].as`, `duplicate alias '${measure.as}'`);\n }\n seen.add(measure.as);\n measureAliases.add(measure.as);\n }\n for (const [index, entry] of having.entries()) {\n if (!measureAliases.has(entry.measure)) {\n fail(`spec.having[${index}].measure`, 'must be a declared measure alias');\n }\n }\n for (const [index, entry] of sort.entries()) {\n if (!seen.has(entry.by)) {\n fail(\n `spec.sort[${index}].by`,\n 'must be a declared dimension or measure alias',\n );\n }\n }\n\n let limit: number = RUNTIME_REPORT_LIMITS.defaultRowLimit;\n if (raw.limit !== undefined) {\n if (\n typeof raw.limit !== 'number' ||\n !Number.isSafeInteger(raw.limit) ||\n raw.limit < 1 ||\n raw.limit > RUNTIME_REPORT_LIMITS.maxRowLimit\n ) {\n fail(\n 'spec.limit',\n `must be an integer between 1 and ${RUNTIME_REPORT_LIMITS.maxRowLimit}`,\n );\n }\n limit = raw.limit;\n }\n\n let chart: RuntimeReportChart = { type: 'table' };\n if (raw.chart !== undefined) {\n const rawChart = strictObject(raw.chart, 'spec.chart', ['type', 'x', 'y']);\n const type = oneOf(\n rawChart.type,\n 'spec.chart.type',\n RUNTIME_REPORT_CHART_TYPES,\n );\n const x =\n rawChart.x === undefined ? undefined : alias(rawChart.x, 'spec.chart.x');\n if (x !== undefined && !dimensionAliases.has(x)) {\n fail('spec.chart.x', 'must be a declared dimension alias');\n }\n const y = strictArray(\n rawChart.y,\n 'spec.chart.y',\n RUNTIME_REPORT_LIMITS.maxMeasures,\n ).map((entry, index) => alias(entry, `spec.chart.y[${index}]`));\n for (const [index, name] of y.entries()) {\n if (!measureAliases.has(name)) {\n fail(`spec.chart.y[${index}]`, 'must be a declared measure alias');\n }\n }\n chart = { type, ...(x ? { x } : {}), ...(y.length > 0 ? { y } : {}) };\n }\n\n return {\n version: RUNTIME_REPORT_SPEC_VERSION,\n title,\n ...(description ? { description } : {}),\n source: raw.source as string,\n dimensions,\n measures,\n filters,\n having,\n sort,\n limit,\n chart,\n };\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [key, canonicalize(value[key])]),\n );\n }\n return value;\n}\n\n/** Stable fingerprint of a NORMALIZED spec; equal specs hash equally. */\nexport function runtimeReportSpecHash(spec: RuntimeReportSpec): string {\n return createHash('sha256')\n .update(JSON.stringify(canonicalize(spec)))\n .digest('hex');\n}\n\n/** Stable JSON text for storage (sorted keys). */\nexport function serializeRuntimeReportSpec(spec: RuntimeReportSpec): string {\n return JSON.stringify(canonicalize(spec));\n}\n","/**\n * Runtime report compiler and runner (#3711).\n *\n * `compileRuntimeReportSpec()` turns a parsed `RuntimeReportSpec` into the same\n * `AggregateSpec` the declared-report compiler targets, and\n * `runRuntimeReport()` executes it through the SDK `buildAggregate()` builder.\n * Nothing the spec says is ever interpolated into SQL text:\n *\n * - Source tables and columns come ONLY from the ObjectRegistry, resolved from\n * a server-owned source allow-list (`context.sources`). A spec names a\n * source id and registry field names; it can never name a table or column.\n * - Fields are admitted by the same exposure policy the report adapter uses:\n * sensitive/secret fields, `readPermission`-gated fields the live principal\n * lacks, transient/non-column/json fields, `_`-prefixed internals and the\n * tenant column are un-nameable. A hidden field is reported exactly like an\n * absent one so the compiler is not an existence oracle.\n * - Filter and having values travel as bound parameters through the SDK\n * `buildWhere()` builder, coerced to the field's type first.\n * - Output aliases are prefixed (`r_<alias>`) inside the SQL so they can never\n * collide with, shadow, or probe a source column.\n * - Tenant isolation is added explicitly (raw aggregates bypass the tenancy\n * interceptors) and fails closed: a tenant-scoped source with no tenant in\n * scope reads only NULL-tenant rows when tenancy is enabled. There is no\n * cross-tenant option.\n */\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\nimport { toSnakeCase } from '@happyvertical/smrt-core/utils';\nimport {\n getTenantId,\n isTenancyEnabled,\n isTenantScopedClass,\n} from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface, SqlAdapterType } from '@happyvertical/sql';\nimport { buildAggregate } from './aggregate.js';\nimport { adapterTypeFromDb, tenantColumn } from './refresh.js';\nimport {\n RUNTIME_REPORT_LIMITS,\n type RuntimeReportChart,\n RuntimeReportError,\n type RuntimeReportFilter,\n type RuntimeReportSpec,\n runtimeReportSpecHash,\n} from './runtime-spec.js';\nimport type { AggregateSelectExpr, AggregateSpec } from './types.js';\n\n/** A server-owned report source. The spec refers to it only by `id`. */\nexport interface RuntimeReportSourceDefinition {\n /** Opaque id the spec names; defaults to nothing, always explicit. */\n id: string;\n /** Registered `ObjectRegistry` class (qualified or bare name). */\n className: string;\n label?: string;\n /**\n * Permission-catalog collection SLUG the host authorizes reads against (the\n * `<collection>` in `<collection>.read`, not a class name). Informational\n * to the compiler; the host's `authorizeSource` consumes it.\n */\n collection?: string;\n description?: string;\n /** Canonical public field names to expose; omitted means all eligible fields. */\n fields?: readonly string[];\n /** Canonical public field names to remove; exclusions always win. */\n excludeFields?: readonly string[];\n}\n\nexport interface RuntimeReportCompileContext {\n /** Server-owned allow-list. A spec can reach nothing outside it. */\n sources: readonly RuntimeReportSourceDefinition[];\n /**\n * The live principal's permission slugs. A `readPermission`-gated field is\n * admitted only when its permission is present. Omitted means none.\n */\n permissions?: readonly string[];\n /**\n * Tenant to scope tenant-scoped sources to. Defaults to the ambient tenant\n * context. There is intentionally no way to widen this to other tenants.\n */\n tenantId?: string | null;\n /** Host authorization for reading the source (for example RBAC `read`). */\n authorizeSource?: (\n source: RuntimeReportSourceDefinition,\n ) => void | Promise<void>;\n}\n\nexport type RuntimeReportColumnType =\n | 'string'\n | 'integer'\n | 'decimal'\n | 'boolean'\n | 'datetime'\n | 'id';\n\nexport interface RuntimeReportColumn {\n id: string;\n label: string;\n role: 'dimension' | 'measure';\n type: RuntimeReportColumnType;\n /** Source field this column derives from (absent for a row count). */\n field?: string;\n fn?: string;\n bucket?: string;\n /** Field format hint carried from the model (for example `money`). */\n format?: string;\n}\n\nexport interface CompiledRuntimeReport {\n version: 1;\n specHash: string;\n spec: RuntimeReportSpec;\n source: {\n id: string;\n className: string;\n label: string;\n table: string;\n };\n columns: RuntimeReportColumn[];\n /** Aggregate plan; output aliases carry the internal `r_` prefix. */\n aggregate: AggregateSpec;\n limit: number;\n tenant: { scoped: boolean; tenantId: string | null };\n}\n\nexport interface RuntimeReportResult {\n version: 1;\n specHash: string;\n title: string;\n columns: RuntimeReportColumn[];\n rows: Record<string, string | number | boolean | null>[];\n rowCount: number;\n /** True when more rows existed than the spec/host limit. */\n truncated: boolean;\n ranAt: string;\n chart: RuntimeReportChart;\n}\n\nconst ALIAS_PREFIX = 'r_';\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\ninterface RegistryFieldShape {\n type?: string;\n transient?: boolean;\n sensitive?: boolean;\n sensitivity?: unknown;\n readPermission?: unknown;\n description?: unknown;\n format?: unknown;\n columnName?: string;\n _meta?: Record<string, unknown>;\n}\n\ninterface SourceField {\n name: string;\n column: string;\n type: RuntimeReportColumnType;\n format?: string;\n label: string;\n}\n\nfunction humanize(name: string): string {\n return name\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .replace(/^./, (value) => value.toUpperCase());\n}\n\nfunction columnTypeFor(\n type: string | undefined,\n): RuntimeReportColumnType | null {\n switch (type) {\n case 'text':\n return 'string';\n case 'integer':\n return 'integer';\n case 'decimal':\n return 'decimal';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'datetime';\n case 'foreignKey':\n case 'crossPackageRef':\n return 'id';\n default:\n return null;\n }\n}\n\nfunction explicitColumn(field: RegistryFieldShape): string | undefined {\n const metaColumn = field._meta?.columnName;\n if (typeof field.columnName === 'string') return field.columnName;\n return typeof metaColumn === 'string' ? metaColumn : undefined;\n}\n\nfunction strictFormat(field: RegistryFieldShape): string | undefined {\n const candidates = [field.format, field._meta?.format];\n return candidates.find(\n (value): value is string => typeof value === 'string' && value.length > 0,\n );\n}\n\n/**\n * Standard SMRT columns that exist on every object table. They are exposed\n * even when a class registers no explicit field for them.\n */\nconst BASE_FIELDS: Record<string, RuntimeReportColumnType> = {\n id: 'id',\n slug: 'string',\n createdAt: 'datetime',\n updatedAt: 'datetime',\n};\n\nfunction isExcluded(\n name: string,\n field: RegistryFieldShape,\n tenantField: string | null,\n permissions: ReadonlySet<string>,\n): boolean {\n if (name.startsWith('_')) return true;\n const meta = field._meta ?? {};\n if (field.transient === true || meta.transient === true) return true;\n const sensitivity = [field.sensitivity, meta.sensitivity].find(\n (value): value is string => typeof value === 'string',\n );\n if (\n field.sensitive === true ||\n meta.sensitive === true ||\n sensitivity === 'sensitive' ||\n sensitivity === 'secret'\n ) {\n return true;\n }\n const readPermission =\n typeof field.readPermission === 'string'\n ? field.readPermission\n : typeof meta.readPermission === 'string'\n ? meta.readPermission\n : undefined;\n if (readPermission && !permissions.has(readPermission)) return true;\n const tenancy = meta.__tenancy as { isTenantIdField?: boolean } | undefined;\n if (tenancy?.isTenantIdField === true) return true;\n if (name === 'tenantId' || name === 'tenant_id') return true;\n if (tenantField && toSnakeCase(name) === tenantField) return true;\n return false;\n}\n\nasync function loadSourceFields(\n qualifiedName: string,\n tenantField: string | null,\n permissions: ReadonlySet<string>,\n source: RuntimeReportSourceDefinition,\n): Promise<Map<string, SourceField>> {\n const registered = (await ObjectRegistry.getAllFields(qualifiedName)) as Map<\n string,\n RegistryFieldShape\n >;\n const baseNames = new Map(\n Object.keys(BASE_FIELDS).map((name) => [toSnakeCase(name), name]),\n );\n const columns = new Map<\n string,\n { name: string; field: RegistryFieldShape }[]\n >();\n for (const [name, field] of registered) {\n const column = toSnakeCase(explicitColumn(field) ?? name);\n const entries = columns.get(column) ?? [];\n entries.push({ name, field });\n columns.set(column, entries);\n }\n for (const [name, type] of Object.entries(BASE_FIELDS)) {\n const column = toSnakeCase(name);\n if (!columns.has(column) && !registered.has(name)) {\n columns.set(column, [\n {\n name,\n field: {\n type:\n type === 'id' ? 'foreignKey' : type === 'string' ? 'text' : type,\n },\n },\n ]);\n }\n }\n // Collapse base-column aliases before applying either model or host policy.\n // Any restriction on a physical column also protects its other spellings.\n const knownNames = new Set<string>();\n for (const [column, entries] of columns) {\n for (const entry of entries)\n knownNames.add(baseNames.get(column) ?? entry.name);\n }\n const policy = (key: 'fields' | 'excludeFields'): Set<string> | undefined => {\n const value = source[key];\n if (value === undefined) return undefined;\n if (\n !Array.isArray(value) ||\n Array.from(value).some(\n (name) => typeof name !== 'string' || !knownNames.has(name),\n )\n ) {\n throw new RuntimeReportError(\n 'unsupported_source',\n `source.${key}`,\n `${key} must contain canonical field names declared on the source`,\n );\n }\n return new Set(value);\n };\n const included = policy('fields');\n const excluded = policy('excludeFields');\n const fields = new Map<string, SourceField>();\n for (const [column, entries] of columns) {\n if (\n column === tenantField ||\n column === 'tenant_id' ||\n entries.some(\n ({ name, field }) =>\n isExcluded(name, field, tenantField, permissions) ||\n excluded?.has(baseNames.get(column) ?? name),\n )\n )\n continue;\n for (const { name: registeredName, field } of entries) {\n const name = baseNames.get(column) ?? registeredName;\n if (fields.has(name) || (included && !included.has(name))) continue;\n const type = columnTypeFor(field.type);\n if (!type) continue;\n const format = strictFormat(field);\n fields.set(name, {\n name,\n column,\n type,\n ...(format ? { format } : {}),\n label:\n typeof field.description === 'string' && field.description.length > 0\n ? field.description\n : humanize(name),\n });\n }\n }\n return fields;\n}\n\nfunction unknownField(path: string, name: string): never {\n throw new RuntimeReportError(\n 'unknown_field',\n path,\n `'${name}' is not a field available on this source`,\n );\n}\n\nfunction badOperation(path: string, message: string): never {\n throw new RuntimeReportError('invalid_operation', path, message);\n}\n\nfunction badValue(path: string, message: string): never {\n throw new RuntimeReportError('invalid_value', path, message);\n}\n\ntype Condition = Record<string, unknown>;\n\nconst OPERATORS_BY_TYPE: Record<\n RuntimeReportColumnType,\n readonly RuntimeReportFilter['op'][]\n> = {\n string: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'contains',\n 'isNull',\n 'isNotNull',\n ],\n integer: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isNull',\n 'isNotNull',\n ],\n decimal: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isNull',\n 'isNotNull',\n ],\n datetime: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isNull',\n 'isNotNull',\n ],\n boolean: ['eq', 'ne', 'isNull', 'isNotNull'],\n id: ['eq', 'ne', 'in', 'notIn', 'isNull', 'isNotNull'],\n};\n\nfunction coerceValue(\n type: RuntimeReportColumnType,\n value: unknown,\n path: string,\n): string | number | boolean | Date {\n switch (type) {\n case 'string':\n if (typeof value !== 'string') badValue(path, 'must be a string');\n return value;\n case 'integer':\n if (typeof value !== 'number' || !Number.isSafeInteger(value)) {\n badValue(path, 'must be a safe integer');\n }\n return value;\n case 'decimal':\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n badValue(path, 'must be a finite number');\n }\n return value;\n case 'boolean':\n if (typeof value !== 'boolean') badValue(path, 'must be true or false');\n return value;\n case 'datetime': {\n if (typeof value !== 'string')\n badValue(path, 'must be an ISO-8601 string');\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime()) || !/^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n badValue(path, 'must be an ISO-8601 date or timestamp');\n }\n return parsed;\n }\n case 'id':\n if (typeof value !== 'string' || !UUID_PATTERN.test(value)) {\n badValue(path, 'must be a UUID');\n }\n return value.toLowerCase();\n }\n}\n\nfunction filterCondition(\n filter: RuntimeReportFilter,\n field: SourceField,\n path: string,\n): Condition {\n if (!OPERATORS_BY_TYPE[field.type].includes(filter.op)) {\n badOperation(\n `${path}.op`,\n `'${filter.op}' is not valid for ${field.type} fields`,\n );\n }\n const column = field.column;\n switch (filter.op) {\n case 'isNull':\n return { [column]: null };\n case 'isNotNull':\n return { [`${column} !=`]: null };\n case 'in':\n case 'notIn': {\n const values = (filter.value as unknown[]).map((entry, index) =>\n coerceValue(field.type, entry, `${path}.value[${index}]`),\n );\n return { [`${column} ${filter.op === 'in' ? 'in' : 'not in'}`]: values };\n }\n case 'contains':\n return {\n [`${column} contains`]: coerceValue(\n field.type,\n filter.value,\n `${path}.value`,\n ),\n };\n default: {\n const suffix = {\n eq: '',\n ne: ' !=',\n gt: ' >',\n gte: ' >=',\n lt: ' <',\n lte: ' <=',\n }[filter.op];\n return {\n [`${column}${suffix}`]: coerceValue(\n field.type,\n filter.value,\n `${path}.value`,\n ),\n };\n }\n }\n}\n\nfunction measureColumnType(\n fn: string,\n field: SourceField | undefined,\n): RuntimeReportColumnType {\n if (fn === 'count' || fn === 'countDistinct') return 'integer';\n if (fn === 'avg') return 'decimal';\n return field?.type ?? 'decimal';\n}\n\nfunction resolveSource(\n context: RuntimeReportCompileContext,\n id: string,\n): RuntimeReportSourceDefinition {\n const source = context.sources.find((candidate) => candidate.id === id);\n if (!source) {\n // Same answer for \"absent\" and \"not offered to this host/principal\".\n throw new RuntimeReportError(\n 'unknown_source',\n 'spec.source',\n `'${id}' is not an available report source`,\n );\n }\n return source;\n}\n\ninterface PreparedSource {\n source: RuntimeReportSourceDefinition;\n registeredName: string;\n qualifiedName: string;\n table: string;\n tenantCol: string | null;\n fields: Map<string, SourceField>;\n}\n\nasync function prepareSource(\n context: RuntimeReportCompileContext,\n id: string,\n): Promise<PreparedSource> {\n const source = resolveSource(context, id);\n await context.authorizeSource?.(source);\n\n const registered = ObjectRegistry.getClass(source.className);\n if (!registered) {\n throw new RuntimeReportError(\n 'unknown_source',\n 'spec.source',\n `'${id}' is not an available report source`,\n );\n }\n const qualifiedName = registered.qualifiedName ?? registered.name;\n const table = ObjectRegistry.getTableName(qualifiedName);\n if (!table) {\n throw new RuntimeReportError(\n 'unsupported_source',\n 'spec.source',\n 'this source has no registered table',\n );\n }\n\n const tenantCol = await tenantColumn(qualifiedName);\n if (isTenantScopedClass(qualifiedName) && !tenantCol) {\n throw new RuntimeReportError(\n 'unsupported_source',\n 'spec.source',\n 'this tenant-scoped source does not expose a tenant column',\n );\n }\n const fields = await loadSourceFields(\n qualifiedName,\n tenantCol,\n new Set(context.permissions ?? []),\n source,\n );\n return {\n source,\n registeredName: registered.name,\n qualifiedName,\n table,\n tenantCol,\n fields,\n };\n}\n\nexport interface RuntimeReportSourceDescription {\n id: string;\n label: string;\n description?: string;\n /** Fields the live principal may group by, filter on or aggregate. */\n fields: {\n name: string;\n label: string;\n type: RuntimeReportColumnType;\n format?: string;\n filterOperators: readonly string[];\n aggregates: readonly string[];\n }[];\n}\n\n/**\n * Describe what a spec may reference on one source for the live principal:\n * exactly the field set the compiler would admit, so a model never has to\n * guess names and never learns about hidden ones.\n */\nexport async function describeRuntimeReportSource(\n context: RuntimeReportCompileContext,\n sourceId: string,\n): Promise<RuntimeReportSourceDescription> {\n const prepared = await prepareSource(context, sourceId);\n return {\n id: prepared.source.id,\n label: prepared.source.label ?? humanize(prepared.registeredName),\n ...(prepared.source.description\n ? { description: prepared.source.description }\n : {}),\n fields: [...prepared.fields.values()].map((field) => ({\n name: field.name,\n label: field.label,\n type: field.type,\n ...(field.format ? { format: field.format } : {}),\n filterOperators: OPERATORS_BY_TYPE[field.type],\n aggregates: aggregatesFor(field.type),\n })),\n };\n}\n\nfunction aggregatesFor(type: RuntimeReportColumnType): readonly string[] {\n if (type === 'integer' || type === 'decimal') {\n return ['count', 'countDistinct', 'sum', 'avg', 'min', 'max'];\n }\n if (type === 'datetime') return ['count', 'countDistinct', 'min', 'max'];\n return ['count', 'countDistinct'];\n}\n\n/**\n * Validate a parsed spec against the registry, the live principal's field\n * policy, and tenancy, and compile it to an executable aggregate plan.\n */\nexport async function compileRuntimeReportSpec(\n spec: RuntimeReportSpec,\n context: RuntimeReportCompileContext,\n): Promise<CompiledRuntimeReport> {\n const { source, registeredName, qualifiedName, table, tenantCol, fields } =\n await prepareSource(context, spec.source);\n\n const lookup = (name: string, path: string): SourceField => {\n const field = fields.get(name);\n if (!field) unknownField(path, name);\n return field;\n };\n\n const columns: RuntimeReportColumn[] = [];\n const select: AggregateSelectExpr[] = [];\n const groupBy: string[] = [];\n\n for (const [index, dimension] of spec.dimensions.entries()) {\n const path = `spec.dimensions[${index}]`;\n const field = lookup(dimension.field, `${path}.field`);\n if (dimension.bucket && field.type !== 'datetime') {\n badOperation(\n `${path}.bucket`,\n 'buckets are only valid on datetime fields',\n );\n }\n const sqlAlias = `${ALIAS_PREFIX}${dimension.as}`;\n if (dimension.bucket) {\n select.push({\n bucket: dimension.bucket,\n column: field.column,\n as: sqlAlias,\n });\n } else {\n select.push({ column: field.column, as: sqlAlias });\n }\n groupBy.push(sqlAlias);\n columns.push({\n id: dimension.as,\n label: humanize(dimension.as),\n role: 'dimension',\n type: dimension.bucket ? 'datetime' : field.type,\n field: field.name,\n ...(dimension.bucket ? { bucket: dimension.bucket } : {}),\n ...(field.format && !dimension.bucket ? { format: field.format } : {}),\n });\n }\n\n for (const [index, measure] of spec.measures.entries()) {\n const path = `spec.measures[${index}]`;\n const field = measure.field\n ? lookup(measure.field, `${path}.field`)\n : undefined;\n if (\n (measure.fn === 'sum' || measure.fn === 'avg') &&\n field?.type !== 'integer' &&\n field?.type !== 'decimal'\n ) {\n badOperation(`${path}.fn`, `${measure.fn} requires a numeric field`);\n }\n if (\n (measure.fn === 'min' || measure.fn === 'max') &&\n field?.type !== 'integer' &&\n field?.type !== 'decimal' &&\n field?.type !== 'datetime'\n ) {\n badOperation(\n `${path}.fn`,\n `${measure.fn} requires a numeric or datetime field`,\n );\n }\n const sqlAlias = `${ALIAS_PREFIX}${measure.as}`;\n select.push({\n fn: measure.fn === 'countDistinct' ? 'count' : measure.fn,\n ...(field ? { column: field.column } : {}),\n as: sqlAlias,\n ...(measure.fn === 'countDistinct' ? { distinct: true } : {}),\n });\n const keepsFormat =\n field?.format &&\n (measure.fn === 'sum' ||\n measure.fn === 'min' ||\n measure.fn === 'max' ||\n measure.fn === 'avg');\n columns.push({\n id: measure.as,\n label: humanize(measure.as),\n role: 'measure',\n type: measureColumnType(measure.fn, field),\n ...(field ? { field: field.name } : {}),\n fn: measure.fn,\n ...(keepsFormat ? { format: field?.format } : {}),\n });\n }\n\n const conditions: Condition[] = [];\n\n // Tenancy: explicit, never widened. See module doc.\n const tenantId =\n context.tenantId !== undefined ? context.tenantId : (getTenantId() ?? null);\n if (tenantCol) {\n if (tenantId) {\n conditions.push({ [tenantCol]: tenantId });\n } else if (isTenancyEnabled() || isTenantScopedClass(qualifiedName)) {\n conditions.push({ [tenantCol]: null });\n }\n }\n\n // Soft delete: honour it when the source declares it.\n const registeredFields = (await ObjectRegistry.getAllFields(\n qualifiedName,\n )) as Map<string, RegistryFieldShape>;\n if (registeredFields.has('deletedAt')) conditions.push({ deleted_at: null });\n\n // STI child sources share a table with siblings: keep to the child's rows.\n if (ObjectRegistry.getTableStrategy(qualifiedName) === 'sti') {\n const base = ObjectRegistry.getSTIBase(qualifiedName);\n if (base !== null && base !== qualifiedName) {\n conditions.push({ _meta_type: qualifiedName });\n }\n }\n\n for (const [index, filter] of spec.filters.entries()) {\n const path = `spec.filters[${index}]`;\n const field = lookup(filter.field, `${path}.field`);\n conditions.push(filterCondition(filter, field, path));\n }\n\n const having: Condition[] = spec.having.map((entry) => {\n const suffix = {\n eq: '',\n ne: ' !=',\n gt: ' >',\n gte: ' >=',\n lt: ' <',\n lte: ' <=',\n }[entry.op];\n return { [`${ALIAS_PREFIX}${entry.measure}${suffix}`]: entry.value };\n });\n\n const orderBy = spec.sort.map(\n (entry) =>\n `${ALIAS_PREFIX}${entry.by} ${entry.direction === 'desc' ? 'DESC' : 'ASC'}`,\n );\n if (orderBy.length === 0 && spec.dimensions.length > 0) {\n orderBy.push(`${ALIAS_PREFIX}${spec.dimensions[0].as} ASC`);\n }\n\n const aggregate: AggregateSpec = {\n from: table,\n select,\n groupBy,\n ...(conditions.length > 0 ? { where: [conditions] } : {}),\n ...(having.length > 0 ? { having: [having] } : {}),\n ...(orderBy.length > 0 ? { orderBy } : {}),\n limit: Math.min(spec.limit, RUNTIME_REPORT_LIMITS.maxRowLimit) + 1,\n };\n\n return {\n version: 1,\n specHash: runtimeReportSpecHash(spec),\n spec,\n source: {\n id: source.id,\n className: qualifiedName,\n label: source.label ?? humanize(registeredName),\n table,\n },\n columns,\n aggregate,\n limit: spec.limit,\n tenant: {\n scoped: Boolean(tenantCol),\n tenantId: tenantCol ? tenantId : null,\n },\n };\n}\n\nfunction adaptWhere(\n where: AggregateSpec['where'],\n adapterType: SqlAdapterType,\n): AggregateSpec['where'] {\n if (!where || !Array.isArray(where)) return where;\n // SQLite binds booleans as integers; other adapters accept native booleans.\n const adapt = (value: unknown): unknown =>\n adapterType === 'sqlite' && typeof value === 'boolean'\n ? value\n ? 1\n : 0\n : value;\n return where.map((group) =>\n group.map((condition: Record<string, unknown>) =>\n Object.fromEntries(\n Object.entries(condition).map(([key, value]) => [\n key,\n Array.isArray(value) ? value.map(adapt) : adapt(value),\n ]),\n ),\n ),\n );\n}\n\nfunction normalizeCell(\n column: RuntimeReportColumn,\n value: unknown,\n): string | number | boolean | null {\n if (value === null || value === undefined) return null;\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'bigint') {\n const asNumber = Number(value);\n if (!Number.isSafeInteger(asNumber)) {\n throw new RuntimeReportError(\n 'invalid_result',\n column.id,\n 'integer result exceeds the JavaScript safe range',\n );\n }\n return asNumber;\n }\n if (column.type === 'boolean') {\n if (value === 1 || value === '1' || value === 'true' || value === true) {\n return true;\n }\n if (value === 0 || value === '0' || value === 'false' || value === false) {\n return false;\n }\n }\n if (column.type === 'integer' || column.type === 'decimal') {\n const numeric = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(numeric)) {\n throw new RuntimeReportError(\n 'invalid_result',\n column.id,\n 'numeric result is not finite',\n );\n }\n if (column.type === 'integer' && !Number.isSafeInteger(numeric)) {\n throw new RuntimeReportError(\n 'invalid_result',\n column.id,\n 'integer result exceeds the JavaScript safe range',\n );\n }\n return numeric;\n }\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n return String(value);\n}\n\nexport interface RunRuntimeReportOptions {\n db: DatabaseInterface;\n adapterType?: SqlAdapterType;\n /** Host row ceiling applied on top of the spec's own limit. */\n maxRows?: number;\n now?: () => Date;\n}\n\n/**\n * Execute a compiled plan. The caller owns authorization: compile with the\n * live principal each time rather than running a plan compiled for someone\n * else. Results are never cached here for exactly that reason.\n */\nexport async function runRuntimeReport(\n compiled: CompiledRuntimeReport,\n options: RunRuntimeReportOptions,\n): Promise<RuntimeReportResult> {\n const adapterType = adapterTypeFromDb(options.db, options.adapterType);\n const aggregate = buildAggregate(\n {\n ...compiled.aggregate,\n where: adaptWhere(compiled.aggregate.where, adapterType),\n },\n 1,\n adapterType,\n );\n const result = await options.db.query(aggregate.sql, ...aggregate.values);\n const rawRows = (result.rows ?? []) as Record<string, unknown>[];\n const limit = Math.min(\n compiled.limit,\n options.maxRows ?? RUNTIME_REPORT_LIMITS.maxRowLimit,\n );\n const truncated = rawRows.length > limit;\n const rows = rawRows.slice(0, limit).map((row) => {\n const out: Record<string, string | number | boolean | null> = {};\n for (const column of compiled.columns) {\n out[column.id] = normalizeCell(\n column,\n row[`${ALIAS_PREFIX}${column.id}`],\n );\n }\n return out;\n });\n return {\n version: 1,\n specHash: compiled.specHash,\n title: compiled.spec.title,\n columns: compiled.columns,\n rows,\n rowCount: rows.length,\n truncated,\n ranAt: (options.now?.() ?? new Date()).toISOString(),\n chart: compiled.spec.chart,\n };\n}\n","import './__smrt-register__.js';\n\n/**\n * Stored runtime report definitions (#3711).\n *\n * A `RuntimeReport` row is a validated {@link RuntimeReportSpec} saved as data.\n * It carries NO authority: the spec is re-parsed on every read and re-compiled\n * against the live principal's field policy, permissions and tenant on every\n * run, so a stored report can never expose more than its current viewer may\n * see. Result rows are deliberately never persisted (a cached result computed\n * for one principal must not be served to another).\n *\n * The assistant creates rows through {@link saveRuntimeReport}, so only a spec\n * that compiled for the saving principal and was confirmed by a human is\n * stored. That is enforced HERE, in the model layer, not just by which\n * surfaces are generated: `validateBeforeSave()` refuses every insert, and\n * every update that changes the spec (or title, source, description or author),\n * unless the instance carries a confirmation proof that only\n * {@link saveRuntimeReport} can attach. Rows built from JSON (a REST body, a\n * manifest tool call) cannot carry the proof, so they are refused whatever\n * surface delivered them. Archiving (a `status` change with the spec\n * untouched) stays allowed. The generated surfaces expose `list`/`get`, plus\n * `create` on the API only so the permission catalog and Postgres RLS bindings\n * know the operation the confirmed save performs.\n */\n\nimport {\n field,\n SmrtCollection,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n type CompiledRuntimeReport,\n compileRuntimeReportSpec,\n type RuntimeReportCompileContext,\n type RuntimeReportResult,\n runRuntimeReport,\n} from './runtime-compiler.js';\nimport {\n parseRuntimeReportSpec,\n RuntimeReportError,\n type RuntimeReportSpec,\n runtimeReportSpecHash,\n serializeRuntimeReportSpec,\n} from './runtime-spec.js';\n\nexport type RuntimeReportStatus = 'active' | 'archived';\n\n/**\n * Confirmation proof carried on a constructor option. A symbol key can never\n * arrive from JSON (REST body, manifest tool arguments), and the symbol is not\n * exported, so only code in this module can mint a row that may be written.\n */\nconst CONFIRMED_SAVE = Symbol('smrt-reports.runtimeReport.confirmedSave');\n\n/** Instance -> spec hash a human confirmed for this exact write. */\nconst confirmedSaves = new WeakMap<object, string>();\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: 'runtime_reports',\n // The exposed operations are exactly: list/get (API, CLI, MCP) and `create`\n // (API only). `create` is enabled so the permission catalog -- and with it\n // role grants -- know the operation the assistant's confirmed save performs\n // (`<collection>.create`); it is NOT a way to author a report. The model layer\n // (validateBeforeSave) refuses any insert that was not minted by\n // saveRuntimeReport() after a human confirmed that exact spec, so a REST\n // `create` body is always refused. `update` and `delete` are deliberately\n // absent from every surface, so they never enter the catalog or RLS grants.\n api: { include: ['list', 'get', 'create'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class RuntimeReport extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-reports\";\n @tenantId()\n tenantId: string = '';\n\n @field({ type: 'text' })\n title: string = '';\n\n @field({ type: 'text' })\n description: string = '';\n\n /** Source id the spec names; resolved against a host allow-list at run. */\n @field({ type: 'text' })\n sourceId: string = '';\n\n /** Normalized spec JSON; use {@link getSpec}/{@link setSpec}. */\n @field({ type: 'text', required: true })\n spec: string = '';\n\n /** Hash of the normalized spec; detects out-of-band edits to `spec`. */\n @field({ type: 'text' })\n specHash: string = '';\n\n @field({ type: 'text', required: true })\n status: RuntimeReportStatus = 'active';\n\n /** Principal that saved the report (an id string; not a foreign key). */\n @field({ type: 'text' })\n createdByUserId: string = '';\n\n constructor(options: SmrtObjectOptions = {}) {\n super(options);\n const proof = (options as Record<symbol, unknown>)[CONFIRMED_SAVE];\n if (typeof proof === 'string') confirmedSaves.set(this, proof);\n }\n\n /** Re-parse the stored JSON; never trust the column without validation. */\n getSpec(): RuntimeReportSpec {\n const parsed = parseRuntimeReportSpec(this.spec);\n if (runtimeReportSpecHash(parsed) !== this.specHash) {\n throw new RuntimeReportError(\n 'invalid_spec',\n 'spec',\n 'stored spec does not match its recorded hash',\n );\n }\n return parsed;\n }\n\n setSpec(spec: RuntimeReportSpec): void {\n const normalized = parseRuntimeReportSpec(spec);\n this.spec = serializeRuntimeReportSpec(normalized);\n this.specHash = runtimeReportSpecHash(normalized);\n this.title = normalized.title;\n this.description = normalized.description ?? '';\n this.sourceId = normalized.source;\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n // Parse whatever was supplied (REST body, service, direct assignment) and\n // re-derive every denormalized column from it, so the columns can never\n // disagree with the spec that runs.\n const parsed = parseRuntimeReportSpec(this.spec);\n await this.assertConfirmedWrite(parsed);\n this.setSpec(parsed);\n if (this.status !== 'active' && this.status !== 'archived') {\n throw new RuntimeReportError('invalid_spec', 'status', 'is invalid');\n }\n }\n\n /**\n * Invariant: a RuntimeReport row is inserted, or has its spec/title/source/\n * description/author changed, only by the confirmed-save path. Anything else\n * (REST `create` body, manifest tool args, `new RuntimeReport().save()`,\n * `collection.update()` of the spec) is refused here. A save that leaves those\n * columns as stored (an archive/unarchive status change) needs no proof.\n */\n private async assertConfirmedWrite(parsed: RuntimeReportSpec): Promise<void> {\n const hash = runtimeReportSpecHash(parsed);\n const proof = confirmedSaves.get(this);\n if (proof !== undefined) {\n // Single use: the proof covers exactly one write of this exact spec.\n confirmedSaves.delete(this);\n if (proof === hash) return;\n } else if (this.isPersisted && this.id) {\n const stored = (await this.db.get(this.tableName, { id: this.id })) as {\n spec_hash?: unknown;\n title?: unknown;\n description?: unknown;\n source_id?: unknown;\n created_by_user_id?: unknown;\n } | null;\n if (\n stored &&\n stored.spec_hash === hash &&\n (stored.title ?? '') === parsed.title &&\n (stored.description ?? '') === (parsed.description ?? '') &&\n (stored.source_id ?? '') === parsed.source &&\n (stored.created_by_user_id ?? '') === (this.createdByUserId ?? '')\n ) {\n return;\n }\n }\n throw new RuntimeReportError(\n 'confirmation_required',\n 'spec',\n 'a runtime report can only be created or changed through the confirmed save of reports.runtime.define; the write was refused',\n );\n }\n}\n\nexport class RuntimeReportCollection extends SmrtCollection<RuntimeReport> {\n static readonly _itemClass = RuntimeReport;\n}\n\nexport interface RuntimeReportStoreOptions {\n db: DatabaseInterface;\n}\n\nexport interface SaveRuntimeReportOptions extends RuntimeReportStoreOptions {\n /** A plan compiled for the SAVING principal; the only accepted input. */\n compiled: CompiledRuntimeReport;\n /**\n * The spec hash a human confirmed (the value handed to the application's\n * confirmation host). It must equal the compiled plan's hash; the row is\n * only minted when it does. Call this ONLY after that confirmation resolved.\n */\n confirmedSpecHash: string;\n createdByUserId: string;\n /** Defaults to the tenant the plan was compiled for, then ambient. */\n tenantId?: string | null;\n}\n\nasync function collectionFor(\n db: DatabaseInterface,\n): Promise<RuntimeReportCollection> {\n return RuntimeReportCollection.create({\n db,\n }) as Promise<RuntimeReportCollection>;\n}\n\n/** Persist a spec that has already compiled for the saving principal. */\nexport async function saveRuntimeReport(\n options: SaveRuntimeReportOptions,\n): Promise<RuntimeReport> {\n const tenant =\n options.tenantId ?? options.compiled.tenant.tenantId ?? getTenantId() ?? '';\n if (!tenant) {\n throw new RuntimeReportError(\n 'tenant_required',\n '',\n 'a tenant is required to save a runtime report',\n );\n }\n const spec = parseRuntimeReportSpec(options.compiled.spec);\n const specHash = runtimeReportSpecHash(spec);\n if (specHash !== options.compiled.specHash) {\n throw new RuntimeReportError(\n 'invalid_spec',\n 'spec',\n 'compiled plan does not match its spec',\n );\n }\n if (options.confirmedSpecHash !== specHash) {\n throw new RuntimeReportError(\n 'confirmation_required',\n 'specHash',\n 'the confirmed spec hash does not match the spec; the report was not saved',\n );\n }\n const collection = await collectionFor(options.db);\n return collection.create({\n tenantId: tenant,\n title: spec.title,\n description: spec.description ?? '',\n sourceId: spec.source,\n spec: serializeRuntimeReportSpec(spec),\n specHash,\n status: 'active',\n createdByUserId: options.createdByUserId,\n // The only place a confirmation proof is minted; see CONFIRMED_SAVE.\n [CONFIRMED_SAVE]: specHash,\n } as Parameters<RuntimeReportCollection['create']>[0]);\n}\n\nexport async function getRuntimeReport(\n options: RuntimeReportStoreOptions & {\n ref: string;\n /**\n * Explicit owner tenant. When given, a row owned by any other tenant is\n * treated as absent even if the ambient tenant context would admit it\n * (a host that knows the principal's tenant should always pass it).\n */\n tenantId?: string;\n },\n): Promise<RuntimeReport | null> {\n const collection = await collectionFor(options.db);\n const report = await collection.get(options.ref);\n if (report && options.tenantId && report.tenantId !== options.tenantId) {\n return null;\n }\n return report;\n}\n\nexport async function listRuntimeReports(\n options: RuntimeReportStoreOptions & {\n status?: RuntimeReportStatus;\n limit?: number;\n /** Explicit owner tenant; filters in addition to the ambient context. */\n tenantId?: string;\n /** Exact author filter, applied before the result limit; never grants authority. */\n createdByUserId?: string;\n /** Exact normalized spec hash from the public runtime report compiler. */\n specHash?: string;\n },\n): Promise<RuntimeReport[]> {\n const collection = await collectionFor(options.db);\n return collection.list({\n where: {\n status: options.status ?? 'active',\n ...(options.tenantId ? { tenantId: options.tenantId } : {}),\n ...(options.createdByUserId !== undefined\n ? { createdByUserId: options.createdByUserId }\n : {}),\n ...(options.specHash !== undefined ? { specHash: options.specHash } : {}),\n },\n orderBy: 'created_at DESC',\n limit: Math.min(Math.max(options.limit ?? 50, 1), 200),\n });\n}\n\nexport async function archiveRuntimeReport(\n options: RuntimeReportStoreOptions & { ref: string },\n): Promise<RuntimeReport | null> {\n const report = await getRuntimeReport(options);\n if (!report) return null;\n report.status = 'archived';\n await report.save();\n return report;\n}\n\n/**\n * Re-validate a stored report against the live principal and run it. The\n * stored spec is parsed again and compiled with the caller's context, so\n * policy changes made after the report was saved apply immediately.\n */\nexport async function runStoredRuntimeReport(\n options: RuntimeReportStoreOptions & {\n report: RuntimeReport;\n context: RuntimeReportCompileContext;\n maxRows?: number;\n },\n): Promise<RuntimeReportResult> {\n if (options.report.status !== 'active') {\n throw new RuntimeReportError(\n 'invalid_spec',\n 'status',\n 'report is archived',\n );\n }\n const compiled = await compileRuntimeReportSpec(\n options.report.getSpec(),\n options.context,\n );\n return runRuntimeReport(compiled, {\n db: options.db,\n maxRows: options.maxRows,\n });\n}\n","/**\n * Saved report-view and export contracts.\n *\n * This module owns only the serializable report boundary. Applications own\n * durable view storage, principal binding, authorization, auditing, artifact\n * storage, download tokens, and background-job execution.\n */\nimport { createHash } from 'node:crypto';\nimport {\n createDataQueryFingerprint,\n normalizeDataQueryRequest,\n} from '@happyvertical/smrt-core';\nimport type {\n DataQueryFreshness,\n DataQueryRequest,\n DataQueryResult,\n DataQuerySort,\n} from '@happyvertical/smrt-types';\nimport {\n type ReportAdapterDescriptor,\n type ReportColumnCapability,\n type ReportDataQueryResult,\n splitReportFilterScopes,\n} from './adapter.js';\n\nconst INHERITED_REPORT_SCOPE = [\n 'principal',\n 'tenant',\n 'report-definition',\n 'field-policy',\n] as const;\n\nconst EXPORT_FORMATS = new Set<ReportExportFormat>(['csv', 'json']);\nconst PINNED_COLUMN_SIDES = new Set<ReportSavedViewPinnedSide>([\n 'start',\n 'end',\n]);\nconst DISPLAY_DENSITIES = new Set<ReportSavedViewDisplay['density']>([\n 'compact',\n 'comfortable',\n]);\nconst RFC_3339_INSTANT =\n /^(\\d{4})-(\\d{2})-(\\d{2})T([01]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)(?:\\.\\d{1,9})?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/;\n\nconst DEFAULT_EXPORT_LIMITS: ReportExportLimits = {\n maxRows: 100_000,\n maxBytes: 25_000_000,\n deadlineMs: 60_000,\n foregroundRowLimit: 1_000,\n};\n\nconst MAX_EXPORT_LIMITS = {\n maxRows: 1_000_000,\n maxBytes: 100_000_000,\n deadlineMs: 300_000,\n foregroundRowLimit: 100_000,\n} as const;\n\nexport class ReportSurfaceValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReportSurfaceValidationError';\n }\n}\n\nexport type ReportSavedViewPinnedSide = 'start' | 'end';\n\n/** A view's column order is its array order; ids are always adapter-defined. */\nexport interface ReportSavedViewColumn {\n id: string;\n width?: number;\n pinned?: ReportSavedViewPinnedSide;\n}\n\nexport interface ReportSavedViewGrouping {\n fields: string[];\n expanded?: boolean;\n}\n\nexport interface ReportSavedViewDisplay {\n density: 'compact' | 'comfortable';\n showTotals?: boolean;\n}\n\n/**\n * A normalized, policy-neutral stored view. The storage host associates it\n * with its owner and tenant; neither identity is accepted here.\n */\nexport interface ReportSavedView {\n version: 1;\n id: string;\n title: string;\n resourceId: string;\n reportClassName: string;\n definitionFingerprint: string;\n query: DataQueryRequest;\n columns: ReportSavedViewColumn[];\n grouping?: ReportSavedViewGrouping;\n display?: ReportSavedViewDisplay;\n}\n\nexport type ReportExportFormat = 'csv' | 'json';\n\n/**\n * Opaque identity of a host-captured materialization snapshot. The application\n * creates and verifies it while bound to its principal and tenant; callers\n * cannot turn an `asOf` label into a snapshot by supplying this id alone.\n */\nexport interface ReportExportSnapshotBinding {\n id: string;\n}\n\nexport interface ReportExportSnapshot {\n version: 1;\n resourceId: string;\n reportClassName: string;\n definitionFingerprint: string;\n binding: ReportExportSnapshotBinding;\n request: DataQueryRequest;\n queryFingerprint: string;\n projection: string[];\n sort: DataQuerySort[];\n freshness: DataQueryFreshness;\n snapshot: {\n asOf: string;\n refreshedAt?: string;\n stale: boolean;\n };\n total: {\n kind: 'exact';\n value: number;\n };\n inherits: Array<(typeof INHERITED_REPORT_SCOPE)[number]>;\n}\n\n/** Every export is bounded before it is streamed or delegated to a worker. */\nexport interface ReportExportLimits {\n maxRows: number;\n maxBytes: number;\n deadlineMs: number;\n /** Exports above this exact row count must use the application queue. */\n foregroundRowLimit: number;\n}\n\n/**\n * A deterministic offset-page plan over the immutable host snapshot. A worker\n * starts at offset zero and advances by `page.limit` until `rowCount` rows have\n * been produced or the byte/deadline limits are reached.\n */\nexport interface ReportExportReadPlan {\n snapshotId: string;\n queryFingerprint: string;\n asOf: string;\n page: {\n kind: 'offset';\n offset: 0;\n limit: number;\n };\n}\n\nexport interface ReportExportRequest {\n version: 1;\n format: ReportExportFormat;\n execution: 'stream' | 'background';\n snapshot: ReportExportSnapshot;\n limits: ReportExportLimits;\n read: ReportExportReadPlan;\n rowCount: number;\n truncated: boolean;\n action: {\n id: 'export';\n requiredPermission: string;\n auditRequired: true;\n confirmationRequired: boolean;\n };\n}\n\n/**\n * An authority-free job handoff. The queue must re-enter the bound principal\n * and tenant, resolve the current report definition/field policy, and verify\n * this snapshot before materializing an artifact.\n */\nexport interface ReportBackgroundExportTask {\n version: 1;\n execution: 'background';\n request: ReportExportRequest;\n inherits: Array<(typeof INHERITED_REPORT_SCOPE)[number]>;\n}\n\nexport interface ReportExportProgress {\n state: 'queued' | 'running' | 'completed' | 'failed';\n rowCount: number;\n byteCount: number;\n truncated: boolean;\n}\n\n/**\n * Artifact metadata is deliberately URL- and token-free. An application-owned\n * serving boundary must authorize every download using the caller's current\n * principal and tenant before it reveals any artifact location.\n */\nexport interface ReportExportArtifact {\n id: string;\n request: ReportExportRequest;\n progress: ReportExportProgress;\n expiresAt: string;\n}\n\nexport interface ReportExportActionContext {\n phase: 'preview' | 'apply';\n reportClassName: string;\n resourceId: string;\n requiredPermission: string;\n confirmationRequired: boolean;\n execution: 'stream' | 'background';\n queryFingerprint: string;\n definitionFingerprint: string;\n snapshotId: string;\n asOf: string;\n pageSize: number;\n}\n\n/** The same host is used by human and agent callers. */\nexport interface ReportExportActionHost {\n /**\n * Prove that this opaque binding still resolves to the exact immutable\n * materialization snapshot under the host's current principal and tenant.\n * The background worker must call `validateReportExportExecution()` again\n * before reading or serving any rows.\n */\n assertSnapshot(context: ReportExportSnapshotContext): Promise<void> | void;\n authorize(context: ReportExportActionContext): Promise<void> | void;\n audit(context: ReportExportActionContext): Promise<void> | void;\n enqueue?(\n task: ReportBackgroundExportTask,\n ): Promise<{ taskId: string }> | { taskId: string };\n}\n\nexport interface ReportExportSnapshotContext {\n bindingId: string;\n resourceId: string;\n reportClassName: string;\n definitionFingerprint: string;\n queryFingerprint: string;\n asOf: string;\n}\n\nexport interface ReportExportPreview {\n phase: 'preview';\n action: ReportExportActionContext;\n request: ReportExportRequest;\n}\n\nexport type AppliedReportExport =\n | {\n phase: 'apply';\n execution: 'stream';\n status: 'ready';\n request: ReportExportRequest;\n }\n | {\n phase: 'apply';\n execution: 'background';\n status: 'queued';\n taskId: string;\n request: ReportExportRequest;\n };\n\ninterface SavedViewInput {\n version?: unknown;\n id: unknown;\n title: unknown;\n resourceId?: unknown;\n reportClassName?: unknown;\n definitionFingerprint?: unknown;\n query: unknown;\n columns?: unknown;\n grouping?: unknown;\n display?: unknown;\n}\n\ninterface ExportRequestInput {\n format: unknown;\n limits?: unknown;\n}\n\nfunction fail(message: string): never {\n throw new ReportSurfaceValidationError(message);\n}\n\nfunction plainObject(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return fail(`${label} must be a plain object`);\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n return fail(`${label} must be a plain object`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction exactKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n label: string,\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.includes(key)) {\n fail(`${label} contains an unsupported field: ${key}`);\n }\n }\n}\n\nfunction requiredString(\n value: unknown,\n label: string,\n maxLength = 256,\n): string {\n if (typeof value !== 'string') return fail(`${label} must be a string`);\n const normalized = value.trim();\n if (!normalized) return fail(`${label} cannot be empty`);\n if (normalized.length > maxLength) {\n return fail(`${label} cannot exceed ${String(maxLength)} characters`);\n }\n return normalized;\n}\n\nfunction optionalBoolean(value: unknown, label: string): boolean | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== 'boolean') return fail(`${label} must be a boolean`);\n return value;\n}\n\nfunction boundedInteger(\n value: unknown,\n label: string,\n minimum: number,\n maximum: number,\n): number {\n if (!Number.isInteger(value) || (value as number) < minimum) {\n return fail(`${label} must be an integer of at least ${String(minimum)}`);\n }\n if ((value as number) > maximum) {\n return fail(`${label} cannot exceed ${String(maximum)}`);\n }\n return value as number;\n}\n\nfunction normalizeIso(value: unknown, label: string): string {\n const text = requiredString(value, label, 64);\n const match = RFC_3339_INSTANT.exec(text);\n if (!match) return fail(`${label} must be an RFC 3339 instant`);\n const [year, month, day] = match.slice(1, 4).map(Number);\n const calendar = new Date(0);\n calendar.setUTCFullYear(year, month - 1, day);\n calendar.setUTCHours(0, 0, 0, 0);\n if (\n calendar.getUTCFullYear() !== year ||\n calendar.getUTCMonth() !== month - 1 ||\n calendar.getUTCDate() !== day\n ) {\n return fail(`${label} must be an RFC 3339 instant`);\n }\n const parsed = new Date(text);\n if (Number.isNaN(parsed.getTime())) {\n return fail(`${label} must be an RFC 3339 instant`);\n }\n return parsed.toISOString();\n}\n\nfunction normalizeSnapshotBinding(value: unknown): ReportExportSnapshotBinding {\n const input = plainObject(value, 'Report export snapshot binding');\n exactKeys(input, ['id'], 'Report export snapshot binding');\n return {\n id: requiredString(input.id, 'Report export snapshot binding id'),\n };\n}\n\nfunction stable(value: unknown): string {\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'number'\n ) {\n return JSON.stringify(value);\n }\n if (typeof value === 'string') return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(stable).join(',')}]`;\n const object = plainObject(value, 'Report surface value');\n return (\n '{' +\n Object.keys(object)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${stable(object[key])}`)\n .join(',') +\n '}'\n );\n}\n\n/**\n * A change to report fields, their capabilities, schema, scope, or source\n * invalidates a stored view/export snapshot rather than silently widening it.\n */\nexport function reportDefinitionFingerprint(\n descriptor: ReportAdapterDescriptor,\n): string {\n const definition = {\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n sourceClassName: descriptor.sourceClassName,\n tenantScoped: descriptor.tenantScoped,\n tenantField: descriptor.tenantField ?? null,\n identityField: descriptor.identityField,\n columns: descriptor.columns.map((column) => ({\n id: column.id,\n fieldName: column.fieldName,\n kind: column.kind,\n filterScope: column.filterScope,\n type: column.type,\n projectable: column.projectable === true,\n sortable: column.sortable === true,\n facetable: column.facetable === true,\n filterOperators: column.filterOperators ?? [],\n capabilities: [...column.capabilities].sort(),\n sensitivity: column.sensitivity ?? null,\n sourceColumn: column.sourceColumn ?? null,\n bucket: column.bucket ?? null,\n aggregate: column.aggregate ?? null,\n distinct: column.distinct ?? null,\n })),\n schema: descriptor.schema,\n };\n return (\n 'rv1_' +\n createHash('sha256').update(stable(definition), 'utf8').digest('base64url')\n );\n}\n\nfunction columnMap(\n descriptor: ReportAdapterDescriptor,\n): Map<string, ReportAdapterDescriptor['columns'][number]> {\n return new Map(descriptor.columns.map((column) => [column.id, column]));\n}\n\nfunction requireColumnCapability(\n descriptor: ReportAdapterDescriptor,\n id: unknown,\n capability: ReportColumnCapability,\n label: string,\n): string {\n const columnId = requiredString(id, label);\n const column = columnMap(descriptor).get(columnId);\n if (!column?.capabilities.includes(capability)) {\n return fail(`${label} is not available under the current report policy`);\n }\n return columnId;\n}\n\nfunction normalizeColumns(\n descriptor: ReportAdapterDescriptor,\n value: unknown,\n): ReportSavedViewColumn[] {\n if (value === undefined) {\n return descriptor.columns\n .filter((column) => column.capabilities.includes('project'))\n .map((column) => ({ id: column.id }));\n }\n if (!Array.isArray(value))\n return fail('Saved report view columns must be an array');\n if (value.length > descriptor.columns.length) {\n return fail(\n 'Saved report view columns cannot repeat or exceed exposed columns',\n );\n }\n const ids = new Set<string>();\n return value.map((entry, index) => {\n const input = plainObject(\n entry,\n `Saved report view columns[${String(index)}]`,\n );\n const id = requireColumnCapability(\n descriptor,\n input.id,\n 'project',\n `Saved report view columns[${String(index)}].id`,\n );\n if (ids.has(id)) return fail('Saved report view columns cannot repeat ids');\n ids.add(id);\n const width =\n input.width === undefined\n ? undefined\n : boundedInteger(\n input.width,\n `Saved report view columns[${String(index)}].width`,\n 40,\n 2_000,\n );\n const pinned =\n input.pinned === undefined\n ? undefined\n : requiredString(\n input.pinned,\n `Saved report view columns[${String(index)}].pinned`,\n 16,\n );\n if (\n pinned !== undefined &&\n !PINNED_COLUMN_SIDES.has(pinned as ReportSavedViewPinnedSide)\n ) {\n return fail(\n `Saved report view columns[${String(index)}].pinned is invalid`,\n );\n }\n return {\n id,\n ...(width === undefined ? {} : { width }),\n ...(pinned === undefined\n ? {}\n : { pinned: pinned as ReportSavedViewPinnedSide }),\n };\n });\n}\n\nfunction normalizeGrouping(\n descriptor: ReportAdapterDescriptor,\n value: unknown,\n): ReportSavedViewGrouping | undefined {\n if (value === undefined) return undefined;\n const input = plainObject(value, 'Saved report view grouping');\n if (!Array.isArray(input.fields)) {\n return fail('Saved report view grouping.fields must be an array');\n }\n const fields = input.fields.map((field, index) =>\n requireColumnCapability(\n descriptor,\n field,\n 'group',\n `Saved report view grouping.fields[${String(index)}]`,\n ),\n );\n if (new Set(fields).size !== fields.length) {\n return fail('Saved report view grouping.fields cannot repeat ids');\n }\n const expanded = optionalBoolean(\n input.expanded,\n 'Saved report view grouping.expanded',\n );\n return {\n fields,\n ...(expanded === undefined ? {} : { expanded }),\n };\n}\n\nfunction normalizeDisplay(value: unknown): ReportSavedViewDisplay | undefined {\n if (value === undefined) return undefined;\n const input = plainObject(value, 'Saved report view display');\n const density = requiredString(\n input.density,\n 'Saved report view display.density',\n 16,\n );\n if (!DISPLAY_DENSITIES.has(density as ReportSavedViewDisplay['density'])) {\n return fail('Saved report view display.density is invalid');\n }\n const showTotals = optionalBoolean(\n input.showTotals,\n 'Saved report view display.showTotals',\n );\n return {\n density: density as ReportSavedViewDisplay['density'],\n ...(showTotals === undefined ? {} : { showTotals }),\n };\n}\n\n/**\n * Version 0 is the original unversioned persisted layout shape. It contains\n * the same allowlisted fields as v1, so the migration only records the schema\n * version; current descriptor normalization still revalidates every field.\n */\nexport function migrateReportSavedView(value: unknown): SavedViewInput {\n const input = plainObject(\n value,\n 'Saved report view',\n ) as unknown as SavedViewInput;\n if (input.version === undefined || input.version === 0) {\n return { ...input, version: 1 };\n }\n if (input.version === 1) return input;\n return fail('Saved report view version is unsupported');\n}\n\n/**\n * Normalize a view both when it is saved and when it is restored. Re-running\n * this against the live descriptor is what prevents a former field/action\n * grant from surviving a policy or definition change.\n */\nexport function normalizeReportSavedView(\n descriptor: ReportAdapterDescriptor,\n value: unknown,\n): ReportSavedView {\n const input = migrateReportSavedView(value);\n const fingerprint = reportDefinitionFingerprint(descriptor);\n if (\n input.resourceId !== undefined &&\n input.resourceId !== descriptor.resourceId\n ) {\n return fail('Saved report view belongs to a different report resource');\n }\n if (\n input.reportClassName !== undefined &&\n input.reportClassName !== descriptor.reportClassName\n ) {\n return fail('Saved report view belongs to a different report class');\n }\n if (\n input.definitionFingerprint !== undefined &&\n input.definitionFingerprint !== fingerprint\n ) {\n return fail('Saved report view definition has changed');\n }\n const query = normalizeDataQueryRequest(input.query, descriptor.schema);\n if (query.mode !== 'rows') {\n return fail('Saved report views must use a rows query');\n }\n splitReportFilterScopes(descriptor, query.filter);\n const columns = normalizeColumns(descriptor, input.columns);\n const grouping = normalizeGrouping(descriptor, input.grouping);\n const display = normalizeDisplay(input.display);\n return {\n version: 1,\n id: requiredString(input.id, 'Saved report view id'),\n title: requiredString(input.title, 'Saved report view title', 240),\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n definitionFingerprint: fingerprint,\n query,\n columns,\n ...(grouping === undefined ? {} : { grouping }),\n ...(display === undefined ? {} : { display }),\n };\n}\n\n/** Restore through current policy rather than trusting a stored JSON record. */\nexport function restoreReportSavedView(\n descriptor: ReportAdapterDescriptor,\n savedView: ReportSavedView,\n): ReportSavedView {\n return normalizeReportSavedView(descriptor, savedView);\n}\n\n/**\n * Freeze a previously executed materialized read for export. The caller must\n * supply the exact request and a result that exposes lifecycle freshness; an\n * export never invents an as-of value or accepts a caller-supplied tenant.\n */\nexport function createReportExportSnapshot(\n descriptor: ReportAdapterDescriptor,\n input: unknown,\n result: Pick<\n DataQueryResult,\n 'queryFingerprint' | 'identityField' | 'total' | 'freshness' | 'truncated'\n > &\n Pick<ReportDataQueryResult, 'reportLifecycle'>,\n binding: unknown,\n): ReportExportSnapshot {\n const request = normalizeDataQueryRequest(input, descriptor.schema);\n if (request.mode !== 'rows') {\n return fail('Report export snapshots require a rows query');\n }\n const queryFingerprint = createDataQueryFingerprint(\n request,\n descriptor.schema,\n );\n if (result.queryFingerprint !== queryFingerprint) {\n return fail(\n 'Report export result does not match the requested query fingerprint',\n );\n }\n if (result.identityField !== descriptor.identityField) {\n return fail('Report export result has an unexpected row identity field');\n }\n if (result.total.kind !== 'exact') {\n return fail('Report export snapshots require an exact row count');\n }\n if (!Number.isSafeInteger(result.total.value) || result.total.value < 0) {\n return fail(\n 'Report export snapshots require a safe non-negative row count',\n );\n }\n if (result.truncated) {\n return fail('Report export snapshots cannot use a truncated query result');\n }\n if (result.freshness.state === 'unknown') {\n return fail('Report export snapshots require lifecycle freshness');\n }\n const lifecycleAsOf = result.reportLifecycle?.snapshot.asOf;\n const freshnessAsOf = result.freshness.asOf;\n const normalizedLifecycleAsOf = lifecycleAsOf\n ? normalizeIso(lifecycleAsOf, 'Report export lifecycle snapshot asOf')\n : undefined;\n const normalizedFreshnessAsOf = freshnessAsOf\n ? normalizeIso(freshnessAsOf, 'Report export freshness asOf')\n : undefined;\n if (\n normalizedLifecycleAsOf !== undefined &&\n normalizedFreshnessAsOf !== undefined &&\n normalizedLifecycleAsOf !== normalizedFreshnessAsOf\n ) {\n return fail(\n 'Report export lifecycle freshness does not match its snapshot',\n );\n }\n const normalizedAsOf = normalizedLifecycleAsOf ?? normalizedFreshnessAsOf;\n if (!normalizedAsOf) {\n return fail(\n 'Report export snapshots require an as-of materialization instant',\n );\n }\n const refreshedAt = result.reportLifecycle?.snapshot.refreshedAt;\n return {\n version: 1,\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n definitionFingerprint: reportDefinitionFingerprint(descriptor),\n binding: normalizeSnapshotBinding(binding),\n request,\n queryFingerprint,\n projection: [...(request.projection ?? [descriptor.identityField])],\n sort: [\n ...(request.sort ??\n descriptor.schema.defaultSort ?? [\n { field: descriptor.identityField, direction: 'asc' },\n ]),\n ],\n freshness: {\n state: result.freshness.state,\n asOf: normalizedAsOf,\n },\n snapshot: {\n asOf: normalizedAsOf,\n ...(refreshedAt\n ? {\n refreshedAt: normalizeIso(\n refreshedAt,\n 'Report export snapshot refreshedAt',\n ),\n }\n : {}),\n stale: result.freshness.state === 'stale',\n },\n total: { kind: 'exact', value: result.total.value },\n inherits: [...INHERITED_REPORT_SCOPE],\n };\n}\n\n/** Reject definitions/policies that changed after a snapshot was frozen. */\nexport function verifyReportExportSnapshot(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n): ReportExportSnapshot {\n const input = plainObject(snapshot, 'Report export snapshot');\n exactKeys(\n input,\n [\n 'version',\n 'resourceId',\n 'reportClassName',\n 'definitionFingerprint',\n 'binding',\n 'request',\n 'queryFingerprint',\n 'projection',\n 'sort',\n 'freshness',\n 'snapshot',\n 'total',\n 'inherits',\n ],\n 'Report export snapshot',\n );\n if (snapshot.version !== 1)\n return fail('Report export snapshot version is unsupported');\n if (\n snapshot.resourceId !== descriptor.resourceId ||\n snapshot.reportClassName !== descriptor.reportClassName\n ) {\n return fail('Report export snapshot belongs to a different report');\n }\n if (\n snapshot.definitionFingerprint !== reportDefinitionFingerprint(descriptor)\n ) {\n return fail('Report export definition has changed');\n }\n const binding = normalizeSnapshotBinding(snapshot.binding);\n const normalized = normalizeDataQueryRequest(\n snapshot.request,\n descriptor.schema,\n );\n if (normalized.mode !== 'rows') {\n return fail('Report export snapshot query must remain a rows query');\n }\n if (\n createDataQueryFingerprint(normalized, descriptor.schema) !==\n snapshot.queryFingerprint\n ) {\n return fail('Report export snapshot query fingerprint is invalid');\n }\n const expectedProjection = normalized.projection ?? [\n descriptor.identityField,\n ];\n const expectedSort = normalized.sort ??\n descriptor.schema.defaultSort ?? [\n { field: descriptor.identityField, direction: 'asc' },\n ];\n if (\n !Array.isArray(snapshot.projection) ||\n snapshot.projection.some((field) => typeof field !== 'string')\n ) {\n return fail('Report export snapshot projection is invalid');\n }\n if (\n snapshot.projection.length !== expectedProjection.length ||\n snapshot.projection.some(\n (field, index) => field !== expectedProjection[index],\n )\n ) {\n return fail('Report export snapshot projection or sort has changed');\n }\n if (!Array.isArray(snapshot.sort)) {\n return fail('Report export snapshot sort is invalid');\n }\n const sort = snapshot.sort.map((value) => {\n const sortInput = plainObject(value, 'Report export snapshot sort');\n exactKeys(sortInput, ['field', 'direction'], 'Report export snapshot sort');\n return {\n field: requiredString(\n sortInput.field,\n 'Report export snapshot sort field',\n ),\n direction: requiredString(\n sortInput.direction,\n 'Report export snapshot sort direction',\n ),\n };\n });\n if (stable(sort) !== stable(expectedSort)) {\n return fail('Report export snapshot projection or sort has changed');\n }\n const freshness = plainObject(\n snapshot.freshness,\n 'Report export snapshot freshness',\n );\n exactKeys(freshness, ['state', 'asOf'], 'Report export snapshot freshness');\n const materialization = plainObject(\n snapshot.snapshot,\n 'Report export snapshot materialization',\n );\n exactKeys(\n materialization,\n ['asOf', 'refreshedAt', 'stale'],\n 'Report export snapshot materialization',\n );\n const total = plainObject(snapshot.total, 'Report export snapshot total');\n exactKeys(total, ['kind', 'value'], 'Report export snapshot total');\n const totalValue = total.value;\n const asOf = normalizeIso(\n materialization.asOf,\n 'Report export snapshot asOf',\n );\n if (freshness.state !== 'fresh' && freshness.state !== 'stale') {\n return fail('Report export snapshot freshness state is invalid');\n }\n const freshnessAsOf = normalizeIso(\n freshness.asOf,\n 'Report export snapshot freshness asOf',\n );\n if (freshnessAsOf !== asOf) {\n return fail(\n 'Report export snapshot freshness does not match its as-of instant',\n );\n }\n const refreshedAt = materialization.refreshedAt\n ? normalizeIso(\n materialization.refreshedAt,\n 'Report export snapshot refreshedAt',\n )\n : undefined;\n if (materialization.stale !== (freshness.state === 'stale')) {\n return fail('Report export snapshot stale state is invalid');\n }\n if (\n total.kind !== 'exact' ||\n typeof totalValue !== 'number' ||\n !Number.isSafeInteger(totalValue) ||\n totalValue < 0\n ) {\n return fail('Report export snapshot row count is invalid');\n }\n if (\n !Array.isArray(snapshot.inherits) ||\n snapshot.inherits.some((value) => typeof value !== 'string') ||\n snapshot.inherits.length !== INHERITED_REPORT_SCOPE.length ||\n snapshot.inherits.some(\n (value, index) => value !== INHERITED_REPORT_SCOPE[index],\n )\n ) {\n return fail('Report export snapshot inheritance contract is invalid');\n }\n return {\n version: 1,\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n definitionFingerprint: reportDefinitionFingerprint(descriptor),\n binding,\n request: normalized,\n queryFingerprint: createDataQueryFingerprint(normalized, descriptor.schema),\n projection: [...expectedProjection],\n sort: expectedSort.map(({ field, direction }) => ({ field, direction })),\n freshness: { state: freshness.state, asOf: freshnessAsOf },\n snapshot: {\n asOf,\n stale: materialization.stale,\n ...(refreshedAt === undefined ? {} : { refreshedAt }),\n },\n total: { kind: 'exact', value: totalValue },\n inherits: [...INHERITED_REPORT_SCOPE],\n };\n}\n\nfunction normalizeExportLimits(value: unknown): ReportExportLimits {\n if (value === undefined) return { ...DEFAULT_EXPORT_LIMITS };\n const input = plainObject(value, 'Report export limits');\n const maxRows = boundedInteger(\n input.maxRows ?? DEFAULT_EXPORT_LIMITS.maxRows,\n 'Report export limits.maxRows',\n 1,\n MAX_EXPORT_LIMITS.maxRows,\n );\n const maxBytes = boundedInteger(\n input.maxBytes ?? DEFAULT_EXPORT_LIMITS.maxBytes,\n 'Report export limits.maxBytes',\n 1,\n MAX_EXPORT_LIMITS.maxBytes,\n );\n const deadlineMs = boundedInteger(\n input.deadlineMs ?? DEFAULT_EXPORT_LIMITS.deadlineMs,\n 'Report export limits.deadlineMs',\n 1,\n MAX_EXPORT_LIMITS.deadlineMs,\n );\n const foregroundRowLimit = boundedInteger(\n input.foregroundRowLimit ??\n Math.min(DEFAULT_EXPORT_LIMITS.foregroundRowLimit, maxRows),\n 'Report export limits.foregroundRowLimit',\n 1,\n Math.min(maxRows, MAX_EXPORT_LIMITS.foregroundRowLimit),\n );\n return { maxRows, maxBytes, deadlineMs, foregroundRowLimit };\n}\n\nfunction hasSensitiveProjection(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n): boolean {\n const columns = columnMap(descriptor);\n return snapshot.projection.some((id) => {\n const sensitivity = columns.get(id)?.sensitivity;\n return (\n sensitivity === 'personal' ||\n sensitivity === 'sensitive' ||\n sensitivity === 'secret'\n );\n });\n}\n\nfunction createReadPlan(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n limits: ReportExportLimits,\n): ReportExportReadPlan {\n return {\n snapshotId: snapshot.binding.id,\n queryFingerprint: snapshot.queryFingerprint,\n asOf: snapshot.snapshot.asOf,\n page: {\n kind: 'offset',\n offset: 0,\n limit: Math.min(\n limits.maxRows,\n descriptor.schema.maxPageLimit ??\n DEFAULT_EXPORT_LIMITS.foregroundRowLimit,\n ),\n },\n };\n}\n\n/**\n * Build one common request for both agent and human export clients. The\n * resulting request carries no actor, tenant, storage location, or token.\n */\nexport function createReportExportRequest(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n value: unknown,\n): ReportExportRequest {\n const input = plainObject(\n value,\n 'Report export request',\n ) as unknown as ExportRequestInput;\n const verified = verifyReportExportSnapshot(descriptor, snapshot);\n const format = requiredString(input.format, 'Report export format', 16);\n if (!EXPORT_FORMATS.has(format as ReportExportFormat)) {\n return fail('Report export format is unsupported');\n }\n const limits = normalizeExportLimits(input.limits);\n const rowCount = Math.min(verified.total.value, limits.maxRows);\n const confirmationRequired = hasSensitiveProjection(descriptor, verified);\n return {\n version: 1,\n format: format as ReportExportFormat,\n execution:\n verified.total.value > limits.foregroundRowLimit\n ? 'background'\n : 'stream',\n snapshot: verified,\n limits,\n read: createReadPlan(descriptor, verified, limits),\n rowCount,\n truncated: verified.total.value > limits.maxRows,\n action: {\n id: 'export',\n requiredPermission: 'reports.export',\n auditRequired: true,\n confirmationRequired,\n },\n };\n}\n\n/**\n * Recreate the deterministic request from its current descriptor and frozen\n * snapshot. Preview, apply, queue, and serving hosts call this instead of\n * trusting browser- or agent-supplied action metadata.\n */\nexport function validateReportExportRequest(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n): ReportExportRequest {\n const expected = createReportExportRequest(descriptor, request.snapshot, {\n format: request.format,\n limits: request.limits,\n });\n if (stable(request) !== stable(expected)) {\n return fail('Report export request does not match current policy');\n }\n return expected;\n}\n\n/**\n * Build one bounded page of the immutable export read. The host applies the\n * opaque snapshot binding separately; this function preserves the frozen\n * projection, predicate, and deterministic sort while replacing only visible\n * pagination. A zero-row export therefore has no pages to execute.\n */\nexport function createReportExportPageRequest(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n offset: number,\n): DataQueryRequest {\n const verified = validateReportExportRequest(descriptor, request);\n if (\n !Number.isSafeInteger(offset) ||\n offset < 0 ||\n offset >= verified.rowCount\n ) {\n return fail('Report export page offset is outside the bounded export');\n }\n const limit = Math.min(verified.read.page.limit, verified.rowCount - offset);\n return normalizeDataQueryRequest(\n {\n ...verified.snapshot.request,\n page: { kind: 'offset', offset, limit },\n },\n descriptor.schema,\n );\n}\n\nfunction actionContext(\n phase: ReportExportActionContext['phase'],\n request: ReportExportRequest,\n): ReportExportActionContext {\n return {\n phase,\n reportClassName: request.snapshot.reportClassName,\n resourceId: request.snapshot.resourceId,\n requiredPermission: request.action.requiredPermission,\n confirmationRequired: request.action.confirmationRequired,\n execution: request.execution,\n queryFingerprint: request.snapshot.queryFingerprint,\n definitionFingerprint: request.snapshot.definitionFingerprint,\n snapshotId: request.read.snapshotId,\n asOf: request.read.asOf,\n pageSize: request.read.page.limit,\n };\n}\n\nfunction snapshotContext(\n request: ReportExportRequest,\n): ReportExportSnapshotContext {\n return {\n bindingId: request.snapshot.binding.id,\n resourceId: request.snapshot.resourceId,\n reportClassName: request.snapshot.reportClassName,\n definitionFingerprint: request.snapshot.definitionFingerprint,\n queryFingerprint: request.snapshot.queryFingerprint,\n asOf: request.snapshot.snapshot.asOf,\n };\n}\n\n/**\n * Revalidate the request and prove the opaque snapshot binding through the\n * application host. Preview, apply, and every background worker use this same\n * operation before reading or serving export data.\n */\nexport async function validateReportExportExecution(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n host: Pick<ReportExportActionHost, 'assertSnapshot'>,\n): Promise<ReportExportRequest> {\n const verified = validateReportExportRequest(descriptor, request);\n await host.assertSnapshot(snapshotContext(verified));\n return verified;\n}\n\nexport async function previewReportExport(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n host: ReportExportActionHost,\n): Promise<ReportExportPreview> {\n const initial = validateReportExportRequest(descriptor, request);\n const action = actionContext('preview', initial);\n await host.authorize(action);\n const verified = await validateReportExportExecution(\n descriptor,\n initial,\n host,\n );\n await host.audit(action);\n return { phase: 'preview', action, request: verified };\n}\n\n/**\n * Queue large exports without embedding rows in a browser/agent response.\n * A host must verify current principal, tenant, report definition, and field\n * policy again before it renders or serves the artifact.\n */\nexport async function applyReportExport(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n host: ReportExportActionHost,\n options: { confirmed?: boolean } = {},\n): Promise<AppliedReportExport> {\n const initial = validateReportExportRequest(descriptor, request);\n if (initial.action.confirmationRequired && options.confirmed !== true) {\n return fail('Sensitive report exports require explicit confirmation');\n }\n const action = actionContext('apply', initial);\n await host.authorize(action);\n const verified = await validateReportExportExecution(\n descriptor,\n initial,\n host,\n );\n await host.audit(action);\n if (verified.execution === 'stream') {\n return {\n phase: 'apply',\n execution: 'stream',\n status: 'ready',\n request: verified,\n };\n }\n if (!host.enqueue) {\n return fail('Background report exports require an application queue host');\n }\n const queued = await host.enqueue({\n version: 1,\n execution: 'background',\n request: verified,\n inherits: [...INHERITED_REPORT_SCOPE],\n });\n if (typeof queued.taskId !== 'string' || queued.taskId.trim().length === 0) {\n return fail('Background report export hosts must return a task id');\n }\n return {\n phase: 'apply',\n execution: 'background',\n status: 'queued',\n taskId: queued.taskId,\n request: verified,\n };\n}\n\n/**\n * Validate artifact metadata before a host serves it. Download locations and\n * tokens stay application-private; expired artifacts fail before that boundary.\n */\nexport function validateReportExportArtifact(\n descriptor: ReportAdapterDescriptor,\n artifact: ReportExportArtifact,\n now = new Date(),\n): ReportExportArtifact {\n const input = plainObject(artifact, 'Report export artifact');\n exactKeys(\n input,\n ['id', 'request', 'progress', 'expiresAt'],\n 'Report export artifact',\n );\n const request = validateReportExportRequest(descriptor, artifact.request);\n const id = requiredString(artifact.id, 'Report export artifact id');\n const expiresAt = normalizeIso(\n artifact.expiresAt,\n 'Report export artifact expiresAt',\n );\n if (new Date(expiresAt).getTime() <= now.getTime()) {\n return fail('Report export artifact has expired');\n }\n const progress = plainObject(\n artifact.progress,\n 'Report export artifact progress',\n );\n exactKeys(\n progress,\n ['state', 'rowCount', 'byteCount', 'truncated'],\n 'Report export artifact progress',\n );\n const state = progress.state;\n if (\n state !== 'queued' &&\n state !== 'running' &&\n state !== 'completed' &&\n state !== 'failed'\n ) {\n return fail('Report export artifact progress state is invalid');\n }\n const rowCount = boundedInteger(\n progress.rowCount,\n 'Report export artifact rowCount',\n 0,\n request.rowCount,\n );\n const byteCount = boundedInteger(\n progress.byteCount,\n 'Report export artifact byteCount',\n 0,\n request.limits.maxBytes,\n );\n const truncated = progress.truncated;\n if (typeof truncated !== 'boolean') {\n return fail('Report export artifact truncated must be a boolean');\n }\n if (state === 'completed' && rowCount !== request.rowCount) {\n return fail(\n 'Completed report export artifacts must contain the requested row count',\n );\n }\n if (state === 'completed' && truncated !== request.truncated) {\n return fail(\n 'Completed report export artifacts must match the requested truncation state',\n );\n }\n return {\n id,\n request,\n expiresAt,\n progress: { state, rowCount, byteCount, truncated },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["suffix","children","filter","field","existing","archived"],"sources":["../src/lifecycle.ts","../src/adapter.ts","../src/materialized-host.ts","../src/runtime-spec.ts","../src/runtime-compiler.ts","../src/runtime-server.ts","../src/runtime-report.ts","../src/recipes.ts","../src/report.ts","../src/views.ts"],"sourcesContent":["import { ObjectRegistry, type SmrtObject } from '@happyvertical/smrt-core';\nimport type { DurableJobPayloadSigner } from '@happyvertical/smrt-jobs';\nimport { getTenantId, withSystemContext } from '@happyvertical/smrt-tenancy';\nimport {\n type DatabaseInterface,\n tableExists,\n validateColumnName,\n} from '@happyvertical/sql';\nimport type { ReportRefreshActionDescriptor } from './adapter.js';\nimport { buildReportDefinition } from './compiler.js';\nimport type { ReportRefreshExecutionAuthority } from './scheduler.js';\nimport { enqueueReportRefresh } from './scheduler.js';\nimport {\n assertReportTablesReady,\n REPORT_LOCKS_TABLE,\n REPORT_RUNS_TABLE,\n scopeKeyForTenant,\n} from './state.js';\nimport type {\n ReportRefreshMode,\n ReportRefreshResult,\n ReportRefreshTrigger,\n} from './types.js';\n\ntype ReportCtor = new (...args: any[]) => SmrtObject;\n\nfunction registeredReport(reportCtor: ReportCtor) {\n return (\n ObjectRegistry.getClassByConstructor(reportCtor) ??\n ObjectRegistry.getClass(reportCtor.name)\n );\n}\n\nexport type ReportLifecycleState =\n | 'current'\n | 'stale'\n | 'refreshing'\n | 'lock-skipped'\n | 'failed';\n\nexport interface ReportLifecycleRun {\n id: string;\n status: 'running' | 'success' | 'failed' | 'skipped';\n mode: ReportRefreshMode;\n trigger: ReportRefreshTrigger;\n startedAt?: string;\n completedAt?: string;\n rowCount: number;\n changedGroupCount: number;\n /** A failed run is safe to retry through the separately permissioned action. */\n mayRetry: boolean;\n}\n\n/**\n * Transport-neutral report lifecycle state. It deliberately never includes a\n * lock owner, a raw failure message, or tenant fanout identifiers.\n */\nexport interface ReportLifecycleSnapshot {\n version: 1;\n state: ReportLifecycleState;\n asOf?: string;\n refreshedAt?: string;\n /** Whether existing materialized rows can remain visible while work changes state. */\n hasUsableRows: boolean;\n mode: ReportRefreshMode;\n run?: ReportLifecycleRun;\n /** A stable, redacted failure signal; raw executor errors stay server-side. */\n failure?: {\n code: 'refresh_failed';\n retryable: true;\n };\n lock: {\n held: boolean;\n expiresAt?: string;\n };\n}\n\nexport interface ReportLifecycleOptions {\n db: DatabaseInterface;\n /** Test seam; production callers use the current clock. */\n now?: Date;\n}\n\nexport interface ReportRefreshJobHandle {\n jobId: string;\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';\n attempts: number;\n maxAttempts: number;\n /** Bounded polling guidance; this API does not create a second queue. */\n pollAfterMs: number;\n}\n\nexport interface ReportRefreshActionContext {\n phase: 'preview' | 'apply';\n reportClassName: string;\n /** The action always applies to the caller's already-bound tenant scope. */\n tenantScope: 'ambient';\n mode: ReportRefreshMode;\n requiredPermission: string;\n}\n\n/** Authority and audit stay with the application action host, not reports. */\nexport interface ReportRefreshActionHost {\n authorize(\n context: ReportRefreshActionContext,\n authority?: ReportRefreshExecutionAuthority,\n ): Promise<void> | void;\n audit(\n context: ReportRefreshActionContext,\n authority?: ReportRefreshExecutionAuthority,\n ): Promise<void> | void;\n /** Capture only a non-secret identity reference for worker-time reauthorization. */\n executionAuthority?(\n context: ReportRefreshActionContext,\n ): ReportRefreshExecutionAuthority | Promise<ReportRefreshExecutionAuthority>;\n /** Server-only signer shared with report worker processes. */\n jobIntegritySigner?(\n context: ReportRefreshActionContext,\n ): DurableJobPayloadSigner | Promise<DurableJobPayloadSigner>;\n}\n\nexport interface PreviewReportRefreshOptions extends ReportLifecycleOptions {\n host: ReportRefreshActionHost;\n mode?: ReportRefreshMode;\n /**\n * Pass `descriptor.refresh.action` when the adapter declares a custom\n * refresh permission, so the displayed and enforced action stay aligned.\n */\n refreshAction?: Pick<ReportRefreshActionDescriptor, 'requiredPermission'>;\n}\n\nexport interface ReportRefreshPreview {\n phase: 'preview';\n lifecycle: ReportLifecycleSnapshot;\n action: ReportRefreshActionContext;\n execution: 'background';\n}\n\nexport interface ApplyReportRefreshOptions extends PreviewReportRefreshOptions {\n jobIntegritySigner?: DurableJobPayloadSigner;\n queue?: string;\n priority?: number;\n timeout?: number;\n maxAttempts?: number;\n tenantJobCap?: number;\n}\n\nexport interface AppliedReportRefresh {\n phase: 'apply';\n job: ReportRefreshJobHandle;\n}\n\nexport interface ReportRefreshOutcome {\n state: 'current' | 'lock-skipped' | 'partial';\n rowCount: number;\n changedGroupCount: number;\n completedScopes: number;\n lockSkippedScopes: number;\n mode: ReportRefreshMode;\n refreshedAt: string;\n runId?: string;\n}\n\nfunction canonicalClassName(reportCtor: ReportCtor): string {\n const registered = registeredReport(reportCtor);\n return registered?.qualifiedName ?? registered?.name ?? reportCtor.name;\n}\n\nfunction reportTableName(reportCtor: ReportCtor): string {\n const reportClassName = canonicalClassName(reportCtor);\n const tableName = ObjectRegistry.getTableName(reportClassName);\n if (!tableName) {\n throw new Error(`No report table registered for ${reportCtor.name}`);\n }\n return validateColumnName(tableName);\n}\n\nasync function reportColumnName(\n reportClassName: string,\n fieldName: string,\n): Promise<string> {\n const fields = await ObjectRegistry.getAllFields(reportClassName);\n const direct = fields.get(fieldName) as\n | { columnName?: string; _meta?: { columnName?: string } }\n | undefined;\n return validateColumnName(\n direct?.columnName ??\n direct?._meta?.columnName ??\n fieldName.replace(/([A-Z])/g, '_$1').toLowerCase(),\n );\n}\n\nfunction toIso(value: unknown): string | undefined {\n if (!value) return undefined;\n const date = value instanceof Date ? value : new Date(String(value));\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString();\n}\n\nfunction latestIso(\n first: string | undefined,\n second: string | undefined,\n): string | undefined {\n if (!first) return second;\n if (!second) return first;\n return new Date(first).getTime() >= new Date(second).getTime()\n ? first\n : second;\n}\n\nfunction lifecycleTenantId(reportCtor: ReportCtor): string | null {\n return registeredReport(reportCtor)?.tenantScopedConfig\n ? (getTenantId() ?? null)\n : null;\n}\n\nfunction numberValue(value: unknown): number {\n const numeric = Number(value ?? 0);\n return Number.isFinite(numeric) ? numeric : 0;\n}\n\nfunction rowWhere(\n reportClassName: string,\n scopeKey: string,\n tenantId: string | null,\n): { sql: string; values: unknown[] } {\n if (tenantId) {\n return {\n sql: 'report_class = ? AND scope_key = ? AND tenant_id = ?',\n values: [reportClassName, scopeKey, tenantId],\n };\n }\n return {\n sql: 'report_class = ? AND scope_key = ? AND tenant_id IS NULL',\n values: [reportClassName, scopeKey],\n };\n}\n\nfunction runFromRow(\n row: Record<string, unknown> | undefined,\n): ReportLifecycleRun | undefined {\n if (!row || typeof row.id !== 'string') return undefined;\n const status = row.status;\n if (\n status !== 'running' &&\n status !== 'success' &&\n status !== 'failed' &&\n status !== 'skipped'\n ) {\n return undefined;\n }\n const mode: ReportRefreshMode =\n row.mode === 'incremental' ? 'incremental' : 'rebuild';\n const trigger: ReportRefreshTrigger =\n row.trigger === 'schedule' ||\n row.trigger === 'change' ||\n row.trigger === 'ttl' ||\n row.trigger === 'job'\n ? row.trigger\n : 'manual';\n return {\n id: row.id,\n status,\n mode,\n trigger,\n ...(toIso(row.started_at) ? { startedAt: toIso(row.started_at) } : {}),\n ...(toIso(row.completed_at)\n ? { completedAt: toIso(row.completed_at) }\n : {}),\n rowCount: numberValue(row.row_count),\n changedGroupCount: numberValue(row.changed_group_count),\n mayRetry: status === 'failed',\n };\n}\n\nfunction jobHandle(job: {\n id?: unknown;\n status: ReportRefreshJobHandle['status'];\n attempts: number;\n maxAttempts: number;\n}): ReportRefreshJobHandle {\n if (typeof job.id !== 'string' || job.id.length === 0) {\n throw new Error('Queued report refresh is missing its job id');\n }\n return {\n jobId: job.id,\n status: job.status,\n attempts: job.attempts,\n maxAttempts: job.maxAttempts,\n pollAfterMs: 1_000,\n };\n}\n\n/**\n * Read only the ambient tenant's report state. The caller cannot supply a\n * tenant selector, which prevents lifecycle lookup from becoming a tenant\n * enumeration surface.\n */\nexport async function getReportLifecycle(\n reportCtor: ReportCtor,\n options: ReportLifecycleOptions,\n): Promise<ReportLifecycleSnapshot> {\n await assertReportTablesReady(options.db, [\n REPORT_RUNS_TABLE,\n REPORT_LOCKS_TABLE,\n ]);\n\n const definition = await buildReportDefinition(reportCtor);\n const reportClassName = canonicalClassName(reportCtor);\n const tenantId = lifecycleTenantId(reportCtor);\n const scopeKey = scopeKeyForTenant(tenantId);\n const where = rowWhere(reportClassName, scopeKey, tenantId);\n const now = options.now ?? new Date();\n\n const [runResult, lockResult] = await Promise.all([\n options.db.query(\n `SELECT id, mode, trigger, status, started_at, completed_at, row_count, changed_group_count\n FROM ${REPORT_RUNS_TABLE}\n WHERE ${where.sql}\n ORDER BY started_at DESC, created_at DESC, id DESC\n LIMIT 1`,\n ...where.values,\n ),\n options.db.query(\n `SELECT expires_at\n FROM ${REPORT_LOCKS_TABLE}\n WHERE ${where.sql} AND expires_at > ?\n LIMIT 1`,\n ...where.values,\n now.toISOString(),\n ),\n ]);\n\n const tableName = reportTableName(reportCtor);\n if (!(await tableExists(options.db, tableName))) {\n throw new Error(\n `Report table '${tableName}' does not exist for ${reportClassName}`,\n );\n }\n const refreshedAtColumn = await reportColumnName(\n reportClassName,\n 'refreshedAt',\n );\n const registered = registeredReport(reportCtor);\n const configuredTenantField = registered?.tenantScopedConfig?.field;\n const tenantColumn = configuredTenantField\n ? await reportColumnName(reportClassName, configuredTenantField)\n : undefined;\n const materialized = tenantColumn\n ? await options.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${tableName} WHERE ${tenantColumn} ${tenantId ? '= ?' : 'IS NULL'}`,\n ...(tenantId ? [tenantId] : []),\n )\n : await options.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${tableName}`,\n );\n\n const run = runFromRow(\n runResult.rows[0] as Record<string, unknown> | undefined,\n );\n const refreshedAt = toIso(materialized.rows[0]?.refreshed_at);\n const completedAt = run?.status === 'success' ? run.completedAt : undefined;\n const asOf = latestIso(refreshedAt, completedAt);\n const ttlMs = definition.refresh?.ttl;\n const isStale =\n !asOf ||\n (ttlMs !== undefined && now.getTime() - new Date(asOf).getTime() > ttlMs);\n const lockExpiresAt = toIso(lockResult.rows[0]?.expires_at);\n const lockHeld = Boolean(lockExpiresAt);\n const state: ReportLifecycleState =\n run?.status === 'skipped'\n ? 'lock-skipped'\n : lockHeld\n ? 'refreshing'\n : run?.status === 'failed'\n ? 'failed'\n : run?.status === 'running'\n ? 'stale'\n : isStale\n ? 'stale'\n : 'current';\n\n return {\n version: 1,\n state,\n ...(asOf ? { asOf } : {}),\n ...(refreshedAt ? { refreshedAt } : {}),\n hasUsableRows: Boolean(refreshedAt),\n mode: run?.mode ?? definition.refresh?.mode ?? 'rebuild',\n ...(run ? { run } : {}),\n ...(run?.status === 'failed'\n ? { failure: { code: 'refresh_failed' as const, retryable: true } }\n : {}),\n lock: {\n held: lockHeld,\n ...(lockExpiresAt ? { expiresAt: lockExpiresAt } : {}),\n },\n };\n}\n\nfunction actionContext(\n reportCtor: ReportCtor,\n phase: ReportRefreshActionContext['phase'],\n mode: ReportRefreshMode,\n refreshAction:\n | Pick<ReportRefreshActionDescriptor, 'requiredPermission'>\n | undefined,\n): ReportRefreshActionContext {\n return {\n phase,\n reportClassName: canonicalClassName(reportCtor),\n tenantScope: 'ambient',\n mode,\n requiredPermission:\n refreshAction?.requiredPermission &&\n refreshAction.requiredPermission.trim().length > 0\n ? refreshAction.requiredPermission\n : 'reports.refresh',\n };\n}\n\nasync function actionMode(\n reportCtor: ReportCtor,\n requested: ReportRefreshMode | undefined,\n): Promise<ReportRefreshMode> {\n if (requested) return requested;\n const definition = await buildReportDefinition(reportCtor);\n return definition.refresh?.mode ?? 'rebuild';\n}\n\n/** Preview only declares a separately authorized and audited refresh request. */\nexport async function previewReportRefresh(\n reportCtor: ReportCtor,\n options: PreviewReportRefreshOptions,\n): Promise<ReportRefreshPreview> {\n const mode = await actionMode(reportCtor, options.mode);\n const action = actionContext(\n reportCtor,\n 'preview',\n mode,\n options.refreshAction,\n );\n await options.host.authorize(action);\n await options.host.audit(action);\n return {\n phase: 'preview',\n lifecycle: await getReportLifecycle(reportCtor, options),\n action,\n execution: 'background',\n };\n}\n\n/** Queue a manual refresh only after the action host authorizes and audits it. */\nexport async function applyReportRefresh(\n reportCtor: ReportCtor,\n options: ApplyReportRefreshOptions,\n): Promise<AppliedReportRefresh> {\n const mode = await actionMode(reportCtor, options.mode);\n const action = actionContext(\n reportCtor,\n 'apply',\n mode,\n options.refreshAction,\n );\n const executionAuthority = await options.host.executionAuthority?.(action);\n if (!executionAuthority) {\n throw new Error('Manual report refresh requires execution-time authority');\n }\n await options.host.authorize(action, executionAuthority);\n await options.host.audit(action, executionAuthority);\n const integritySigner =\n options.jobIntegritySigner ??\n (await options.host.jobIntegritySigner?.(action));\n if (!integritySigner) {\n throw new Error(\n 'Report refresh queue requires a durable job integrity signer',\n );\n }\n const tenantId = lifecycleTenantId(reportCtor);\n const enqueue = () =>\n enqueueReportRefresh({\n db: options.db,\n reportClass: canonicalClassName(reportCtor),\n mode,\n trigger: 'manual',\n tenantId,\n executionAuthority,\n queue: options.queue,\n priority: options.priority,\n timeout: options.timeout,\n maxAttempts: options.maxAttempts,\n tenantJobCap: options.tenantJobCap,\n integritySigner,\n });\n const job =\n tenantId === null && getTenantId()\n ? await withSystemContext(enqueue)\n : await enqueue();\n return { phase: 'apply', job: jobHandle(job) };\n}\n\n/** Normalize executor results without exposing the tenant identifiers in a fanout. */\nexport function reportRefreshOutcome(\n result: ReportRefreshResult,\n): ReportRefreshOutcome {\n const scopes = result.tenantResults ?? [result];\n const lockSkippedScopes = scopes.filter((scope) => scope.skipped).length;\n const completedScopes = scopes.length - lockSkippedScopes;\n return {\n state:\n scopes.length > 1 && lockSkippedScopes > 0\n ? 'partial'\n : lockSkippedScopes > 0\n ? 'lock-skipped'\n : 'current',\n rowCount: result.rowCount,\n changedGroupCount: result.changedGroupCount ?? 0,\n completedScopes,\n lockSkippedScopes,\n mode: result.mode,\n refreshedAt: result.refreshedAt.toISOString(),\n ...(result.runId ? { runId: result.runId } : {}),\n };\n}\n","import {\n createDataQueryFingerprint,\n DataQueryValidationError,\n normalizeDataQueryRequest,\n normalizeDataQueryResult,\n ObjectRegistry,\n type SmrtObject,\n} from '@happyvertical/smrt-core';\nimport { toSnakeCase } from '@happyvertical/smrt-core/utils';\nimport type {\n DataQueryCondition,\n DataQueryFieldDescriptor,\n DataQueryFilter,\n DataQueryFilterOperator,\n DataQueryFreshness,\n DataQueryRequest,\n DataQueryResult,\n DataQueryScalar,\n DataQuerySchema,\n} from '@happyvertical/smrt-types';\nimport { buildReportDefinition } from './compiler.js';\nimport {\n getReportLifecycle,\n type ReportLifecycleOptions,\n type ReportLifecycleSnapshot,\n} from './lifecycle.js';\nimport type {\n ReportAggregateFn,\n ReportDefinition,\n ReportFieldDefinition,\n ReportRefreshConfig,\n ReportTimeBucketUnit,\n} from './types.js';\n\n/** Presentation and policy metadata understood by the report adapter. */\nexport type ReportColumnSensitivity =\n | 'public'\n | 'personal'\n | 'sensitive'\n | 'secret';\n\nexport type ReportColumnCapability =\n | 'read'\n | 'project'\n | 'filter'\n | 'sort'\n | 'facet'\n | 'group'\n | 'aggregate';\n\nexport type ReportColumnKind = 'identity' | 'group' | 'bucket' | 'aggregate';\n\n/**\n * Source-query clause a field belongs to. The materialized read executor\n * applies both kinds through its tenant-scoped collection, but consumers use\n * this declaration to keep dimensions/periods (WHERE) distinct from measures\n * (HAVING) when constructing drilldowns, saved views, or a live query.\n */\nexport type ReportFilterScope = 'where' | 'having';\n\nexport interface ReportColumnDescriptor extends DataQueryFieldDescriptor {\n /** Stable output column id (never a property path). */\n id: string;\n fieldName: string;\n label: string;\n kind: ReportColumnKind;\n filterScope: ReportFilterScope;\n /** Capabilities available from this adapter revision. */\n capabilities: ReportColumnCapability[];\n format?: string;\n sensitivity?: ReportColumnSensitivity;\n sourceColumn?: string;\n bucket?: ReportTimeBucketUnit;\n aggregate?: ReportAggregateFn;\n distinct?: boolean;\n}\n\nexport interface ReportRefreshDescriptor {\n mode: 'rebuild' | 'incremental';\n /**\n * Whether the report configuration lets a registered SmrtReportCollection\n * synchronously refresh a stale read. Generic collection reads stay\n * read-only and report unknown freshness until the lifecycle adapter runs.\n */\n mayRefreshOnRead: boolean;\n ttlMs?: number;\n triggers: Array<'manual' | 'schedule' | 'change' | 'ttl' | 'job'>;\n /** Declared only; the lifecycle adapter owns authorization, audit, and run state. */\n action: ReportRefreshActionDescriptor;\n}\n\n/** A report-wide lifecycle action, never a mutation performed by this adapter. */\nexport interface ReportRefreshActionDescriptor {\n id: 'refresh';\n label: 'Refresh report';\n scope: 'surface';\n phases: Array<'preview' | 'apply'>;\n requiresPermission: true;\n requiredPermission: string;\n auditRequired: true;\n}\n\n/**\n * The report-owned, transport-neutral descriptor. Consumers can map `schema`\n * to the canonical data-query runtime and `columns` to their presentation\n * contract without importing smrt-ui or a report domain class.\n */\nexport interface ReportAdapterDescriptor {\n version: 1;\n resourceId: string;\n reportClassName: string;\n sourceClassName: string;\n tenantScoped: boolean;\n tenantField?: string;\n identityField: 'id';\n columns: ReportColumnDescriptor[];\n schema: DataQuerySchema;\n queryExecution: ReportQueryExecutionDescriptor;\n dataTable: ReportDataTableDescriptor;\n drilldown: ReportDrilldownDescriptor;\n refresh: ReportRefreshDescriptor;\n}\n\n/**\n * Delivery choices for the same bounded report query. They never add\n * authority: a host owns visible state and background-job execution.\n */\nexport type ReportQueryExecutionMode = 'visible' | 'background' | 'silent';\n\nexport interface ReportQueryExecutionDescriptor {\n modes: ReportQueryExecutionMode[];\n /** The caller may apply the returned rows to an already-authorized surface. */\n visible: { delivery: 'result' };\n /** A host queues the authority-free task and returns no materialized rows yet. */\n background: { delivery: 'queued'; requiresHost: true };\n /** The caller receives rows but the adapter makes no visible-surface change. */\n silent: { delivery: 'result'; mutatesVisibleSurface: false };\n}\n\n/**\n * The exact bounded request a background host may persist. Tenant, principal,\n * collection, database, and display state deliberately remain with that host.\n */\nexport interface ReportBackgroundQueryTask {\n version: 1;\n execution: 'background';\n resourceId: string;\n reportClassName: string;\n request: DataQueryRequest;\n inherits: Array<\n 'principal' | 'tenant' | 'report-definition' | 'field-policy'\n >;\n}\n\n/** Queuing a background query returns a handle, never rows from another scope. */\nexport interface ReportBackgroundQueryResult {\n version: 1;\n execution: 'background';\n status: 'queued';\n taskId: string;\n queryFingerprint: string;\n}\n\n/** One row value that can safely constrain a source-record drilldown. */\nexport interface ReportDrilldownFieldDescriptor {\n /** Stable report column id; never a display label. */\n id: string;\n /** Declared source field/column chosen by report metadata, not caller input. */\n sourceColumn: string;\n kind: 'group' | 'bucket';\n /** A bucket stays declarative so the source adapter preserves report timezone semantics. */\n bucket?: ReportTimeBucketUnit;\n}\n\n/**\n * Declarative source-query handoff for a report row. No client can supply a\n * principal, tenant, report definition, or arbitrary source field here.\n */\nexport interface ReportDrilldownDescriptor {\n id: 'drilldown';\n sourceClassName: string;\n fields: ReportDrilldownFieldDescriptor[];\n inherits: Array<\n 'principal' | 'tenant' | 'report-definition' | 'field-policy'\n >;\n}\n\nexport interface ReportDrilldownConstraint {\n id: string;\n sourceColumn: string;\n kind: 'group' | 'bucket';\n value: unknown;\n bucket?: ReportTimeBucketUnit;\n}\n\n/** A server adapter uses this authority-free handoff to execute a source drilldown. */\nexport interface ReportDrilldownQuery {\n version: 1;\n resourceId: string;\n reportClassName: string;\n sourceClassName: string;\n constraints: ReportDrilldownConstraint[];\n inherits: Array<\n 'principal' | 'tenant' | 'report-definition' | 'field-policy'\n >;\n}\n\n/** Structural DataTable view hints; deliberately not a smrt-ui dependency. */\nexport interface ReportDataTableHeaderPathSegment {\n /** Stable group identity within a header level. */\n id: string;\n /** Human-readable grouped-header label. */\n label: string;\n}\n\n/** Responsive metadata that maps directly to a consumer's table contract. */\nexport interface ReportDataTableColumnResponsive {\n /** Higher values make a column more important during responsive collapse. */\n priority?: number;\n /** Keep key dimensions reachable during responsive collapse. */\n keepVisible?: boolean;\n}\n\n/**\n * A rendering instruction for a raw materialized value. Formatting is never\n * applied to a query row, so sorting, export, and agent consumers retain it.\n */\nexport type ReportDataTableValueFormat =\n | 'text'\n | 'date'\n | 'datetime'\n | 'percentage'\n | 'count'\n | 'money'\n | 'number';\n\nexport type ReportDataTableColumnRole = 'data' | 'status' | 'action';\n\nexport interface ReportDataTableColumn {\n id: string;\n label: string;\n accessor: string;\n sortable: boolean;\n searchable: false;\n filterable: boolean;\n /** Group ancestry for consumers with multi-level table headers. */\n headerPath: ReportDataTableHeaderPathSegment[];\n /** Consumer-side display instruction; materialized rows remain raw. */\n valueFormat: ReportDataTableValueFormat;\n /** The default alignment for the formatted display value. */\n align: 'left' | 'right';\n /** Generic semantic role for status/action columns introduced by later slices. */\n role: ReportDataTableColumnRole;\n responsive: ReportDataTableColumnResponsive;\n}\n\nexport type ReportDataTableStructuralRowKind =\n | 'summary'\n | 'subtotal'\n | 'aggregate'\n | 'footer';\n\n/** Input supplied by a report consumer that computes a summary or subtotal. */\nexport interface ReportDataTableStructuralRowInput {\n id: string;\n kind: ReportDataTableStructuralRowKind;\n label: string;\n /** Raw values keyed by the adapter's stable column id. */\n values?: Readonly<Record<string, unknown>>;\n /** Column that renders this row's accessible row header. */\n labelColumnId?: string;\n}\n\n/**\n * Structural rows are intentionally separate from materialized data rows.\n * Consumers pass them to their DataTable's structural-row slot/prop, never its\n * selectable data collection.\n */\nexport interface ReportDataTableStructuralRow\n extends ReportDataTableStructuralRowInput {\n selection: 'excluded';\n actions: 'excluded';\n}\n\n/** Per-column presentation overrides owned by the consuming report surface. */\nexport interface ReportDataTableColumnOverride {\n label?: string;\n headerPath?: readonly ReportDataTableHeaderPathSegment[];\n valueFormat?: ReportDataTableValueFormat;\n align?: 'left' | 'right';\n role?: ReportDataTableColumnRole;\n responsive?: ReportDataTableColumnResponsive;\n}\n\nexport interface ReportDataTablePresentationOptions {\n /** Overrides are keyed by stable adapter column id, not display labels. */\n columns?: Readonly<Record<string, ReportDataTableColumnOverride>>;\n /** Summary/subtotal rows remain structural rather than materialized data rows. */\n structuralRows?: readonly ReportDataTableStructuralRowInput[];\n}\n\nexport interface ReportDataTableDescriptor {\n rowKey: 'id';\n manualPagination: true;\n manualSorting: true;\n enableFiltering: true;\n enableSearch: false;\n columns: ReportDataTableColumn[];\n structuralRows: ReportDataTableStructuralRow[];\n}\n\nexport interface ReportAdapterOptions {\n /** Scope used only to make a stable resource id; it is not authority. */\n tenantScope?: 'current' | 'global' | 'tenant';\n /** Permission that a lifecycle action host must require before refresh. */\n refreshPermission?: string;\n /** Consumer-owned presentational preferences; they never affect query rows. */\n dataTable?: ReportDataTablePresentationOptions;\n}\n\ninterface ReportQueryCommonOptions {\n /** Injected collection seam for tests and application-owned adapters. */\n collection?: {\n list(\n options: Record<string, unknown>,\n ): Promise<Array<Record<string, unknown>>>;\n count(options?: Record<string, unknown>): Promise<number>;\n facets?(options: Record<string, unknown>): Promise<\n Array<{\n field: string;\n values: Array<{\n value: string | number | boolean | null;\n count: number;\n }>;\n }>\n >;\n };\n db?: import('@happyvertical/sql').DatabaseInterface;\n /**\n * Consumer-owned descriptor preferences. They contribute to the stable\n * resource identity and must match the catalog used to select this report.\n */\n adapter?: ReportAdapterOptions;\n /**\n * Opt in to a tenant-safe lifecycle snapshot alongside this materialized\n * read. It never makes a generic read mutate.\n */\n lifecycle?: Omit<ReportLifecycleOptions, 'db'>;\n}\n\n/** Visible is the default; silent has identical data authority but no UI intent. */\nexport interface ReportQueryOptions extends ReportQueryCommonOptions {\n execution?: 'visible' | 'silent';\n}\n\n/** Background execution is possible only through an application-owned queue host. */\nexport interface ReportBackgroundQueryOptions extends ReportQueryCommonOptions {\n execution: 'background';\n enqueueBackgroundQuery(\n task: ReportBackgroundQueryTask,\n ): Promise<{ taskId: string }>;\n}\n\n/** Lifecycle context attached only when a caller explicitly opts in. */\nexport interface ReportMaterializedReadLifecycle {\n snapshot: ReportLifecycleSnapshot;\n /** Whether this collection read appears to have completed a TTL refresh. */\n read: 'current' | 'stale' | 'refresh-triggered';\n}\n\nexport interface ReportDataQueryResult extends DataQueryResult {\n /** Delivery intent only; the adapter never mutates a visible surface. */\n execution: 'visible' | 'silent';\n reportLifecycle?: ReportMaterializedReadLifecycle;\n}\n\ntype RegistryField = {\n type?: string;\n transient?: boolean;\n description?: string;\n sensitive?: boolean;\n readPermission?: string;\n format?: unknown;\n sensitivity?: unknown;\n _meta?: Record<string, unknown>;\n};\nconst SENSITIVITIES = new Set<ReportColumnSensitivity>([\n 'public',\n 'personal',\n 'sensitive',\n 'secret',\n]);\n\nfunction registeredClass(\n ctor: new (...args: any[]) => SmrtObject,\n): ReturnType<typeof ObjectRegistry.getClassByConstructor> {\n return (\n ObjectRegistry.getClassByConstructor(ctor) ??\n ObjectRegistry.getClass(ctor.name)\n );\n}\n\nfunction fieldPolicy(field: RegistryField | undefined): {\n sensitive: boolean;\n readPermission?: string;\n} {\n const meta = field?._meta ?? {};\n const sensitivity = [field?.sensitivity, meta.sensitivity].find(\n (value): value is string => typeof value === 'string',\n );\n return {\n sensitive:\n field?.sensitive === true ||\n meta.sensitive === true ||\n sensitivity === 'sensitive' ||\n sensitivity === 'secret',\n readPermission:\n typeof field?.readPermission === 'string'\n ? field.readPermission\n : typeof meta.readPermission === 'string'\n ? meta.readPermission\n : undefined,\n };\n}\n\nfunction descriptorMetadata(field: RegistryField | undefined): {\n format?: string;\n sensitivity?: ReportColumnSensitivity;\n} {\n const metadata = field?._meta ?? {};\n const format = [field?.format, metadata.format].find(\n (value): value is string => typeof value === 'string' && value.length > 0,\n );\n const rawSensitivity = [field?.sensitivity, metadata.sensitivity].find(\n (value): value is string =>\n typeof value === 'string' &&\n SENSITIVITIES.has(value as ReportColumnSensitivity),\n );\n return {\n ...(format ? { format } : {}),\n ...(rawSensitivity\n ? { sensitivity: rawSensitivity as ReportColumnSensitivity }\n : {}),\n };\n}\n\nfunction labelFor(fieldName: string): string {\n return fieldName\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .replace(/^./, (value) => value.toUpperCase());\n}\n\nfunction queryType(type: string | undefined): DataQueryFieldDescriptor['type'] {\n switch (type) {\n case 'integer':\n case 'decimal':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'datetime';\n case 'json':\n return 'json';\n default:\n return 'string';\n }\n}\n\nfunction configuredTenantField(configured?: string): string | undefined {\n return configured ? toSnakeCase(configured) : undefined;\n}\n\nfunction isColumnBackedField(field: RegistryField | undefined): boolean {\n if (!field) return false;\n if (field.transient === true || field._meta?.transient === true) return false;\n return !['meta', 'oneToMany', 'manyToMany'].includes(field.type ?? '');\n}\n\nfunction reportColumn(\n field: ReportFieldDefinition,\n registryField: RegistryField | undefined,\n): ReportColumnDescriptor | undefined {\n const policy = fieldPolicy(registryField);\n // A descriptor is an exposure boundary. Without a principal/permission\n // context, sensitive, permission-gated, and non-column fields fail closed.\n if (\n policy.sensitive ||\n policy.readPermission ||\n !isColumnBackedField(registryField)\n ) {\n return undefined;\n }\n\n const id = field.columnName ?? toSnakeCase(field.fieldName);\n const report = field.report;\n if (!report) return undefined;\n const type = queryType(field.type ?? registryField?.type);\n const filterOperators = filterOperatorsFor(type);\n const base: ReportColumnDescriptor = {\n id,\n fieldName: field.fieldName,\n label: registryField?.description || labelFor(field.fieldName),\n kind: report.kind,\n filterScope: report.kind === 'aggregate' ? 'having' : 'where',\n type,\n projectable: true,\n sortable: true,\n facetable: report.kind !== 'aggregate',\n ...(filterOperators ? { filterOperators } : {}),\n capabilities: [\n 'project',\n 'read',\n ...(filterOperators ? (['filter'] as const) : []),\n 'sort',\n ...(report.kind !== 'aggregate' ? (['facet'] as const) : []),\n ...(report.kind === 'aggregate'\n ? (['aggregate'] as const)\n : report.kind === 'group'\n ? (['group'] as const)\n : []),\n ],\n ...(report.kind === 'group'\n ? { sourceColumn: toSnakeCase(report.sourceColumn ?? field.fieldName) }\n : {}),\n ...(report.kind === 'bucket'\n ? { bucket: report.unit, sourceColumn: toSnakeCase(report.sourceColumn) }\n : {}),\n ...(report.kind === 'aggregate'\n ? {\n aggregate: report.fn,\n ...(report.column\n ? { sourceColumn: toSnakeCase(report.column) }\n : {}),\n ...(report.distinct === undefined\n ? {}\n : { distinct: report.distinct }),\n }\n : {}),\n ...descriptorMetadata(registryField),\n };\n return base;\n}\n\nfunction identityColumn(): ReportColumnDescriptor {\n return {\n id: 'id',\n fieldName: 'id',\n label: 'ID',\n kind: 'identity',\n filterScope: 'where',\n type: 'string',\n projectable: true,\n sortable: true,\n facetable: false,\n filterOperators: filterOperatorsFor('string'),\n capabilities: ['project', 'read', 'filter', 'sort'],\n };\n}\n\nfunction toQueryField(\n column: ReportColumnDescriptor,\n): DataQueryFieldDescriptor {\n return {\n id: column.id,\n type: column.type,\n ...(column.projectable === undefined\n ? {}\n : { projectable: column.projectable }),\n sortable: column.sortable === true,\n facetable: column.facetable === true,\n ...(column.filterOperators === undefined\n ? {}\n : { filterOperators: [...column.filterOperators] }),\n };\n}\n\nfunction filterOperatorsFor(\n type: DataQueryFieldDescriptor['type'],\n): DataQueryFilterOperator[] | undefined {\n switch (type) {\n case 'string':\n return ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', 'like'];\n case 'number':\n case 'datetime':\n return ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn'];\n case 'boolean':\n return ['eq', 'ne', 'in', 'notIn'];\n case 'json':\n return undefined;\n }\n}\n\nfunction refreshDescriptor(\n refresh?: ReportRefreshConfig,\n refreshPermission = 'reports.refresh',\n): ReportRefreshDescriptor {\n const config = refresh ?? {};\n const triggers = new Set<ReportRefreshDescriptor['triggers'][number]>([\n 'manual',\n ]);\n if (!config.manual) {\n const hasSchedule = Boolean(config.schedule || config.fullRebuildSchedule);\n const hasChangeTrigger = Boolean(config.onChange?.length);\n if (hasSchedule) triggers.add('schedule');\n if (hasChangeTrigger) triggers.add('change');\n if (config.ttl !== undefined && config.ttl > 0) triggers.add('ttl');\n // Scheduler and on-change refreshes enqueue a durable job in either mode;\n // incremental mode alone is not itself a trigger.\n if (hasSchedule || hasChangeTrigger) triggers.add('job');\n }\n return {\n mode: config.mode ?? 'rebuild',\n mayRefreshOnRead:\n config.ttl !== undefined && config.ttl > 0 && !config.manual,\n ...(config.ttl === undefined ? {} : { ttlMs: config.ttl }),\n triggers: [...triggers],\n action: {\n id: 'refresh',\n label: 'Refresh report',\n scope: 'surface',\n phases: ['preview', 'apply'],\n requiresPermission: true,\n requiredPermission:\n refreshPermission.trim().length > 0\n ? refreshPermission\n : 'reports.refresh',\n auditRequired: true,\n },\n };\n}\n\nfunction resourceId(\n definition: ReportDefinition,\n scope: ReportAdapterOptions['tenantScope'],\n): string {\n return `${definition.reportClassName}#${scope ?? 'current'}`;\n}\n\nconst VALUE_FORMAT_ALIASES: Readonly<\n Record<string, ReportDataTableValueFormat>\n> = {\n text: 'text',\n date: 'date',\n datetime: 'datetime',\n 'date-time': 'datetime',\n percentage: 'percentage',\n percent: 'percentage',\n count: 'count',\n money: 'money',\n currency: 'money',\n number: 'number',\n decimal: 'number',\n integer: 'number',\n};\n\nconst VALUE_FORMATS = new Set<ReportDataTableValueFormat>(\n Object.values(VALUE_FORMAT_ALIASES),\n);\nconst COLUMN_ROLES = new Set<ReportDataTableColumnRole>([\n 'data',\n 'status',\n 'action',\n]);\nconst STRUCTURAL_ROW_KINDS = new Set<ReportDataTableStructuralRowKind>([\n 'summary',\n 'subtotal',\n 'aggregate',\n 'footer',\n]);\n\nfunction valueFormat(\n column: ReportColumnDescriptor,\n): ReportDataTableValueFormat {\n const configured = column.format?.trim().toLowerCase();\n if (configured && Object.hasOwn(VALUE_FORMAT_ALIASES, configured)) {\n return VALUE_FORMAT_ALIASES[configured];\n }\n if (column.kind === 'bucket') {\n return column.bucket === 'minute' || column.bucket === 'hour'\n ? 'datetime'\n : 'date';\n }\n if (column.kind === 'aggregate' && column.aggregate === 'count') {\n return 'count';\n }\n if (column.type === 'datetime') return 'datetime';\n if (column.type === 'number') return 'number';\n return 'text';\n}\n\nfunction headerPath(\n column: ReportColumnDescriptor,\n): ReportDataTableHeaderPathSegment[] {\n if (column.kind === 'aggregate') {\n return [\n { id: 'measures', label: 'Measures' },\n {\n id: `aggregate:${column.aggregate ?? 'value'}`,\n label: labelFor(column.aggregate ?? 'value'),\n },\n ];\n }\n if (column.kind === 'bucket') {\n return [\n { id: 'dimensions', label: 'Dimensions' },\n { id: 'time', label: 'Time' },\n ];\n }\n if (column.kind === 'group') {\n return [\n { id: 'dimensions', label: 'Dimensions' },\n { id: 'groups', label: 'Groups' },\n ];\n }\n return [{ id: 'dimensions', label: 'Dimensions' }];\n}\n\nfunction responsive(\n column: ReportColumnDescriptor,\n): ReportDataTableColumnResponsive {\n if (column.kind === 'group' || column.kind === 'bucket') {\n return { priority: 100, keepVisible: true };\n }\n if (column.kind === 'identity') return { priority: 80 };\n return { priority: 20 };\n}\n\nfunction assertHeaderPath(\n columnId: string,\n path: readonly ReportDataTableHeaderPathSegment[],\n): ReportDataTableHeaderPathSegment[] {\n if (!Array.isArray(path)) {\n throw new TypeError(\n `Report DataTable headerPath for ${columnId} must be an array`,\n );\n }\n return path.map((segment) => {\n if (\n !segment ||\n typeof segment.id !== 'string' ||\n segment.id.trim().length === 0 ||\n typeof segment.label !== 'string' ||\n segment.label.trim().length === 0\n ) {\n throw new TypeError(\n `Report DataTable headerPath entries for ${columnId} require non-empty id and label`,\n );\n }\n return { id: segment.id, label: segment.label };\n });\n}\n\nfunction dataTableColumn(\n column: ReportColumnDescriptor,\n override?: ReportDataTableColumnOverride,\n): ReportDataTableColumn {\n const format = override?.valueFormat ?? valueFormat(column);\n const path = override?.headerPath ?? headerPath(column);\n if (!VALUE_FORMATS.has(format)) {\n throw new TypeError(\n `Report DataTable valueFormat for ${column.id} is not supported: ${String(format)}`,\n );\n }\n if (override?.role !== undefined && !COLUMN_ROLES.has(override.role)) {\n throw new TypeError(\n `Report DataTable role for ${column.id} is not supported: ${String(override.role)}`,\n );\n }\n if (\n override?.label !== undefined &&\n (typeof override.label !== 'string' || override.label.trim().length === 0)\n ) {\n throw new TypeError(\n `Report DataTable label for ${column.id} must not be empty`,\n );\n }\n if (\n override?.align !== undefined &&\n override.align !== 'left' &&\n override.align !== 'right'\n ) {\n throw new TypeError(\n `Report DataTable align for ${column.id} is not supported: ${String(override.align)}`,\n );\n }\n if (\n override?.responsive?.priority !== undefined &&\n (!Number.isFinite(override.responsive.priority) ||\n override.responsive.priority < 0)\n ) {\n throw new TypeError(\n `Report DataTable responsive priority for ${column.id} must be a non-negative finite number`,\n );\n }\n if (\n override?.responsive?.keepVisible !== undefined &&\n typeof override.responsive.keepVisible !== 'boolean'\n ) {\n throw new TypeError(\n `Report DataTable keepVisible for ${column.id} must be a boolean`,\n );\n }\n return {\n id: column.id,\n label: override?.label ?? column.label,\n accessor: column.id,\n sortable: column.sortable === true,\n searchable: false,\n filterable: column.filterOperators !== undefined,\n headerPath: assertHeaderPath(column.id, path),\n valueFormat: format,\n align:\n override?.align ??\n (['count', 'money', 'number', 'percentage'].includes(format)\n ? 'right'\n : 'left'),\n role: override?.role ?? 'data',\n responsive: { ...responsive(column), ...override?.responsive },\n };\n}\n\nfunction structuralRows(\n columnIds: ReadonlySet<string>,\n rows: readonly ReportDataTableStructuralRowInput[] = [],\n): ReportDataTableStructuralRow[] {\n const ids = new Set<string>();\n return rows.map((row) => {\n if (\n !row ||\n typeof row.id !== 'string' ||\n row.id.trim().length === 0 ||\n typeof row.label !== 'string' ||\n row.label.trim().length === 0\n ) {\n throw new TypeError(\n 'Report structural rows require non-empty id and label values',\n );\n }\n if (ids.has(row.id)) {\n throw new TypeError(`Report structural row id must be unique: ${row.id}`);\n }\n if (!STRUCTURAL_ROW_KINDS.has(row.kind)) {\n throw new TypeError(\n `Report structural row kind is not supported: ${String(row.kind)}`,\n );\n }\n if (row.labelColumnId !== undefined) {\n if (\n typeof row.labelColumnId !== 'string' ||\n row.labelColumnId.trim().length === 0 ||\n !columnIds.has(row.labelColumnId)\n ) {\n throw new TypeError(\n `Report structural row labelColumnId must name an adapter column: ${String(row.labelColumnId)}`,\n );\n }\n }\n if (\n row.values !== undefined &&\n (typeof row.values !== 'object' ||\n row.values === null ||\n Array.isArray(row.values))\n ) {\n throw new TypeError('Report structural row values must be an object');\n }\n if (\n row.values &&\n Object.keys(row.values).some((columnId) => !columnIds.has(columnId))\n ) {\n throw new TypeError(\n 'Report structural row values must use adapter column ids',\n );\n }\n ids.add(row.id);\n return {\n id: row.id,\n kind: row.kind,\n label: row.label,\n ...(row.values !== undefined\n ? {\n values: jsonSafeValue(row.values) as Record<string, unknown>,\n }\n : {}),\n ...(row.labelColumnId !== undefined\n ? { labelColumnId: row.labelColumnId }\n : {}),\n selection: 'excluded' as const,\n actions: 'excluded' as const,\n };\n });\n}\n\nfunction drilldownDescriptor(\n columns: readonly ReportColumnDescriptor[],\n sourceClassName: string,\n): ReportDrilldownDescriptor {\n return {\n id: 'drilldown',\n sourceClassName,\n fields: columns\n .filter(\n (\n column,\n ): column is ReportColumnDescriptor & {\n kind: 'group' | 'bucket';\n sourceColumn: string;\n } =>\n (column.kind === 'group' || column.kind === 'bucket') &&\n typeof column.sourceColumn === 'string',\n )\n .map((column) => ({\n id: column.id,\n sourceColumn: column.sourceColumn,\n kind: column.kind,\n ...(column.kind === 'bucket' && column.bucket\n ? { bucket: column.bucket }\n : {}),\n })),\n inherits: ['principal', 'tenant', 'report-definition', 'field-policy'],\n };\n}\n\nexport async function buildReportAdapterDescriptor(\n reportCtor: new (...args: any[]) => SmrtObject,\n options: ReportAdapterOptions = {},\n): Promise<ReportAdapterDescriptor> {\n const definition = await buildReportDefinition(reportCtor);\n const registered = registeredClass(reportCtor);\n const fields = (await ObjectRegistry.getAllFields(\n definition.reportClassName,\n )) as Map<string, RegistryField>;\n // A tenant-looking field is not an isolation boundary. Only registered\n // tenant scoping installs the collection interceptor used by the executor.\n const tenantField = configuredTenantField(\n registered?.tenantScopedConfig?.field,\n );\n const columns = [\n identityColumn(),\n ...definition.fields\n .map((field) => reportColumn(field, fields.get(field.fieldName)))\n .filter((field): field is ReportColumnDescriptor => Boolean(field)),\n ].sort((left, right) => left.id.localeCompare(right.id));\n const schema: DataQuerySchema = {\n version: 1,\n identityField: 'id',\n fields: columns.map(toQueryField),\n defaultSort: [{ field: 'id', direction: 'asc' }],\n supports: { cursorPagination: false, consistency: false, facets: true },\n };\n const dataTable: ReportDataTableDescriptor = {\n rowKey: 'id',\n manualPagination: true,\n manualSorting: true,\n enableFiltering: true,\n enableSearch: false,\n columns: columns.map((column) =>\n dataTableColumn(column, options.dataTable?.columns?.[column.id]),\n ),\n structuralRows: structuralRows(\n new Set(columns.map((column) => column.id)),\n options.dataTable?.structuralRows,\n ),\n };\n return {\n version: 1,\n resourceId: resourceId(definition, options.tenantScope),\n reportClassName: definition.reportClassName,\n sourceClassName: definition.sourceClassName,\n tenantScoped: Boolean(registered?.tenantScopedConfig),\n ...(tenantField ? { tenantField } : {}),\n identityField: 'id',\n columns,\n schema,\n queryExecution: {\n modes: ['visible', 'background', 'silent'],\n visible: { delivery: 'result' },\n background: { delivery: 'queued', requiresHost: true },\n silent: { delivery: 'result', mutatesVisibleSurface: false },\n },\n dataTable,\n drilldown: drilldownDescriptor(columns, definition.sourceClassName),\n refresh: refreshDescriptor(definition.refresh, options.refreshPermission),\n };\n}\n\nfunction publicFieldMap(\n descriptor: ReportAdapterDescriptor,\n): Map<string, string> {\n return new Map(\n descriptor.columns.map((column) => [column.id, column.fieldName]),\n );\n}\n\n/**\n * Bind a materialized report row to its declared source dimensions. This is a\n * query handoff, not an executor: an authenticated source adapter must apply\n * the inherited principal, tenant, definition, and field policy before it\n * reads source records.\n */\nexport async function buildReportDrilldownQuery(\n reportCtor: new (...args: any[]) => SmrtObject,\n row: Readonly<Record<string, unknown>>,\n options: ReportAdapterOptions = {},\n): Promise<ReportDrilldownQuery> {\n const descriptor = await buildReportAdapterDescriptor(reportCtor, options);\n const constraints = descriptor.drilldown.fields.map((field) => {\n if (!Object.hasOwn(row, field.id)) {\n throw new DataQueryValidationError(\n `Report drilldown row is missing grouping field: ${field.id}`,\n 'DATA_QUERY_RESULT_INVALID',\n );\n }\n return {\n id: field.id,\n sourceColumn: field.sourceColumn,\n kind: field.kind,\n value: jsonSafeValue(row[field.id]),\n ...(field.bucket ? { bucket: field.bucket } : {}),\n };\n });\n return {\n version: 1,\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n sourceClassName: descriptor.drilldown.sourceClassName,\n constraints,\n inherits: [...descriptor.drilldown.inherits],\n };\n}\n\ntype MaterializedWhere = Array<Array<Record<string, unknown>>>;\n\n/** Keep OR expansion bounded before it reaches the database collection. */\nconst MAX_REPORT_FILTER_OR_GROUPS = 128;\n\nfunction reportFilterError(message: string): never {\n throw new DataQueryValidationError(message, 'DATA_QUERY_UNSUPPORTED');\n}\n\nfunction crossProductWhere(\n left: MaterializedWhere,\n right: MaterializedWhere,\n): MaterializedWhere {\n if (left.length * right.length > MAX_REPORT_FILTER_OR_GROUPS) {\n return reportFilterError(\n `Report filter expands beyond ${MAX_REPORT_FILTER_OR_GROUPS} OR groups`,\n );\n }\n return left.flatMap((leftGroup) =>\n right.map((rightGroup) => [...leftGroup, ...rightGroup]),\n );\n}\n\nfunction inverseOperator(\n operator: DataQueryFilterOperator,\n): DataQueryFilterOperator {\n switch (operator) {\n case 'eq':\n return 'ne';\n case 'ne':\n return 'eq';\n case 'gt':\n return 'lte';\n case 'gte':\n return 'lt';\n case 'lt':\n return 'gte';\n case 'lte':\n return 'gt';\n case 'in':\n return 'notIn';\n case 'notIn':\n return 'in';\n case 'like':\n return reportFilterError(\n 'Report filters do not support negating a LIKE predicate',\n );\n }\n}\n\nfunction collectionCondition(\n field: string,\n operator: DataQueryFilterOperator,\n value: DataQueryCondition['value'],\n): MaterializedWhere {\n const keyFor = (suffix: string) => (suffix ? `${field} ${suffix}` : field);\n const scalar = (key: string, scalarValue: unknown): MaterializedWhere => [\n [{ [key]: scalarValue }],\n ];\n\n if (operator === 'in') {\n const values = value as Array<string | number | boolean | null>;\n const nonNull = values.filter((entry) => entry !== null);\n if (nonNull.length === 0) return scalar(field, null);\n if (nonNull.length === values.length) return scalar(keyFor('in'), nonNull);\n // SQL IN does not match NULL. Model the user-visible union explicitly.\n return [[{ [field]: null }], [{ [keyFor('in')]: nonNull }]];\n }\n\n if (operator === 'notIn') {\n const values = value as Array<string | number | boolean | null>;\n // `buildWhere()` does not have a `NOT IN` primitive. A bounded AND of\n // inequality predicates has the same null-safe semantics and remains fully\n // validated by the collection.\n return [values.map((entry) => ({ [keyFor('!=')]: entry }))];\n }\n\n const suffix: Record<\n Exclude<DataQueryFilterOperator, 'in' | 'notIn'>,\n string\n > = {\n eq: '',\n ne: '!=',\n gt: '>',\n gte: '>=',\n lt: '<',\n lte: '<=',\n like: 'like',\n };\n return scalar(keyFor(suffix[operator]), value);\n}\n\nfunction materializedWhereForFilter(\n filter: DataQueryFilter,\n fields: Map<string, string>,\n negate = false,\n): MaterializedWhere {\n if (filter.kind === 'condition') {\n const field = fields.get(filter.field);\n if (!field) {\n return reportFilterError(\n `Report filter field is not declared: ${filter.field}`,\n );\n }\n return collectionCondition(\n field,\n negate ? inverseOperator(filter.operator) : filter.operator,\n filter.value,\n );\n }\n\n if (filter.kind === 'not') {\n return materializedWhereForFilter(filter.filter, fields, !negate);\n }\n\n const combineWithAnd =\n (filter.kind === 'all' && !negate) || (filter.kind === 'any' && negate);\n if (combineWithAnd) {\n return filter.filters.reduce<MaterializedWhere>(\n (combined, child) =>\n crossProductWhere(\n combined,\n materializedWhereForFilter(child, fields, negate),\n ),\n [[]],\n );\n }\n\n const groups = filter.filters.flatMap((child) =>\n materializedWhereForFilter(child, fields, negate),\n );\n if (groups.length > MAX_REPORT_FILTER_OR_GROUPS) {\n return reportFilterError(\n `Report filter expands beyond ${MAX_REPORT_FILTER_OR_GROUPS} OR groups`,\n );\n }\n return groups;\n}\n\n/**\n * Converts a normalized report filter to collection-owned, parameterized\n * predicates. The returned DNF form gives each OR branch a complete AND\n * clause, so tenant interception can add its tenant predicate to every branch.\n */\nfunction materializedWhere(\n filter: DataQueryFilter | undefined,\n fields: Map<string, string>,\n): MaterializedWhere | undefined {\n return filter ? materializedWhereForFilter(filter, fields) : undefined;\n}\n\nfunction filterScopeForColumn(\n column: ReportColumnDescriptor,\n): ReportFilterScope {\n return column.filterScope;\n}\n\n/**\n * Split the declared filter language by report semantics for consumers that\n * construct a live source query. Mixed AND expressions are represented as two\n * independent clauses; mixed OR/NOT expressions are rejected because moving\n * either half across WHERE/HAVING would change their meaning.\n */\nexport function splitReportFilterScopes(\n descriptor: ReportAdapterDescriptor,\n filter: DataQueryFilter | undefined,\n): { where?: DataQueryFilter; having?: DataQueryFilter } {\n if (!filter) return {};\n const columns = new Map(\n descriptor.columns.map((column) => [column.id, column]),\n );\n const combineAll = (\n filters: DataQueryFilter[],\n ): DataQueryFilter | undefined => {\n const flattened = filters.flatMap((candidate) =>\n candidate.kind === 'all' ? candidate.filters : [candidate],\n );\n return flattened.length === 0\n ? undefined\n : flattened.length === 1\n ? flattened[0]\n : { kind: 'all', filters: flattened };\n };\n const split = (\n candidate: DataQueryFilter,\n ): { where?: DataQueryFilter; having?: DataQueryFilter } => {\n if (candidate.kind === 'condition') {\n const column = columns.get(candidate.field);\n if (!column) {\n reportFilterError(\n `Report filter field is not declared: ${candidate.field}`,\n );\n }\n return filterScopeForColumn(column) === 'where'\n ? { where: candidate }\n : { having: candidate };\n }\n\n if (candidate.kind === 'all') {\n const children = candidate.filters.map(split);\n const where = combineAll(\n children.flatMap((child) => (child.where ? [child.where] : [])),\n );\n const having = combineAll(\n children.flatMap((child) => (child.having ? [child.having] : [])),\n );\n return {\n ...(where ? { where } : {}),\n ...(having ? { having } : {}),\n };\n }\n\n const children =\n candidate.kind === 'not'\n ? [split(candidate.filter)]\n : candidate.filters.map(split);\n const scopes = new Set(\n children.flatMap((child) => [\n ...(child.where ? (['where'] as const) : []),\n ...(child.having ? (['having'] as const) : []),\n ]),\n );\n if (scopes.size !== 1) {\n reportFilterError(\n 'Report WHERE and HAVING filters cannot be mixed inside one OR or NOT expression',\n );\n }\n const scope = scopes.has('where') ? 'where' : 'having';\n const filters = children.flatMap((child) => {\n const filter = scope === 'where' ? child.where : child.having;\n return filter ? [filter] : [];\n });\n if (candidate.kind === 'not') {\n const [filter] = filters;\n if (!filter) {\n reportFilterError('Report NOT expressions must contain one filter');\n }\n return scope === 'where'\n ? { where: { kind: 'not', filter } }\n : { having: { kind: 'not', filter } };\n }\n return scope === 'where'\n ? { where: { kind: 'any', filters } }\n : { having: { kind: 'any', filters } };\n };\n\n return split(filter);\n}\n\nconst DATE_ONLY_VALUE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * `YYYY-MM-DD[T ]HH:MM[:SS[.fff]]` with no zone designator — the shape SQLite's\n * `CURRENT_TIMESTAMP` / `datetime('now')` persist. SQLite writes those in UTC,\n * but `new Date('2026-09-17 12:00:00')` reads the space-separated form as\n * *local* time, so the zone is appended explicitly instead of inferred.\n */\nconst NAIVE_TIMESTAMP_VALUE =\n /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?$/;\n\n/** ISO-8601/RFC 3339 instant in UTC, or `null` for an unrepresentable date. */\nfunction instantOrNull(value: Date): string | null {\n return Number.isNaN(value.getTime()) ? null : value.toISOString();\n}\n\nfunction epochToInstant(value: number): string | null {\n if (!Number.isFinite(value)) return null;\n return instantOrNull(new Date(value));\n}\n\n/**\n * Serialize one temporal row value to an RFC 3339 instant in UTC (#2934).\n *\n * `SmrtCollection.list()` hydrates a `datetime` field into a `Date`, and a raw\n * driver row can hand back the stored string or an epoch number instead. The\n * shared result validator only accepts JSON scalars, and normalizes a\n * `datetime` descriptor's value through `normalizedInstant`, so every one of\n * those forms has to reach it as an instant string.\n *\n * An unparseable string is returned unchanged on purpose: the shared validator\n * owns that error, and its message names the field and the RFC 3339 contract.\n */\nfunction temporalToInstant(value: unknown): unknown {\n if (value instanceof Date) return instantOrNull(value);\n if (typeof value === 'number') return epochToInstant(value);\n if (typeof value === 'bigint') {\n // An epoch outside the safe-integer range would round on the way through\n // `Number`, producing a WRONG instant. For a temporal value a missing one\n // is safer than a silently shifted one.\n const numeric = Number(value);\n return Number.isSafeInteger(numeric) ? epochToInstant(numeric) : null;\n }\n if (typeof value !== 'string') return value;\n const text = value.trim();\n if (text.length === 0) return null;\n if (DATE_ONLY_VALUE.test(text)) return `${text}T00:00:00.000Z`;\n if (NAIVE_TIMESTAMP_VALUE.test(text)) {\n return epochToInstant(Date.parse(`${text.replace(' ', 'T')}Z`)) ?? value;\n }\n const parsed = Date.parse(text);\n if (!Number.isFinite(parsed)) return value;\n return epochToInstant(parsed) ?? value;\n}\n\nfunction jsonSafeValue(\n value: unknown,\n ancestors = new WeakSet<object>(),\n): unknown {\n if (value instanceof Date) return instantOrNull(value);\n if (typeof value === 'bigint') {\n const numeric = Number(value);\n if (!Number.isSafeInteger(numeric)) {\n throw new RangeError(\n 'Materialized bigint values must be safely representable as numbers',\n );\n }\n return numeric;\n }\n if (value && typeof value === 'object') {\n if (ancestors.has(value)) {\n throw new TypeError('Values must not contain circular references');\n }\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n return value.map((entry) => jsonSafeValue(entry, ancestors));\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [\n key,\n jsonSafeValue(entry, ancestors),\n ]),\n );\n } finally {\n ancestors.delete(value);\n }\n }\n return value;\n}\n\n/** Normalize hydrated values according to the public descriptor (#2934). */\nfunction toDeclaredValue(\n value: unknown,\n descriptor: DataQueryFieldDescriptor,\n shortened: Set<string>,\n): unknown {\n const cap = (text: string): string => {\n if (text.length <= 4096) return text;\n shortened.add(descriptor.id);\n // Keep a UTF-16 surrogate pair together at the scalar length boundary.\n const last = text.charCodeAt(4095);\n const next = text.charCodeAt(4096);\n const splitsPair =\n last >= 0xd800 && last <= 0xdbff && next >= 0xdc00 && next <= 0xdfff;\n return text.slice(0, splitsPair ? 4095 : 4096);\n };\n // Identity is authoritative: reject unsupported values instead of rewriting it.\n if (descriptor.id === 'id') return value;\n if (value === undefined || value === null) return null;\n if (descriptor.type === 'datetime') return temporalToInstant(value);\n if (descriptor.type === 'json') return jsonSafeValue(value);\n if (typeof value === 'object' && !(value instanceof Date)) {\n try {\n const rendered = JSON.stringify(jsonSafeValue(value));\n return rendered === undefined ? null : cap(rendered);\n } catch (error) {\n if (error instanceof RangeError) throw error;\n return null;\n }\n }\n if (descriptor.type === 'boolean' && typeof value === 'number')\n return value !== 0;\n if (typeof value === 'string') return cap(value);\n return jsonSafeValue(value);\n}\n\nfunction mapMaterializedRow(\n row: Record<string, unknown>,\n projection: readonly string[],\n fieldMap: Map<string, string>,\n schema: DataQuerySchema,\n shortened: Set<string>,\n): Record<string, unknown> {\n const mapped: Record<string, unknown> = {};\n for (const id of projection) {\n const sourceField = fieldMap.get(id) ?? id;\n const descriptor = schema.fields.find((field) => field.id === id);\n if (sourceField in row && descriptor)\n mapped[id] = toDeclaredValue(row[sourceField], descriptor, shortened);\n }\n return mapped;\n}\n\nfunction queryFreshness(\n lifecycle: ReportLifecycleSnapshot,\n): DataQueryFreshness {\n switch (lifecycle.state) {\n case 'current':\n return {\n state: 'fresh',\n ...(lifecycle.asOf ? { asOf: lifecycle.asOf } : {}),\n };\n case 'stale':\n case 'lock-skipped':\n case 'failed':\n return {\n state: 'stale',\n ...(lifecycle.asOf ? { asOf: lifecycle.asOf } : {}),\n };\n case 'refreshing':\n return lifecycle.hasUsableRows\n ? {\n state: 'stale',\n ...(lifecycle.asOf ? { asOf: lifecycle.asOf } : {}),\n }\n : { state: 'unknown' };\n }\n}\n\n/**\n * Execute bounded materialized report reads through the canonical query\n * envelope. Every predicate is an adapter-declared field/operator pair; the\n * collection converts it to parameterized SQL and applies tenant interceptors\n * to list, count, and facet reads alike.\n */\nexport function queryReportMaterializedRows(\n reportCtor: new (...args: any[]) => SmrtObject,\n input: unknown,\n options: ReportBackgroundQueryOptions,\n): Promise<ReportBackgroundQueryResult>;\nexport function queryReportMaterializedRows(\n reportCtor: new (...args: any[]) => SmrtObject,\n input: unknown,\n options?: ReportQueryOptions,\n): Promise<ReportDataQueryResult>;\nexport async function queryReportMaterializedRows(\n reportCtor: new (...args: any[]) => SmrtObject,\n input: unknown,\n options: ReportQueryOptions | ReportBackgroundQueryOptions = {},\n): Promise<ReportDataQueryResult | ReportBackgroundQueryResult> {\n const descriptor = await buildReportAdapterDescriptor(\n reportCtor,\n options.adapter,\n );\n const request = normalizeDataQueryRequest(input, descriptor.schema);\n // Validate the semantic split even though materialized-row reads execute the\n // complete predicate against one persisted table. It prevents an adapter\n // consumer from silently treating a mixed source WHERE/HAVING expression as\n // either side of the aggregate boundary.\n splitReportFilterScopes(descriptor, request.filter);\n const queryFingerprint = createDataQueryFingerprint(\n request,\n descriptor.schema,\n );\n if (options.execution === 'background') {\n const queued = await options.enqueueBackgroundQuery({\n version: 1,\n execution: 'background',\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n request,\n inherits: ['principal', 'tenant', 'report-definition', 'field-policy'],\n });\n if (typeof queued.taskId !== 'string' || queued.taskId.length === 0) {\n throw new Error('Background report query hosts must return a task id');\n }\n return {\n version: 1,\n execution: 'background',\n status: 'queued',\n taskId: queued.taskId,\n queryFingerprint,\n };\n }\n const execution = options.execution ?? 'visible';\n const lifecycleDb = options.db;\n if (options.lifecycle && !lifecycleDb) {\n throw new Error('Report lifecycle disclosure requires a database handle');\n }\n const lifecycleOptions =\n options.lifecycle && lifecycleDb\n ? { db: lifecycleDb, ...options.lifecycle }\n : undefined;\n const lifecycleBefore = lifecycleOptions\n ? await getReportLifecycle(reportCtor, lifecycleOptions)\n : undefined;\n const fieldMap = publicFieldMap(descriptor);\n const where = materializedWhere(request.filter, fieldMap);\n const collection: NonNullable<ReportQueryOptions['collection']> =\n options.collection ??\n ((await ObjectRegistry.getCollection(descriptor.reportClassName, {\n db: options.db,\n })) as unknown as NonNullable<ReportQueryOptions['collection']>);\n const shortened = new Set<string>();\n let rows: Record<string, unknown>[] = [];\n let page: DataQueryResult['page'];\n let total: number;\n let facets: DataQueryResult['facets'];\n if (request.mode === 'rows') {\n const projection = request.projection ?? [descriptor.identityField];\n const select = projection.map((id) => fieldMap.get(id) ?? id);\n const offset = request.page?.kind === 'offset' ? request.page.offset : 0;\n const limit = request.page?.limit ?? 50;\n const orderBy = request.sort?.map(\n ({ field, direction }) =>\n `${fieldMap.get(field) ?? field} ${direction.toUpperCase()}`,\n );\n const materialized = await collection.list({\n select,\n offset,\n limit,\n orderBy: orderBy?.length === 1 ? orderBy[0] : orderBy,\n ...(where === undefined ? {} : { where }),\n });\n rows = materialized.map((row) =>\n mapMaterializedRow(\n row,\n projection,\n fieldMap,\n descriptor.schema,\n shortened,\n ),\n );\n rows.forEach((row) => {\n if (typeof row.id !== 'string' || row.id.length === 0) {\n throw new Error(\n 'Materialized report rows require a non-empty string id',\n );\n }\n });\n // SmrtReportCollection performs an eligible TTL refresh from list(). Count\n // must follow that operation so total/hasMore describe the same snapshot.\n total = await collection.count(where === undefined ? undefined : { where });\n page = {\n kind: 'offset',\n offset,\n limit,\n hasMore: offset + rows.length < total,\n };\n } else {\n // Count-only reads still enter SmrtReportCollection's list lifecycle to\n // refresh an eligible stale report before calculating its exact total.\n await collection.list({\n select: ['id'],\n offset: 0,\n limit: 1,\n orderBy: 'id ASC',\n ...(where === undefined ? {} : { where }),\n });\n total = await collection.count(where === undefined ? undefined : { where });\n if (request.mode === 'facets') {\n if (!collection.facets) {\n throw new Error(\n 'Report materialized facet reads require a collection facets() implementation',\n );\n }\n const requested = request.facets ?? [];\n const sourceFacets = await collection.facets({\n fields: requested.map((facet) => ({\n field: fieldMap.get(facet.field) ?? facet.field,\n limit: facet.limit,\n })),\n ...(where === undefined ? {} : { where }),\n });\n const byField = new Map(\n sourceFacets.map((facet) => [facet.field, facet]),\n );\n facets = requested.map((facet) => {\n const sourceField = fieldMap.get(facet.field) ?? facet.field;\n const values = byField.get(sourceField)?.values ?? [];\n const field = descriptor.schema.fields.find(\n (field) => field.id === facet.field,\n );\n if (!field) throw new Error('Unknown report facet field');\n return {\n field: facet.field,\n values: values.map((value) => ({\n value: toDeclaredValue(\n value.value,\n field,\n shortened,\n ) as DataQueryScalar,\n count: value.count,\n })),\n // The collection deliberately bounds this database grouping query;\n // an exactly-full page may have more values, so report conservatively.\n truncated: values.length >= facet.limit,\n };\n });\n }\n }\n const result = {\n version: 1 as const,\n requestId: request.requestId,\n queryFingerprint,\n identityField: descriptor.identityField,\n rows,\n ...(page ? { page } : {}),\n total: { kind: 'exact' as const, value: total },\n ...(facets === undefined ? {} : { facets }),\n freshness: { state: 'unknown' as const },\n warnings: shortened.size\n ? ['Values exceeding the scalar result limit were shortened.']\n : [],\n truncated: shortened.size > 0,\n };\n const normalized = normalizeDataQueryResult(\n result,\n request,\n descriptor.schema,\n );\n if (!lifecycleBefore || !lifecycleOptions) {\n return { ...normalized, execution };\n }\n\n const lifecycleAfter = await getReportLifecycle(reportCtor, lifecycleOptions);\n return {\n ...normalized,\n execution,\n freshness: queryFreshness(lifecycleAfter),\n reportLifecycle: {\n snapshot: lifecycleAfter,\n read:\n lifecycleBefore.state !== 'current' &&\n lifecycleAfter.state === 'current'\n ? 'refresh-triggered'\n : lifecycleAfter.state === 'current'\n ? 'current'\n : 'stale',\n },\n };\n}\n\n/** Read the already-materialized primary key; never use a display/page index. */\nexport function reportMaterializedRowKey(row: Record<string, unknown>): string {\n const id = row.id;\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error('Materialized report rows require a non-empty string id');\n }\n return id;\n}\n","import type {\n ReportAdapterDescriptor,\n ReportDataQueryResult,\n} from './adapter.js';\n\n/** Verified request context supplied by an application route, never the browser. */\nexport interface MaterializedReportHostContext {\n userId: string;\n tenantId: string;\n permissions: readonly string[];\n}\n\n/** The only browser-controlled selections accepted by a materialized-report host. */\nexport interface MaterializedReportCellRequest {\n id: string;\n columnId: string;\n}\n\n/** A host-normalized monetary value; values stay in integer minor units. */\nexport interface MaterializedReportDrilldownValues {\n valueMinor?: number | null;\n taxableMinor?: number | null;\n taxMinor?: number | null;\n}\n\n/** One user-visible record contributing to a materialized report cell. */\nexport interface MaterializedReportDrilldownContributor {\n id: string;\n source: string;\n identity: string;\n date?: string | null;\n party?: string | null;\n values: MaterializedReportDrilldownValues;\n}\n\n/** A host-declared warning that keeps incomplete or divergent evidence visible. */\nexport interface MaterializedReportDrilldownWarning {\n code: string;\n kind: 'incomplete' | 'drift';\n message: string;\n}\n\n/**\n * Domain-neutral presentation returned by a materialized-report host.\n *\n * The route serializes this value unchanged. Hosts normalize their own source\n * facts here so generic browser surfaces neither import nor infer report domains.\n */\nexport interface MaterializedReportDrilldownPresentation {\n version: 1;\n selectedMeasure: { id: string; label: string };\n currency: string;\n contributors: readonly MaterializedReportDrilldownContributor[];\n complete: boolean;\n warnings: readonly MaterializedReportDrilldownWarning[];\n}\n\n/**\n * Application-owned bridge for one declared materialized report.\n *\n * Registrations are server-only and bind tenant/principal from the route\n * context. Hosts must re-read the selected row before resolving a cell.\n */\nexport interface MaterializedReportHost<Drilldown = unknown> {\n id: string;\n /** Registered collection and model used by the route's normal read gate. */\n collection: string;\n className: string;\n /** The report host fails closed unless this published permission is present. */\n readPermission: string;\n /** Closed visible columns that may request a source drilldown. */\n drilldownColumnIds: readonly string[];\n descriptor(\n context: MaterializedReportHostContext,\n ): Promise<ReportAdapterDescriptor>;\n query(\n context: MaterializedReportHostContext,\n request: unknown,\n ): Promise<ReportDataQueryResult>;\n drilldown(\n context: MaterializedReportHostContext,\n request: MaterializedReportCellRequest,\n ): Promise<Drilldown>;\n}\n\nexport function assertMaterializedReportRead(\n host: MaterializedReportHost,\n context: MaterializedReportHostContext,\n): void {\n if (\n !context.userId?.trim() ||\n !context.tenantId?.trim() ||\n !context.permissions?.includes(host.readPermission)\n ) {\n throw new Error('Materialized report access denied.');\n }\n}\n\nexport function findMaterializedReportHost(\n hosts: readonly MaterializedReportHost[],\n id: string,\n): MaterializedReportHost | undefined {\n return hosts.find((host) => host.id === id);\n}\n","/**\n * Declarative runtime report specification (#3711).\n *\n * A runtime report is DATA, never code: a closed, versioned structure that a\n * user (or the assistant on a user's behalf) can propose at runtime. The spec\n * grammar deliberately has no free-form SQL, no expression language, no raw\n * identifiers and no join syntax. Every name in it is later resolved against\n * the ObjectRegistry field policy by `compileRuntimeReportSpec()`; this module\n * only enforces the STRUCTURE (shape, bounds, alias hygiene) and normalizes\n * defaults so equal specs hash equally.\n *\n * The parser accepts no authority. Nothing in a spec names a tenant, a\n * principal, a permission, a table, a column alias that is not a plain\n * identifier, or an SQL fragment.\n */\n\nimport { createHash } from 'node:crypto';\nimport { SmrtError } from '@happyvertical/smrt-core';\n\nexport const RUNTIME_REPORT_SPEC_VERSION = 1 as const;\n\nexport const RUNTIME_REPORT_LIMITS = Object.freeze({\n maxTitleLength: 120,\n maxDescriptionLength: 500,\n maxDimensions: 4,\n maxMeasures: 6,\n maxFilters: 12,\n maxHaving: 4,\n maxSort: 3,\n maxInValues: 100,\n maxStringValueLength: 256,\n defaultRowLimit: 100,\n maxRowLimit: 1000,\n maxAliasLength: 40,\n maxFieldNameLength: 64,\n maxSourceIdLength: 120,\n});\n\nexport const RUNTIME_REPORT_BUCKETS = [\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n 'quarter',\n 'year',\n] as const;\nexport type RuntimeReportBucket = (typeof RUNTIME_REPORT_BUCKETS)[number];\n\nexport const RUNTIME_REPORT_MEASURE_FNS = [\n 'count',\n 'countDistinct',\n 'sum',\n 'avg',\n 'min',\n 'max',\n] as const;\nexport type RuntimeReportMeasureFn =\n (typeof RUNTIME_REPORT_MEASURE_FNS)[number];\n\nexport const RUNTIME_REPORT_FILTER_OPS = [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'contains',\n 'isNull',\n 'isNotNull',\n] as const;\nexport type RuntimeReportFilterOp = (typeof RUNTIME_REPORT_FILTER_OPS)[number];\n\nexport const RUNTIME_REPORT_HAVING_OPS = [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n] as const;\nexport type RuntimeReportHavingOp = (typeof RUNTIME_REPORT_HAVING_OPS)[number];\n\nexport const RUNTIME_REPORT_CHART_TYPES = [\n 'table',\n 'bar',\n 'line',\n 'pie',\n 'stat',\n] as const;\nexport type RuntimeReportChartType =\n (typeof RUNTIME_REPORT_CHART_TYPES)[number];\n\nexport type RuntimeReportScalar = string | number | boolean;\n\nexport interface RuntimeReportDimension {\n /** Source field name as declared on the model (for example `issuedAt`). */\n field: string;\n /** Output column alias. Defaults to the snake_case field (plus bucket). */\n as: string;\n /** Time bucket; only valid on datetime fields. */\n bucket?: RuntimeReportBucket;\n}\n\nexport interface RuntimeReportMeasure {\n fn: RuntimeReportMeasureFn;\n /** Source field; omitted only for a plain row `count`. */\n field?: string;\n as: string;\n}\n\nexport interface RuntimeReportFilter {\n field: string;\n op: RuntimeReportFilterOp;\n /** Scalar, or a bounded array for `in`/`notIn`; absent for null tests. */\n value?: RuntimeReportScalar | RuntimeReportScalar[];\n}\n\nexport interface RuntimeReportHaving {\n /** A measure alias declared by this spec. */\n measure: string;\n op: RuntimeReportHavingOp;\n value: number;\n}\n\nexport interface RuntimeReportSort {\n /** A dimension or measure alias declared by this spec. */\n by: string;\n direction: 'asc' | 'desc';\n}\n\nexport interface RuntimeReportChart {\n type: RuntimeReportChartType;\n /** Dimension alias for the category/x axis. */\n x?: string;\n /** Measure aliases for the value/y axis. */\n y?: string[];\n}\n\nexport interface RuntimeReportSpec {\n version: typeof RUNTIME_REPORT_SPEC_VERSION;\n title: string;\n description?: string;\n /** A server-owned source id; resolved against an allow-list at compile. */\n source: string;\n dimensions: RuntimeReportDimension[];\n measures: RuntimeReportMeasure[];\n filters: RuntimeReportFilter[];\n having: RuntimeReportHaving[];\n sort: RuntimeReportSort[];\n limit: number;\n chart: RuntimeReportChart;\n}\n\nexport type RuntimeReportErrorCode =\n | 'invalid_spec'\n | 'unknown_source'\n | 'unknown_field'\n | 'invalid_operation'\n | 'invalid_value'\n | 'tenant_required'\n | 'confirmation_required'\n | 'unsupported_source'\n | 'invalid_result';\n\n/**\n * Raised for any spec or compile rejection. The message is safe to hand back\n * to a model so it can repair the spec; it never echoes restricted-field\n * metadata (a hidden field is reported exactly like an absent one).\n */\nexport class RuntimeReportError extends SmrtError {\n readonly code: RuntimeReportErrorCode;\n readonly path: string;\n /**\n * HTTP-style status so tool loops classify it: 4xx input problems are\n * repairable by the caller, `tenant_required` and `confirmation_required`\n * are denials, results that cannot be represented are server errors.\n */\n readonly status: number;\n\n constructor(code: RuntimeReportErrorCode, path: string, message: string) {\n super(path ? `${path}: ${message}` : message, code, 'validation');\n this.name = 'RuntimeReportError';\n this.code = code;\n this.path = path;\n this.status =\n code === 'tenant_required' || code === 'confirmation_required'\n ? 403\n : code === 'invalid_result'\n ? 500\n : 422;\n }\n}\n\nfunction fail(path: string, message: string): never {\n throw new RuntimeReportError('invalid_spec', path, message);\n}\n\n/** Output aliases that would be reserved words in at least one SQL dialect. */\nconst RESERVED_ALIASES: ReadonlySet<string> = new Set([\n 'all',\n 'and',\n 'as',\n 'asc',\n 'between',\n 'by',\n 'case',\n 'cast',\n 'check',\n 'column',\n 'constraint',\n 'create',\n 'cross',\n 'default',\n 'delete',\n 'desc',\n 'distinct',\n 'drop',\n 'else',\n 'end',\n 'except',\n 'exists',\n 'false',\n 'for',\n 'foreign',\n 'from',\n 'full',\n 'group',\n 'having',\n 'in',\n 'inner',\n 'insert',\n 'intersect',\n 'into',\n 'is',\n 'join',\n 'left',\n 'like',\n 'limit',\n 'natural',\n 'not',\n 'null',\n 'offset',\n 'on',\n 'or',\n 'order',\n 'outer',\n 'primary',\n 'references',\n 'right',\n 'select',\n 'set',\n 'table',\n 'then',\n 'to',\n 'true',\n 'union',\n 'unique',\n 'update',\n 'user',\n 'using',\n 'values',\n 'when',\n 'where',\n 'with',\n]);\n\nconst ALIAS_PATTERN = /^[a-z][a-z0-9_]*$/;\nconst FIELD_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/;\nconst SOURCE_PATTERN = /^[A-Za-z@][A-Za-z0-9_@./:-]*$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype ||\n Object.getPrototypeOf(value) === null)\n );\n}\n\nfunction strictObject(\n value: unknown,\n path: string,\n allowed: readonly string[],\n): Record<string, unknown> {\n if (!isRecord(value)) fail(path, 'must be an object');\n for (const key of Object.keys(value)) {\n if (!allowed.includes(key)) fail(`${path}.${key}`, 'is not a known key');\n }\n return value;\n}\n\nfunction strictArray(\n value: unknown,\n path: string,\n max: number,\n min = 0,\n): unknown[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) fail(path, 'must be an array');\n if (value.length > max) fail(path, `must have at most ${max} entries`);\n if (value.length < min) fail(path, `must have at least ${min} entries`);\n return value;\n}\n\nfunction text(\n value: unknown,\n path: string,\n max: number,\n options: { optional?: boolean } = {},\n): string {\n if (typeof value !== 'string') {\n if (options.optional && value === undefined) return '';\n fail(path, 'must be a string');\n }\n const trimmed = value.trim();\n if (trimmed.length === 0 && !options.optional) {\n fail(path, 'must not be empty');\n }\n if (trimmed.length > max) fail(path, `must be at most ${max} characters`);\n // Titles/descriptions are echoed into UIs and prompts: keep them printable.\n // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional guard\n if (/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/.test(trimmed)) {\n fail(path, 'must not contain control characters');\n }\n return trimmed;\n}\n\nfunction oneOf<T extends string>(\n value: unknown,\n path: string,\n allowed: readonly T[],\n): T {\n if (typeof value !== 'string' || !allowed.includes(value as T)) {\n fail(path, `must be one of: ${allowed.join(', ')}`);\n }\n return value as T;\n}\n\nfunction fieldName(value: unknown, path: string): string {\n if (typeof value !== 'string') fail(path, 'must be a string');\n if (\n value.length === 0 ||\n value.length > RUNTIME_REPORT_LIMITS.maxFieldNameLength ||\n !FIELD_PATTERN.test(value)\n ) {\n fail(path, 'must be a plain field name (letters, digits, underscore)');\n }\n return value;\n}\n\nfunction alias(value: unknown, path: string): string {\n if (typeof value !== 'string') fail(path, 'must be a string');\n if (\n value.length === 0 ||\n value.length > RUNTIME_REPORT_LIMITS.maxAliasLength ||\n !ALIAS_PATTERN.test(value)\n ) {\n fail(\n path,\n `must be a lowercase identifier of at most ${RUNTIME_REPORT_LIMITS.maxAliasLength} characters (a-z, 0-9, underscore)`,\n );\n }\n if (RESERVED_ALIASES.has(value)) fail(path, `'${value}' is a reserved word`);\n return value;\n}\n\nfunction scalar(value: unknown, path: string): RuntimeReportScalar {\n if (typeof value === 'string') {\n if (value.length > RUNTIME_REPORT_LIMITS.maxStringValueLength) {\n fail(\n path,\n `must be at most ${RUNTIME_REPORT_LIMITS.maxStringValueLength} characters`,\n );\n }\n if (value.includes('\\u0000')) fail(path, 'must not contain NUL');\n return value;\n }\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) fail(path, 'must be a finite number');\n return value;\n }\n if (typeof value === 'boolean') return value;\n return fail(path, 'must be a string, number or boolean');\n}\n\nfunction snake(name: string): string {\n return name\n .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n .toLowerCase();\n}\n\nfunction parseDimension(value: unknown, path: string): RuntimeReportDimension {\n const raw = strictObject(value, path, ['field', 'as', 'bucket']);\n const field = fieldName(raw.field, `${path}.field`);\n const bucket =\n raw.bucket === undefined\n ? undefined\n : oneOf(raw.bucket, `${path}.bucket`, RUNTIME_REPORT_BUCKETS);\n const as =\n raw.as === undefined\n ? alias(bucket ? `${snake(field)}_${bucket}` : snake(field), `${path}.as`)\n : alias(raw.as, `${path}.as`);\n return { field, as, ...(bucket ? { bucket } : {}) };\n}\n\nfunction parseMeasure(value: unknown, path: string): RuntimeReportMeasure {\n const raw = strictObject(value, path, ['fn', 'field', 'as']);\n const fn = oneOf(raw.fn, `${path}.fn`, RUNTIME_REPORT_MEASURE_FNS);\n const field =\n raw.field === undefined ? undefined : fieldName(raw.field, `${path}.field`);\n if (!field && fn !== 'count') fail(`${path}.field`, `is required for ${fn}`);\n const as =\n raw.as === undefined\n ? alias(\n field ? `${snake(fn)}_${snake(field)}` : 'row_count',\n `${path}.as`,\n )\n : alias(raw.as, `${path}.as`);\n return { fn, ...(field ? { field } : {}), as };\n}\n\nfunction parseFilter(value: unknown, path: string): RuntimeReportFilter {\n const raw = strictObject(value, path, ['field', 'op', 'value']);\n const field = fieldName(raw.field, `${path}.field`);\n const op = oneOf(raw.op, `${path}.op`, RUNTIME_REPORT_FILTER_OPS);\n if (op === 'isNull' || op === 'isNotNull') {\n if (raw.value !== undefined)\n fail(`${path}.value`, `must be omitted for ${op}`);\n return { field, op };\n }\n if (raw.value === undefined) fail(`${path}.value`, `is required for ${op}`);\n if (op === 'in' || op === 'notIn') {\n const values = strictArray(\n raw.value,\n `${path}.value`,\n RUNTIME_REPORT_LIMITS.maxInValues,\n 1,\n ).map((entry, index) => scalar(entry, `${path}.value[${index}]`));\n return { field, op, value: values };\n }\n if (Array.isArray(raw.value))\n fail(`${path}.value`, `must be a scalar for ${op}`);\n const parsed = scalar(raw.value, `${path}.value`);\n if (op === 'contains' && typeof parsed !== 'string') {\n fail(`${path}.value`, 'must be a string for contains');\n }\n return { field, op, value: parsed };\n}\n\nfunction parseHaving(value: unknown, path: string): RuntimeReportHaving {\n const raw = strictObject(value, path, ['measure', 'op', 'value']);\n const measure = alias(raw.measure, `${path}.measure`);\n const op = oneOf(raw.op, `${path}.op`, RUNTIME_REPORT_HAVING_OPS);\n if (typeof raw.value !== 'number' || !Number.isFinite(raw.value)) {\n fail(`${path}.value`, 'must be a finite number');\n }\n return { measure, op, value: raw.value };\n}\n\nfunction parseSort(value: unknown, path: string): RuntimeReportSort {\n const raw = strictObject(value, path, ['by', 'direction']);\n const by = alias(raw.by, `${path}.by`);\n const direction =\n raw.direction === undefined\n ? 'asc'\n : oneOf(raw.direction, `${path}.direction`, ['asc', 'desc'] as const);\n return { by, direction };\n}\n\n/**\n * Parse and normalize an untrusted spec (an object, or its JSON string form).\n *\n * Structural only: aliases are unique and well-formed, sort/having/chart refer\n * to aliases the spec itself declares, and every bound is enforced. Field,\n * source, permission and type checks happen at compile time because they\n * depend on the registry and the live principal.\n */\nexport function parseRuntimeReportSpec(input: unknown): RuntimeReportSpec {\n let candidate = input;\n if (typeof input === 'string') {\n if (input.length > 64 * 1024) fail('', 'spec JSON is too large');\n try {\n candidate = JSON.parse(input);\n } catch {\n fail('', 'spec is not valid JSON');\n }\n }\n const raw = strictObject(candidate, 'spec', [\n 'version',\n 'title',\n 'description',\n 'source',\n 'dimensions',\n 'measures',\n 'filters',\n 'having',\n 'sort',\n 'limit',\n 'chart',\n ]);\n if (\n raw.version !== undefined &&\n raw.version !== RUNTIME_REPORT_SPEC_VERSION\n ) {\n fail(\n 'spec.version',\n `unsupported version (expected ${RUNTIME_REPORT_SPEC_VERSION})`,\n );\n }\n const title = text(\n raw.title,\n 'spec.title',\n RUNTIME_REPORT_LIMITS.maxTitleLength,\n );\n const description = text(\n raw.description,\n 'spec.description',\n RUNTIME_REPORT_LIMITS.maxDescriptionLength,\n { optional: true },\n );\n if (\n typeof raw.source !== 'string' ||\n raw.source.length === 0 ||\n raw.source.length > RUNTIME_REPORT_LIMITS.maxSourceIdLength ||\n !SOURCE_PATTERN.test(raw.source)\n ) {\n fail('spec.source', 'must be a source id');\n }\n\n const dimensions = strictArray(\n raw.dimensions,\n 'spec.dimensions',\n RUNTIME_REPORT_LIMITS.maxDimensions,\n ).map((entry, index) => parseDimension(entry, `spec.dimensions[${index}]`));\n const measures = strictArray(\n raw.measures,\n 'spec.measures',\n RUNTIME_REPORT_LIMITS.maxMeasures,\n 1,\n ).map((entry, index) => parseMeasure(entry, `spec.measures[${index}]`));\n const filters = strictArray(\n raw.filters,\n 'spec.filters',\n RUNTIME_REPORT_LIMITS.maxFilters,\n ).map((entry, index) => parseFilter(entry, `spec.filters[${index}]`));\n const having = strictArray(\n raw.having,\n 'spec.having',\n RUNTIME_REPORT_LIMITS.maxHaving,\n ).map((entry, index) => parseHaving(entry, `spec.having[${index}]`));\n const sort = strictArray(\n raw.sort,\n 'spec.sort',\n RUNTIME_REPORT_LIMITS.maxSort,\n ).map((entry, index) => parseSort(entry, `spec.sort[${index}]`));\n\n const dimensionAliases = new Set<string>();\n const measureAliases = new Set<string>();\n const seen = new Set<string>();\n for (const [index, dimension] of dimensions.entries()) {\n if (seen.has(dimension.as)) {\n fail(`spec.dimensions[${index}].as`, `duplicate alias '${dimension.as}'`);\n }\n seen.add(dimension.as);\n dimensionAliases.add(dimension.as);\n }\n for (const [index, measure] of measures.entries()) {\n if (seen.has(measure.as)) {\n fail(`spec.measures[${index}].as`, `duplicate alias '${measure.as}'`);\n }\n seen.add(measure.as);\n measureAliases.add(measure.as);\n }\n for (const [index, entry] of having.entries()) {\n if (!measureAliases.has(entry.measure)) {\n fail(`spec.having[${index}].measure`, 'must be a declared measure alias');\n }\n }\n for (const [index, entry] of sort.entries()) {\n if (!seen.has(entry.by)) {\n fail(\n `spec.sort[${index}].by`,\n 'must be a declared dimension or measure alias',\n );\n }\n }\n\n let limit: number = RUNTIME_REPORT_LIMITS.defaultRowLimit;\n if (raw.limit !== undefined) {\n if (\n typeof raw.limit !== 'number' ||\n !Number.isSafeInteger(raw.limit) ||\n raw.limit < 1 ||\n raw.limit > RUNTIME_REPORT_LIMITS.maxRowLimit\n ) {\n fail(\n 'spec.limit',\n `must be an integer between 1 and ${RUNTIME_REPORT_LIMITS.maxRowLimit}`,\n );\n }\n limit = raw.limit;\n }\n\n let chart: RuntimeReportChart = { type: 'table' };\n if (raw.chart !== undefined) {\n const rawChart = strictObject(raw.chart, 'spec.chart', ['type', 'x', 'y']);\n const type = oneOf(\n rawChart.type,\n 'spec.chart.type',\n RUNTIME_REPORT_CHART_TYPES,\n );\n const x =\n rawChart.x === undefined ? undefined : alias(rawChart.x, 'spec.chart.x');\n if (x !== undefined && !dimensionAliases.has(x)) {\n fail('spec.chart.x', 'must be a declared dimension alias');\n }\n const y = strictArray(\n rawChart.y,\n 'spec.chart.y',\n RUNTIME_REPORT_LIMITS.maxMeasures,\n ).map((entry, index) => alias(entry, `spec.chart.y[${index}]`));\n for (const [index, name] of y.entries()) {\n if (!measureAliases.has(name)) {\n fail(`spec.chart.y[${index}]`, 'must be a declared measure alias');\n }\n }\n chart = { type, ...(x ? { x } : {}), ...(y.length > 0 ? { y } : {}) };\n }\n\n return {\n version: RUNTIME_REPORT_SPEC_VERSION,\n title,\n ...(description ? { description } : {}),\n source: raw.source as string,\n dimensions,\n measures,\n filters,\n having,\n sort,\n limit,\n chart,\n };\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [key, canonicalize(value[key])]),\n );\n }\n return value;\n}\n\n/** Stable fingerprint of a NORMALIZED spec; equal specs hash equally. */\nexport function runtimeReportSpecHash(spec: RuntimeReportSpec): string {\n return createHash('sha256')\n .update(JSON.stringify(canonicalize(spec)))\n .digest('hex');\n}\n\n/** Stable JSON text for storage (sorted keys). */\nexport function serializeRuntimeReportSpec(spec: RuntimeReportSpec): string {\n return JSON.stringify(canonicalize(spec));\n}\n","/**\n * Runtime report compiler and runner (#3711).\n *\n * `compileRuntimeReportSpec()` turns a parsed `RuntimeReportSpec` into the same\n * `AggregateSpec` the declared-report compiler targets, and\n * `runRuntimeReport()` executes it through the SDK `buildAggregate()` builder.\n * Nothing the spec says is ever interpolated into SQL text:\n *\n * - Source tables and columns come ONLY from the ObjectRegistry, resolved from\n * a server-owned source allow-list (`context.sources`). A spec names a\n * source id and registry field names; it can never name a table or column.\n * - Fields are admitted by the same exposure policy the report adapter uses:\n * sensitive/secret fields, `readPermission`-gated fields the live principal\n * lacks, transient/non-column/json fields, `_`-prefixed internals and the\n * tenant column are un-nameable. A hidden field is reported exactly like an\n * absent one so the compiler is not an existence oracle.\n * - Filter and having values travel as bound parameters through the SDK\n * `buildWhere()` builder, coerced to the field's type first.\n * - Output aliases are prefixed (`r_<alias>`) inside the SQL so they can never\n * collide with, shadow, or probe a source column.\n * - Tenant isolation is added explicitly (raw aggregates bypass the tenancy\n * interceptors) and fails closed: a tenant-scoped source with no tenant in\n * scope reads only NULL-tenant rows when tenancy is enabled. There is no\n * cross-tenant option.\n */\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\nimport { toSnakeCase } from '@happyvertical/smrt-core/utils';\nimport {\n getTenantId,\n isTenancyEnabled,\n isTenantScopedClass,\n} from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface, SqlAdapterType } from '@happyvertical/sql';\nimport { buildAggregate } from './aggregate.js';\nimport { adapterTypeFromDb, tenantColumn } from './refresh.js';\nimport {\n RUNTIME_REPORT_LIMITS,\n type RuntimeReportChart,\n RuntimeReportError,\n type RuntimeReportFilter,\n type RuntimeReportSpec,\n runtimeReportSpecHash,\n} from './runtime-spec.js';\nimport type { AggregateSelectExpr, AggregateSpec } from './types.js';\n\n/** A server-owned report source. The spec refers to it only by `id`. */\nexport interface RuntimeReportSourceDefinition {\n /** Opaque id the spec names; defaults to nothing, always explicit. */\n id: string;\n /** Registered `ObjectRegistry` class (qualified or bare name). */\n className: string;\n label?: string;\n /**\n * Permission-catalog collection SLUG the host authorizes reads against (the\n * `<collection>` in `<collection>.read`, not a class name). Informational\n * to the compiler; the host's `authorizeSource` consumes it.\n */\n collection?: string;\n description?: string;\n /** Canonical public field names to expose; omitted means all eligible fields. */\n fields?: readonly string[];\n /** Canonical public field names to remove; exclusions always win. */\n excludeFields?: readonly string[];\n}\n\nexport interface RuntimeReportCompileContext {\n /** Server-owned allow-list. A spec can reach nothing outside it. */\n sources: readonly RuntimeReportSourceDefinition[];\n /**\n * The live principal's permission slugs. A `readPermission`-gated field is\n * admitted only when its permission is present. Omitted means none.\n */\n permissions?: readonly string[];\n /**\n * Tenant to scope tenant-scoped sources to. Defaults to the ambient tenant\n * context. There is intentionally no way to widen this to other tenants.\n */\n tenantId?: string | null;\n /** Host authorization for reading the source (for example RBAC `read`). */\n authorizeSource?: (\n source: RuntimeReportSourceDefinition,\n ) => void | Promise<void>;\n}\n\nexport type RuntimeReportColumnType =\n | 'string'\n | 'integer'\n | 'decimal'\n | 'boolean'\n | 'datetime'\n | 'id';\n\nexport interface RuntimeReportColumn {\n id: string;\n label: string;\n role: 'dimension' | 'measure';\n type: RuntimeReportColumnType;\n /** Source field this column derives from (absent for a row count). */\n field?: string;\n fn?: string;\n bucket?: string;\n /** Field format hint carried from the model (for example `money`). */\n format?: string;\n}\n\nexport interface CompiledRuntimeReport {\n version: 1;\n specHash: string;\n spec: RuntimeReportSpec;\n source: {\n id: string;\n className: string;\n label: string;\n table: string;\n };\n columns: RuntimeReportColumn[];\n /** Aggregate plan; output aliases carry the internal `r_` prefix. */\n aggregate: AggregateSpec;\n limit: number;\n tenant: { scoped: boolean; tenantId: string | null };\n}\n\nexport interface RuntimeReportResult {\n version: 1;\n specHash: string;\n title: string;\n columns: RuntimeReportColumn[];\n rows: Record<string, string | number | boolean | null>[];\n rowCount: number;\n /** True when more rows existed than the spec/host limit. */\n truncated: boolean;\n ranAt: string;\n chart: RuntimeReportChart;\n}\n\nconst ALIAS_PREFIX = 'r_';\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\ninterface RegistryFieldShape {\n type?: string;\n transient?: boolean;\n sensitive?: boolean;\n sensitivity?: unknown;\n readPermission?: unknown;\n description?: unknown;\n format?: unknown;\n columnName?: string;\n _meta?: Record<string, unknown>;\n}\n\ninterface SourceField {\n name: string;\n column: string;\n type: RuntimeReportColumnType;\n format?: string;\n label: string;\n}\n\nfunction humanize(name: string): string {\n return name\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .replace(/^./, (value) => value.toUpperCase());\n}\n\nfunction columnTypeFor(\n type: string | undefined,\n): RuntimeReportColumnType | null {\n switch (type) {\n case 'text':\n return 'string';\n case 'integer':\n return 'integer';\n case 'decimal':\n return 'decimal';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'datetime';\n case 'foreignKey':\n case 'crossPackageRef':\n return 'id';\n default:\n return null;\n }\n}\n\nfunction explicitColumn(field: RegistryFieldShape): string | undefined {\n const metaColumn = field._meta?.columnName;\n if (typeof field.columnName === 'string') return field.columnName;\n return typeof metaColumn === 'string' ? metaColumn : undefined;\n}\n\nfunction strictFormat(field: RegistryFieldShape): string | undefined {\n const candidates = [field.format, field._meta?.format];\n return candidates.find(\n (value): value is string => typeof value === 'string' && value.length > 0,\n );\n}\n\n/**\n * Standard SMRT columns that exist on every object table. They are exposed\n * even when a class registers no explicit field for them.\n */\nconst BASE_FIELDS: Record<string, RuntimeReportColumnType> = {\n id: 'id',\n slug: 'string',\n createdAt: 'datetime',\n updatedAt: 'datetime',\n};\n\nfunction isExcluded(\n name: string,\n field: RegistryFieldShape,\n tenantField: string | null,\n permissions: ReadonlySet<string>,\n): boolean {\n if (name.startsWith('_')) return true;\n const meta = field._meta ?? {};\n if (field.transient === true || meta.transient === true) return true;\n const sensitivity = [field.sensitivity, meta.sensitivity].find(\n (value): value is string => typeof value === 'string',\n );\n if (\n field.sensitive === true ||\n meta.sensitive === true ||\n sensitivity === 'sensitive' ||\n sensitivity === 'secret'\n ) {\n return true;\n }\n const readPermission =\n typeof field.readPermission === 'string'\n ? field.readPermission\n : typeof meta.readPermission === 'string'\n ? meta.readPermission\n : undefined;\n if (readPermission && !permissions.has(readPermission)) return true;\n const tenancy = meta.__tenancy as { isTenantIdField?: boolean } | undefined;\n if (tenancy?.isTenantIdField === true) return true;\n if (name === 'tenantId' || name === 'tenant_id') return true;\n if (tenantField && toSnakeCase(name) === tenantField) return true;\n return false;\n}\n\nasync function loadSourceFields(\n qualifiedName: string,\n tenantField: string | null,\n permissions: ReadonlySet<string>,\n source: RuntimeReportSourceDefinition,\n): Promise<Map<string, SourceField>> {\n const registered = (await ObjectRegistry.getAllFields(qualifiedName)) as Map<\n string,\n RegistryFieldShape\n >;\n const baseNames = new Map(\n Object.keys(BASE_FIELDS).map((name) => [toSnakeCase(name), name]),\n );\n const columns = new Map<\n string,\n { name: string; field: RegistryFieldShape }[]\n >();\n for (const [name, field] of registered) {\n const column = toSnakeCase(explicitColumn(field) ?? name);\n const entries = columns.get(column) ?? [];\n entries.push({ name, field });\n columns.set(column, entries);\n }\n for (const [name, type] of Object.entries(BASE_FIELDS)) {\n const column = toSnakeCase(name);\n if (!columns.has(column) && !registered.has(name)) {\n columns.set(column, [\n {\n name,\n field: {\n type:\n type === 'id' ? 'foreignKey' : type === 'string' ? 'text' : type,\n },\n },\n ]);\n }\n }\n // Collapse base-column aliases before applying either model or host policy.\n // Any restriction on a physical column also protects its other spellings.\n const knownNames = new Set<string>();\n for (const [column, entries] of columns) {\n for (const entry of entries)\n knownNames.add(baseNames.get(column) ?? entry.name);\n }\n const policy = (key: 'fields' | 'excludeFields'): Set<string> | undefined => {\n const value = source[key];\n if (value === undefined) return undefined;\n if (\n !Array.isArray(value) ||\n Array.from(value).some(\n (name) => typeof name !== 'string' || !knownNames.has(name),\n )\n ) {\n throw new RuntimeReportError(\n 'unsupported_source',\n `source.${key}`,\n `${key} must contain canonical field names declared on the source`,\n );\n }\n return new Set(value);\n };\n const included = policy('fields');\n const excluded = policy('excludeFields');\n const fields = new Map<string, SourceField>();\n for (const [column, entries] of columns) {\n if (\n column === tenantField ||\n column === 'tenant_id' ||\n entries.some(\n ({ name, field }) =>\n isExcluded(name, field, tenantField, permissions) ||\n excluded?.has(baseNames.get(column) ?? name),\n )\n )\n continue;\n for (const { name: registeredName, field } of entries) {\n const name = baseNames.get(column) ?? registeredName;\n if (fields.has(name) || (included && !included.has(name))) continue;\n const type = columnTypeFor(field.type);\n if (!type) continue;\n const format = strictFormat(field);\n fields.set(name, {\n name,\n column,\n type,\n ...(format ? { format } : {}),\n label:\n typeof field.description === 'string' && field.description.length > 0\n ? field.description\n : humanize(name),\n });\n }\n }\n return fields;\n}\n\nfunction unknownField(path: string, name: string): never {\n throw new RuntimeReportError(\n 'unknown_field',\n path,\n `'${name}' is not a field available on this source`,\n );\n}\n\nfunction badOperation(path: string, message: string): never {\n throw new RuntimeReportError('invalid_operation', path, message);\n}\n\nfunction badValue(path: string, message: string): never {\n throw new RuntimeReportError('invalid_value', path, message);\n}\n\ntype Condition = Record<string, unknown>;\n\nconst OPERATORS_BY_TYPE: Record<\n RuntimeReportColumnType,\n readonly RuntimeReportFilter['op'][]\n> = {\n string: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'contains',\n 'isNull',\n 'isNotNull',\n ],\n integer: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isNull',\n 'isNotNull',\n ],\n decimal: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isNull',\n 'isNotNull',\n ],\n datetime: [\n 'eq',\n 'ne',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isNull',\n 'isNotNull',\n ],\n boolean: ['eq', 'ne', 'isNull', 'isNotNull'],\n id: ['eq', 'ne', 'in', 'notIn', 'isNull', 'isNotNull'],\n};\n\nfunction coerceValue(\n type: RuntimeReportColumnType,\n value: unknown,\n path: string,\n): string | number | boolean | Date {\n switch (type) {\n case 'string':\n if (typeof value !== 'string') badValue(path, 'must be a string');\n return value;\n case 'integer':\n if (typeof value !== 'number' || !Number.isSafeInteger(value)) {\n badValue(path, 'must be a safe integer');\n }\n return value;\n case 'decimal':\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n badValue(path, 'must be a finite number');\n }\n return value;\n case 'boolean':\n if (typeof value !== 'boolean') badValue(path, 'must be true or false');\n return value;\n case 'datetime': {\n if (typeof value !== 'string')\n badValue(path, 'must be an ISO-8601 string');\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime()) || !/^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n badValue(path, 'must be an ISO-8601 date or timestamp');\n }\n return parsed;\n }\n case 'id':\n if (typeof value !== 'string' || !UUID_PATTERN.test(value)) {\n badValue(path, 'must be a UUID');\n }\n return value.toLowerCase();\n }\n}\n\nfunction filterCondition(\n filter: RuntimeReportFilter,\n field: SourceField,\n path: string,\n): Condition {\n if (!OPERATORS_BY_TYPE[field.type].includes(filter.op)) {\n badOperation(\n `${path}.op`,\n `'${filter.op}' is not valid for ${field.type} fields`,\n );\n }\n const column = field.column;\n switch (filter.op) {\n case 'isNull':\n return { [column]: null };\n case 'isNotNull':\n return { [`${column} !=`]: null };\n case 'in':\n case 'notIn': {\n const values = (filter.value as unknown[]).map((entry, index) =>\n coerceValue(field.type, entry, `${path}.value[${index}]`),\n );\n return { [`${column} ${filter.op === 'in' ? 'in' : 'not in'}`]: values };\n }\n case 'contains':\n return {\n [`${column} contains`]: coerceValue(\n field.type,\n filter.value,\n `${path}.value`,\n ),\n };\n default: {\n const suffix = {\n eq: '',\n ne: ' !=',\n gt: ' >',\n gte: ' >=',\n lt: ' <',\n lte: ' <=',\n }[filter.op];\n return {\n [`${column}${suffix}`]: coerceValue(\n field.type,\n filter.value,\n `${path}.value`,\n ),\n };\n }\n }\n}\n\nfunction measureColumnType(\n fn: string,\n field: SourceField | undefined,\n): RuntimeReportColumnType {\n if (fn === 'count' || fn === 'countDistinct') return 'integer';\n if (fn === 'avg') return 'decimal';\n return field?.type ?? 'decimal';\n}\n\nfunction resolveSource(\n context: RuntimeReportCompileContext,\n id: string,\n): RuntimeReportSourceDefinition {\n const source = context.sources.find((candidate) => candidate.id === id);\n if (!source) {\n // Same answer for \"absent\" and \"not offered to this host/principal\".\n throw new RuntimeReportError(\n 'unknown_source',\n 'spec.source',\n `'${id}' is not an available report source`,\n );\n }\n return source;\n}\n\ninterface PreparedSource {\n source: RuntimeReportSourceDefinition;\n registeredName: string;\n qualifiedName: string;\n table: string;\n tenantCol: string | null;\n fields: Map<string, SourceField>;\n}\n\nasync function prepareSource(\n context: RuntimeReportCompileContext,\n id: string,\n): Promise<PreparedSource> {\n const source = resolveSource(context, id);\n await context.authorizeSource?.(source);\n\n const registered = ObjectRegistry.getClass(source.className);\n if (!registered) {\n throw new RuntimeReportError(\n 'unknown_source',\n 'spec.source',\n `'${id}' is not an available report source`,\n );\n }\n const qualifiedName = registered.qualifiedName ?? registered.name;\n const table = ObjectRegistry.getTableName(qualifiedName);\n if (!table) {\n throw new RuntimeReportError(\n 'unsupported_source',\n 'spec.source',\n 'this source has no registered table',\n );\n }\n\n const tenantCol = await tenantColumn(qualifiedName);\n if (isTenantScopedClass(qualifiedName) && !tenantCol) {\n throw new RuntimeReportError(\n 'unsupported_source',\n 'spec.source',\n 'this tenant-scoped source does not expose a tenant column',\n );\n }\n const fields = await loadSourceFields(\n qualifiedName,\n tenantCol,\n new Set(context.permissions ?? []),\n source,\n );\n return {\n source,\n registeredName: registered.name,\n qualifiedName,\n table,\n tenantCol,\n fields,\n };\n}\n\nexport interface RuntimeReportSourceDescription {\n id: string;\n label: string;\n description?: string;\n /** Fields the live principal may group by, filter on or aggregate. */\n fields: {\n name: string;\n label: string;\n type: RuntimeReportColumnType;\n format?: string;\n filterOperators: readonly string[];\n aggregates: readonly string[];\n }[];\n}\n\n/**\n * Describe what a spec may reference on one source for the live principal:\n * exactly the field set the compiler would admit, so a model never has to\n * guess names and never learns about hidden ones.\n */\nexport async function describeRuntimeReportSource(\n context: RuntimeReportCompileContext,\n sourceId: string,\n): Promise<RuntimeReportSourceDescription> {\n const prepared = await prepareSource(context, sourceId);\n return {\n id: prepared.source.id,\n label: prepared.source.label ?? humanize(prepared.registeredName),\n ...(prepared.source.description\n ? { description: prepared.source.description }\n : {}),\n fields: [...prepared.fields.values()].map((field) => ({\n name: field.name,\n label: field.label,\n type: field.type,\n ...(field.format ? { format: field.format } : {}),\n filterOperators: OPERATORS_BY_TYPE[field.type],\n aggregates: aggregatesFor(field.type),\n })),\n };\n}\n\nfunction aggregatesFor(type: RuntimeReportColumnType): readonly string[] {\n if (type === 'integer' || type === 'decimal') {\n return ['count', 'countDistinct', 'sum', 'avg', 'min', 'max'];\n }\n if (type === 'datetime') return ['count', 'countDistinct', 'min', 'max'];\n return ['count', 'countDistinct'];\n}\n\n/**\n * Validate a parsed spec against the registry, the live principal's field\n * policy, and tenancy, and compile it to an executable aggregate plan.\n */\nexport async function compileRuntimeReportSpec(\n spec: RuntimeReportSpec,\n context: RuntimeReportCompileContext,\n): Promise<CompiledRuntimeReport> {\n const { source, registeredName, qualifiedName, table, tenantCol, fields } =\n await prepareSource(context, spec.source);\n\n const lookup = (name: string, path: string): SourceField => {\n const field = fields.get(name);\n if (!field) unknownField(path, name);\n return field;\n };\n\n const columns: RuntimeReportColumn[] = [];\n const select: AggregateSelectExpr[] = [];\n const groupBy: string[] = [];\n\n for (const [index, dimension] of spec.dimensions.entries()) {\n const path = `spec.dimensions[${index}]`;\n const field = lookup(dimension.field, `${path}.field`);\n if (dimension.bucket && field.type !== 'datetime') {\n badOperation(\n `${path}.bucket`,\n 'buckets are only valid on datetime fields',\n );\n }\n const sqlAlias = `${ALIAS_PREFIX}${dimension.as}`;\n if (dimension.bucket) {\n select.push({\n bucket: dimension.bucket,\n column: field.column,\n as: sqlAlias,\n });\n } else {\n select.push({ column: field.column, as: sqlAlias });\n }\n groupBy.push(sqlAlias);\n columns.push({\n id: dimension.as,\n label: humanize(dimension.as),\n role: 'dimension',\n type: dimension.bucket ? 'datetime' : field.type,\n field: field.name,\n ...(dimension.bucket ? { bucket: dimension.bucket } : {}),\n ...(field.format && !dimension.bucket ? { format: field.format } : {}),\n });\n }\n\n for (const [index, measure] of spec.measures.entries()) {\n const path = `spec.measures[${index}]`;\n const field = measure.field\n ? lookup(measure.field, `${path}.field`)\n : undefined;\n if (\n (measure.fn === 'sum' || measure.fn === 'avg') &&\n field?.type !== 'integer' &&\n field?.type !== 'decimal'\n ) {\n badOperation(`${path}.fn`, `${measure.fn} requires a numeric field`);\n }\n if (\n (measure.fn === 'min' || measure.fn === 'max') &&\n field?.type !== 'integer' &&\n field?.type !== 'decimal' &&\n field?.type !== 'datetime'\n ) {\n badOperation(\n `${path}.fn`,\n `${measure.fn} requires a numeric or datetime field`,\n );\n }\n const sqlAlias = `${ALIAS_PREFIX}${measure.as}`;\n select.push({\n fn: measure.fn === 'countDistinct' ? 'count' : measure.fn,\n ...(field ? { column: field.column } : {}),\n as: sqlAlias,\n ...(measure.fn === 'countDistinct' ? { distinct: true } : {}),\n });\n const keepsFormat =\n field?.format &&\n (measure.fn === 'sum' ||\n measure.fn === 'min' ||\n measure.fn === 'max' ||\n measure.fn === 'avg');\n columns.push({\n id: measure.as,\n label: humanize(measure.as),\n role: 'measure',\n type: measureColumnType(measure.fn, field),\n ...(field ? { field: field.name } : {}),\n fn: measure.fn,\n ...(keepsFormat ? { format: field?.format } : {}),\n });\n }\n\n const conditions: Condition[] = [];\n\n // Tenancy: explicit, never widened. See module doc.\n const tenantId =\n context.tenantId !== undefined ? context.tenantId : (getTenantId() ?? null);\n if (tenantCol) {\n if (tenantId) {\n conditions.push({ [tenantCol]: tenantId });\n } else if (isTenancyEnabled() || isTenantScopedClass(qualifiedName)) {\n conditions.push({ [tenantCol]: null });\n }\n }\n\n // Soft delete: honour it when the source declares it.\n const registeredFields = (await ObjectRegistry.getAllFields(\n qualifiedName,\n )) as Map<string, RegistryFieldShape>;\n if (registeredFields.has('deletedAt')) conditions.push({ deleted_at: null });\n\n // STI child sources share a table with siblings: keep to the child's rows.\n if (ObjectRegistry.getTableStrategy(qualifiedName) === 'sti') {\n const base = ObjectRegistry.getSTIBase(qualifiedName);\n if (base !== null && base !== qualifiedName) {\n conditions.push({ _meta_type: qualifiedName });\n }\n }\n\n for (const [index, filter] of spec.filters.entries()) {\n const path = `spec.filters[${index}]`;\n const field = lookup(filter.field, `${path}.field`);\n conditions.push(filterCondition(filter, field, path));\n }\n\n const having: Condition[] = spec.having.map((entry) => {\n const suffix = {\n eq: '',\n ne: ' !=',\n gt: ' >',\n gte: ' >=',\n lt: ' <',\n lte: ' <=',\n }[entry.op];\n return { [`${ALIAS_PREFIX}${entry.measure}${suffix}`]: entry.value };\n });\n\n const orderBy = spec.sort.map(\n (entry) =>\n `${ALIAS_PREFIX}${entry.by} ${entry.direction === 'desc' ? 'DESC' : 'ASC'}`,\n );\n if (orderBy.length === 0 && spec.dimensions.length > 0) {\n orderBy.push(`${ALIAS_PREFIX}${spec.dimensions[0].as} ASC`);\n }\n\n const aggregate: AggregateSpec = {\n from: table,\n select,\n groupBy,\n ...(conditions.length > 0 ? { where: [conditions] } : {}),\n ...(having.length > 0 ? { having: [having] } : {}),\n ...(orderBy.length > 0 ? { orderBy } : {}),\n limit: Math.min(spec.limit, RUNTIME_REPORT_LIMITS.maxRowLimit) + 1,\n };\n\n return {\n version: 1,\n specHash: runtimeReportSpecHash(spec),\n spec,\n source: {\n id: source.id,\n className: qualifiedName,\n label: source.label ?? humanize(registeredName),\n table,\n },\n columns,\n aggregate,\n limit: spec.limit,\n tenant: {\n scoped: Boolean(tenantCol),\n tenantId: tenantCol ? tenantId : null,\n },\n };\n}\n\nfunction adaptWhere(\n where: AggregateSpec['where'],\n adapterType: SqlAdapterType,\n): AggregateSpec['where'] {\n if (!where || !Array.isArray(where)) return where;\n // SQLite binds booleans as integers; other adapters accept native booleans.\n const adapt = (value: unknown): unknown =>\n adapterType === 'sqlite' && typeof value === 'boolean'\n ? value\n ? 1\n : 0\n : value;\n return where.map((group) =>\n group.map((condition: Record<string, unknown>) =>\n Object.fromEntries(\n Object.entries(condition).map(([key, value]) => [\n key,\n Array.isArray(value) ? value.map(adapt) : adapt(value),\n ]),\n ),\n ),\n );\n}\n\nfunction normalizeCell(\n column: RuntimeReportColumn,\n value: unknown,\n): string | number | boolean | null {\n if (value === null || value === undefined) return null;\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'bigint') {\n const asNumber = Number(value);\n if (!Number.isSafeInteger(asNumber)) {\n throw new RuntimeReportError(\n 'invalid_result',\n column.id,\n 'integer result exceeds the JavaScript safe range',\n );\n }\n return asNumber;\n }\n if (column.type === 'boolean') {\n if (value === 1 || value === '1' || value === 'true' || value === true) {\n return true;\n }\n if (value === 0 || value === '0' || value === 'false' || value === false) {\n return false;\n }\n }\n if (column.type === 'integer' || column.type === 'decimal') {\n const numeric = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(numeric)) {\n throw new RuntimeReportError(\n 'invalid_result',\n column.id,\n 'numeric result is not finite',\n );\n }\n if (column.type === 'integer' && !Number.isSafeInteger(numeric)) {\n throw new RuntimeReportError(\n 'invalid_result',\n column.id,\n 'integer result exceeds the JavaScript safe range',\n );\n }\n return numeric;\n }\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n return String(value);\n}\n\nexport interface RunRuntimeReportOptions {\n db: DatabaseInterface;\n adapterType?: SqlAdapterType;\n /** Host row ceiling applied on top of the spec's own limit. */\n maxRows?: number;\n now?: () => Date;\n}\n\n/**\n * Execute a compiled plan. The caller owns authorization: compile with the\n * live principal each time rather than running a plan compiled for someone\n * else. Results are never cached here for exactly that reason.\n */\nexport async function runRuntimeReport(\n compiled: CompiledRuntimeReport,\n options: RunRuntimeReportOptions,\n): Promise<RuntimeReportResult> {\n const adapterType = adapterTypeFromDb(options.db, options.adapterType);\n const aggregate = buildAggregate(\n {\n ...compiled.aggregate,\n where: adaptWhere(compiled.aggregate.where, adapterType),\n },\n 1,\n adapterType,\n );\n const result = await options.db.query(aggregate.sql, ...aggregate.values);\n const rawRows = (result.rows ?? []) as Record<string, unknown>[];\n const limit = Math.min(\n compiled.limit,\n options.maxRows ?? RUNTIME_REPORT_LIMITS.maxRowLimit,\n );\n const truncated = rawRows.length > limit;\n const rows = rawRows.slice(0, limit).map((row) => {\n const out: Record<string, string | number | boolean | null> = {};\n for (const column of compiled.columns) {\n out[column.id] = normalizeCell(\n column,\n row[`${ALIAS_PREFIX}${column.id}`],\n );\n }\n return out;\n });\n return {\n version: 1,\n specHash: compiled.specHash,\n title: compiled.spec.title,\n columns: compiled.columns,\n rows,\n rowCount: rows.length,\n truncated,\n ranAt: (options.now?.() ?? new Date()).toISOString(),\n chart: compiled.spec.chart,\n };\n}\n","/** Server-owned authority and browser confirmation for runtime reports. */\nimport { getPackageConfig } from '@happyvertical/smrt-config';\nimport { runOnce } from '@happyvertical/smrt-core';\nimport { getCurrentTenant, withTenant } from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n compileRuntimeReportSpec,\n type RuntimeReportCompileContext,\n type RuntimeReportResult,\n type RuntimeReportSourceDefinition,\n} from './runtime-compiler.js';\nimport {\n getRuntimeReport,\n listRuntimeReports,\n runStoredRuntimeReport,\n saveRuntimeReport,\n} from './runtime-report.js';\nimport {\n parseRuntimeReportSpec,\n RuntimeReportError,\n type RuntimeReportSpec,\n runtimeReportSpecHash,\n} from './runtime-spec.js';\n\n/** Browser proposal; carries data, never proof or permission to write. */\nexport interface RuntimeReportAwaitingConfirmation {\n status: 'awaiting_confirmation';\n specHash: string;\n spec: RuntimeReportSpec;\n sourceLabel: string;\n preview: RuntimeReportResult;\n confirmPath: string;\n}\n\n/** Trusted session principal and its request-scoped database/transaction. */\nexport interface RuntimeReportPrincipal {\n db: DatabaseInterface;\n userId: string;\n tenantId: string;\n permissions: readonly string[];\n}\n\n/** A source must declare its permission-catalog slug, never a class name. */\nexport interface RuntimeReportServerSource\n extends RuntimeReportSourceDefinition {\n collection: string;\n}\n\n/** Host-owned configuration; never read it from a request body. */\nexport interface RuntimeReportServerOptions {\n sources: readonly RuntimeReportServerSource[];\n /** Called after a confirmed save (including a successful retry). */\n audit?: (entry: {\n action: 'confirm';\n userId: string;\n tenantId: string;\n specHash: string;\n reportId: string;\n reused: boolean;\n }) => unknown;\n}\n\n/** Public action failure with a stable HTTP status and code. */\nexport class RuntimeReportHttpError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = 'RuntimeReportHttpError';\n }\n}\n\nfunction isRuntimeReportAccessError(error: RuntimeReportError): boolean {\n return error.code === 'unknown_field' || error.code === 'unknown_source';\n}\n\n/** Require an authenticated tenant principal; do not honor system bypass. */\nexport function assertRuntimeReportPrincipal(\n context: RuntimeReportPrincipal | null | undefined,\n permission: string,\n): asserts context is RuntimeReportPrincipal {\n if (!context?.userId) {\n throw new RuntimeReportHttpError(\n 401,\n 'unauthenticated',\n 'Sign in required',\n );\n }\n const active = getCurrentTenant();\n if (\n !context.tenantId ||\n (active && active.tenantId !== context.tenantId) ||\n (active?.userId && active.userId !== context.userId) ||\n !context.permissions.includes(permission)\n ) {\n throw new RuntimeReportHttpError(403, 'forbidden', 'Report access denied');\n }\n}\n\n/** Narrow sources before compilation so hidden source ids cannot be probed. */\nexport function runtimeReportPrincipalCompileContext(\n options: RuntimeReportServerOptions,\n principal: RuntimeReportPrincipal,\n): RuntimeReportCompileContext {\n return {\n sources: options.sources.filter((source) =>\n principal.permissions.includes(`${source.collection}.read`),\n ),\n permissions: principal.permissions,\n tenantId: principal.tenantId,\n };\n}\n\n/**\n * Mount at POST /api/_reports/runtime/confirm. Context must come from the\n * verified server session, never the JSON body. The same request executor is\n * used for lookup and save, preserving an enclosing RLS transaction.\n */\nexport function createRuntimeReportConfirmHandler(\n options?: RuntimeReportServerOptions,\n): (\n request: Request,\n context: RuntimeReportPrincipal | null | undefined,\n) => Promise<Response> {\n return async (request, context) => {\n try {\n if (request.method !== 'POST') {\n return Response.json(\n { code: 'method_not_allowed' },\n {\n status: 405,\n headers: { Allow: 'POST' },\n },\n );\n }\n const origin = request.headers.get('origin');\n const site = request.headers.get('sec-fetch-site');\n if (\n (origin !== null && origin !== new URL(request.url).origin) ||\n (site !== null && site !== 'same-origin') ||\n (origin === null && site !== 'same-origin')\n ) {\n throw new RuntimeReportHttpError(\n 403,\n 'cross_origin',\n 'Same-origin request required',\n );\n }\n assertRuntimeReportPrincipal(context, 'runtimereports.create');\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n throw new RuntimeReportHttpError(\n 422,\n 'invalid_spec',\n 'Invalid JSON body',\n );\n }\n if (\n !body ||\n typeof body !== 'object' ||\n Array.isArray(body) ||\n Object.keys(body).some((key) => key !== 'spec' && key !== 'specHash')\n ) {\n throw new RuntimeReportHttpError(\n 422,\n 'invalid_spec',\n 'Expected spec and specHash',\n );\n }\n const input = body as { spec?: unknown; specHash?: unknown };\n const spec = parseRuntimeReportSpec(input.spec);\n const hash = runtimeReportSpecHash(spec);\n if (input.specHash !== hash) {\n throw new RuntimeReportHttpError(\n 422,\n 'spec_hash_mismatch',\n 'The approved spec hash does not match',\n );\n }\n const principal = context;\n return await withTenant(\n {\n tenantId: principal.tenantId,\n userId: principal.userId,\n permissions: new Set(principal.permissions),\n },\n async () => {\n const serverOptions = options ?? getRuntimeReportServerOptions();\n const transaction = principal.db.transaction?.bind(principal.db);\n if (!transaction) {\n throw new RuntimeReportHttpError(\n 500,\n 'transaction_required',\n 'Runtime report confirmation requires transaction support',\n );\n }\n // Read the active definition and retry generation in one snapshot.\n // Embedded adapters serialize this transaction with the durable claim;\n // an unscoped lookup could otherwise overlap a pending DuckDB query.\n const { existing, archived } = await transaction(async (tx) => {\n const lookup = {\n db: tx,\n tenantId: principal.tenantId,\n createdByUserId: principal.userId,\n specHash: hash,\n limit: 1,\n };\n const [existing] = await listRuntimeReports(lookup);\n const [archived] = existing\n ? []\n : await listRuntimeReports({\n ...lookup,\n status: 'archived',\n });\n return { existing, archived };\n });\n if (archived) {\n throw new RuntimeReportHttpError(\n 409,\n 'report_archived',\n 'Restore the archived report before confirming it again',\n );\n }\n // Compile even a retry: previously saved data grants no current\n // authority. Hidden sources/fields on an active retry are current\n // access revocation, while the same error on a new spec is invalid\n // input and remains a 422.\n let compiled: Awaited<ReturnType<typeof compileRuntimeReportSpec>>;\n try {\n compiled = await compileRuntimeReportSpec(\n spec,\n runtimeReportPrincipalCompileContext(serverOptions, principal),\n );\n } catch (error) {\n if (\n existing &&\n error instanceof RuntimeReportError &&\n isRuntimeReportAccessError(error)\n ) {\n throw new RuntimeReportHttpError(\n 403,\n 'forbidden',\n 'Report access denied',\n );\n }\n throw error;\n }\n let created = false;\n let report = existing\n ? { id: existing.id, specHash: hash, title: existing.title }\n : undefined;\n if (!report) {\n // The durable claim serializes simultaneous confirms across hosts.\n report = await runOnce(\n {\n db: principal.db,\n tenantId: principal.tenantId,\n actor: principal.userId,\n token: 'runtime-report-confirm',\n content: spec,\n },\n async (tx) => {\n // An in-process host may have saved between the outer lookup and\n // this transaction. It uses the same active-author/hash identity.\n const [current] = await listRuntimeReports({\n db: tx,\n tenantId: principal.tenantId,\n createdByUserId: principal.userId,\n specHash: hash,\n limit: 1,\n });\n const saved =\n current ??\n (await saveRuntimeReport({\n db: tx,\n tenantId: principal.tenantId,\n createdByUserId: principal.userId,\n compiled,\n confirmedSpecHash: hash,\n }));\n created = !current;\n if (!saved.id) throw new Error('Saved report has no id');\n return { id: saved.id, specHash: hash, title: saved.title };\n },\n );\n }\n if (!report.id) throw new Error('Saved report has no id');\n await serverOptions.audit?.({\n action: 'confirm',\n userId: principal.userId,\n tenantId: principal.tenantId,\n specHash: hash,\n reportId: report.id,\n reused: !created,\n });\n return Response.json(\n { id: report.id, specHash: hash, title: report.title },\n {\n status: created ? 201 : 200,\n headers: { 'Cache-Control': 'no-store' },\n },\n );\n },\n );\n } catch (error) {\n if (\n error instanceof RuntimeReportHttpError ||\n error instanceof RuntimeReportError\n ) {\n return Response.json(\n { code: error.code, message: error.message },\n {\n status: error instanceof RuntimeReportError ? 422 : error.status,\n headers: { 'Cache-Control': 'no-store' },\n },\n );\n }\n // Database/provider errors can contain connection details; never echo them.\n return Response.json(\n { code: 'internal_error', message: 'Unable to confirm report' },\n {\n status: 500,\n headers: { 'Cache-Control': 'no-store' },\n },\n );\n }\n };\n}\n\n/** Runtime source allow-list configured in packages.reports.runtime.sources. */\nexport function getRuntimeReportServerOptions(): RuntimeReportServerOptions {\n const config = getPackageConfig<{ runtime?: RuntimeReportServerOptions }>(\n 'reports',\n );\n return config.runtime ?? { sources: [] };\n}\n\n/** Obtain authority from the authenticated execution scope, never model options. */\nexport function currentRuntimeReportPrincipal(\n db: DatabaseInterface,\n): RuntimeReportPrincipal {\n const context = getCurrentTenant();\n return {\n db,\n userId: context?.userId ?? '',\n tenantId: context?.tenantId ?? '',\n permissions: [...(context?.permissions ?? [])],\n };\n}\n\n/** Run a saved report as this viewer, without persisting result rows. */\nexport async function runRuntimeReportForPrincipal(\n ref: string,\n principal: RuntimeReportPrincipal,\n options: RuntimeReportServerOptions = getRuntimeReportServerOptions(),\n): Promise<RuntimeReportResult> {\n assertRuntimeReportPrincipal(principal, 'runtimereports.read');\n return withTenant(\n {\n tenantId: principal.tenantId,\n userId: principal.userId,\n permissions: new Set(principal.permissions),\n },\n async () => {\n const report = await getRuntimeReport({\n db: principal.db,\n ref,\n tenantId: principal.tenantId,\n });\n if (!report)\n throw new RuntimeReportHttpError(404, 'not_found', 'Report not found');\n if (report.status === 'archived') {\n throw new RuntimeReportHttpError(\n 409,\n 'report_archived',\n 'Restore the archived report before running it',\n );\n }\n try {\n return await runStoredRuntimeReport({\n db: principal.db,\n report,\n context: runtimeReportPrincipalCompileContext(options, principal),\n });\n } catch (error) {\n if (error instanceof RuntimeReportError) {\n if (isRuntimeReportAccessError(error)) {\n throw new RuntimeReportHttpError(\n 403,\n 'forbidden',\n 'Report access denied',\n );\n }\n throw new RuntimeReportHttpError(422, error.code, error.message);\n }\n throw error;\n }\n },\n );\n}\n\n/** Change only the saved status under the tenant writer's authority. */\nexport async function archiveRuntimeReportForPrincipal(\n ref: string,\n archived: boolean,\n principal: RuntimeReportPrincipal,\n): Promise<{ id: string; status: 'active' | 'archived' }> {\n assertRuntimeReportPrincipal(principal, 'runtimereports.create');\n if (typeof archived !== 'boolean') {\n throw new RuntimeReportHttpError(\n 422,\n 'invalid_value',\n 'archived must be a boolean',\n );\n }\n return withTenant(\n {\n tenantId: principal.tenantId,\n userId: principal.userId,\n permissions: new Set(principal.permissions),\n },\n async () => {\n const report = await getRuntimeReport({\n db: principal.db,\n ref,\n tenantId: principal.tenantId,\n });\n if (!report?.id)\n throw new RuntimeReportHttpError(404, 'not_found', 'Report not found');\n const status = archived ? 'archived' : 'active';\n if (report.status !== status) {\n report.status = status;\n await report.save();\n }\n return { id: report.id, status };\n },\n );\n}\n\n/** Recipe loader; context.reportPrincipal is supplied by the server host. */\nexport async function loadRuntimeReportChart(\n options: Record<string, unknown>,\n context: { reportPrincipal?: RuntimeReportPrincipal; currency?: string },\n): Promise<{\n points: { label: string; value: number }[];\n format: 'integer' | 'decimal' | 'money';\n currency?: string;\n href: string;\n}> {\n assertRuntimeReportPrincipal(context.reportPrincipal, 'runtimereports.read');\n if (\n typeof options.reportId !== 'string' ||\n typeof options.measure !== 'string'\n ) {\n throw new RuntimeReportHttpError(\n 422,\n 'invalid_value',\n 'Select a report and measure',\n );\n }\n const result = await runRuntimeReportForPrincipal(\n options.reportId,\n context.reportPrincipal,\n );\n const measure = result.columns.find(\n (column) => column.id === options.measure && column.role === 'measure',\n );\n const dimension =\n options.dimension === undefined\n ? result.columns.find((column) => column.role === 'dimension')\n : result.columns.find(\n (column) =>\n column.id === options.dimension && column.role === 'dimension',\n );\n if (!measure || (options.dimension !== undefined && !dimension)) {\n throw new RuntimeReportHttpError(\n 422,\n 'invalid_value',\n 'Invalid report measure or dimension',\n );\n }\n const points = result.rows.map((row) => {\n const value = row[measure.id];\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new RuntimeReportHttpError(\n 422,\n 'invalid_result',\n 'Chart requires numeric measures',\n );\n }\n return {\n label: dimension ? String(row[dimension.id] ?? '') : result.title,\n value,\n };\n });\n return {\n points,\n format:\n measure.format === 'money'\n ? 'money'\n : measure.type === 'integer'\n ? 'integer'\n : 'decimal',\n ...(context.currency ? { currency: context.currency } : {}),\n href: `/reports/${encodeURIComponent(options.reportId)}`,\n };\n}\n","import './__smrt-register__.js';\n\n/**\n * Stored runtime report definitions (#3711).\n *\n * A `RuntimeReport` row is a validated {@link RuntimeReportSpec} saved as data.\n * It carries NO authority: the spec is re-parsed on every read and re-compiled\n * against the live principal's field policy, permissions and tenant on every\n * run, so a stored report can never expose more than its current viewer may\n * see. Result rows are deliberately never persisted (a cached result computed\n * for one principal must not be served to another).\n *\n * The assistant creates rows through {@link saveRuntimeReport}, so only a spec\n * that compiled for the saving principal and was confirmed by a human is\n * stored. That is enforced HERE, in the model layer, not just by which\n * surfaces are generated: `validateBeforeSave()` refuses every insert, and\n * every update that changes the spec (or title, source, description or author),\n * unless the instance carries a confirmation proof that only\n * {@link saveRuntimeReport} can attach. Rows built from JSON (a REST body, a\n * manifest tool call) cannot carry the proof, so they are refused whatever\n * surface delivered them. Archiving (a `status` change with the spec\n * untouched) stays allowed. The generated surfaces expose `list`/`get`, plus\n * `create` on the API only so the permission catalog and Postgres RLS bindings\n * know the operation the confirmed save performs.\n */\n\nimport {\n field,\n SmrtCollection,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n type CompiledRuntimeReport,\n compileRuntimeReportSpec,\n type RuntimeReportCompileContext,\n type RuntimeReportResult,\n runRuntimeReport,\n} from './runtime-compiler.js';\nimport {\n archiveRuntimeReportForPrincipal,\n currentRuntimeReportPrincipal,\n runRuntimeReportForPrincipal,\n} from './runtime-server.js';\nimport {\n parseRuntimeReportSpec,\n RuntimeReportError,\n type RuntimeReportSpec,\n runtimeReportSpecHash,\n serializeRuntimeReportSpec,\n} from './runtime-spec.js';\n\nexport type RuntimeReportStatus = 'active' | 'archived';\n\n/**\n * Confirmation proof carried on a constructor option. A symbol key can never\n * arrive from JSON (REST body, manifest tool arguments), and the symbol is not\n * exported, so only code in this module can mint a row that may be written.\n */\nconst CONFIRMED_SAVE = Symbol('smrt-reports.runtimeReport.confirmedSave');\n\n/** Instance -> spec hash a human confirmed for this exact write. */\nconst confirmedSaves = new WeakMap<object, string>();\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: 'runtime_reports',\n indexes: [\n {\n name: 'idx_runtime_reports_confirm',\n columns: ['tenantId', 'createdByUserId', 'specHash', 'status'],\n },\n ],\n operationPermissions: {\n run: { action: 'read' },\n archive: { action: 'create', databaseActions: ['SELECT', 'UPDATE'] },\n },\n // Raw create exists to catalog the confirmed-save grant; model validation\n // still refuses every JSON-authored insert. Custom methods reuse the read\n // and create grants; no general update/delete operation is exposed.\n api: {\n include: ['list', 'get', 'create', 'run', 'archive'],\n principalContext: true,\n routes: {\n run: {\n method: 'POST',\n scope: 'item',\n effect: 'read',\n idempotent: true,\n openWorld: false,\n },\n archive: {\n method: 'POST',\n scope: 'item',\n effect: 'write',\n idempotent: true,\n openWorld: false,\n },\n },\n },\n mcp: { include: ['list', 'get', 'run', 'archive'] },\n cli: { include: ['list', 'get', 'run', 'archive'] },\n})\nexport class RuntimeReport extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-reports\";\n @tenantId()\n tenantId: string = '';\n\n @field({ type: 'text' })\n title: string = '';\n\n @field({ type: 'text' })\n description: string = '';\n\n /** Source id the spec names; resolved against a host allow-list at run. */\n @field({ type: 'text' })\n sourceId: string = '';\n\n /** Normalized spec JSON; use {@link getSpec}/{@link setSpec}. */\n @field({ type: 'text', required: true })\n spec: string = '';\n\n /** Hash of the normalized spec; detects out-of-band edits to `spec`. */\n @field({ type: 'text' })\n specHash: string = '';\n\n @field({ type: 'text', required: true })\n status: RuntimeReportStatus = 'active';\n\n /** Principal that saved the report (an id string; not a foreign key). */\n @field({ type: 'text' })\n createdByUserId: string = '';\n\n constructor(options: SmrtObjectOptions = {}) {\n super(options);\n const proof = (options as Record<symbol, unknown>)[CONFIRMED_SAVE];\n if (typeof proof === 'string') confirmedSaves.set(this, proof);\n }\n\n /** Run fresh totals using the authenticated viewer's current permissions. */\n async run(): Promise<RuntimeReportResult> {\n return runRuntimeReportForPrincipal(\n this.id ?? '',\n currentRuntimeReportPrincipal(this.db),\n );\n }\n\n /** Archive or restore this definition; no report content can be changed. */\n async archive(options: {\n archived: boolean;\n }): Promise<{ id: string; status: RuntimeReportStatus }> {\n return archiveRuntimeReportForPrincipal(\n this.id ?? '',\n options?.archived,\n currentRuntimeReportPrincipal(this.db),\n );\n }\n\n /** Re-parse the stored JSON; never trust the column without validation. */\n getSpec(): RuntimeReportSpec {\n const parsed = parseRuntimeReportSpec(this.spec);\n if (runtimeReportSpecHash(parsed) !== this.specHash) {\n throw new RuntimeReportError(\n 'invalid_spec',\n 'spec',\n 'stored spec does not match its recorded hash',\n );\n }\n return parsed;\n }\n\n setSpec(spec: RuntimeReportSpec): void {\n const normalized = parseRuntimeReportSpec(spec);\n this.spec = serializeRuntimeReportSpec(normalized);\n this.specHash = runtimeReportSpecHash(normalized);\n this.title = normalized.title;\n this.description = normalized.description ?? '';\n this.sourceId = normalized.source;\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n // Parse whatever was supplied (REST body, service, direct assignment) and\n // re-derive every denormalized column from it, so the columns can never\n // disagree with the spec that runs.\n const parsed = parseRuntimeReportSpec(this.spec);\n await this.assertConfirmedWrite(parsed);\n this.setSpec(parsed);\n if (this.status !== 'active' && this.status !== 'archived') {\n throw new RuntimeReportError('invalid_spec', 'status', 'is invalid');\n }\n }\n\n /**\n * Invariant: a RuntimeReport row is inserted, or has its spec/title/source/\n * description/author changed, only by the confirmed-save path. Anything else\n * (REST `create` body, manifest tool args, `new RuntimeReport().save()`,\n * `collection.update()` of the spec) is refused here. A save that leaves those\n * columns as stored (an archive/unarchive status change) needs no proof.\n */\n private async assertConfirmedWrite(parsed: RuntimeReportSpec): Promise<void> {\n const hash = runtimeReportSpecHash(parsed);\n const proof = confirmedSaves.get(this);\n if (proof !== undefined) {\n // Single use: the proof covers exactly one write of this exact spec.\n confirmedSaves.delete(this);\n if (proof === hash) return;\n } else if (this.isPersisted && this.id) {\n const stored = (await this.db.get(this.tableName, { id: this.id })) as {\n spec_hash?: unknown;\n title?: unknown;\n description?: unknown;\n source_id?: unknown;\n created_by_user_id?: unknown;\n } | null;\n if (\n stored &&\n stored.spec_hash === hash &&\n (stored.title ?? '') === parsed.title &&\n (stored.description ?? '') === (parsed.description ?? '') &&\n (stored.source_id ?? '') === parsed.source &&\n (stored.created_by_user_id ?? '') === (this.createdByUserId ?? '')\n ) {\n return;\n }\n }\n throw new RuntimeReportError(\n 'confirmation_required',\n 'spec',\n 'a runtime report can only be created or changed through the confirmed save of reports.runtime.define; the write was refused',\n );\n }\n}\n\nexport class RuntimeReportCollection extends SmrtCollection<RuntimeReport> {\n static readonly _itemClass = RuntimeReport;\n}\n\nexport interface RuntimeReportStoreOptions {\n db: DatabaseInterface;\n}\n\nexport interface SaveRuntimeReportOptions extends RuntimeReportStoreOptions {\n /** A plan compiled for the SAVING principal; the only accepted input. */\n compiled: CompiledRuntimeReport;\n /**\n * The spec hash a human confirmed (the value handed to the application's\n * confirmation host). It must equal the compiled plan's hash; the row is\n * only minted when it does. Call this ONLY after that confirmation resolved.\n */\n confirmedSpecHash: string;\n createdByUserId: string;\n /** Defaults to the tenant the plan was compiled for, then ambient. */\n tenantId?: string | null;\n}\n\nasync function collectionFor(\n db: DatabaseInterface,\n): Promise<RuntimeReportCollection> {\n return RuntimeReportCollection.create({\n db,\n }) as Promise<RuntimeReportCollection>;\n}\n\n/** Persist a spec that has already compiled for the saving principal. */\nexport async function saveRuntimeReport(\n options: SaveRuntimeReportOptions,\n): Promise<RuntimeReport> {\n const tenant =\n options.tenantId ?? options.compiled.tenant.tenantId ?? getTenantId() ?? '';\n if (!tenant) {\n throw new RuntimeReportError(\n 'tenant_required',\n '',\n 'a tenant is required to save a runtime report',\n );\n }\n const spec = parseRuntimeReportSpec(options.compiled.spec);\n const specHash = runtimeReportSpecHash(spec);\n if (specHash !== options.compiled.specHash) {\n throw new RuntimeReportError(\n 'invalid_spec',\n 'spec',\n 'compiled plan does not match its spec',\n );\n }\n if (options.confirmedSpecHash !== specHash) {\n throw new RuntimeReportError(\n 'confirmation_required',\n 'specHash',\n 'the confirmed spec hash does not match the spec; the report was not saved',\n );\n }\n const collection = await collectionFor(options.db);\n return collection.create({\n tenantId: tenant,\n title: spec.title,\n description: spec.description ?? '',\n sourceId: spec.source,\n spec: serializeRuntimeReportSpec(spec),\n specHash,\n status: 'active',\n createdByUserId: options.createdByUserId,\n // The only place a confirmation proof is minted; see CONFIRMED_SAVE.\n [CONFIRMED_SAVE]: specHash,\n } as Parameters<RuntimeReportCollection['create']>[0]);\n}\n\nexport async function getRuntimeReport(\n options: RuntimeReportStoreOptions & {\n ref: string;\n /**\n * Explicit owner tenant. When given, a row owned by any other tenant is\n * treated as absent even if the ambient tenant context would admit it\n * (a host that knows the principal's tenant should always pass it).\n */\n tenantId?: string;\n },\n): Promise<RuntimeReport | null> {\n const collection = await collectionFor(options.db);\n const report = await collection.get(options.ref);\n if (report && options.tenantId && report.tenantId !== options.tenantId) {\n return null;\n }\n return report;\n}\n\nexport async function listRuntimeReports(\n options: RuntimeReportStoreOptions & {\n status?: RuntimeReportStatus;\n limit?: number;\n /** Explicit owner tenant; filters in addition to the ambient context. */\n tenantId?: string;\n /** Exact author filter, applied before the result limit; never grants authority. */\n createdByUserId?: string;\n /** Exact normalized spec hash from the public runtime report compiler. */\n specHash?: string;\n },\n): Promise<RuntimeReport[]> {\n const collection = await collectionFor(options.db);\n return collection.list({\n where: {\n status: options.status ?? 'active',\n ...(options.tenantId ? { tenantId: options.tenantId } : {}),\n ...(options.createdByUserId !== undefined\n ? { createdByUserId: options.createdByUserId }\n : {}),\n ...(options.specHash !== undefined ? { specHash: options.specHash } : {}),\n },\n orderBy: 'created_at DESC',\n limit: Math.min(Math.max(options.limit ?? 50, 1), 200),\n });\n}\n\nexport async function archiveRuntimeReport(\n options: RuntimeReportStoreOptions & { ref: string },\n): Promise<RuntimeReport | null> {\n const report = await getRuntimeReport(options);\n if (!report) return null;\n report.status = 'archived';\n await report.save();\n return report;\n}\n\n/**\n * Re-validate a stored report against the live principal and run it. The\n * stored spec is parsed again and compiled with the caller's context, so\n * policy changes made after the report was saved apply immediately.\n */\nexport async function runStoredRuntimeReport(\n options: RuntimeReportStoreOptions & {\n report: RuntimeReport;\n context: RuntimeReportCompileContext;\n maxRows?: number;\n },\n): Promise<RuntimeReportResult> {\n if (options.report.status !== 'active') {\n throw new RuntimeReportError(\n 'invalid_spec',\n 'status',\n 'report is archived',\n );\n }\n const compiled = await compileRuntimeReportSpec(\n options.report.getSpec(),\n options.context,\n );\n return runRuntimeReport(compiled, {\n db: options.db,\n maxRows: options.maxRows,\n });\n}\n","/**\n * Declared recipes for smrt-reports (#3719): user-facing units of\n * functionality an app or agent can pick instead of the whole package.\n * The scanner reads these statics into the `recipes` array of `manifest.json`\n * and `smrt-knowledge.json`; nothing here runs at that point.\n *\n * `reports.materialized` brings the refresh bookkeeping tables a declared\n * (`@report`) report needs. The report classes themselves belong to the app, so\n * they are not listed here. It declares no surfaces: this package ships no\n * Svelte components, and the assistant reaches declared reports through the\n * `reports.query` tools in `@happyvertical/smrt-agents`.\n *\n * @packageDocumentation\n */\n\nimport { SmrtRecipe } from '@happyvertical/smrt-core';\nimport { RuntimeReport } from './runtime-report.js';\nimport {\n SmrtPrincipalReportRefreshTask,\n SmrtReportRefreshTask,\n} from './scheduler.js';\nimport {\n SmrtReportLock,\n SmrtReportRun,\n SmrtReportSchedule,\n SmrtReportWatermark,\n} from './state.js';\n\n/** Reports: totals and trends kept ready to read, refreshed on a schedule. */\nexport class MaterializedReportsRecipe extends SmrtRecipe {\n static id = 'reports.materialized';\n static help = './materialized.recipe.md';\n static label = 'Reports';\n static summary =\n 'Keep totals and trends ready to read, refreshed on a schedule and open to the assistant.';\n static synonyms = [\n 'reports',\n 'totals',\n 'summaries',\n 'rollups',\n 'kpis',\n 'trends',\n 'dashboards',\n ];\n // Refresh bookkeeping only. Every table is internal (`_smrt_` prefix, no REST\n // or MCP surface), so there is no `nav`; the app's own `@report` classes bring\n // their own rows and views.\n static models = [\n SmrtReportRun,\n SmrtReportWatermark,\n SmrtReportLock,\n SmrtReportSchedule,\n SmrtReportRefreshTask,\n SmrtPrincipalReportRefreshTask,\n ];\n // Aggregation runs as SQL against the app database, and scheduled refreshes\n // are queued through smrt-jobs; neither can run in a browser.\n static runtime = 'server' as const;\n}\n\n/** Tenant-shared reports proposed by the assistant and approved by a person. */\nexport class RuntimeReportsRecipe extends SmrtRecipe {\n static id = 'reports.runtime';\n static label = 'Reports';\n static summary =\n 'Ask for a report, approve it, and share its live totals with your team.';\n static help = './runtime.recipe.md';\n static models = [RuntimeReport];\n static nav = [{ label: 'Reports', model: RuntimeReport, icon: 'fileText' }];\n static surfaces = [\n {\n kind: 'route',\n path: '/reports',\n export: '@happyvertical/smrt-reports/svelte#RuntimeReportsRoute',\n label: 'Reports',\n },\n {\n kind: 'route',\n path: '/reports/:id',\n export: '@happyvertical/smrt-reports/svelte#RuntimeReportDetailRoute',\n label: 'Report detail',\n },\n {\n kind: 'widget',\n type: 'runtime-report-chart',\n export: '@happyvertical/smrt-reports/svelte#RuntimeReportChartWidget',\n label: 'Report chart',\n description: 'Chart a measure from a saved report.',\n icon: 'chart',\n optionsEditor:\n '@happyvertical/smrt-reports/svelte#RuntimeReportWidgetOptions',\n options: [\n { key: 'reportId', type: 'text', label: 'Report', required: true },\n {\n key: 'measure',\n type: 'identifier',\n label: 'Measure',\n required: true,\n },\n { key: 'dimension', type: 'identifier', label: 'Dimension' },\n ],\n data: {\n load: '@happyvertical/smrt-reports#loadRuntimeReportChart',\n models: ['@happyvertical/smrt-reports:RuntimeReport'],\n },\n defaultSpan: 2,\n maxSpan: 4,\n },\n ] as const;\n static runtime = 'server' as const;\n}\n","import {\n ObjectRegistry,\n SmrtCollection,\n type SmrtListOptions,\n SmrtObject,\n type SmrtObjectOptions,\n type SmrtSelectedRow,\n type SmrtSelectField,\n type SmrtStiReadScope,\n} from '@happyvertical/smrt-core';\nimport { toSnakeCase } from '@happyvertical/smrt-core/utils';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { validateColumnName } from '@happyvertical/sql';\nimport { buildReportDefinition } from './compiler.js';\nimport { refreshReport } from './refresh.js';\nimport type { ReportRefreshOptions, ReportRefreshResult } from './types.js';\n\ntype RegistryField = {\n columnName?: string;\n _meta?: {\n columnName?: string;\n __tenancy?: { isTenantIdField?: boolean };\n };\n};\n\nfunction registryColumnName(fieldName: string, field?: RegistryField): string {\n return validateColumnName(\n field?.columnName ?? field?._meta?.columnName ?? toSnakeCase(fieldName),\n );\n}\n\nfunction findFieldColumn(\n fields: Map<string, RegistryField>,\n fieldName: string,\n): string {\n const direct = fields.get(fieldName);\n if (direct) return registryColumnName(fieldName, direct);\n const requestedColumn = toSnakeCase(fieldName);\n for (const [name, field] of fields.entries()) {\n if (toSnakeCase(name) === requestedColumn) {\n return registryColumnName(name, field);\n }\n }\n return validateColumnName(requestedColumn);\n}\n\nfunction findTenantColumn(\n fields: Map<string, RegistryField>,\n configuredField?: string,\n): string | null {\n if (configuredField) {\n return registryColumnName(configuredField, fields.get(configuredField));\n }\n for (const [fieldName, field] of fields.entries()) {\n if (fieldName === 'tenantId' || field?._meta?.__tenancy?.isTenantIdField) {\n return registryColumnName(fieldName, field);\n }\n }\n return null;\n}\n\nexport class SmrtReport extends SmrtObject {\n static readonly _isReportBase = true as const;\n\n refreshedAt: Date | null = null;\n\n constructor(options: SmrtObjectOptions = {}) {\n super(options);\n if (options.refreshedAt !== undefined) {\n this.refreshedAt =\n options.refreshedAt instanceof Date\n ? options.refreshedAt\n : options.refreshedAt\n ? new Date(options.refreshedAt)\n : null;\n }\n }\n\n isStale(ttlMs?: number): boolean {\n if (!this.refreshedAt) return true;\n if (ttlMs === undefined) return false;\n return Date.now() - this.refreshedAt.getTime() > ttlMs;\n }\n\n async refresh(\n options: Omit<ReportRefreshOptions, 'db'> = {},\n ): Promise<ReportRefreshResult> {\n const result = await refreshReport(this.constructor as typeof SmrtReport, {\n ...options,\n db: this.db,\n });\n this.refreshedAt = result.refreshedAt;\n return result;\n }\n}\n\nexport class SmrtReportCollection<\n ModelType extends SmrtReport,\n> extends SmrtCollection<ModelType> {\n private async refreshIfStale(): Promise<void> {\n const reportCtor = this.getItemClass();\n const definition = await buildReportDefinition(reportCtor);\n const refresh = definition.refresh;\n if (!refresh?.ttl || refresh.manual) return;\n\n const registered =\n ObjectRegistry.getClassByConstructor(reportCtor) ??\n ObjectRegistry.getClass(reportCtor.name);\n const reportClass =\n registered?.qualifiedName ?? registered?.name ?? reportCtor.name;\n const tableName = ObjectRegistry.getTableName(reportClass);\n if (!tableName) return;\n\n const fields = (await ObjectRegistry.getAllFields(reportClass)) as Map<\n string,\n RegistryField\n >;\n const safeTableName = validateColumnName(tableName);\n const refreshedAtColumn = findFieldColumn(fields, 'refreshedAt');\n const tenantColumn = findTenantColumn(\n fields,\n registered?.tenantScopedConfig?.field,\n );\n const tenantId = getTenantId() ?? null;\n const result = tenantColumn\n ? await this.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${safeTableName} WHERE ${tenantColumn} ${tenantId ? '= ?' : 'IS NULL'}`,\n ...(tenantId ? [tenantId] : []),\n )\n : await this.db.query(\n `SELECT MAX(${refreshedAtColumn}) AS refreshed_at FROM ${safeTableName}`,\n );\n const refreshedAt = result.rows[0]?.refreshed_at\n ? new Date(result.rows[0].refreshed_at as string)\n : null;\n const stale =\n !refreshedAt || Date.now() - refreshedAt.getTime() > refresh.ttl;\n if (!stale) return;\n\n await refreshReport(reportCtor, {\n db: this.db,\n mode: refresh.mode ?? 'rebuild',\n trigger: 'ttl',\n tenantId,\n });\n }\n\n async refresh(\n options: Omit<ReportRefreshOptions, 'db'> = {},\n ): Promise<ReportRefreshResult> {\n return refreshReport(this.getItemClass(), {\n ...options,\n db: this.db,\n });\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<ModelType>[],\n >(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<Record<string, unknown>[]>;\n override async list<\n const Select extends readonly SmrtSelectField<ModelType>[],\n >(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<ModelType, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<ModelType[]>;\n override async list(\n options: Omit<SmrtListOptions<ModelType>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<ModelType[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<ModelType>, 'select'> & { select?: undefined })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<ModelType> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<ModelType> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n await this.refreshIfStale();\n return super.list(options);\n }\n\n override async get(\n filter: Parameters<SmrtCollection<ModelType>['get']>[0],\n options: Parameters<SmrtCollection<ModelType>['get']>[1] = {},\n ): Promise<ModelType | null> {\n await this.refreshIfStale();\n return super.get(filter, options);\n }\n}\n","/**\n * Saved report-view and export contracts.\n *\n * This module owns only the serializable report boundary. Applications own\n * durable view storage, principal binding, authorization, auditing, artifact\n * storage, download tokens, and background-job execution.\n */\nimport { createHash } from 'node:crypto';\nimport {\n createDataQueryFingerprint,\n normalizeDataQueryRequest,\n} from '@happyvertical/smrt-core';\nimport type {\n DataQueryFreshness,\n DataQueryRequest,\n DataQueryResult,\n DataQuerySort,\n} from '@happyvertical/smrt-types';\nimport {\n type ReportAdapterDescriptor,\n type ReportColumnCapability,\n type ReportDataQueryResult,\n splitReportFilterScopes,\n} from './adapter.js';\n\nconst INHERITED_REPORT_SCOPE = [\n 'principal',\n 'tenant',\n 'report-definition',\n 'field-policy',\n] as const;\n\nconst EXPORT_FORMATS = new Set<ReportExportFormat>(['csv', 'json']);\nconst PINNED_COLUMN_SIDES = new Set<ReportSavedViewPinnedSide>([\n 'start',\n 'end',\n]);\nconst DISPLAY_DENSITIES = new Set<ReportSavedViewDisplay['density']>([\n 'compact',\n 'comfortable',\n]);\nconst RFC_3339_INSTANT =\n /^(\\d{4})-(\\d{2})-(\\d{2})T([01]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)(?:\\.\\d{1,9})?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/;\n\nconst DEFAULT_EXPORT_LIMITS: ReportExportLimits = {\n maxRows: 100_000,\n maxBytes: 25_000_000,\n deadlineMs: 60_000,\n foregroundRowLimit: 1_000,\n};\n\nconst MAX_EXPORT_LIMITS = {\n maxRows: 1_000_000,\n maxBytes: 100_000_000,\n deadlineMs: 300_000,\n foregroundRowLimit: 100_000,\n} as const;\n\nexport class ReportSurfaceValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReportSurfaceValidationError';\n }\n}\n\nexport type ReportSavedViewPinnedSide = 'start' | 'end';\n\n/** A view's column order is its array order; ids are always adapter-defined. */\nexport interface ReportSavedViewColumn {\n id: string;\n width?: number;\n pinned?: ReportSavedViewPinnedSide;\n}\n\nexport interface ReportSavedViewGrouping {\n fields: string[];\n expanded?: boolean;\n}\n\nexport interface ReportSavedViewDisplay {\n density: 'compact' | 'comfortable';\n showTotals?: boolean;\n}\n\n/**\n * A normalized, policy-neutral stored view. The storage host associates it\n * with its owner and tenant; neither identity is accepted here.\n */\nexport interface ReportSavedView {\n version: 1;\n id: string;\n title: string;\n resourceId: string;\n reportClassName: string;\n definitionFingerprint: string;\n query: DataQueryRequest;\n columns: ReportSavedViewColumn[];\n grouping?: ReportSavedViewGrouping;\n display?: ReportSavedViewDisplay;\n}\n\nexport type ReportExportFormat = 'csv' | 'json';\n\n/**\n * Opaque identity of a host-captured materialization snapshot. The application\n * creates and verifies it while bound to its principal and tenant; callers\n * cannot turn an `asOf` label into a snapshot by supplying this id alone.\n */\nexport interface ReportExportSnapshotBinding {\n id: string;\n}\n\nexport interface ReportExportSnapshot {\n version: 1;\n resourceId: string;\n reportClassName: string;\n definitionFingerprint: string;\n binding: ReportExportSnapshotBinding;\n request: DataQueryRequest;\n queryFingerprint: string;\n projection: string[];\n sort: DataQuerySort[];\n freshness: DataQueryFreshness;\n snapshot: {\n asOf: string;\n refreshedAt?: string;\n stale: boolean;\n };\n total: {\n kind: 'exact';\n value: number;\n };\n inherits: Array<(typeof INHERITED_REPORT_SCOPE)[number]>;\n}\n\n/** Every export is bounded before it is streamed or delegated to a worker. */\nexport interface ReportExportLimits {\n maxRows: number;\n maxBytes: number;\n deadlineMs: number;\n /** Exports above this exact row count must use the application queue. */\n foregroundRowLimit: number;\n}\n\n/**\n * A deterministic offset-page plan over the immutable host snapshot. A worker\n * starts at offset zero and advances by `page.limit` until `rowCount` rows have\n * been produced or the byte/deadline limits are reached.\n */\nexport interface ReportExportReadPlan {\n snapshotId: string;\n queryFingerprint: string;\n asOf: string;\n page: {\n kind: 'offset';\n offset: 0;\n limit: number;\n };\n}\n\nexport interface ReportExportRequest {\n version: 1;\n format: ReportExportFormat;\n execution: 'stream' | 'background';\n snapshot: ReportExportSnapshot;\n limits: ReportExportLimits;\n read: ReportExportReadPlan;\n rowCount: number;\n truncated: boolean;\n action: {\n id: 'export';\n requiredPermission: string;\n auditRequired: true;\n confirmationRequired: boolean;\n };\n}\n\n/**\n * An authority-free job handoff. The queue must re-enter the bound principal\n * and tenant, resolve the current report definition/field policy, and verify\n * this snapshot before materializing an artifact.\n */\nexport interface ReportBackgroundExportTask {\n version: 1;\n execution: 'background';\n request: ReportExportRequest;\n inherits: Array<(typeof INHERITED_REPORT_SCOPE)[number]>;\n}\n\nexport interface ReportExportProgress {\n state: 'queued' | 'running' | 'completed' | 'failed';\n rowCount: number;\n byteCount: number;\n truncated: boolean;\n}\n\n/**\n * Artifact metadata is deliberately URL- and token-free. An application-owned\n * serving boundary must authorize every download using the caller's current\n * principal and tenant before it reveals any artifact location.\n */\nexport interface ReportExportArtifact {\n id: string;\n request: ReportExportRequest;\n progress: ReportExportProgress;\n expiresAt: string;\n}\n\nexport interface ReportExportActionContext {\n phase: 'preview' | 'apply';\n reportClassName: string;\n resourceId: string;\n requiredPermission: string;\n confirmationRequired: boolean;\n execution: 'stream' | 'background';\n queryFingerprint: string;\n definitionFingerprint: string;\n snapshotId: string;\n asOf: string;\n pageSize: number;\n}\n\n/** The same host is used by human and agent callers. */\nexport interface ReportExportActionHost {\n /**\n * Prove that this opaque binding still resolves to the exact immutable\n * materialization snapshot under the host's current principal and tenant.\n * The background worker must call `validateReportExportExecution()` again\n * before reading or serving any rows.\n */\n assertSnapshot(context: ReportExportSnapshotContext): Promise<void> | void;\n authorize(context: ReportExportActionContext): Promise<void> | void;\n audit(context: ReportExportActionContext): Promise<void> | void;\n enqueue?(\n task: ReportBackgroundExportTask,\n ): Promise<{ taskId: string }> | { taskId: string };\n}\n\nexport interface ReportExportSnapshotContext {\n bindingId: string;\n resourceId: string;\n reportClassName: string;\n definitionFingerprint: string;\n queryFingerprint: string;\n asOf: string;\n}\n\nexport interface ReportExportPreview {\n phase: 'preview';\n action: ReportExportActionContext;\n request: ReportExportRequest;\n}\n\nexport type AppliedReportExport =\n | {\n phase: 'apply';\n execution: 'stream';\n status: 'ready';\n request: ReportExportRequest;\n }\n | {\n phase: 'apply';\n execution: 'background';\n status: 'queued';\n taskId: string;\n request: ReportExportRequest;\n };\n\ninterface SavedViewInput {\n version?: unknown;\n id: unknown;\n title: unknown;\n resourceId?: unknown;\n reportClassName?: unknown;\n definitionFingerprint?: unknown;\n query: unknown;\n columns?: unknown;\n grouping?: unknown;\n display?: unknown;\n}\n\ninterface ExportRequestInput {\n format: unknown;\n limits?: unknown;\n}\n\nfunction fail(message: string): never {\n throw new ReportSurfaceValidationError(message);\n}\n\nfunction plainObject(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return fail(`${label} must be a plain object`);\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n return fail(`${label} must be a plain object`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction exactKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n label: string,\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.includes(key)) {\n fail(`${label} contains an unsupported field: ${key}`);\n }\n }\n}\n\nfunction requiredString(\n value: unknown,\n label: string,\n maxLength = 256,\n): string {\n if (typeof value !== 'string') return fail(`${label} must be a string`);\n const normalized = value.trim();\n if (!normalized) return fail(`${label} cannot be empty`);\n if (normalized.length > maxLength) {\n return fail(`${label} cannot exceed ${String(maxLength)} characters`);\n }\n return normalized;\n}\n\nfunction optionalBoolean(value: unknown, label: string): boolean | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== 'boolean') return fail(`${label} must be a boolean`);\n return value;\n}\n\nfunction boundedInteger(\n value: unknown,\n label: string,\n minimum: number,\n maximum: number,\n): number {\n if (!Number.isInteger(value) || (value as number) < minimum) {\n return fail(`${label} must be an integer of at least ${String(minimum)}`);\n }\n if ((value as number) > maximum) {\n return fail(`${label} cannot exceed ${String(maximum)}`);\n }\n return value as number;\n}\n\nfunction normalizeIso(value: unknown, label: string): string {\n const text = requiredString(value, label, 64);\n const match = RFC_3339_INSTANT.exec(text);\n if (!match) return fail(`${label} must be an RFC 3339 instant`);\n const [year, month, day] = match.slice(1, 4).map(Number);\n const calendar = new Date(0);\n calendar.setUTCFullYear(year, month - 1, day);\n calendar.setUTCHours(0, 0, 0, 0);\n if (\n calendar.getUTCFullYear() !== year ||\n calendar.getUTCMonth() !== month - 1 ||\n calendar.getUTCDate() !== day\n ) {\n return fail(`${label} must be an RFC 3339 instant`);\n }\n const parsed = new Date(text);\n if (Number.isNaN(parsed.getTime())) {\n return fail(`${label} must be an RFC 3339 instant`);\n }\n return parsed.toISOString();\n}\n\nfunction normalizeSnapshotBinding(value: unknown): ReportExportSnapshotBinding {\n const input = plainObject(value, 'Report export snapshot binding');\n exactKeys(input, ['id'], 'Report export snapshot binding');\n return {\n id: requiredString(input.id, 'Report export snapshot binding id'),\n };\n}\n\nfunction stable(value: unknown): string {\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'number'\n ) {\n return JSON.stringify(value);\n }\n if (typeof value === 'string') return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(stable).join(',')}]`;\n const object = plainObject(value, 'Report surface value');\n return (\n '{' +\n Object.keys(object)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${stable(object[key])}`)\n .join(',') +\n '}'\n );\n}\n\n/**\n * A change to report fields, their capabilities, schema, scope, or source\n * invalidates a stored view/export snapshot rather than silently widening it.\n */\nexport function reportDefinitionFingerprint(\n descriptor: ReportAdapterDescriptor,\n): string {\n const definition = {\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n sourceClassName: descriptor.sourceClassName,\n tenantScoped: descriptor.tenantScoped,\n tenantField: descriptor.tenantField ?? null,\n identityField: descriptor.identityField,\n columns: descriptor.columns.map((column) => ({\n id: column.id,\n fieldName: column.fieldName,\n kind: column.kind,\n filterScope: column.filterScope,\n type: column.type,\n projectable: column.projectable === true,\n sortable: column.sortable === true,\n facetable: column.facetable === true,\n filterOperators: column.filterOperators ?? [],\n capabilities: [...column.capabilities].sort(),\n sensitivity: column.sensitivity ?? null,\n sourceColumn: column.sourceColumn ?? null,\n bucket: column.bucket ?? null,\n aggregate: column.aggregate ?? null,\n distinct: column.distinct ?? null,\n })),\n schema: descriptor.schema,\n };\n return (\n 'rv1_' +\n createHash('sha256').update(stable(definition), 'utf8').digest('base64url')\n );\n}\n\nfunction columnMap(\n descriptor: ReportAdapterDescriptor,\n): Map<string, ReportAdapterDescriptor['columns'][number]> {\n return new Map(descriptor.columns.map((column) => [column.id, column]));\n}\n\nfunction requireColumnCapability(\n descriptor: ReportAdapterDescriptor,\n id: unknown,\n capability: ReportColumnCapability,\n label: string,\n): string {\n const columnId = requiredString(id, label);\n const column = columnMap(descriptor).get(columnId);\n if (!column?.capabilities.includes(capability)) {\n return fail(`${label} is not available under the current report policy`);\n }\n return columnId;\n}\n\nfunction normalizeColumns(\n descriptor: ReportAdapterDescriptor,\n value: unknown,\n): ReportSavedViewColumn[] {\n if (value === undefined) {\n return descriptor.columns\n .filter((column) => column.capabilities.includes('project'))\n .map((column) => ({ id: column.id }));\n }\n if (!Array.isArray(value))\n return fail('Saved report view columns must be an array');\n if (value.length > descriptor.columns.length) {\n return fail(\n 'Saved report view columns cannot repeat or exceed exposed columns',\n );\n }\n const ids = new Set<string>();\n return value.map((entry, index) => {\n const input = plainObject(\n entry,\n `Saved report view columns[${String(index)}]`,\n );\n const id = requireColumnCapability(\n descriptor,\n input.id,\n 'project',\n `Saved report view columns[${String(index)}].id`,\n );\n if (ids.has(id)) return fail('Saved report view columns cannot repeat ids');\n ids.add(id);\n const width =\n input.width === undefined\n ? undefined\n : boundedInteger(\n input.width,\n `Saved report view columns[${String(index)}].width`,\n 40,\n 2_000,\n );\n const pinned =\n input.pinned === undefined\n ? undefined\n : requiredString(\n input.pinned,\n `Saved report view columns[${String(index)}].pinned`,\n 16,\n );\n if (\n pinned !== undefined &&\n !PINNED_COLUMN_SIDES.has(pinned as ReportSavedViewPinnedSide)\n ) {\n return fail(\n `Saved report view columns[${String(index)}].pinned is invalid`,\n );\n }\n return {\n id,\n ...(width === undefined ? {} : { width }),\n ...(pinned === undefined\n ? {}\n : { pinned: pinned as ReportSavedViewPinnedSide }),\n };\n });\n}\n\nfunction normalizeGrouping(\n descriptor: ReportAdapterDescriptor,\n value: unknown,\n): ReportSavedViewGrouping | undefined {\n if (value === undefined) return undefined;\n const input = plainObject(value, 'Saved report view grouping');\n if (!Array.isArray(input.fields)) {\n return fail('Saved report view grouping.fields must be an array');\n }\n const fields = input.fields.map((field, index) =>\n requireColumnCapability(\n descriptor,\n field,\n 'group',\n `Saved report view grouping.fields[${String(index)}]`,\n ),\n );\n if (new Set(fields).size !== fields.length) {\n return fail('Saved report view grouping.fields cannot repeat ids');\n }\n const expanded = optionalBoolean(\n input.expanded,\n 'Saved report view grouping.expanded',\n );\n return {\n fields,\n ...(expanded === undefined ? {} : { expanded }),\n };\n}\n\nfunction normalizeDisplay(value: unknown): ReportSavedViewDisplay | undefined {\n if (value === undefined) return undefined;\n const input = plainObject(value, 'Saved report view display');\n const density = requiredString(\n input.density,\n 'Saved report view display.density',\n 16,\n );\n if (!DISPLAY_DENSITIES.has(density as ReportSavedViewDisplay['density'])) {\n return fail('Saved report view display.density is invalid');\n }\n const showTotals = optionalBoolean(\n input.showTotals,\n 'Saved report view display.showTotals',\n );\n return {\n density: density as ReportSavedViewDisplay['density'],\n ...(showTotals === undefined ? {} : { showTotals }),\n };\n}\n\n/**\n * Version 0 is the original unversioned persisted layout shape. It contains\n * the same allowlisted fields as v1, so the migration only records the schema\n * version; current descriptor normalization still revalidates every field.\n */\nexport function migrateReportSavedView(value: unknown): SavedViewInput {\n const input = plainObject(\n value,\n 'Saved report view',\n ) as unknown as SavedViewInput;\n if (input.version === undefined || input.version === 0) {\n return { ...input, version: 1 };\n }\n if (input.version === 1) return input;\n return fail('Saved report view version is unsupported');\n}\n\n/**\n * Normalize a view both when it is saved and when it is restored. Re-running\n * this against the live descriptor is what prevents a former field/action\n * grant from surviving a policy or definition change.\n */\nexport function normalizeReportSavedView(\n descriptor: ReportAdapterDescriptor,\n value: unknown,\n): ReportSavedView {\n const input = migrateReportSavedView(value);\n const fingerprint = reportDefinitionFingerprint(descriptor);\n if (\n input.resourceId !== undefined &&\n input.resourceId !== descriptor.resourceId\n ) {\n return fail('Saved report view belongs to a different report resource');\n }\n if (\n input.reportClassName !== undefined &&\n input.reportClassName !== descriptor.reportClassName\n ) {\n return fail('Saved report view belongs to a different report class');\n }\n if (\n input.definitionFingerprint !== undefined &&\n input.definitionFingerprint !== fingerprint\n ) {\n return fail('Saved report view definition has changed');\n }\n const query = normalizeDataQueryRequest(input.query, descriptor.schema);\n if (query.mode !== 'rows') {\n return fail('Saved report views must use a rows query');\n }\n splitReportFilterScopes(descriptor, query.filter);\n const columns = normalizeColumns(descriptor, input.columns);\n const grouping = normalizeGrouping(descriptor, input.grouping);\n const display = normalizeDisplay(input.display);\n return {\n version: 1,\n id: requiredString(input.id, 'Saved report view id'),\n title: requiredString(input.title, 'Saved report view title', 240),\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n definitionFingerprint: fingerprint,\n query,\n columns,\n ...(grouping === undefined ? {} : { grouping }),\n ...(display === undefined ? {} : { display }),\n };\n}\n\n/** Restore through current policy rather than trusting a stored JSON record. */\nexport function restoreReportSavedView(\n descriptor: ReportAdapterDescriptor,\n savedView: ReportSavedView,\n): ReportSavedView {\n return normalizeReportSavedView(descriptor, savedView);\n}\n\n/**\n * Freeze a previously executed materialized read for export. The caller must\n * supply the exact request and a result that exposes lifecycle freshness; an\n * export never invents an as-of value or accepts a caller-supplied tenant.\n */\nexport function createReportExportSnapshot(\n descriptor: ReportAdapterDescriptor,\n input: unknown,\n result: Pick<\n DataQueryResult,\n 'queryFingerprint' | 'identityField' | 'total' | 'freshness' | 'truncated'\n > &\n Pick<ReportDataQueryResult, 'reportLifecycle'>,\n binding: unknown,\n): ReportExportSnapshot {\n const request = normalizeDataQueryRequest(input, descriptor.schema);\n if (request.mode !== 'rows') {\n return fail('Report export snapshots require a rows query');\n }\n const queryFingerprint = createDataQueryFingerprint(\n request,\n descriptor.schema,\n );\n if (result.queryFingerprint !== queryFingerprint) {\n return fail(\n 'Report export result does not match the requested query fingerprint',\n );\n }\n if (result.identityField !== descriptor.identityField) {\n return fail('Report export result has an unexpected row identity field');\n }\n if (result.total.kind !== 'exact') {\n return fail('Report export snapshots require an exact row count');\n }\n if (!Number.isSafeInteger(result.total.value) || result.total.value < 0) {\n return fail(\n 'Report export snapshots require a safe non-negative row count',\n );\n }\n if (result.truncated) {\n return fail('Report export snapshots cannot use a truncated query result');\n }\n if (result.freshness.state === 'unknown') {\n return fail('Report export snapshots require lifecycle freshness');\n }\n const lifecycleAsOf = result.reportLifecycle?.snapshot.asOf;\n const freshnessAsOf = result.freshness.asOf;\n const normalizedLifecycleAsOf = lifecycleAsOf\n ? normalizeIso(lifecycleAsOf, 'Report export lifecycle snapshot asOf')\n : undefined;\n const normalizedFreshnessAsOf = freshnessAsOf\n ? normalizeIso(freshnessAsOf, 'Report export freshness asOf')\n : undefined;\n if (\n normalizedLifecycleAsOf !== undefined &&\n normalizedFreshnessAsOf !== undefined &&\n normalizedLifecycleAsOf !== normalizedFreshnessAsOf\n ) {\n return fail(\n 'Report export lifecycle freshness does not match its snapshot',\n );\n }\n const normalizedAsOf = normalizedLifecycleAsOf ?? normalizedFreshnessAsOf;\n if (!normalizedAsOf) {\n return fail(\n 'Report export snapshots require an as-of materialization instant',\n );\n }\n const refreshedAt = result.reportLifecycle?.snapshot.refreshedAt;\n return {\n version: 1,\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n definitionFingerprint: reportDefinitionFingerprint(descriptor),\n binding: normalizeSnapshotBinding(binding),\n request,\n queryFingerprint,\n projection: [...(request.projection ?? [descriptor.identityField])],\n sort: [\n ...(request.sort ??\n descriptor.schema.defaultSort ?? [\n { field: descriptor.identityField, direction: 'asc' },\n ]),\n ],\n freshness: {\n state: result.freshness.state,\n asOf: normalizedAsOf,\n },\n snapshot: {\n asOf: normalizedAsOf,\n ...(refreshedAt\n ? {\n refreshedAt: normalizeIso(\n refreshedAt,\n 'Report export snapshot refreshedAt',\n ),\n }\n : {}),\n stale: result.freshness.state === 'stale',\n },\n total: { kind: 'exact', value: result.total.value },\n inherits: [...INHERITED_REPORT_SCOPE],\n };\n}\n\n/** Reject definitions/policies that changed after a snapshot was frozen. */\nexport function verifyReportExportSnapshot(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n): ReportExportSnapshot {\n const input = plainObject(snapshot, 'Report export snapshot');\n exactKeys(\n input,\n [\n 'version',\n 'resourceId',\n 'reportClassName',\n 'definitionFingerprint',\n 'binding',\n 'request',\n 'queryFingerprint',\n 'projection',\n 'sort',\n 'freshness',\n 'snapshot',\n 'total',\n 'inherits',\n ],\n 'Report export snapshot',\n );\n if (snapshot.version !== 1)\n return fail('Report export snapshot version is unsupported');\n if (\n snapshot.resourceId !== descriptor.resourceId ||\n snapshot.reportClassName !== descriptor.reportClassName\n ) {\n return fail('Report export snapshot belongs to a different report');\n }\n if (\n snapshot.definitionFingerprint !== reportDefinitionFingerprint(descriptor)\n ) {\n return fail('Report export definition has changed');\n }\n const binding = normalizeSnapshotBinding(snapshot.binding);\n const normalized = normalizeDataQueryRequest(\n snapshot.request,\n descriptor.schema,\n );\n if (normalized.mode !== 'rows') {\n return fail('Report export snapshot query must remain a rows query');\n }\n if (\n createDataQueryFingerprint(normalized, descriptor.schema) !==\n snapshot.queryFingerprint\n ) {\n return fail('Report export snapshot query fingerprint is invalid');\n }\n const expectedProjection = normalized.projection ?? [\n descriptor.identityField,\n ];\n const expectedSort = normalized.sort ??\n descriptor.schema.defaultSort ?? [\n { field: descriptor.identityField, direction: 'asc' },\n ];\n if (\n !Array.isArray(snapshot.projection) ||\n snapshot.projection.some((field) => typeof field !== 'string')\n ) {\n return fail('Report export snapshot projection is invalid');\n }\n if (\n snapshot.projection.length !== expectedProjection.length ||\n snapshot.projection.some(\n (field, index) => field !== expectedProjection[index],\n )\n ) {\n return fail('Report export snapshot projection or sort has changed');\n }\n if (!Array.isArray(snapshot.sort)) {\n return fail('Report export snapshot sort is invalid');\n }\n const sort = snapshot.sort.map((value) => {\n const sortInput = plainObject(value, 'Report export snapshot sort');\n exactKeys(sortInput, ['field', 'direction'], 'Report export snapshot sort');\n return {\n field: requiredString(\n sortInput.field,\n 'Report export snapshot sort field',\n ),\n direction: requiredString(\n sortInput.direction,\n 'Report export snapshot sort direction',\n ),\n };\n });\n if (stable(sort) !== stable(expectedSort)) {\n return fail('Report export snapshot projection or sort has changed');\n }\n const freshness = plainObject(\n snapshot.freshness,\n 'Report export snapshot freshness',\n );\n exactKeys(freshness, ['state', 'asOf'], 'Report export snapshot freshness');\n const materialization = plainObject(\n snapshot.snapshot,\n 'Report export snapshot materialization',\n );\n exactKeys(\n materialization,\n ['asOf', 'refreshedAt', 'stale'],\n 'Report export snapshot materialization',\n );\n const total = plainObject(snapshot.total, 'Report export snapshot total');\n exactKeys(total, ['kind', 'value'], 'Report export snapshot total');\n const totalValue = total.value;\n const asOf = normalizeIso(\n materialization.asOf,\n 'Report export snapshot asOf',\n );\n if (freshness.state !== 'fresh' && freshness.state !== 'stale') {\n return fail('Report export snapshot freshness state is invalid');\n }\n const freshnessAsOf = normalizeIso(\n freshness.asOf,\n 'Report export snapshot freshness asOf',\n );\n if (freshnessAsOf !== asOf) {\n return fail(\n 'Report export snapshot freshness does not match its as-of instant',\n );\n }\n const refreshedAt = materialization.refreshedAt\n ? normalizeIso(\n materialization.refreshedAt,\n 'Report export snapshot refreshedAt',\n )\n : undefined;\n if (materialization.stale !== (freshness.state === 'stale')) {\n return fail('Report export snapshot stale state is invalid');\n }\n if (\n total.kind !== 'exact' ||\n typeof totalValue !== 'number' ||\n !Number.isSafeInteger(totalValue) ||\n totalValue < 0\n ) {\n return fail('Report export snapshot row count is invalid');\n }\n if (\n !Array.isArray(snapshot.inherits) ||\n snapshot.inherits.some((value) => typeof value !== 'string') ||\n snapshot.inherits.length !== INHERITED_REPORT_SCOPE.length ||\n snapshot.inherits.some(\n (value, index) => value !== INHERITED_REPORT_SCOPE[index],\n )\n ) {\n return fail('Report export snapshot inheritance contract is invalid');\n }\n return {\n version: 1,\n resourceId: descriptor.resourceId,\n reportClassName: descriptor.reportClassName,\n definitionFingerprint: reportDefinitionFingerprint(descriptor),\n binding,\n request: normalized,\n queryFingerprint: createDataQueryFingerprint(normalized, descriptor.schema),\n projection: [...expectedProjection],\n sort: expectedSort.map(({ field, direction }) => ({ field, direction })),\n freshness: { state: freshness.state, asOf: freshnessAsOf },\n snapshot: {\n asOf,\n stale: materialization.stale,\n ...(refreshedAt === undefined ? {} : { refreshedAt }),\n },\n total: { kind: 'exact', value: totalValue },\n inherits: [...INHERITED_REPORT_SCOPE],\n };\n}\n\nfunction normalizeExportLimits(value: unknown): ReportExportLimits {\n if (value === undefined) return { ...DEFAULT_EXPORT_LIMITS };\n const input = plainObject(value, 'Report export limits');\n const maxRows = boundedInteger(\n input.maxRows ?? DEFAULT_EXPORT_LIMITS.maxRows,\n 'Report export limits.maxRows',\n 1,\n MAX_EXPORT_LIMITS.maxRows,\n );\n const maxBytes = boundedInteger(\n input.maxBytes ?? DEFAULT_EXPORT_LIMITS.maxBytes,\n 'Report export limits.maxBytes',\n 1,\n MAX_EXPORT_LIMITS.maxBytes,\n );\n const deadlineMs = boundedInteger(\n input.deadlineMs ?? DEFAULT_EXPORT_LIMITS.deadlineMs,\n 'Report export limits.deadlineMs',\n 1,\n MAX_EXPORT_LIMITS.deadlineMs,\n );\n const foregroundRowLimit = boundedInteger(\n input.foregroundRowLimit ??\n Math.min(DEFAULT_EXPORT_LIMITS.foregroundRowLimit, maxRows),\n 'Report export limits.foregroundRowLimit',\n 1,\n Math.min(maxRows, MAX_EXPORT_LIMITS.foregroundRowLimit),\n );\n return { maxRows, maxBytes, deadlineMs, foregroundRowLimit };\n}\n\nfunction hasSensitiveProjection(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n): boolean {\n const columns = columnMap(descriptor);\n return snapshot.projection.some((id) => {\n const sensitivity = columns.get(id)?.sensitivity;\n return (\n sensitivity === 'personal' ||\n sensitivity === 'sensitive' ||\n sensitivity === 'secret'\n );\n });\n}\n\nfunction createReadPlan(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n limits: ReportExportLimits,\n): ReportExportReadPlan {\n return {\n snapshotId: snapshot.binding.id,\n queryFingerprint: snapshot.queryFingerprint,\n asOf: snapshot.snapshot.asOf,\n page: {\n kind: 'offset',\n offset: 0,\n limit: Math.min(\n limits.maxRows,\n descriptor.schema.maxPageLimit ??\n DEFAULT_EXPORT_LIMITS.foregroundRowLimit,\n ),\n },\n };\n}\n\n/**\n * Build one common request for both agent and human export clients. The\n * resulting request carries no actor, tenant, storage location, or token.\n */\nexport function createReportExportRequest(\n descriptor: ReportAdapterDescriptor,\n snapshot: ReportExportSnapshot,\n value: unknown,\n): ReportExportRequest {\n const input = plainObject(\n value,\n 'Report export request',\n ) as unknown as ExportRequestInput;\n const verified = verifyReportExportSnapshot(descriptor, snapshot);\n const format = requiredString(input.format, 'Report export format', 16);\n if (!EXPORT_FORMATS.has(format as ReportExportFormat)) {\n return fail('Report export format is unsupported');\n }\n const limits = normalizeExportLimits(input.limits);\n const rowCount = Math.min(verified.total.value, limits.maxRows);\n const confirmationRequired = hasSensitiveProjection(descriptor, verified);\n return {\n version: 1,\n format: format as ReportExportFormat,\n execution:\n verified.total.value > limits.foregroundRowLimit\n ? 'background'\n : 'stream',\n snapshot: verified,\n limits,\n read: createReadPlan(descriptor, verified, limits),\n rowCount,\n truncated: verified.total.value > limits.maxRows,\n action: {\n id: 'export',\n requiredPermission: 'reports.export',\n auditRequired: true,\n confirmationRequired,\n },\n };\n}\n\n/**\n * Recreate the deterministic request from its current descriptor and frozen\n * snapshot. Preview, apply, queue, and serving hosts call this instead of\n * trusting browser- or agent-supplied action metadata.\n */\nexport function validateReportExportRequest(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n): ReportExportRequest {\n const expected = createReportExportRequest(descriptor, request.snapshot, {\n format: request.format,\n limits: request.limits,\n });\n if (stable(request) !== stable(expected)) {\n return fail('Report export request does not match current policy');\n }\n return expected;\n}\n\n/**\n * Build one bounded page of the immutable export read. The host applies the\n * opaque snapshot binding separately; this function preserves the frozen\n * projection, predicate, and deterministic sort while replacing only visible\n * pagination. A zero-row export therefore has no pages to execute.\n */\nexport function createReportExportPageRequest(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n offset: number,\n): DataQueryRequest {\n const verified = validateReportExportRequest(descriptor, request);\n if (\n !Number.isSafeInteger(offset) ||\n offset < 0 ||\n offset >= verified.rowCount\n ) {\n return fail('Report export page offset is outside the bounded export');\n }\n const limit = Math.min(verified.read.page.limit, verified.rowCount - offset);\n return normalizeDataQueryRequest(\n {\n ...verified.snapshot.request,\n page: { kind: 'offset', offset, limit },\n },\n descriptor.schema,\n );\n}\n\nfunction actionContext(\n phase: ReportExportActionContext['phase'],\n request: ReportExportRequest,\n): ReportExportActionContext {\n return {\n phase,\n reportClassName: request.snapshot.reportClassName,\n resourceId: request.snapshot.resourceId,\n requiredPermission: request.action.requiredPermission,\n confirmationRequired: request.action.confirmationRequired,\n execution: request.execution,\n queryFingerprint: request.snapshot.queryFingerprint,\n definitionFingerprint: request.snapshot.definitionFingerprint,\n snapshotId: request.read.snapshotId,\n asOf: request.read.asOf,\n pageSize: request.read.page.limit,\n };\n}\n\nfunction snapshotContext(\n request: ReportExportRequest,\n): ReportExportSnapshotContext {\n return {\n bindingId: request.snapshot.binding.id,\n resourceId: request.snapshot.resourceId,\n reportClassName: request.snapshot.reportClassName,\n definitionFingerprint: request.snapshot.definitionFingerprint,\n queryFingerprint: request.snapshot.queryFingerprint,\n asOf: request.snapshot.snapshot.asOf,\n };\n}\n\n/**\n * Revalidate the request and prove the opaque snapshot binding through the\n * application host. Preview, apply, and every background worker use this same\n * operation before reading or serving export data.\n */\nexport async function validateReportExportExecution(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n host: Pick<ReportExportActionHost, 'assertSnapshot'>,\n): Promise<ReportExportRequest> {\n const verified = validateReportExportRequest(descriptor, request);\n await host.assertSnapshot(snapshotContext(verified));\n return verified;\n}\n\nexport async function previewReportExport(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n host: ReportExportActionHost,\n): Promise<ReportExportPreview> {\n const initial = validateReportExportRequest(descriptor, request);\n const action = actionContext('preview', initial);\n await host.authorize(action);\n const verified = await validateReportExportExecution(\n descriptor,\n initial,\n host,\n );\n await host.audit(action);\n return { phase: 'preview', action, request: verified };\n}\n\n/**\n * Queue large exports without embedding rows in a browser/agent response.\n * A host must verify current principal, tenant, report definition, and field\n * policy again before it renders or serves the artifact.\n */\nexport async function applyReportExport(\n descriptor: ReportAdapterDescriptor,\n request: ReportExportRequest,\n host: ReportExportActionHost,\n options: { confirmed?: boolean } = {},\n): Promise<AppliedReportExport> {\n const initial = validateReportExportRequest(descriptor, request);\n if (initial.action.confirmationRequired && options.confirmed !== true) {\n return fail('Sensitive report exports require explicit confirmation');\n }\n const action = actionContext('apply', initial);\n await host.authorize(action);\n const verified = await validateReportExportExecution(\n descriptor,\n initial,\n host,\n );\n await host.audit(action);\n if (verified.execution === 'stream') {\n return {\n phase: 'apply',\n execution: 'stream',\n status: 'ready',\n request: verified,\n };\n }\n if (!host.enqueue) {\n return fail('Background report exports require an application queue host');\n }\n const queued = await host.enqueue({\n version: 1,\n execution: 'background',\n request: verified,\n inherits: [...INHERITED_REPORT_SCOPE],\n });\n if (typeof queued.taskId !== 'string' || queued.taskId.trim().length === 0) {\n return fail('Background report export hosts must return a task id');\n }\n return {\n phase: 'apply',\n execution: 'background',\n status: 'queued',\n taskId: queued.taskId,\n request: verified,\n };\n}\n\n/**\n * Validate artifact metadata before a host serves it. Download locations and\n * tokens stay application-private; expired artifacts fail before that boundary.\n */\nexport function validateReportExportArtifact(\n descriptor: ReportAdapterDescriptor,\n artifact: ReportExportArtifact,\n now = new Date(),\n): ReportExportArtifact {\n const input = plainObject(artifact, 'Report export artifact');\n exactKeys(\n input,\n ['id', 'request', 'progress', 'expiresAt'],\n 'Report export artifact',\n );\n const request = validateReportExportRequest(descriptor, artifact.request);\n const id = requiredString(artifact.id, 'Report export artifact id');\n const expiresAt = normalizeIso(\n artifact.expiresAt,\n 'Report export artifact expiresAt',\n );\n if (new Date(expiresAt).getTime() <= now.getTime()) {\n return fail('Report export artifact has expired');\n }\n const progress = plainObject(\n artifact.progress,\n 'Report export artifact progress',\n );\n exactKeys(\n progress,\n ['state', 'rowCount', 'byteCount', 'truncated'],\n 'Report export artifact progress',\n );\n const state = progress.state;\n if (\n state !== 'queued' &&\n state !== 'running' &&\n state !== 'completed' &&\n state !== 'failed'\n ) {\n return fail('Report export artifact progress state is invalid');\n }\n const rowCount = boundedInteger(\n progress.rowCount,\n 'Report export artifact rowCount',\n 0,\n request.rowCount,\n );\n const byteCount = boundedInteger(\n progress.byteCount,\n 'Report export artifact byteCount',\n 0,\n request.limits.maxBytes,\n );\n const truncated = progress.truncated;\n if (typeof truncated !== 'boolean') {\n return fail('Report export artifact truncated must be a boolean');\n }\n if (state === 'completed' && rowCount !== request.rowCount) {\n return fail(\n 'Completed report export artifacts must contain the requested row count',\n );\n }\n if (state === 'completed' && truncated !== request.truncated) {\n return fail(\n 'Completed report export artifacts must match the requested truncation state',\n );\n }\n return {\n id,\n request,\n expiresAt,\n progress: { state, rowCount, byteCount, truncated },\n };\n}\n"],"mappings":"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"}