@happyvertical/smrt-agents 0.49.2 → 0.49.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -5
- package/dist/index.js +1 -1
- package/dist/manifest.json +631 -16
- package/dist/server/data-surface-actions.d.ts +36 -13
- package/dist/server/data-surface-actions.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/jobs-data-surface-action-queue.d.ts +33 -0
- package/dist/server/jobs-data-surface-action-queue.d.ts.map +1 -0
- package/dist/server/sql-data-surface-action-state.d.ts +60 -0
- package/dist/server/sql-data-surface-action-state.d.ts.map +1 -0
- package/dist/server.js +468 -20
- package/dist/server.js.map +1 -1
- package/dist/smrt-knowledge.json +165 -5
- package/package.json +14 -12
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","names":["result"],"sources":["../src/server/api-routes.ts","../src/server/config-loader.ts","../src/server/data-surface-actions.ts","../src/server/serialization.ts"],"sourcesContent":["/**\n * Server-side API route resolution for SMRT agents\n *\n * Reads agent package manifests and builds a route map from resource\n * paths (e.g., 'performers', 'video-contents') to SmrtObject class\n * names and allowed CRUD actions. The catch-all API handler uses this\n * to resolve incoming requests.\n *\n * @module @happyvertical/smrt-agents/server\n */\n\nimport type { PackageManifest } from './manifest-utils.js';\n\n/**\n * Info about a single API route (one SmrtObject with api.include)\n */\nexport interface AgentAPIRouteInfo {\n /** SmrtObject class name (e.g., 'Performer') */\n className: string;\n /** Allowed CRUD actions (e.g., ['list', 'get', 'create', 'update', 'delete']) */\n allowedActions: string[];\n /** Package that owns this resource */\n packageName?: string;\n}\n\n/**\n * Result of resolving a URL path against the route map\n */\nexport interface ResolvedAPIRoute {\n /** The matched route info */\n route: AgentAPIRouteInfo;\n /** Resource ID if path includes one (e.g., 'performers/abc-123') */\n id?: string;\n /** Custom action name if path includes one (e.g., 'performers/abc-123/generate-image') */\n action?: string;\n}\n\n/**\n * Build a route map from loaded package manifests.\n *\n * Iterates all objects in each manifest, and for any object with a\n * `decoratorConfig.api.include` array, registers a route. The route\n * path is derived from `decoratorConfig.api.path` if set, otherwise\n * from the table name with underscores converted to hyphens.\n *\n * @param manifests - Array of parsed package manifest JSON objects\n * @returns Map of resource path -> route info\n *\n * @example\n * ```typescript\n * const manifests = [histrioManifest, praecoManifest];\n * const routes = buildRouteMap(manifests);\n * // routes.get('performers') => { className: 'Performer', allowedActions: ['list', 'get', 'create', 'update', 'delete'] }\n * // routes.get('video-contents') => { className: 'VideoShot', allowedActions: ['list', 'get', 'create', 'update'] }\n * ```\n */\nexport function buildRouteMap(\n manifests: PackageManifest[],\n): Map<string, AgentAPIRouteInfo> {\n const routes = new Map<string, AgentAPIRouteInfo>();\n\n for (const manifest of manifests) {\n const packageName = (manifest as Record<string, unknown>).packageName as\n | string\n | undefined;\n\n for (const obj of Object.values(manifest.objects)) {\n const config = obj.decoratorConfig as Record<string, unknown> | undefined;\n if (!config) continue;\n\n const api = config.api as\n | { include?: string[]; path?: string }\n | undefined;\n if (!api?.include || api.include.length === 0) continue;\n\n // Derive the URL path: explicit api.path, or table name with _ -> -\n const tableName = config.tableName as string | undefined;\n const path =\n api.path || (tableName ? tableName.replace(/_/g, '-') : null);\n if (!path) continue;\n\n routes.set(path, {\n className: obj.className,\n allowedActions: api.include,\n packageName,\n });\n }\n }\n\n return routes;\n}\n\n/**\n * Resolve a URL resource path against a route map.\n *\n * Handles three URL patterns:\n * - `performers` → list/create (no id)\n * - `performers/abc-123` → get/update/delete (with id)\n * - `performers/abc-123/generate-image` → custom action\n *\n * @param urlPath - The resource portion of the URL (after `/api/agents/{agentId}/`)\n * @param routes - Route map from {@link buildRouteMap}\n * @returns Resolved route with optional id/action, or null if no match\n */\nexport function resolveAPIRoute(\n urlPath: string,\n routes: Map<string, AgentAPIRouteInfo>,\n): ResolvedAPIRoute | null {\n // Normalize: strip leading/trailing slashes\n const normalized = urlPath.replace(/^\\/+|\\/+$/g, '');\n if (!normalized) return null;\n\n const segments = normalized.split('/');\n\n // Try 1-segment: \"performers\"\n if (segments.length === 1) {\n const route = routes.get(segments[0]);\n if (route) return { route };\n return null;\n }\n\n // Try 2-segment: \"performers/{id}\"\n if (segments.length === 2) {\n const route = routes.get(segments[0]);\n if (route) return { route, id: segments[1] };\n return null;\n }\n\n // Try 3-segment: \"performers/{id}/{action}\"\n if (segments.length === 3) {\n const route = routes.get(segments[0]);\n if (route) return { route, id: segments[1], action: segments[2] };\n return null;\n }\n\n return null;\n}\n","/**\n * Server-side agent config loading utilities\n *\n * Loads slot configurations from the agent_configs table for a set of agents.\n * Agent-specific table loading (e.g., praeco_sources) stays in the host app.\n *\n * @module @happyvertical/smrt-agents/server\n */\n\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { AgentConfig } from '../config.js';\n\n/**\n * Load slot configs for multiple agents from the agent_configs table.\n *\n * Returns a nested map: agentId -> slotId -> configData.\n * Agent-specific tables (e.g., praeco_sources, praeco_reports)\n * are NOT loaded here — those stay in the host application.\n *\n * @param agents - Array of agent identifiers (id + agentClass)\n * @param dbOptions - Database options for SmrtCollection.create()\n * @returns Map of agentId -> slotId -> config data\n */\nexport async function loadSlotConfigs(\n agents: Array<{ id: string; agentClass: string }>,\n dbOptions: SmrtClassOptions,\n): Promise<Record<string, Record<string, unknown>>> {\n if (agents.length === 0) {\n return {};\n }\n\n try {\n const configsByAgent = await AgentConfig.forAgents(\n agents.map((agent) => agent.id),\n dbOptions,\n );\n\n const configs: Record<string, Record<string, unknown>> = {};\n for (const [agentId, slotConfigs] of configsByAgent) {\n const agentConfig: Record<string, unknown> = {};\n for (const [slotId, configData] of slotConfigs) {\n agentConfig[slotId] = configData;\n }\n if (Object.keys(agentConfig).length > 0) {\n configs[agentId] = agentConfig;\n }\n }\n\n return configs;\n } catch (error) {\n if (isMissingAgentConfigTableError(error)) {\n return {};\n }\n throw error;\n }\n}\n\nfunction isMissingAgentConfigTableError(error: unknown): boolean {\n const message = String((error as Error)?.message || error || '');\n\n return (\n message.includes(\"Run 'smrt db:migrate'\") ||\n /no such table[:\\s]+agent_configs/i.test(message) ||\n /relation .*agent_configs.*does not exist/i.test(message) ||\n /table .*agent_configs.*doesn'?t exist/i.test(message)\n );\n}\n","/**\n * Principal-bound preview/apply orchestration for data-surface actions.\n *\n * Browser state is treated only as an input hint. Every preview and apply is\n * executed under the bound principal, resolves the surface and selection\n * afresh, and delegates durable work only after authorization and eligibility\n * checks have passed.\n */\nimport { createHash, randomBytes } from 'node:crypto';\nimport type {\n DataSurfaceActionDescriptor,\n DataSurfaceActionRequest,\n DataSurfaceActionResult,\n DataSurfaceDescriptor,\n DataSurfaceIdentity,\n DataSurfaceJsonObject,\n DataSurfaceJsonValue,\n DataSurfaceRowId,\n DataSurfaceSelectionReference,\n} from '@happyvertical/smrt-ui/data';\nimport {\n type ExecuteAsPrincipalOptions,\n executeAsPrincipal,\n type PrincipalRun,\n} from '../execute-as-principal.js';\n\nexport type DataSurfaceConfirmationPolicy = 'required' | 'none';\nexport type DataSurfaceActionExecution = 'foreground' | 'background';\n\nexport interface DataSurfaceActionEligibility {\n eligible: boolean;\n reason?: string;\n}\n\nexport type DataSurfaceActionPayloadValidation =\n | { valid: true }\n | { valid: false; reason?: string };\n\nexport interface DataSurfaceActionRowOutcome {\n rowId: DataSurfaceRowId;\n status: 'accepted' | 'skipped' | 'failed';\n reason?: string;\n /** Serializable per-row result returned by the action implementation. */\n metadata?: DataSurfaceJsonObject;\n}\n\nexport interface ResolvedDataSurfaceSelection {\n /** Fresh server-side revision of the selected surface/query. */\n revision: number;\n /** Canonical fingerprint of the frozen query represented by the selection. */\n queryFingerprint: string;\n /** Authoritatively resolved row ids. Browser-provided ids are only hints. */\n rowIds: DataSurfaceRowId[];\n}\n\nexport interface DataSurfaceActionInvocation {\n run: PrincipalRun;\n request: DataSurfaceServerActionRequest;\n descriptor: DataSurfaceDescriptor;\n action: DataSurfaceServerActionDefinition;\n selection: ResolvedDataSurfaceSelection;\n}\n\nexport interface DataSurfaceServerActionDefinition {\n descriptor: DataSurfaceActionDescriptor;\n /** Serializable declaration for transport/schema generators; null means no input. */\n inputSchema: DataSurfaceJsonObject | null;\n /** Runtime enforcement for the declared schema; absence is never permissive. */\n validatePayload(\n payload: DataSurfaceJsonValue | undefined,\n ):\n | DataSurfaceActionPayloadValidation\n | Promise<DataSurfaceActionPayloadValidation>;\n /** Explicit for every action, including sensitive/public/destructive ones. */\n confirmation: DataSurfaceConfirmationPolicy;\n execution: DataSurfaceActionExecution;\n /** Fail-closed persona capability checked by PrincipalRun. */\n tool: string;\n /** Explicit RBAC catalog gate, enforced independently of callback convention. */\n operation: {\n id: string;\n collection: Parameters<PrincipalRun['assertOperation']>[0];\n action: string;\n };\n /** Fresh permission/domain authorization check, run for preview and apply. */\n authorize(\n invocation: DataSurfaceActionInvocation,\n ): boolean | Promise<boolean>;\n /** Fresh per-row domain precondition check, repeated at apply time. */\n eligible(\n invocation: DataSurfaceActionInvocation,\n rowId: DataSurfaceRowId,\n ): DataSurfaceActionEligibility | Promise<DataSurfaceActionEligibility>;\n /** Foreground mutation. Background definitions are run by the injected queue. */\n apply(\n invocation: DataSurfaceActionInvocation,\n rowId: DataSurfaceRowId,\n ):\n | undefined\n | DataSurfaceJsonValue\n | Promise<undefined | DataSurfaceJsonValue>;\n}\n\nexport interface ResolvedDataSurfaceActions {\n descriptor: DataSurfaceDescriptor;\n /** Current server-side revision, never trusted from the browser. */\n revision: number;\n actions: Record<string, DataSurfaceServerActionDefinition>;\n}\n\nexport interface DataSurfaceServerActionRequest\n extends DataSurfaceActionRequest {\n /** Required on apply and bound into the preview token. */\n expectedRevision: number;\n /** Required on apply. Identical retries replay the first terminal result. */\n idempotencyKey?: string;\n}\n\nexport interface DataSurfaceActionContext {\n principal: ExecuteAsPrincipalOptions;\n}\n\nexport interface DataSurfaceBackgroundActionJob {\n idempotencyKey: string;\n identity: DataSurfaceIdentity;\n actionId: string;\n rowIds: DataSurfaceRowId[];\n /**\n * The queue must call this task to perform the work. It re-enters the bound\n * principal and repeats descriptor, authorization, selection, and eligibility\n * checks before any mutation.\n */\n run: () => Promise<DataSurfaceActionResult>;\n}\n\nexport interface DataSurfaceBackgroundQueue {\n enqueue(\n job: DataSurfaceBackgroundActionJob,\n ): Promise<{ jobId: string; details?: DataSurfaceJsonObject }>;\n}\n\nexport interface DataSurfacePreviewTokenRecord {\n expiresAt: number;\n actorUserId: string;\n tenantId: string | null;\n onBehalfOfUserId: string | null;\n actsAsProfileId: string | null;\n agentClass: string | null;\n identityKey: string;\n actionId: string;\n actionFingerprint: string;\n revision: number;\n queryFingerprint: string;\n selectionFingerprint: string;\n resolvedRowsFingerprint: string;\n requestFingerprint: string;\n consumedBy?: string;\n}\n\nexport type DataSurfaceIdempotencyRecord =\n | {\n status: 'reserved';\n requestFingerprint: string;\n ownerToken: string;\n reservedAt: number;\n }\n | {\n status: 'completed';\n requestFingerprint: string;\n result: DataSurfaceActionResult;\n };\n\nexport interface DataSurfaceIdempotencyReservation {\n requestFingerprint: string;\n ownerToken: string;\n reservedAt: number;\n}\n\nexport interface DataSurfaceActionStateStore {\n putToken(\n token: string,\n record: DataSurfacePreviewTokenRecord,\n ): Promise<void> | void;\n getToken(\n token: string,\n ):\n | Promise<DataSurfacePreviewTokenRecord | undefined>\n | DataSurfacePreviewTokenRecord\n | undefined;\n markTokenConsumed(\n token: string,\n idempotencyKey: string,\n ): Promise<boolean> | boolean;\n getIdempotency(\n key: string,\n ):\n | Promise<DataSurfaceIdempotencyRecord | undefined>\n | DataSurfaceIdempotencyRecord\n | undefined;\n /** Atomically create a durable reservation or return the existing record. */\n reserveIdempotency(\n key: string,\n reservation: DataSurfaceIdempotencyReservation,\n ): Promise<DataSurfaceIdempotencyRecord> | DataSurfaceIdempotencyRecord;\n completeIdempotency(\n key: string,\n ownerToken: string,\n result: DataSurfaceActionResult,\n ): Promise<boolean> | boolean;\n releaseIdempotency(\n key: string,\n ownerToken: string,\n ): Promise<boolean> | boolean;\n}\n\n/** Explicit single-process/testing store; production callers inject shared state. */\nexport class InMemoryDataSurfaceActionStateStore\n implements DataSurfaceActionStateStore\n{\n private readonly tokens = new Map<string, DataSurfacePreviewTokenRecord>();\n private readonly idempotency = new Map<\n string,\n DataSurfaceIdempotencyRecord\n >();\n\n putToken(token: string, record: DataSurfacePreviewTokenRecord): void {\n this.tokens.set(token, record);\n }\n\n getToken(token: string): DataSurfacePreviewTokenRecord | undefined {\n return this.tokens.get(token);\n }\n\n markTokenConsumed(token: string, idempotencyKey: string): boolean {\n const record = this.tokens.get(token);\n if (!record) return false;\n if (record.consumedBy && record.consumedBy !== idempotencyKey) return false;\n record.consumedBy = idempotencyKey;\n return true;\n }\n\n getIdempotency(key: string): DataSurfaceIdempotencyRecord | undefined {\n return this.idempotency.get(key);\n }\n\n reserveIdempotency(\n key: string,\n reservation: DataSurfaceIdempotencyReservation,\n ): DataSurfaceIdempotencyRecord {\n const existing = this.idempotency.get(key);\n if (existing) return existing;\n const record: DataSurfaceIdempotencyRecord = {\n status: 'reserved',\n ...reservation,\n };\n this.idempotency.set(key, record);\n return record;\n }\n\n completeIdempotency(\n key: string,\n ownerToken: string,\n result: DataSurfaceActionResult,\n ): boolean {\n const existing = this.idempotency.get(key);\n if (existing?.status !== 'reserved' || existing.ownerToken !== ownerToken)\n return false;\n this.idempotency.set(key, {\n status: 'completed',\n requestFingerprint: existing.requestFingerprint,\n result,\n });\n return true;\n }\n\n releaseIdempotency(key: string, ownerToken: string): boolean {\n const existing = this.idempotency.get(key);\n if (existing?.status !== 'reserved' || existing.ownerToken !== ownerToken)\n return false;\n return this.idempotency.delete(key);\n }\n}\n\nexport interface DataSurfaceActionAdapterOptions {\n resolveSurface(\n run: PrincipalRun,\n identity: DataSurfaceIdentity,\n ): Promise<ResolvedDataSurfaceActions>;\n resolveSelection(\n invocation: Omit<DataSurfaceActionInvocation, 'selection'>,\n selection: DataSurfaceSelectionReference,\n ): Promise<ResolvedDataSurfaceSelection>;\n backgroundQueue?: DataSurfaceBackgroundQueue;\n /** Required durable, shared backend in production; memory storage is opt-in. */\n state: DataSurfaceActionStateStore;\n tokenTtlMs?: number;\n now?: () => number;\n createToken?: () => string;\n runAsPrincipal?: typeof executeAsPrincipal;\n /**\n * Re-resolve the complete current binding immediately before deferred work.\n * Background execution fails closed when this seam is absent or returns a\n * binding for a different principal.\n */\n resolveDeferredPrincipal?(\n reference: Readonly<{\n runAsUserId: string;\n tenantId: string | null;\n actsAsProfileId: string | null;\n onBehalfOfUserId: string | null;\n agentClass?: string;\n }>,\n ): ExecuteAsPrincipalOptions | Promise<ExecuteAsPrincipalOptions>;\n idempotencyPollIntervalMs?: number;\n idempotencyWaitTimeoutMs?: number;\n /** Domain-specific request input that must participate in confirmation/idempotency. */\n requestFingerprintExtension?(\n request: DataSurfaceServerActionRequest,\n ): DataSurfaceJsonValue | undefined;\n /** Maps terminal domain failures; return undefined to preserve queue retries. */\n mapError?(\n error: unknown,\n request: DataSurfaceServerActionRequest,\n ): string | undefined;\n}\n\nexport interface DataSurfaceActionAdapter {\n preview(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult>;\n apply(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult>;\n}\n\nconst DEFAULT_TOKEN_TTL_MS = 5 * 60 * 1_000;\nconst MAX_IDENTIFIER_LENGTH = 256;\nconst MAX_JSON_DEPTH = 16;\nconst MAX_JSON_ITEMS = 1_000;\nconst FORBIDDEN_JSON_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isBoundedJsonValue(\n value: unknown,\n depth = 0,\n seen = new Set<object>(),\n): value is DataSurfaceJsonValue {\n if (value === null) return true;\n if (['string', 'boolean'].includes(typeof value)) return true;\n if (typeof value === 'number') return Number.isFinite(value);\n if (typeof value !== 'object' || depth >= MAX_JSON_DEPTH || seen.has(value))\n return false;\n seen.add(value);\n if (Array.isArray(value)) {\n if (value.length > MAX_JSON_ITEMS) return false;\n return value.every((item) => isBoundedJsonValue(item, depth + 1, seen));\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return false;\n const entries = Object.entries(value);\n if (entries.length > MAX_JSON_ITEMS) return false;\n return entries.every(\n ([key, item]) =>\n !FORBIDDEN_JSON_KEYS.has(key) &&\n isBoundedJsonValue(item, depth + 1, seen),\n );\n}\n\n/** Validates untrusted extension values before they enter canonical hashing. */\nexport function isBoundedDataSurfaceJsonValue(\n value: unknown,\n): value is DataSurfaceJsonValue {\n return isBoundedJsonValue(value);\n}\n\nfunction validIdentifier(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= MAX_IDENTIFIER_LENGTH\n );\n}\n\nfunction validSelection(\n selection: unknown,\n): selection is DataSurfaceSelectionReference {\n if (!selection || typeof selection !== 'object') return false;\n const candidate = selection as Record<string, unknown>;\n if (candidate.scope === 'current-page') return true;\n if (candidate.scope === 'all-matching')\n return validIdentifier(candidate.queryFingerprint);\n if (candidate.scope !== 'explicit-ids' || !Array.isArray(candidate.rowIds))\n return false;\n if (candidate.rowIds.length > MAX_JSON_ITEMS) return false;\n return candidate.rowIds.every(\n (rowId) =>\n (typeof rowId === 'string' && rowId.length > 0) ||\n (typeof rowId === 'number' && Number.isFinite(rowId)),\n );\n}\n\nfunction stable(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(stable).join(',')}]`;\n return `{${Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))\n .map(([key, item]) => `${JSON.stringify(key)}:${stable(item)}`)\n .join(',')}}`;\n}\n\nfunction fingerprint(value: unknown): string {\n return createHash('sha256').update(stable(value)).digest('hex');\n}\n\nfunction identityKey(identity: DataSurfaceIdentity): string {\n return stable(canonicalIdentity(identity));\n}\n\nfunction canonicalIdentity(identity: DataSurfaceIdentity): DataSurfaceIdentity {\n return {\n kind: identity.kind,\n surfaceId: identity.surfaceId,\n ...(identity.subject\n ? {\n subject: {\n type: identity.subject.type,\n id: identity.subject.id,\n },\n }\n : {}),\n };\n}\n\nfunction rowIdKey(rowId: DataSurfaceRowId): string {\n return `${typeof rowId}:${String(rowId)}`;\n}\n\nfunction compareRowIds(\n left: DataSurfaceRowId,\n right: DataSurfaceRowId,\n): number {\n if (typeof left !== typeof right) return typeof left === 'number' ? -1 : 1;\n if (typeof left === 'number' && typeof right === 'number')\n return left - right;\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction canonicalRowIds(\n rowIds: readonly DataSurfaceRowId[],\n): DataSurfaceRowId[] {\n const ids = new Map<string, DataSurfaceRowId>();\n for (const rowId of rowIds) ids.set(rowIdKey(rowId), rowId);\n return [...ids.values()].sort(compareRowIds);\n}\n\nfunction canonicalSelection(\n selection: DataSurfaceSelectionReference,\n): DataSurfaceSelectionReference {\n if (selection.scope !== 'explicit-ids') return selection;\n return { scope: selection.scope, rowIds: canonicalRowIds(selection.rowIds) };\n}\n\nfunction requestFingerprint(\n request: DataSurfaceServerActionRequest,\n extension?: DataSurfaceJsonValue,\n): string {\n return fingerprint({\n identity: canonicalIdentity(request.identity),\n actionId: request.actionId,\n selection: canonicalSelection(request.selection),\n payload: request.payload,\n expectedRevision: request.expectedRevision,\n ...(extension === undefined ? {} : { extension }),\n });\n}\n\nfunction deepFreeze<T>(value: T, seen = new WeakSet<object>()): T {\n if (!value || typeof value !== 'object' || seen.has(value)) return value;\n seen.add(value);\n for (const nested of Object.values(value)) deepFreeze(nested, seen);\n Object.freeze(value);\n return value;\n}\n\nfunction snapshotRequest(\n request: DataSurfaceServerActionRequest,\n): DataSurfaceServerActionRequest {\n return deepFreeze(structuredClone(request));\n}\n\nfunction snapshotActionContext(\n context: DataSurfaceActionContext,\n): DataSurfaceActionContext {\n const principal = {\n ...context.principal.principal,\n ...(context.principal.principal.allowedTools\n ? { allowedTools: [...context.principal.principal.allowedTools] }\n : {}),\n };\n if (principal.allowedTools) Object.freeze(principal.allowedTools);\n Object.freeze(principal);\n const permissions = context.principal.permissions\n ? [...context.principal.permissions]\n : undefined;\n if (permissions) Object.freeze(permissions);\n const auditMetadata = context.principal.auditMetadata\n ? deepFreeze(structuredClone(context.principal.auditMetadata))\n : undefined;\n const principalOptions: ExecuteAsPrincipalOptions = {\n ...context.principal,\n principal,\n ...(permissions ? { permissions } : {}),\n ...(auditMetadata ? { auditMetadata } : {}),\n };\n Object.freeze(principalOptions);\n return Object.freeze({ principal: principalOptions });\n}\n\nfunction actionFingerprint(action: DataSurfaceServerActionDefinition): string {\n return fingerprint({\n descriptor: action.descriptor,\n inputSchema: action.inputSchema,\n confirmation: action.confirmation,\n execution: action.execution,\n tool: action.tool,\n operationId: action.operation.id,\n operationCollection: action.operation.collection,\n operationAction: action.operation.action,\n });\n}\n\nfunction result(\n request: DataSurfaceServerActionRequest,\n ok: boolean,\n reason?: string,\n details?: DataSurfaceJsonObject,\n confirmationToken?: string,\n): DataSurfaceActionResult {\n return {\n version: 1,\n requestId: request.requestId,\n identity: request.identity,\n actionId: request.actionId,\n phase: request.phase,\n ok,\n ...(reason ? { reason } : {}),\n ...(details ? { details } : {}),\n ...(confirmationToken ? { confirmationToken } : {}),\n };\n}\n\nfunction replayResult(\n request: DataSurfaceServerActionRequest,\n stored: DataSurfaceActionResult,\n): DataSurfaceActionResult {\n // Idempotency keys identify one logical execution, but each transport retry\n // has its own correlation id. Preserve the stored outcome while binding the\n // replay envelope to the request that is receiving it.\n return { ...stored, requestId: request.requestId };\n}\n\nfunction outcomesDetails(\n outcomes: DataSurfaceActionRowOutcome[],\n extra: DataSurfaceJsonObject = {},\n): DataSurfaceJsonObject {\n const accepted = outcomes.filter(\n ({ status }) => status === 'accepted',\n ).length;\n const skipped = outcomes.filter(({ status }) => status === 'skipped').length;\n const failed = outcomes.filter(({ status }) => status === 'failed').length;\n return {\n accepted,\n skipped,\n failed,\n outcomes: outcomes.map(({ metadata, ...outcome }) => ({\n ...(metadata ?? {}),\n ...outcome,\n })),\n ...extra,\n };\n}\n\nfunction validateRequest(\n request: DataSurfaceServerActionRequest,\n phase: 'preview' | 'apply',\n): string | undefined {\n if (!request || typeof request !== 'object') return 'invalid_request';\n if (request.version !== 1 || request.phase !== phase)\n return 'invalid_request';\n if (\n !validIdentifier(request.requestId) ||\n !validIdentifier(request.actionId) ||\n !validIdentifier(request.identity?.surfaceId) ||\n !['table', 'list', 'report', 'custom'].includes(request.identity?.kind) ||\n !validSelection(request.selection) ||\n (request.payload !== undefined && !isBoundedJsonValue(request.payload))\n )\n return 'invalid_request';\n if (\n !Number.isSafeInteger(request.expectedRevision) ||\n request.expectedRevision < 0\n )\n return 'invalid_request';\n if (\n phase === 'apply' &&\n (!validIdentifier(request.idempotencyKey) ||\n (request.confirmationToken !== undefined &&\n !validIdentifier(request.confirmationToken)))\n )\n return 'invalid_request';\n return undefined;\n}\n\n/** Create a transport-neutral, principal-bound data-surface action adapter. */\nexport function createDataSurfaceActionAdapter(\n options: DataSurfaceActionAdapterOptions,\n): DataSurfaceActionAdapter {\n const state = options.state;\n const now = options.now ?? Date.now;\n const createToken =\n options.createToken ?? (() => randomBytes(32).toString('base64url'));\n const tokenTtlMs = options.tokenTtlMs ?? DEFAULT_TOKEN_TTL_MS;\n const runAsPrincipal = options.runAsPrincipal ?? executeAsPrincipal;\n const idempotencyPollIntervalMs = Math.max(\n 1,\n options.idempotencyPollIntervalMs ?? 10,\n );\n const idempotencyWaitTimeoutMs = Math.max(\n 0,\n options.idempotencyWaitTimeoutMs ?? 5_000,\n );\n const fingerprintRequest = (request: DataSurfaceServerActionRequest) =>\n requestFingerprint(request, options.requestFingerprintExtension?.(request));\n\n async function resolveInvocation(\n request: DataSurfaceServerActionRequest,\n run: PrincipalRun,\n ): Promise<DataSurfaceActionInvocation | DataSurfaceActionResult> {\n const surface = await options.resolveSurface(run, request.identity);\n if (\n identityKey(surface.descriptor.identity) !== identityKey(request.identity)\n ) {\n return result(request, false, 'not_found');\n }\n const action = surface.actions[request.actionId];\n const declared = surface.descriptor.actions.find(\n ({ id }) => id === request.actionId,\n );\n if (\n !action ||\n !declared ||\n action.descriptor.id !== declared.id ||\n Boolean(declared.requiresConfirmation) !==\n (action.confirmation === 'required')\n ) {\n return result(request, false, 'unsupported');\n }\n if (\n !action.tool ||\n !validIdentifier(action.operation?.id) ||\n !validIdentifier(action.operation?.action)\n )\n return result(request, false, 'denied');\n run.assertToolAllowed(action.tool);\n await run.assertOperation(\n action.operation.collection,\n action.operation.action,\n );\n const payloadValidation = await action.validatePayload(request.payload);\n if (!payloadValidation.valid)\n return result(\n request,\n false,\n payloadValidation.reason ?? 'invalid_payload',\n );\n if (\n !declared.selectionScopes.includes(request.selection.scope) ||\n !action.descriptor.selectionScopes.includes(request.selection.scope)\n ) {\n return result(request, false, 'selection_not_supported');\n }\n const base = {\n run,\n request,\n descriptor: surface.descriptor,\n action,\n };\n const resolvedSelection = await options.resolveSelection(\n base,\n canonicalSelection(request.selection),\n );\n const selection = {\n ...resolvedSelection,\n rowIds: canonicalRowIds(resolvedSelection.rowIds),\n };\n const invocation = { ...base, selection };\n if (!(await action.authorize(invocation))) {\n return result(request, false, 'denied');\n }\n if (selection.rowIds.length > surface.descriptor.limits.maxSelectionSize) {\n return result(request, false, 'limit_exceeded');\n }\n return invocation;\n }\n\n async function preview(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult> {\n const invalid = validateRequest(request, 'preview');\n if (invalid) return result(request, false, invalid);\n const boundContext = snapshotActionContext(context);\n return runAsPrincipal(\n {\n ...boundContext.principal,\n action: 'data_surface.action.preview',\n auditMetadata: {\n ...boundContext.principal.auditMetadata,\n surfaceId: request.identity.surfaceId,\n actionId: request.actionId,\n requestId: request.requestId,\n },\n },\n async (run) => {\n const invocation = await resolveInvocation(request, run);\n if ('ok' in invocation) return invocation;\n if (invocation.selection.revision !== request.expectedRevision) {\n return result(request, false, 'stale_revision');\n }\n const outcomes: DataSurfaceActionRowOutcome[] = [];\n for (const rowId of invocation.selection.rowIds) {\n const eligibility = await invocation.action.eligible(\n invocation,\n rowId,\n );\n outcomes.push({\n rowId,\n status: eligibility.eligible ? 'accepted' : 'skipped',\n ...(eligibility.reason ? { reason: eligibility.reason } : {}),\n });\n }\n const confirmationToken = createToken();\n const selectionFingerprint = fingerprint(\n canonicalSelection(request.selection),\n );\n const requestFingerprintValue = fingerprintRequest(request);\n const expiresAt = now() + tokenTtlMs;\n await state.putToken(confirmationToken, {\n expiresAt,\n actorUserId: boundContext.principal.principal.runAsUserId,\n tenantId: boundContext.principal.principal.tenantId,\n onBehalfOfUserId: boundContext.principal.onBehalfOfUserId ?? null,\n actsAsProfileId:\n boundContext.principal.principal.actsAsProfileId ?? null,\n agentClass: boundContext.principal.agentClass ?? null,\n identityKey: identityKey(request.identity),\n actionId: request.actionId,\n actionFingerprint: actionFingerprint(invocation.action),\n revision: invocation.selection.revision,\n queryFingerprint: invocation.selection.queryFingerprint,\n selectionFingerprint,\n resolvedRowsFingerprint: fingerprint(\n canonicalRowIds(invocation.selection.rowIds),\n ),\n requestFingerprint: requestFingerprintValue,\n });\n return result(\n request,\n true,\n undefined,\n outcomesDetails(outcomes, {\n count: invocation.selection.rowIds.length,\n revision: invocation.selection.revision,\n queryFingerprint: invocation.selection.queryFingerprint,\n expiresAt,\n }),\n confirmationToken,\n );\n },\n );\n }\n\n async function executeForeground(\n request: DataSurfaceServerActionRequest,\n invocation: DataSurfaceActionInvocation,\n ): Promise<DataSurfaceActionResult> {\n const outcomes: DataSurfaceActionRowOutcome[] = [];\n for (const rowId of invocation.selection.rowIds) {\n try {\n const eligibility = await invocation.action.eligible(invocation, rowId);\n if (!eligibility.eligible) {\n outcomes.push({\n rowId,\n status: 'skipped',\n ...(eligibility.reason ? { reason: eligibility.reason } : {}),\n });\n continue;\n }\n const applied = await invocation.action.apply(invocation, rowId);\n outcomes.push({\n rowId,\n status: 'accepted',\n ...(applied !== null &&\n typeof applied === 'object' &&\n !Array.isArray(applied)\n ? { metadata: applied }\n : {}),\n });\n } catch (error) {\n outcomes.push({\n rowId,\n status: 'failed',\n reason: options.mapError?.(error, request) ?? 'execution_failed',\n });\n }\n }\n return result(request, true, undefined, outcomesDetails(outcomes));\n }\n\n async function executeBackgroundOnce(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n token: DataSurfacePreviewTokenRecord | undefined,\n reference: Readonly<{\n runAsUserId: string;\n tenantId: string | null;\n actsAsProfileId: string | null;\n onBehalfOfUserId: string | null;\n agentClass?: string;\n }>,\n ): Promise<DataSurfaceActionResult> {\n const ownerToken = randomBytes(16).toString('base64url');\n const executionFingerprint = fingerprint({\n kind: 'background-execution',\n request: token?.requestFingerprint ?? fingerprintRequest(request),\n action: token?.actionFingerprint ?? request.actionId,\n });\n const executionScope = fingerprint({\n kind: 'background-execution',\n actorUserId: reference.runAsUserId,\n tenantId: reference.tenantId,\n onBehalfOfUserId: reference.onBehalfOfUserId,\n actsAsProfileId: reference.actsAsProfileId,\n agentClass: reference.agentClass ?? null,\n identity: canonicalIdentity(request.identity),\n actionId: request.actionId,\n idempotencyKey: request.idempotencyKey,\n });\n const maxPolls = Math.max(\n 1,\n Math.ceil(idempotencyWaitTimeoutMs / idempotencyPollIntervalMs),\n );\n for (let poll = 0; poll <= maxPolls; poll += 1) {\n const winner = await state.reserveIdempotency(executionScope, {\n requestFingerprint: executionFingerprint,\n ownerToken,\n reservedAt: now(),\n });\n if (winner.requestFingerprint !== executionFingerprint)\n return result(request, false, 'idempotency_conflict');\n if (winner.status === 'completed')\n return replayResult(request, winner.result);\n if (winner.ownerToken === ownerToken) {\n let executed: DataSurfaceActionResult;\n try {\n // A queued job may run long after the request that created it. The\n // complete persona binding (including the TenantAgent-capped tool\n // allow-list) must therefore be resolved again at execution time.\n const refreshed = await options.resolveDeferredPrincipal?.(reference);\n if (\n !refreshed ||\n refreshed.principal.runAsUserId !== reference.runAsUserId ||\n refreshed.principal.tenantId !== reference.tenantId ||\n (refreshed.principal.actsAsProfileId ?? null) !==\n reference.actsAsProfileId ||\n (refreshed.onBehalfOfUserId ?? null) !==\n reference.onBehalfOfUserId ||\n (refreshed.agentClass ?? null) !== (reference.agentClass ?? null) ||\n !Array.isArray(refreshed.principal.allowedTools)\n ) {\n throw new Error(\n 'Deferred data-surface action principal binding could not be resolved safely',\n );\n }\n // Permission snapshots are never carried across the queue boundary;\n // executeAsPrincipal resolves current RBAC/membership immediately.\n const { permissions: _permissions, ...livePrincipal } = refreshed;\n executed = await authorizedApply(\n request,\n { ...context, principal: livePrincipal },\n token,\n false,\n );\n } catch (error) {\n const reason = options.mapError?.(error, request);\n if (!reason) {\n await state.releaseIdempotency(executionScope, ownerToken);\n throw error;\n }\n executed = result(request, false, reason);\n }\n if (\n !(await state.completeIdempotency(\n executionScope,\n ownerToken,\n executed,\n ))\n ) {\n throw new Error('Lost background action idempotency reservation');\n }\n return executed;\n }\n if (poll < maxPolls) {\n await new Promise<void>((resolve) =>\n setTimeout(resolve, idempotencyPollIntervalMs),\n );\n const current = await state.getIdempotency(executionScope);\n if (current?.status === 'completed')\n return replayResult(request, current.result);\n }\n }\n return result(request, false, 'idempotency_in_progress');\n }\n\n async function authorizedApply(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n token: DataSurfacePreviewTokenRecord | undefined,\n allowBackground: boolean,\n ): Promise<DataSurfaceActionResult> {\n const idempotencyKey = request.idempotencyKey;\n if (!idempotencyKey) return result(request, false, 'invalid_request');\n // Capture the immutable binding before any asynchronous authorization.\n // The host may reuse or mutate its request context after enqueue returns.\n const deferredPrincipalReference = Object.freeze({\n runAsUserId: context.principal.principal.runAsUserId,\n tenantId: context.principal.principal.tenantId,\n actsAsProfileId: context.principal.principal.actsAsProfileId ?? null,\n onBehalfOfUserId: context.principal.onBehalfOfUserId ?? null,\n ...(context.principal.agentClass\n ? { agentClass: context.principal.agentClass }\n : {}),\n });\n return runAsPrincipal(\n {\n ...context.principal,\n action: 'data_surface.action.apply',\n auditMetadata: {\n ...context.principal.auditMetadata,\n surfaceId: request.identity.surfaceId,\n actionId: request.actionId,\n requestId: request.requestId,\n idempotencyKey: request.idempotencyKey,\n },\n },\n async (run) => {\n const invocation = await resolveInvocation(request, run);\n if ('ok' in invocation) return invocation;\n if (token) {\n if (\n fingerprintRequest(request) !== token.requestFingerprint ||\n invocation.selection.revision !== token.revision ||\n invocation.selection.revision !== request.expectedRevision ||\n invocation.selection.queryFingerprint !== token.queryFingerprint ||\n fingerprint(canonicalSelection(request.selection)) !==\n token.selectionFingerprint ||\n actionFingerprint(invocation.action) !== token.actionFingerprint ||\n fingerprint(canonicalRowIds(invocation.selection.rowIds)) !==\n token.resolvedRowsFingerprint\n ) {\n return result(request, false, 'stale_preview');\n }\n } else if (invocation.action.confirmation === 'required') {\n return result(request, false, 'confirmation_required');\n } else if (invocation.selection.revision !== request.expectedRevision) {\n return result(request, false, 'stale_revision');\n }\n if (invocation.action.execution === 'background' && allowBackground) {\n if (!options.backgroundQueue || !options.resolveDeferredPrincipal) {\n return result(request, false, 'background_unavailable');\n }\n const queued = await options.backgroundQueue.enqueue({\n idempotencyKey,\n identity: request.identity,\n actionId: request.actionId,\n rowIds: invocation.selection.rowIds,\n run: () =>\n executeBackgroundOnce(\n request,\n context,\n token,\n deferredPrincipalReference,\n ),\n });\n return result(request, true, undefined, {\n accepted: invocation.selection.rowIds.length,\n skipped: 0,\n failed: 0,\n ...(queued.details ?? {}),\n background: true,\n jobId: queued.jobId,\n // A replayed apply has a new transport request id, while the\n // already-queued job still returns the original execution result.\n // Preserve that correlation id across the replay envelope.\n jobRequestId: request.requestId,\n });\n }\n return executeForeground(request, invocation);\n },\n );\n }\n\n async function apply(\n input: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult> {\n const invalid = validateRequest(input, 'apply');\n if (invalid) return result(input, false, invalid);\n const request = snapshotRequest(input);\n const boundContext = snapshotActionContext(context);\n const confirmationToken = request.confirmationToken;\n const idempotencyKey = request.idempotencyKey;\n if (!idempotencyKey) return result(request, false, 'invalid_request');\n const actorUserId = boundContext.principal.principal.runAsUserId;\n const tenantId = boundContext.principal.principal.tenantId;\n const onBehalfOfUserId = boundContext.principal.onBehalfOfUserId ?? null;\n const actsAsProfileId =\n boundContext.principal.principal.actsAsProfileId ?? null;\n const agentClass = boundContext.principal.agentClass ?? null;\n const requestFingerprintValue = fingerprintRequest(request);\n const idempotencyScope = fingerprint({\n actorUserId,\n tenantId,\n onBehalfOfUserId,\n actsAsProfileId,\n agentClass,\n identity: canonicalIdentity(request.identity),\n actionId: request.actionId,\n idempotencyKey,\n });\n const prior = await state.getIdempotency(idempotencyScope);\n if (prior && prior.requestFingerprint !== requestFingerprintValue)\n return result(request, false, 'idempotency_conflict');\n // A completed durable result is safe to replay from its actor/tenant-bound\n // idempotency scope even when the one-time confirmation has expired.\n if (prior?.status === 'completed')\n return replayResult(request, prior.result);\n\n let token: DataSurfacePreviewTokenRecord | undefined;\n if (confirmationToken) {\n token = await state.getToken(confirmationToken);\n if (!token || token.expiresAt <= now()) {\n return result(request, false, 'invalid_or_expired_confirmation');\n }\n if (\n token.actorUserId !== actorUserId ||\n token.tenantId !== tenantId ||\n token.onBehalfOfUserId !== onBehalfOfUserId ||\n token.actsAsProfileId !== actsAsProfileId ||\n token.agentClass !== agentClass ||\n token.identityKey !== identityKey(request.identity) ||\n token.actionId !== request.actionId ||\n token.requestFingerprint !== requestFingerprintValue\n ) {\n return result(request, false, 'confirmation_mismatch');\n }\n if (!(await state.markTokenConsumed(confirmationToken, idempotencyKey))) {\n return result(request, false, 'confirmation_replayed');\n }\n }\n // Ownership is an internal compare-and-set nonce. Keep it independent of\n // the injectable preview-token factory, which tests or callers may make\n // deterministic without weakening concurrent winner selection.\n const ownerToken = randomBytes(16).toString('base64url');\n const maxPolls = Math.max(\n 1,\n Math.ceil(idempotencyWaitTimeoutMs / idempotencyPollIntervalMs),\n );\n for (let poll = 0; poll <= maxPolls; poll += 1) {\n const winner = await state.reserveIdempotency(idempotencyScope, {\n requestFingerprint: requestFingerprintValue,\n ownerToken,\n reservedAt: now(),\n });\n if (winner.requestFingerprint !== requestFingerprintValue)\n return result(request, false, 'idempotency_conflict');\n if (winner.status === 'completed')\n return replayResult(request, winner.result);\n if (winner.ownerToken === ownerToken) {\n let applied: DataSurfaceActionResult;\n try {\n applied = await authorizedApply(request, boundContext, token, true);\n } catch (error) {\n await state.releaseIdempotency(idempotencyScope, ownerToken);\n throw error;\n }\n // A confirmation-required request without a token is a recoverable\n // precondition failure. Do not consume its idempotency key: the caller\n // may preview and retry with the same key.\n if (!applied.ok && applied.reason === 'confirmation_required') {\n await state.releaseIdempotency(idempotencyScope, ownerToken);\n return applied;\n }\n // Once execution returns, never release on a persistence failure: a\n // durable reservation is safer than allowing duplicate side effects.\n if (\n !(await state.completeIdempotency(\n idempotencyScope,\n ownerToken,\n applied,\n ))\n ) {\n throw new Error('Lost data-surface idempotency reservation');\n }\n return applied;\n }\n if (poll < maxPolls) {\n await new Promise<void>((resolve) =>\n setTimeout(resolve, idempotencyPollIntervalMs),\n );\n const current = await state.getIdempotency(idempotencyScope);\n if (current?.status === 'completed')\n return replayResult(request, current.result);\n }\n }\n return result(request, false, 'idempotency_in_progress');\n }\n\n return { preview, apply };\n}\n","/**\n * Serialization utilities for resolved agents\n *\n * Converts ResolvedAgentAvailability (database + manifest data) into\n * a JSON-safe shape suitable for passing to client components.\n *\n * @module @happyvertical/smrt-agents/server\n */\n\nimport { sanitizeConfig } from '@happyvertical/smrt-config';\nimport type { ResolvedAgentAvailability } from '../tenant-agent.js';\nimport type { AgentAdminRoute, AgentUISlots } from '../ui.js';\n\n/**\n * Serialized agent data for passing to client components.\n *\n * Includes manifest-derived fields (icon, permissions, slots)\n * alongside resolution metadata (source, sourceTenantId).\n */\nexport interface SerializedAgent {\n /** Agent instance ID, or a synthetic key if no instance exists */\n id: string;\n /** Human-readable name from manifest */\n name?: string;\n /** Human-readable agent class name (e.g., 'Praeco') */\n agentClass: string;\n /** Canonical agent type (qualified name when available) */\n agentType: string;\n /** STI type discriminator (same as agentType) */\n _meta_type?: string;\n /** UI slot definitions from manifest */\n slots?: AgentUISlots;\n /** Admin route declarations from manifest */\n adminRoutes?: AgentAdminRoute[];\n /** How this agent was resolved for the tenant */\n source?: 'explicit' | 'inherited';\n /** Which tenant the binding came from */\n sourceTenantId?: string;\n /** Merged permissions from manifest + tenant overrides */\n permissions?: Record<string, boolean>;\n /** Agent icon from manifest */\n icon?: string;\n /**\n * Tenant-level config overrides, **secret-sanitized** for client transport.\n *\n * SECURITY (#1553, follow-up to #1552): the raw `TenantAgent.config` is the\n * tenant's own override blob and is `@field({ sensitive: true })` (stripped\n * from the generated CRUD api/mcp surfaces). This hand-written admin\n * serialization runs it through `sanitizeConfig()` from\n * `@happyvertical/smrt-config` before it leaves the server, so secret-shaped\n * keys (apiKey/token/password/…) are dropped and secret-shaped values\n * (`sk-…`, `AKIA…`, `Bearer …`, URL credentials, PEM blocks) are masked —\n * non-secret config still reaches the authorized admin UI for display.\n *\n * This is **display-only**: do not edit-round-trip it back to the server\n * (a masked value would overwrite the real secret). Best practice remains to\n * reference secrets by id via `@happyvertical/smrt-secrets` so only an opaque\n * handle is ever stored in tenant config.\n */\n config?: Record<string, unknown>;\n}\n\n/**\n * Convert a ResolvedAgentAvailability to a serializable shape for the UI.\n *\n * @param resolved - Output from TenantAgentCollection.resolveForTenant()\n * @returns Serialized agent data safe for JSON transport\n */\nexport function serializeResolvedAgent(\n resolved: ResolvedAgentAvailability,\n): SerializedAgent {\n const manifest = resolved.manifest;\n\n return {\n id: resolved.agentId || `${resolved.sourceTenantId}:${resolved.agentType}`,\n name: manifest?.name || resolved.agentClass,\n agentClass: resolved.agentClass,\n agentType: resolved.agentType,\n _meta_type: resolved.agentType,\n slots: manifest?.uiSlots as AgentUISlots | undefined,\n adminRoutes: manifest?.adminRoutes as AgentAdminRoute[] | undefined,\n source: resolved.source,\n sourceTenantId: resolved.sourceTenantId,\n permissions: resolved.permissions,\n icon: manifest?.icon,\n // Secret-sanitize before the blob crosses into the client payload (#1553).\n config: sanitizeConfig(resolved.config) as SerializedAgent['config'],\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","names":["result"],"sources":["../src/server/api-routes.ts","../src/server/config-loader.ts","../src/server/data-surface-actions.ts","../src/server/jobs-data-surface-action-queue.ts","../src/server/serialization.ts","../src/server/sql-data-surface-action-state.ts"],"sourcesContent":["/**\n * Server-side API route resolution for SMRT agents\n *\n * Reads agent package manifests and builds a route map from resource\n * paths (e.g., 'performers', 'video-contents') to SmrtObject class\n * names and allowed CRUD actions. The catch-all API handler uses this\n * to resolve incoming requests.\n *\n * @module @happyvertical/smrt-agents/server\n */\n\nimport type { PackageManifest } from './manifest-utils.js';\n\n/**\n * Info about a single API route (one SmrtObject with api.include)\n */\nexport interface AgentAPIRouteInfo {\n /** SmrtObject class name (e.g., 'Performer') */\n className: string;\n /** Allowed CRUD actions (e.g., ['list', 'get', 'create', 'update', 'delete']) */\n allowedActions: string[];\n /** Package that owns this resource */\n packageName?: string;\n}\n\n/**\n * Result of resolving a URL path against the route map\n */\nexport interface ResolvedAPIRoute {\n /** The matched route info */\n route: AgentAPIRouteInfo;\n /** Resource ID if path includes one (e.g., 'performers/abc-123') */\n id?: string;\n /** Custom action name if path includes one (e.g., 'performers/abc-123/generate-image') */\n action?: string;\n}\n\n/**\n * Build a route map from loaded package manifests.\n *\n * Iterates all objects in each manifest, and for any object with a\n * `decoratorConfig.api.include` array, registers a route. The route\n * path is derived from `decoratorConfig.api.path` if set, otherwise\n * from the table name with underscores converted to hyphens.\n *\n * @param manifests - Array of parsed package manifest JSON objects\n * @returns Map of resource path -> route info\n *\n * @example\n * ```typescript\n * const manifests = [histrioManifest, praecoManifest];\n * const routes = buildRouteMap(manifests);\n * // routes.get('performers') => { className: 'Performer', allowedActions: ['list', 'get', 'create', 'update', 'delete'] }\n * // routes.get('video-contents') => { className: 'VideoShot', allowedActions: ['list', 'get', 'create', 'update'] }\n * ```\n */\nexport function buildRouteMap(\n manifests: PackageManifest[],\n): Map<string, AgentAPIRouteInfo> {\n const routes = new Map<string, AgentAPIRouteInfo>();\n\n for (const manifest of manifests) {\n const packageName = (manifest as Record<string, unknown>).packageName as\n | string\n | undefined;\n\n for (const obj of Object.values(manifest.objects)) {\n const config = obj.decoratorConfig as Record<string, unknown> | undefined;\n if (!config) continue;\n\n const api = config.api as\n | { include?: string[]; path?: string }\n | undefined;\n if (!api?.include || api.include.length === 0) continue;\n\n // Derive the URL path: explicit api.path, or table name with _ -> -\n const tableName = config.tableName as string | undefined;\n const path =\n api.path || (tableName ? tableName.replace(/_/g, '-') : null);\n if (!path) continue;\n\n routes.set(path, {\n className: obj.className,\n allowedActions: api.include,\n packageName,\n });\n }\n }\n\n return routes;\n}\n\n/**\n * Resolve a URL resource path against a route map.\n *\n * Handles three URL patterns:\n * - `performers` → list/create (no id)\n * - `performers/abc-123` → get/update/delete (with id)\n * - `performers/abc-123/generate-image` → custom action\n *\n * @param urlPath - The resource portion of the URL (after `/api/agents/{agentId}/`)\n * @param routes - Route map from {@link buildRouteMap}\n * @returns Resolved route with optional id/action, or null if no match\n */\nexport function resolveAPIRoute(\n urlPath: string,\n routes: Map<string, AgentAPIRouteInfo>,\n): ResolvedAPIRoute | null {\n // Normalize: strip leading/trailing slashes\n const normalized = urlPath.replace(/^\\/+|\\/+$/g, '');\n if (!normalized) return null;\n\n const segments = normalized.split('/');\n\n // Try 1-segment: \"performers\"\n if (segments.length === 1) {\n const route = routes.get(segments[0]);\n if (route) return { route };\n return null;\n }\n\n // Try 2-segment: \"performers/{id}\"\n if (segments.length === 2) {\n const route = routes.get(segments[0]);\n if (route) return { route, id: segments[1] };\n return null;\n }\n\n // Try 3-segment: \"performers/{id}/{action}\"\n if (segments.length === 3) {\n const route = routes.get(segments[0]);\n if (route) return { route, id: segments[1], action: segments[2] };\n return null;\n }\n\n return null;\n}\n","/**\n * Server-side agent config loading utilities\n *\n * Loads slot configurations from the agent_configs table for a set of agents.\n * Agent-specific table loading (e.g., praeco_sources) stays in the host app.\n *\n * @module @happyvertical/smrt-agents/server\n */\n\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { AgentConfig } from '../config.js';\n\n/**\n * Load slot configs for multiple agents from the agent_configs table.\n *\n * Returns a nested map: agentId -> slotId -> configData.\n * Agent-specific tables (e.g., praeco_sources, praeco_reports)\n * are NOT loaded here — those stay in the host application.\n *\n * @param agents - Array of agent identifiers (id + agentClass)\n * @param dbOptions - Database options for SmrtCollection.create()\n * @returns Map of agentId -> slotId -> config data\n */\nexport async function loadSlotConfigs(\n agents: Array<{ id: string; agentClass: string }>,\n dbOptions: SmrtClassOptions,\n): Promise<Record<string, Record<string, unknown>>> {\n if (agents.length === 0) {\n return {};\n }\n\n try {\n const configsByAgent = await AgentConfig.forAgents(\n agents.map((agent) => agent.id),\n dbOptions,\n );\n\n const configs: Record<string, Record<string, unknown>> = {};\n for (const [agentId, slotConfigs] of configsByAgent) {\n const agentConfig: Record<string, unknown> = {};\n for (const [slotId, configData] of slotConfigs) {\n agentConfig[slotId] = configData;\n }\n if (Object.keys(agentConfig).length > 0) {\n configs[agentId] = agentConfig;\n }\n }\n\n return configs;\n } catch (error) {\n if (isMissingAgentConfigTableError(error)) {\n return {};\n }\n throw error;\n }\n}\n\nfunction isMissingAgentConfigTableError(error: unknown): boolean {\n const message = String((error as Error)?.message || error || '');\n\n return (\n message.includes(\"Run 'smrt db:migrate'\") ||\n /no such table[:\\s]+agent_configs/i.test(message) ||\n /relation .*agent_configs.*does not exist/i.test(message) ||\n /table .*agent_configs.*doesn'?t exist/i.test(message)\n );\n}\n","/**\n * Principal-bound preview/apply orchestration for data-surface actions.\n *\n * Browser state is treated only as an input hint. Every preview and apply is\n * executed under the bound principal, resolves the surface and selection\n * afresh, and delegates durable work only after authorization and eligibility\n * checks have passed.\n */\nimport { createHash, randomBytes } from 'node:crypto';\nimport {\n createHmacDurableJobPayloadSigner,\n type DurableJobPayloadIntegrity,\n} from '@happyvertical/smrt-jobs';\nimport type {\n DataSurfaceActionDescriptor,\n DataSurfaceActionResult,\n DataSurfaceActionRowOutcome,\n DataSurfaceActionWireRequest,\n DataSurfaceDescriptor,\n DataSurfaceIdentity,\n DataSurfaceJsonObject,\n DataSurfaceJsonValue,\n DataSurfaceRowId,\n DataSurfaceSelectionReference,\n} from '@happyvertical/smrt-types';\nimport {\n type ExecuteAsPrincipalOptions,\n executeAsPrincipal,\n type PrincipalRun,\n} from '../execute-as-principal.js';\n\nexport type DataSurfaceConfirmationPolicy = 'required' | 'none';\nexport type DataSurfaceActionExecution = 'foreground' | 'background';\n\nexport interface DataSurfaceActionEligibility {\n eligible: boolean;\n reason?: string;\n}\n\nexport type DataSurfaceActionPayloadValidation =\n | { valid: true }\n | { valid: false; reason?: string };\n\nexport interface ResolvedDataSurfaceSelection {\n /** Fresh server-side revision of the selected surface/query. */\n revision: number;\n /** Canonical fingerprint of the frozen query represented by the selection. */\n queryFingerprint: string;\n /** Authoritatively resolved row ids. Browser-provided ids are only hints. */\n rowIds: DataSurfaceRowId[];\n}\n\nexport interface DataSurfaceActionInvocation {\n run: PrincipalRun;\n request: DataSurfaceServerActionRequest;\n descriptor: DataSurfaceDescriptor;\n action: DataSurfaceServerActionDefinition;\n selection: ResolvedDataSurfaceSelection;\n}\n\nexport interface DataSurfaceServerActionDefinition {\n descriptor: DataSurfaceActionDescriptor;\n /** Serializable declaration for transport/schema generators; null means no input. */\n inputSchema: DataSurfaceJsonObject | null;\n /** Runtime enforcement for the declared schema; absence is never permissive. */\n validatePayload(\n payload: DataSurfaceJsonValue | undefined,\n ):\n | DataSurfaceActionPayloadValidation\n | Promise<DataSurfaceActionPayloadValidation>;\n /** Explicit for every action, including sensitive/public/destructive ones. */\n confirmation: DataSurfaceConfirmationPolicy;\n execution: DataSurfaceActionExecution;\n /** Fail-closed persona capability checked by PrincipalRun. */\n tool: string;\n /** Explicit RBAC catalog gate, enforced independently of callback convention. */\n operation: {\n id: string;\n collection: Parameters<PrincipalRun['assertOperation']>[0];\n action: string;\n };\n /** Fresh permission/domain authorization check, run for preview and apply. */\n authorize(\n invocation: DataSurfaceActionInvocation,\n ): boolean | Promise<boolean>;\n /** Fresh per-row domain precondition check, repeated at apply time. */\n eligible(\n invocation: DataSurfaceActionInvocation,\n rowId: DataSurfaceRowId,\n ): DataSurfaceActionEligibility | Promise<DataSurfaceActionEligibility>;\n /** Foreground mutation. Background definitions are run by the injected queue. */\n apply(\n invocation: DataSurfaceActionInvocation,\n rowId: DataSurfaceRowId,\n ):\n | undefined\n | DataSurfaceJsonValue\n | Promise<undefined | DataSurfaceJsonValue>;\n}\n\nexport interface ResolvedDataSurfaceActions {\n descriptor: DataSurfaceDescriptor;\n /** Current server-side revision, never trusted from the browser. */\n revision: number;\n actions: Record<string, DataSurfaceServerActionDefinition>;\n}\n\nexport interface DataSurfaceServerActionRequest\n extends DataSurfaceActionWireRequest {}\n\nexport interface DataSurfaceActionContext {\n principal: ExecuteAsPrincipalOptions;\n}\n\nexport interface DataSurfaceDeferredPrincipalReference {\n runAsUserId: string;\n tenantId: string | null;\n actsAsProfileId: string | null;\n onBehalfOfUserId: string | null;\n agentClass?: string;\n}\n\n/** Serializable, versioned payload persisted by a durable background queue. */\nexport interface DataSurfaceBackgroundActionEnvelope {\n version: 1;\n handlerId: string;\n request: DataSurfaceServerActionRequest;\n principal: DataSurfaceDeferredPrincipalReference;\n previewToken?: DataSurfacePreviewTokenRecord;\n /** Server-authenticated binding over every other persisted envelope field. */\n binding: DurableJobPayloadIntegrity;\n}\n\nexport interface DataSurfaceBackgroundActionJob {\n idempotencyKey: string;\n identity: DataSurfaceIdentity;\n actionId: string;\n rowIds: DataSurfaceRowId[];\n envelope: DataSurfaceBackgroundActionEnvelope;\n /**\n * The queue must call this task to perform the work. It re-enters the bound\n * principal and repeats descriptor, authorization, selection, and eligibility\n * checks before any mutation.\n */\n run: () => Promise<DataSurfaceActionResult>;\n}\n\nexport interface DataSurfaceBackgroundQueue {\n enqueue(\n job: DataSurfaceBackgroundActionJob,\n ): Promise<{ jobId: string; details?: DataSurfaceJsonObject }>;\n}\n\nexport interface DataSurfacePreviewTokenRecord {\n expiresAt: number;\n actorUserId: string;\n tenantId: string | null;\n onBehalfOfUserId: string | null;\n actsAsProfileId: string | null;\n agentClass: string | null;\n identityKey: string;\n actionId: string;\n actionFingerprint: string;\n revision: number;\n queryFingerprint: string;\n selectionFingerprint: string;\n resolvedRowsFingerprint: string;\n requestFingerprint: string;\n consumedBy?: string;\n}\n\nexport type DataSurfaceIdempotencyRecord =\n | {\n status: 'reserved';\n requestFingerprint: string;\n ownerToken: string;\n reservedAt: number;\n }\n | {\n status: 'completed';\n requestFingerprint: string;\n result: DataSurfaceActionResult;\n recovery?: DataSurfaceIdempotencyRecoveryEvidence;\n };\n\nexport interface DataSurfaceIdempotencyRecoveryEvidence {\n authorizedBy: string;\n evidence: string;\n reconciledAt: number;\n}\n\nexport interface DataSurfaceIdempotencyReservation {\n requestFingerprint: string;\n ownerToken: string;\n reservedAt: number;\n}\n\nexport interface DataSurfaceActionStateStore {\n putToken(\n token: string,\n record: DataSurfacePreviewTokenRecord,\n ): Promise<void> | void;\n getToken(\n token: string,\n ):\n | Promise<DataSurfacePreviewTokenRecord | undefined>\n | DataSurfacePreviewTokenRecord\n | undefined;\n markTokenConsumed(\n token: string,\n idempotencyKey: string,\n ): Promise<boolean> | boolean;\n /** Atomically consume a preview token and create/read its apply reservation. */\n consumeTokenAndReserveIdempotency(\n token: string,\n idempotencyKey: string,\n scope: string,\n reservation: DataSurfaceIdempotencyReservation,\n ):\n | Promise<DataSurfaceIdempotencyRecord | undefined>\n | DataSurfaceIdempotencyRecord\n | undefined;\n getIdempotency(\n key: string,\n ):\n | Promise<DataSurfaceIdempotencyRecord | undefined>\n | DataSurfaceIdempotencyRecord\n | undefined;\n /** Atomically create a durable reservation or return the existing record. */\n reserveIdempotency(\n key: string,\n reservation: DataSurfaceIdempotencyReservation,\n ): Promise<DataSurfaceIdempotencyRecord> | DataSurfaceIdempotencyRecord;\n completeIdempotency(\n key: string,\n ownerToken: string,\n result: DataSurfaceActionResult,\n ): Promise<boolean> | boolean;\n releaseIdempotency(\n key: string,\n ownerToken: string,\n ): Promise<boolean> | boolean;\n}\n\n/** Explicit single-process/testing store; production callers inject shared state. */\nexport class InMemoryDataSurfaceActionStateStore\n implements DataSurfaceActionStateStore\n{\n private readonly tokens = new Map<string, DataSurfacePreviewTokenRecord>();\n private readonly idempotency = new Map<\n string,\n DataSurfaceIdempotencyRecord\n >();\n\n putToken(token: string, record: DataSurfacePreviewTokenRecord): void {\n this.tokens.set(token, record);\n }\n\n getToken(token: string): DataSurfacePreviewTokenRecord | undefined {\n return this.tokens.get(token);\n }\n\n markTokenConsumed(token: string, idempotencyKey: string): boolean {\n const record = this.tokens.get(token);\n if (!record) return false;\n if (record.consumedBy && record.consumedBy !== idempotencyKey) return false;\n record.consumedBy = idempotencyKey;\n return true;\n }\n\n consumeTokenAndReserveIdempotency(\n token: string,\n idempotencyKey: string,\n scope: string,\n reservation: DataSurfaceIdempotencyReservation,\n ): DataSurfaceIdempotencyRecord | undefined {\n const tokenRecord = this.tokens.get(token);\n if (\n !tokenRecord ||\n (tokenRecord.consumedBy && tokenRecord.consumedBy !== idempotencyKey)\n ) {\n return undefined;\n }\n const existing = this.idempotency.get(scope);\n if (!existing) {\n this.idempotency.set(scope, { status: 'reserved', ...reservation });\n }\n tokenRecord.consumedBy = idempotencyKey;\n return this.idempotency.get(scope);\n }\n\n getIdempotency(key: string): DataSurfaceIdempotencyRecord | undefined {\n return this.idempotency.get(key);\n }\n\n reserveIdempotency(\n key: string,\n reservation: DataSurfaceIdempotencyReservation,\n ): DataSurfaceIdempotencyRecord {\n const existing = this.idempotency.get(key);\n if (existing) return existing;\n const record: DataSurfaceIdempotencyRecord = {\n status: 'reserved',\n ...reservation,\n };\n this.idempotency.set(key, record);\n return record;\n }\n\n completeIdempotency(\n key: string,\n ownerToken: string,\n result: DataSurfaceActionResult,\n ): boolean {\n const existing = this.idempotency.get(key);\n if (existing?.status !== 'reserved' || existing.ownerToken !== ownerToken)\n return false;\n this.idempotency.set(key, {\n status: 'completed',\n requestFingerprint: existing.requestFingerprint,\n result,\n });\n return true;\n }\n\n releaseIdempotency(key: string, ownerToken: string): boolean {\n const existing = this.idempotency.get(key);\n if (existing?.status !== 'reserved' || existing.ownerToken !== ownerToken)\n return false;\n return this.idempotency.delete(key);\n }\n}\n\nexport interface DataSurfaceActionAdapterOptions {\n resolveSurface(\n run: PrincipalRun,\n identity: DataSurfaceIdentity,\n ): Promise<ResolvedDataSurfaceActions>;\n resolveSelection(\n invocation: Omit<DataSurfaceActionInvocation, 'selection'>,\n selection: DataSurfaceSelectionReference,\n ): Promise<ResolvedDataSurfaceSelection>;\n backgroundQueue?: DataSurfaceBackgroundQueue;\n /** Stable worker registration key required by durable background queues. */\n backgroundHandlerId?: string;\n /** Secret used only in-process to authenticate durable background envelopes. */\n deferredEnvelopeSigningKey?: string | Uint8Array;\n /** Required durable, shared backend in production; memory storage is opt-in. */\n state: DataSurfaceActionStateStore;\n tokenTtlMs?: number;\n now?: () => number;\n createToken?: () => string;\n runAsPrincipal?: typeof executeAsPrincipal;\n /**\n * Re-resolve the complete current binding immediately before deferred work.\n * Background execution fails closed when this seam is absent or returns a\n * binding for a different principal.\n */\n resolveDeferredPrincipal?(\n reference: Readonly<{\n runAsUserId: string;\n tenantId: string | null;\n actsAsProfileId: string | null;\n onBehalfOfUserId: string | null;\n agentClass?: string;\n }>,\n ): ExecuteAsPrincipalOptions | Promise<ExecuteAsPrincipalOptions>;\n idempotencyPollIntervalMs?: number;\n idempotencyWaitTimeoutMs?: number;\n /** Domain-specific request input that must participate in confirmation/idempotency. */\n requestFingerprintExtension?(\n request: DataSurfaceServerActionRequest,\n ): DataSurfaceJsonValue | undefined;\n /** Maps terminal domain failures; return undefined to preserve queue retries. */\n mapError?(\n error: unknown,\n request: DataSurfaceServerActionRequest,\n ): string | undefined;\n}\n\nexport interface DataSurfaceActionAdapter {\n preview(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult>;\n apply(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult>;\n /** Worker entry point; re-resolves current authority before any mutation. */\n executeDeferred(\n envelope: DataSurfaceBackgroundActionEnvelope,\n ): Promise<DataSurfaceActionResult>;\n}\n\nconst DEFAULT_TOKEN_TTL_MS = 5 * 60 * 1_000;\nconst MAX_IDENTIFIER_LENGTH = 256;\nconst MAX_JSON_DEPTH = 16;\nconst MAX_JSON_ITEMS = 1_000;\nconst FORBIDDEN_JSON_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isBoundedJsonValue(\n value: unknown,\n depth = 0,\n seen = new Set<object>(),\n): value is DataSurfaceJsonValue {\n if (value === null) return true;\n if (['string', 'boolean'].includes(typeof value)) return true;\n if (typeof value === 'number') return Number.isFinite(value);\n if (typeof value !== 'object' || depth >= MAX_JSON_DEPTH || seen.has(value))\n return false;\n seen.add(value);\n if (Array.isArray(value)) {\n if (value.length > MAX_JSON_ITEMS) return false;\n return value.every((item) => isBoundedJsonValue(item, depth + 1, seen));\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return false;\n const entries = Object.entries(value);\n if (entries.length > MAX_JSON_ITEMS) return false;\n return entries.every(\n ([key, item]) =>\n !FORBIDDEN_JSON_KEYS.has(key) &&\n isBoundedJsonValue(item, depth + 1, seen),\n );\n}\n\n/** Validates untrusted extension values before they enter canonical hashing. */\nexport function isBoundedDataSurfaceJsonValue(\n value: unknown,\n): value is DataSurfaceJsonValue {\n return isBoundedJsonValue(value);\n}\n\nfunction validIdentifier(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= MAX_IDENTIFIER_LENGTH\n );\n}\n\nfunction validSelection(\n selection: unknown,\n): selection is DataSurfaceSelectionReference {\n if (!selection || typeof selection !== 'object') return false;\n const candidate = selection as Record<string, unknown>;\n if (candidate.scope === 'current-page') return true;\n if (candidate.scope === 'all-matching')\n return validIdentifier(candidate.queryFingerprint);\n if (candidate.scope !== 'explicit-ids' || !Array.isArray(candidate.rowIds))\n return false;\n if (candidate.rowIds.length > MAX_JSON_ITEMS) return false;\n return candidate.rowIds.every(\n (rowId) =>\n (typeof rowId === 'string' && rowId.length > 0) ||\n (typeof rowId === 'number' && Number.isFinite(rowId)),\n );\n}\n\nfunction stable(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(stable).join(',')}]`;\n return `{${Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))\n .map(([key, item]) => `${JSON.stringify(key)}:${stable(item)}`)\n .join(',')}}`;\n}\n\nfunction fingerprint(value: unknown): string {\n return createHash('sha256').update(stable(value)).digest('hex');\n}\n\nfunction envelopeBinding(\n envelope: Omit<DataSurfaceBackgroundActionEnvelope, 'binding'>,\n key: string | Uint8Array,\n): DurableJobPayloadIntegrity {\n return createHmacDurableJobPayloadSigner({\n keyId: 'data-surface-envelope-v1',\n key,\n }).sign(envelope);\n}\n\nfunction validSigningKey(key: string | Uint8Array | undefined): boolean {\n return (\n key !== undefined &&\n (typeof key === 'string' ? Buffer.byteLength(key) : key.byteLength) >= 32\n );\n}\n\nfunction bindingMatches(\n envelope: DataSurfaceBackgroundActionEnvelope,\n key: string | Uint8Array,\n): boolean {\n const { binding, ...unsigned } = envelope;\n return createHmacDurableJobPayloadSigner({\n keyId: 'data-surface-envelope-v1',\n key,\n }).verify(unsigned, binding);\n}\n\nfunction identityKey(identity: DataSurfaceIdentity): string {\n return stable(canonicalIdentity(identity));\n}\n\nfunction canonicalIdentity(identity: DataSurfaceIdentity): DataSurfaceIdentity {\n return {\n kind: identity.kind,\n surfaceId: identity.surfaceId,\n ...(identity.subject\n ? {\n subject: {\n type: identity.subject.type,\n id: identity.subject.id,\n },\n }\n : {}),\n };\n}\n\nfunction rowIdKey(rowId: DataSurfaceRowId): string {\n return `${typeof rowId}:${String(rowId)}`;\n}\n\nfunction compareRowIds(\n left: DataSurfaceRowId,\n right: DataSurfaceRowId,\n): number {\n if (typeof left !== typeof right) return typeof left === 'number' ? -1 : 1;\n if (typeof left === 'number' && typeof right === 'number')\n return left - right;\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction canonicalRowIds(\n rowIds: readonly DataSurfaceRowId[],\n): DataSurfaceRowId[] {\n const ids = new Map<string, DataSurfaceRowId>();\n for (const rowId of rowIds) ids.set(rowIdKey(rowId), rowId);\n return [...ids.values()].sort(compareRowIds);\n}\n\nfunction canonicalSelection(\n selection: DataSurfaceSelectionReference,\n): DataSurfaceSelectionReference {\n if (selection.scope !== 'explicit-ids') return selection;\n return { scope: selection.scope, rowIds: canonicalRowIds(selection.rowIds) };\n}\n\nfunction requestFingerprint(\n request: DataSurfaceServerActionRequest,\n extension?: DataSurfaceJsonValue,\n): string {\n return fingerprint({\n identity: canonicalIdentity(request.identity),\n actionId: request.actionId,\n selection: canonicalSelection(request.selection),\n payload: request.payload,\n expectedRevision: request.expectedRevision,\n ...(extension === undefined ? {} : { extension }),\n });\n}\n\nfunction deepFreeze<T>(value: T, seen = new WeakSet<object>()): T {\n if (!value || typeof value !== 'object' || seen.has(value)) return value;\n seen.add(value);\n for (const nested of Object.values(value)) deepFreeze(nested, seen);\n Object.freeze(value);\n return value;\n}\n\nfunction snapshotRequest(\n request: DataSurfaceServerActionRequest,\n): DataSurfaceServerActionRequest {\n return deepFreeze(structuredClone(request));\n}\n\nfunction snapshotActionContext(\n context: DataSurfaceActionContext,\n): DataSurfaceActionContext {\n const principal = {\n ...context.principal.principal,\n ...(context.principal.principal.allowedTools\n ? { allowedTools: [...context.principal.principal.allowedTools] }\n : {}),\n };\n if (principal.allowedTools) Object.freeze(principal.allowedTools);\n Object.freeze(principal);\n const permissions = context.principal.permissions\n ? [...context.principal.permissions]\n : undefined;\n if (permissions) Object.freeze(permissions);\n const auditMetadata = context.principal.auditMetadata\n ? deepFreeze(structuredClone(context.principal.auditMetadata))\n : undefined;\n const principalOptions: ExecuteAsPrincipalOptions = {\n ...context.principal,\n principal,\n ...(permissions ? { permissions } : {}),\n ...(auditMetadata ? { auditMetadata } : {}),\n };\n Object.freeze(principalOptions);\n return Object.freeze({ principal: principalOptions });\n}\n\nfunction actionFingerprint(action: DataSurfaceServerActionDefinition): string {\n return fingerprint({\n descriptor: action.descriptor,\n inputSchema: action.inputSchema,\n confirmation: action.confirmation,\n execution: action.execution,\n tool: action.tool,\n operationId: action.operation.id,\n operationCollection: action.operation.collection,\n operationAction: action.operation.action,\n });\n}\n\nfunction result(\n request: DataSurfaceServerActionRequest,\n ok: boolean,\n reason?: string,\n details?: DataSurfaceJsonObject,\n confirmationToken?: string,\n): DataSurfaceActionResult {\n return {\n version: 1,\n requestId: request.requestId,\n identity: request.identity,\n actionId: request.actionId,\n phase: request.phase,\n ok,\n ...(reason ? { reason } : {}),\n ...(details ? { details } : {}),\n ...(confirmationToken ? { confirmationToken } : {}),\n };\n}\n\nfunction replayResult(\n request: DataSurfaceServerActionRequest,\n stored: DataSurfaceActionResult,\n): DataSurfaceActionResult {\n // Idempotency keys identify one logical execution, but each transport retry\n // has its own correlation id. Preserve the stored outcome while binding the\n // replay envelope to the request that is receiving it.\n return { ...stored, requestId: request.requestId };\n}\n\nfunction outcomesDetails(\n outcomes: DataSurfaceActionRowOutcome[],\n extra: DataSurfaceJsonObject = {},\n): DataSurfaceJsonObject {\n const accepted = outcomes.filter(\n ({ status }) => status === 'accepted',\n ).length;\n const skipped = outcomes.filter(({ status }) => status === 'skipped').length;\n const failed = outcomes.filter(({ status }) => status === 'failed').length;\n return {\n accepted,\n skipped,\n failed,\n outcomes: outcomes.map(({ metadata, ...outcome }) => ({\n ...(metadata ?? {}),\n ...outcome,\n })),\n ...extra,\n };\n}\n\nfunction validateRequest(\n request: DataSurfaceServerActionRequest,\n phase: 'preview' | 'apply',\n): string | undefined {\n if (!request || typeof request !== 'object') return 'invalid_request';\n if (request.version !== 1 || request.phase !== phase)\n return 'invalid_request';\n if (\n !validIdentifier(request.requestId) ||\n !validIdentifier(request.actionId) ||\n !validIdentifier(request.identity?.surfaceId) ||\n !['table', 'list', 'report', 'custom'].includes(request.identity?.kind) ||\n !validSelection(request.selection) ||\n (request.payload !== undefined && !isBoundedJsonValue(request.payload))\n )\n return 'invalid_request';\n if (\n !Number.isSafeInteger(request.expectedRevision) ||\n request.expectedRevision < 0\n )\n return 'invalid_request';\n if (\n phase === 'apply' &&\n (!validIdentifier(request.idempotencyKey) ||\n (request.confirmationToken !== undefined &&\n !validIdentifier(request.confirmationToken)))\n )\n return 'invalid_request';\n return undefined;\n}\n\n/** Create a transport-neutral, principal-bound data-surface action adapter. */\nexport function createDataSurfaceActionAdapter(\n options: DataSurfaceActionAdapterOptions,\n): DataSurfaceActionAdapter {\n const state = options.state;\n const now = options.now ?? Date.now;\n const createToken =\n options.createToken ?? (() => randomBytes(32).toString('base64url'));\n const tokenTtlMs = options.tokenTtlMs ?? DEFAULT_TOKEN_TTL_MS;\n const runAsPrincipal = options.runAsPrincipal ?? executeAsPrincipal;\n const idempotencyPollIntervalMs = Math.max(\n 1,\n options.idempotencyPollIntervalMs ?? 10,\n );\n const idempotencyWaitTimeoutMs = Math.max(\n 0,\n options.idempotencyWaitTimeoutMs ?? 5_000,\n );\n const fingerprintRequest = (request: DataSurfaceServerActionRequest) =>\n requestFingerprint(request, options.requestFingerprintExtension?.(request));\n\n async function resolveInvocation(\n request: DataSurfaceServerActionRequest,\n run: PrincipalRun,\n ): Promise<DataSurfaceActionInvocation | DataSurfaceActionResult> {\n const surface = await options.resolveSurface(run, request.identity);\n if (\n identityKey(surface.descriptor.identity) !== identityKey(request.identity)\n ) {\n return result(request, false, 'not_found');\n }\n const action = surface.actions[request.actionId];\n const declared = surface.descriptor.actions.find(\n ({ id }) => id === request.actionId,\n );\n if (\n !action ||\n !declared ||\n action.descriptor.id !== declared.id ||\n Boolean(declared.requiresConfirmation) !==\n (action.confirmation === 'required')\n ) {\n return result(request, false, 'unsupported');\n }\n if (\n !action.tool ||\n !validIdentifier(action.operation?.id) ||\n !validIdentifier(action.operation?.action)\n )\n return result(request, false, 'denied');\n run.assertToolAllowed(action.tool);\n await run.assertOperation(\n action.operation.collection,\n action.operation.action,\n );\n const payloadValidation = await action.validatePayload(request.payload);\n if (!payloadValidation.valid)\n return result(\n request,\n false,\n payloadValidation.reason ?? 'invalid_payload',\n );\n if (\n !declared.selectionScopes.includes(request.selection.scope) ||\n !action.descriptor.selectionScopes.includes(request.selection.scope)\n ) {\n return result(request, false, 'selection_not_supported');\n }\n const base = {\n run,\n request,\n descriptor: surface.descriptor,\n action,\n };\n const resolvedSelection = await options.resolveSelection(\n base,\n canonicalSelection(request.selection),\n );\n const selection = {\n ...resolvedSelection,\n rowIds: canonicalRowIds(resolvedSelection.rowIds),\n };\n const invocation = { ...base, selection };\n if (!(await action.authorize(invocation))) {\n return result(request, false, 'denied');\n }\n if (selection.rowIds.length > surface.descriptor.limits.maxSelectionSize) {\n return result(request, false, 'limit_exceeded');\n }\n return invocation;\n }\n\n async function preview(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult> {\n const invalid = validateRequest(request, 'preview');\n if (invalid) return result(request, false, invalid);\n const boundContext = snapshotActionContext(context);\n return runAsPrincipal(\n {\n ...boundContext.principal,\n action: 'data_surface.action.preview',\n auditMetadata: {\n ...boundContext.principal.auditMetadata,\n surfaceId: request.identity.surfaceId,\n actionId: request.actionId,\n requestId: request.requestId,\n },\n },\n async (run) => {\n const invocation = await resolveInvocation(request, run);\n if ('ok' in invocation) return invocation;\n if (invocation.selection.revision !== request.expectedRevision) {\n return result(request, false, 'stale_revision');\n }\n const outcomes: DataSurfaceActionRowOutcome[] = [];\n for (const rowId of invocation.selection.rowIds) {\n const eligibility = await invocation.action.eligible(\n invocation,\n rowId,\n );\n outcomes.push({\n rowId,\n status: eligibility.eligible ? 'accepted' : 'skipped',\n ...(eligibility.reason ? { reason: eligibility.reason } : {}),\n });\n }\n const confirmationToken = createToken();\n const selectionFingerprint = fingerprint(\n canonicalSelection(request.selection),\n );\n const requestFingerprintValue = fingerprintRequest(request);\n const expiresAt = now() + tokenTtlMs;\n await state.putToken(confirmationToken, {\n expiresAt,\n actorUserId: boundContext.principal.principal.runAsUserId,\n tenantId: boundContext.principal.principal.tenantId,\n onBehalfOfUserId: boundContext.principal.onBehalfOfUserId ?? null,\n actsAsProfileId:\n boundContext.principal.principal.actsAsProfileId ?? null,\n agentClass: boundContext.principal.agentClass ?? null,\n identityKey: identityKey(request.identity),\n actionId: request.actionId,\n actionFingerprint: actionFingerprint(invocation.action),\n revision: invocation.selection.revision,\n queryFingerprint: invocation.selection.queryFingerprint,\n selectionFingerprint,\n resolvedRowsFingerprint: fingerprint(\n canonicalRowIds(invocation.selection.rowIds),\n ),\n requestFingerprint: requestFingerprintValue,\n });\n return result(\n request,\n true,\n undefined,\n outcomesDetails(outcomes, {\n count: invocation.selection.rowIds.length,\n revision: invocation.selection.revision,\n queryFingerprint: invocation.selection.queryFingerprint,\n expiresAt,\n }),\n confirmationToken,\n );\n },\n );\n }\n\n async function executeForeground(\n request: DataSurfaceServerActionRequest,\n invocation: DataSurfaceActionInvocation,\n ): Promise<DataSurfaceActionResult> {\n const outcomes: DataSurfaceActionRowOutcome[] = [];\n for (const rowId of invocation.selection.rowIds) {\n try {\n const eligibility = await invocation.action.eligible(invocation, rowId);\n if (!eligibility.eligible) {\n outcomes.push({\n rowId,\n status: 'skipped',\n ...(eligibility.reason ? { reason: eligibility.reason } : {}),\n });\n continue;\n }\n const applied = await invocation.action.apply(invocation, rowId);\n outcomes.push({\n rowId,\n status: 'accepted',\n ...(applied !== null &&\n typeof applied === 'object' &&\n !Array.isArray(applied)\n ? { metadata: applied }\n : {}),\n });\n } catch (error) {\n outcomes.push({\n rowId,\n status: 'failed',\n reason: options.mapError?.(error, request) ?? 'execution_failed',\n });\n }\n }\n return result(request, true, undefined, outcomesDetails(outcomes));\n }\n\n async function executeBackgroundOnce(\n request: DataSurfaceServerActionRequest,\n token: DataSurfacePreviewTokenRecord | undefined,\n reference: Readonly<DataSurfaceDeferredPrincipalReference>,\n ): Promise<DataSurfaceActionResult> {\n const ownerToken = randomBytes(16).toString('base64url');\n const executionFingerprint = fingerprint({\n kind: 'background-execution',\n request: token?.requestFingerprint ?? fingerprintRequest(request),\n action: token?.actionFingerprint ?? request.actionId,\n });\n const executionScope = fingerprint({\n kind: 'background-execution',\n actorUserId: reference.runAsUserId,\n tenantId: reference.tenantId,\n onBehalfOfUserId: reference.onBehalfOfUserId,\n actsAsProfileId: reference.actsAsProfileId,\n agentClass: reference.agentClass ?? null,\n identity: canonicalIdentity(request.identity),\n actionId: request.actionId,\n idempotencyKey: request.idempotencyKey,\n });\n const maxPolls = Math.max(\n 1,\n Math.ceil(idempotencyWaitTimeoutMs / idempotencyPollIntervalMs),\n );\n for (let poll = 0; poll <= maxPolls; poll += 1) {\n const winner = await state.reserveIdempotency(executionScope, {\n requestFingerprint: executionFingerprint,\n ownerToken,\n reservedAt: now(),\n });\n if (winner.requestFingerprint !== executionFingerprint)\n return result(request, false, 'idempotency_conflict');\n if (winner.status === 'completed')\n return replayResult(request, winner.result);\n if (winner.ownerToken === ownerToken) {\n let refreshed: ExecuteAsPrincipalOptions;\n try {\n // A queued job may run long after the request that created it. The\n // complete persona binding (including the TenantAgent-capped tool\n // allow-list) must therefore be resolved again at execution time.\n const resolved = await options.resolveDeferredPrincipal?.(reference);\n if (\n !resolved ||\n resolved.principal.runAsUserId !== reference.runAsUserId ||\n resolved.principal.tenantId !== reference.tenantId ||\n (resolved.principal.actsAsProfileId ?? null) !==\n reference.actsAsProfileId ||\n (resolved.onBehalfOfUserId ?? null) !==\n reference.onBehalfOfUserId ||\n (resolved.agentClass ?? null) !== (reference.agentClass ?? null) ||\n !Array.isArray(resolved.principal.allowedTools)\n ) {\n throw new Error(\n 'Deferred data-surface action principal binding could not be resolved safely',\n );\n }\n refreshed = resolved;\n } catch (error) {\n const reason = options.mapError?.(error, request);\n if (!reason) {\n // No side effect has started, so a later queue attempt may safely\n // acquire a fresh reservation and re-check current authority.\n await state.releaseIdempotency(executionScope, ownerToken);\n throw error;\n }\n const denied = result(request, false, reason);\n if (\n !(await state.completeIdempotency(\n executionScope,\n ownerToken,\n denied,\n ))\n ) {\n throw new Error('Lost background action idempotency reservation');\n }\n return denied;\n }\n let executed: DataSurfaceActionResult;\n let mutationStarted = false;\n try {\n // Permission snapshots are never carried across the queue boundary;\n // executeAsPrincipal resolves current RBAC/membership immediately.\n const { permissions: _permissions, ...livePrincipal } = refreshed;\n executed = await authorizedApply(\n request,\n { principal: livePrincipal },\n token,\n false,\n () => {\n mutationStarted = true;\n },\n );\n } catch (error) {\n const reason = options.mapError?.(error, request);\n if (!reason) {\n if (!mutationStarted) {\n await state.releaseIdempotency(executionScope, ownerToken);\n }\n // Once mutation starts, effects are unknown; retain the reservation\n // until evidence-based reconciliation rather than retrying blindly.\n throw error;\n }\n executed = result(request, false, reason);\n }\n if (\n !(await state.completeIdempotency(\n executionScope,\n ownerToken,\n executed,\n ))\n ) {\n throw new Error('Lost background action idempotency reservation');\n }\n return executed;\n }\n if (poll < maxPolls) {\n await new Promise<void>((resolve) =>\n setTimeout(resolve, idempotencyPollIntervalMs),\n );\n const current = await state.getIdempotency(executionScope);\n if (current?.status === 'completed')\n return replayResult(request, current.result);\n }\n }\n return result(request, false, 'idempotency_in_progress');\n }\n\n async function authorizedApply(\n request: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n token: DataSurfacePreviewTokenRecord | undefined,\n allowBackground: boolean,\n beforeMutation?: () => void,\n ): Promise<DataSurfaceActionResult> {\n const idempotencyKey = request.idempotencyKey;\n if (!idempotencyKey) return result(request, false, 'invalid_request');\n // Capture the immutable binding before any asynchronous authorization.\n // The host may reuse or mutate its request context after enqueue returns.\n const deferredPrincipalReference = Object.freeze({\n runAsUserId: context.principal.principal.runAsUserId,\n tenantId: context.principal.principal.tenantId,\n actsAsProfileId: context.principal.principal.actsAsProfileId ?? null,\n onBehalfOfUserId: context.principal.onBehalfOfUserId ?? null,\n ...(context.principal.agentClass\n ? { agentClass: context.principal.agentClass }\n : {}),\n });\n return runAsPrincipal(\n {\n ...context.principal,\n action: 'data_surface.action.apply',\n auditMetadata: {\n ...context.principal.auditMetadata,\n surfaceId: request.identity.surfaceId,\n actionId: request.actionId,\n requestId: request.requestId,\n idempotencyKey: request.idempotencyKey,\n },\n },\n async (run) => {\n const invocation = await resolveInvocation(request, run);\n if ('ok' in invocation) return invocation;\n if (token) {\n if (\n fingerprintRequest(request) !== token.requestFingerprint ||\n invocation.selection.revision !== token.revision ||\n invocation.selection.revision !== request.expectedRevision ||\n invocation.selection.queryFingerprint !== token.queryFingerprint ||\n fingerprint(canonicalSelection(request.selection)) !==\n token.selectionFingerprint ||\n actionFingerprint(invocation.action) !== token.actionFingerprint ||\n fingerprint(canonicalRowIds(invocation.selection.rowIds)) !==\n token.resolvedRowsFingerprint\n ) {\n return result(request, false, 'stale_preview');\n }\n } else if (invocation.action.confirmation === 'required') {\n return result(request, false, 'confirmation_required');\n } else if (invocation.selection.revision !== request.expectedRevision) {\n return result(request, false, 'stale_revision');\n }\n if (invocation.action.execution === 'background' && allowBackground) {\n if (\n !options.backgroundQueue ||\n !validIdentifier(options.backgroundHandlerId) ||\n !options.resolveDeferredPrincipal ||\n !validSigningKey(options.deferredEnvelopeSigningKey)\n ) {\n return result(request, false, 'background_unavailable');\n }\n const { confirmationToken: _confirmationToken, ...deferredRequest } =\n request;\n const unsignedEnvelope = {\n version: 1,\n handlerId: options.backgroundHandlerId ?? '',\n request: deferredRequest,\n principal: deferredPrincipalReference,\n ...(token ? { previewToken: token } : {}),\n } as const;\n const queued = await options.backgroundQueue.enqueue({\n idempotencyKey,\n identity: request.identity,\n actionId: request.actionId,\n rowIds: invocation.selection.rowIds,\n envelope: {\n ...unsignedEnvelope,\n binding: envelopeBinding(\n unsignedEnvelope,\n options.deferredEnvelopeSigningKey as string | Uint8Array,\n ),\n },\n run: () =>\n executeBackgroundOnce(request, token, deferredPrincipalReference),\n });\n return result(request, true, undefined, {\n accepted: invocation.selection.rowIds.length,\n skipped: 0,\n failed: 0,\n ...(queued.details ?? {}),\n background: true,\n jobId: queued.jobId,\n // A replayed apply has a new transport request id, while the\n // already-queued job still returns the original execution result.\n // Preserve that correlation id across the replay envelope.\n jobRequestId: request.requestId,\n });\n }\n beforeMutation?.();\n return executeForeground(request, invocation);\n },\n );\n }\n\n async function apply(\n input: DataSurfaceServerActionRequest,\n context: DataSurfaceActionContext,\n ): Promise<DataSurfaceActionResult> {\n const invalid = validateRequest(input, 'apply');\n if (invalid) return result(input, false, invalid);\n const request = snapshotRequest(input);\n const boundContext = snapshotActionContext(context);\n const confirmationToken = request.confirmationToken;\n const idempotencyKey = request.idempotencyKey;\n if (!idempotencyKey) return result(request, false, 'invalid_request');\n const actorUserId = boundContext.principal.principal.runAsUserId;\n const tenantId = boundContext.principal.principal.tenantId;\n const onBehalfOfUserId = boundContext.principal.onBehalfOfUserId ?? null;\n const actsAsProfileId =\n boundContext.principal.principal.actsAsProfileId ?? null;\n const agentClass = boundContext.principal.agentClass ?? null;\n const requestFingerprintValue = fingerprintRequest(request);\n const idempotencyScope = fingerprint({\n actorUserId,\n tenantId,\n onBehalfOfUserId,\n actsAsProfileId,\n agentClass,\n identity: canonicalIdentity(request.identity),\n actionId: request.actionId,\n idempotencyKey,\n });\n const prior = await state.getIdempotency(idempotencyScope);\n if (prior && prior.requestFingerprint !== requestFingerprintValue)\n return result(request, false, 'idempotency_conflict');\n // A completed durable result is safe to replay from its actor/tenant-bound\n // idempotency scope even when the one-time confirmation has expired.\n if (prior?.status === 'completed')\n return replayResult(request, prior.result);\n\n let token: DataSurfacePreviewTokenRecord | undefined;\n if (confirmationToken) {\n token = await state.getToken(confirmationToken);\n if (!token || token.expiresAt <= now()) {\n return result(request, false, 'invalid_or_expired_confirmation');\n }\n if (\n token.actorUserId !== actorUserId ||\n token.tenantId !== tenantId ||\n token.onBehalfOfUserId !== onBehalfOfUserId ||\n token.actsAsProfileId !== actsAsProfileId ||\n token.agentClass !== agentClass ||\n token.identityKey !== identityKey(request.identity) ||\n token.actionId !== request.actionId ||\n token.requestFingerprint !== requestFingerprintValue\n ) {\n return result(request, false, 'confirmation_mismatch');\n }\n }\n // Resolve and validate deferred execution before consuming a one-time\n // confirmation or reserving idempotency. Execution re-authorizes below;\n // this preflight only prevents broken worker configuration from burning a\n // retryable preview.\n const backgroundPreflight = await runAsPrincipal(\n {\n ...boundContext.principal,\n action: 'data_surface.action.apply',\n auditMetadata: boundContext.principal.auditMetadata,\n },\n async (run) => {\n const surface = await options.resolveSurface(run, request.identity);\n if (\n identityKey(surface.descriptor.identity) !==\n identityKey(request.identity)\n )\n return undefined;\n const action = surface.actions[request.actionId];\n const declared = surface.descriptor.actions.find(\n ({ id }) => id === request.actionId,\n );\n if (!action || !declared || action.descriptor.id !== declared.id)\n return undefined;\n if (\n action.execution === 'background' &&\n (!options.backgroundQueue ||\n !validIdentifier(options.backgroundHandlerId) ||\n !options.resolveDeferredPrincipal ||\n !validSigningKey(options.deferredEnvelopeSigningKey))\n ) {\n return result(request, false, 'background_unavailable');\n }\n return undefined;\n },\n );\n if (backgroundPreflight) return backgroundPreflight;\n // Ownership is an internal compare-and-set nonce. Keep it independent of\n // the injectable preview-token factory, which tests or callers may make\n // deterministic without weakening concurrent winner selection.\n const ownerToken = randomBytes(16).toString('base64url');\n const reservation = {\n requestFingerprint: requestFingerprintValue,\n ownerToken,\n reservedAt: now(),\n };\n let firstWinner: DataSurfaceIdempotencyRecord | undefined;\n if (confirmationToken) {\n firstWinner = await state.consumeTokenAndReserveIdempotency(\n confirmationToken,\n idempotencyKey,\n idempotencyScope,\n reservation,\n );\n if (!firstWinner) return result(request, false, 'confirmation_replayed');\n }\n const maxPolls = Math.max(\n 1,\n Math.ceil(idempotencyWaitTimeoutMs / idempotencyPollIntervalMs),\n );\n for (let poll = 0; poll <= maxPolls; poll += 1) {\n const winner =\n poll === 0 && firstWinner\n ? firstWinner\n : await state.reserveIdempotency(idempotencyScope, reservation);\n if (winner.requestFingerprint !== requestFingerprintValue)\n return result(request, false, 'idempotency_conflict');\n if (winner.status === 'completed')\n return replayResult(request, winner.result);\n if (winner.ownerToken === ownerToken) {\n let applied: DataSurfaceActionResult;\n try {\n applied = await authorizedApply(request, boundContext, token, true);\n } catch (error) {\n await state.releaseIdempotency(idempotencyScope, ownerToken);\n throw error;\n }\n // A confirmation-required request without a token is a recoverable\n // precondition failure. Do not consume its idempotency key: the caller\n // may preview and retry with the same key.\n if (!applied.ok && applied.reason === 'confirmation_required') {\n await state.releaseIdempotency(idempotencyScope, ownerToken);\n return applied;\n }\n // Once execution returns, never release on a persistence failure: a\n // durable reservation is safer than allowing duplicate side effects.\n if (\n !(await state.completeIdempotency(\n idempotencyScope,\n ownerToken,\n applied,\n ))\n ) {\n throw new Error('Lost data-surface idempotency reservation');\n }\n return applied;\n }\n if (poll < maxPolls) {\n await new Promise<void>((resolve) =>\n setTimeout(resolve, idempotencyPollIntervalMs),\n );\n const current = await state.getIdempotency(idempotencyScope);\n if (current?.status === 'completed')\n return replayResult(request, current.result);\n }\n }\n return result(request, false, 'idempotency_in_progress');\n }\n\n async function executeDeferred(\n envelope: DataSurfaceBackgroundActionEnvelope,\n ): Promise<DataSurfaceActionResult> {\n if (\n !validSigningKey(options.deferredEnvelopeSigningKey) ||\n !bindingMatches(\n envelope,\n options.deferredEnvelopeSigningKey as string | Uint8Array,\n )\n ) {\n throw new Error('Invalid durable data-surface action envelope binding');\n }\n const principal = envelope.principal;\n if (\n envelope.version !== 1 ||\n !options.backgroundHandlerId ||\n envelope.handlerId !== options.backgroundHandlerId ||\n !principal ||\n !validIdentifier(principal.runAsUserId) ||\n (principal.tenantId !== null && !validIdentifier(principal.tenantId)) ||\n (principal.actsAsProfileId !== null &&\n !validIdentifier(principal.actsAsProfileId)) ||\n (principal.onBehalfOfUserId !== null &&\n !validIdentifier(principal.onBehalfOfUserId)) ||\n (principal.agentClass !== undefined &&\n !validIdentifier(principal.agentClass))\n ) {\n return result(envelope.request, false, 'invalid_request');\n }\n const invalid = validateRequest(envelope.request, 'apply');\n if (invalid) return result(envelope.request, false, invalid);\n return executeBackgroundOnce(\n snapshotRequest(envelope.request),\n envelope.previewToken,\n Object.freeze({ ...envelope.principal }),\n );\n }\n\n return { preview, apply, executeDeferred };\n}\n","import {\n field,\n ObjectRegistry,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n backgroundEligible,\n getActiveJobExecutionContext,\n isRunnerExecutionContext,\n type JobExecutionContext,\n type SmrtJob,\n SmrtJobCollection,\n} from '@happyvertical/smrt-jobs';\nimport {\n getTenantId,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport type {\n DataSurfaceActionResult,\n DataSurfaceJsonObject,\n} from '@happyvertical/smrt-types';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type {\n DataSurfaceBackgroundActionEnvelope,\n DataSurfaceBackgroundActionJob,\n DataSurfaceBackgroundQueue,\n} from './data-surface-actions.js';\n\nconst handlers = new Map<\n string,\n (\n envelope: DataSurfaceBackgroundActionEnvelope,\n ) => Promise<DataSurfaceActionResult>\n>();\n\nexport interface DataSurfaceActionJobArgs {\n version: 1;\n envelope: DataSurfaceBackgroundActionEnvelope;\n}\n\nexport interface JobsDataSurfaceBackgroundQueueOptions {\n db: DatabaseInterface;\n handlerId: string;\n execute(\n envelope: DataSurfaceBackgroundActionEnvelope,\n ): Promise<DataSurfaceActionResult>;\n queue?: string;\n priority?: number;\n timeout?: number;\n maxAttempts?: number;\n tenantJobCap?: number;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: '_smrt_data_surface_action_tasks',\n api: false,\n cli: false,\n mcp: false,\n})\nexport class SmrtDataSurfaceActionTask extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @field({ type: 'json', required: true })\n args: DataSurfaceActionJobArgs = {\n version: 1,\n envelope: {} as DataSurfaceBackgroundActionEnvelope,\n };\n\n @backgroundEligible()\n async run(\n args: DataSurfaceActionJobArgs = this.args,\n context?: JobExecutionContext,\n ): Promise<DataSurfaceActionResult> {\n const envelope = args?.envelope;\n const executionContext = getActiveJobExecutionContext() ?? context;\n if (executionContext && !isRunnerExecutionContext(executionContext)) {\n throw new Error('Invalid durable data-surface action job context');\n }\n // A runner context owns scope even when the queued job is global. Persisted\n // instance configuration must never replace that explicit null.\n let jobTenantId: string | null;\n if (executionContext) {\n const runnerTenantId = executionContext.job.tenantId;\n if (runnerTenantId === null) {\n jobTenantId = null;\n } else if (\n typeof runnerTenantId === 'string' &&\n runnerTenantId.length > 0\n ) {\n jobTenantId = runnerTenantId;\n } else {\n throw new Error('Invalid durable data-surface action job tenant');\n }\n } else {\n jobTenantId = this.tenantId ?? getTenantId() ?? null;\n }\n if (\n args?.version !== 1 ||\n envelope?.version !== 1 ||\n typeof envelope.handlerId !== 'string' ||\n envelope.handlerId.length === 0 ||\n envelope.principal?.tenantId !== jobTenantId\n ) {\n throw new Error('Invalid durable data-surface action envelope');\n }\n const handler = handlers.get(envelope.handlerId);\n if (!handler) {\n throw new Error(\n `No data-surface action handler registered for ${envelope.handlerId}`,\n );\n }\n const result = await handler(envelope);\n if (!result.ok && result.reason === 'idempotency_in_progress') {\n throw new Error('Data-surface action outcome requires reconciliation');\n }\n return result;\n }\n}\n\n/**\n * Register the host handler used by workers after process restart.\n * The returned disposer only removes the same registration.\n */\nexport function registerDataSurfaceBackgroundActionHandler(\n handlerId: string,\n execute: (\n envelope: DataSurfaceBackgroundActionEnvelope,\n ) => Promise<DataSurfaceActionResult>,\n): () => void {\n if (!handlerId || handlerId.length > 256) {\n throw new Error(\n 'Data-surface action handlerId must contain 1-256 characters',\n );\n }\n const existing = handlers.get(handlerId);\n if (existing && existing !== execute) {\n throw new Error(\n `Data-surface action handler already registered: ${handlerId}`,\n );\n }\n handlers.set(handlerId, execute);\n return () => {\n if (handlers.get(handlerId) === execute) handlers.delete(handlerId);\n };\n}\n\nexport function createJobsDataSurfaceBackgroundQueue(\n options: JobsDataSurfaceBackgroundQueueOptions,\n): DataSurfaceBackgroundQueue & { unregister(): void } {\n const unregister = registerDataSurfaceBackgroundActionHandler(\n options.handlerId,\n options.execute,\n );\n return {\n unregister,\n async enqueue(job: DataSurfaceBackgroundActionJob) {\n if (job.envelope.handlerId !== options.handlerId) {\n throw new Error('Data-surface action envelope handler mismatch');\n }\n const persisted = await enqueueDataSurfaceActionJob(\n options,\n job.envelope,\n );\n if (!persisted.id)\n throw new Error('Durable data-surface action job has no ID');\n return {\n jobId: persisted.id,\n details: { queue: persisted.queue } as DataSurfaceJsonObject,\n };\n },\n };\n}\n\nasync function enqueueDataSurfaceActionJob(\n options: JobsDataSurfaceBackgroundQueueOptions,\n envelope: DataSurfaceBackgroundActionEnvelope,\n): Promise<SmrtJob> {\n await ObjectRegistry.ensureManifestLoaded('SmrtJob');\n const jobs = await SmrtJobCollection.create({ db: options.db });\n const registered =\n ObjectRegistry.getClassByConstructor(SmrtDataSurfaceActionTask) ??\n ObjectRegistry.getClass('SmrtDataSurfaceActionTask');\n const objectType =\n registered?.qualifiedName ??\n registered?.name ??\n SmrtDataSurfaceActionTask.name;\n return jobs.enqueueJob(\n {\n tenantId: envelope.principal.tenantId,\n queue: options.queue ?? 'data-surface-actions',\n objectType,\n objectId: null,\n method: 'run',\n args: { version: 1, envelope },\n priority: options.priority ?? 70,\n timeout: options.timeout ?? 300_000,\n maxAttempts: options.maxAttempts ?? 3,\n },\n { tenantJobCap: options.tenantJobCap },\n );\n}\n","/**\n * Serialization utilities for resolved agents\n *\n * Converts ResolvedAgentAvailability (database + manifest data) into\n * a JSON-safe shape suitable for passing to client components.\n *\n * @module @happyvertical/smrt-agents/server\n */\n\nimport { sanitizeConfig } from '@happyvertical/smrt-config';\nimport type { ResolvedAgentAvailability } from '../tenant-agent.js';\nimport type { AgentAdminRoute, AgentUISlots } from '../ui.js';\n\n/**\n * Serialized agent data for passing to client components.\n *\n * Includes manifest-derived fields (icon, permissions, slots)\n * alongside resolution metadata (source, sourceTenantId).\n */\nexport interface SerializedAgent {\n /** Agent instance ID, or a synthetic key if no instance exists */\n id: string;\n /** Human-readable name from manifest */\n name?: string;\n /** Human-readable agent class name (e.g., 'Praeco') */\n agentClass: string;\n /** Canonical agent type (qualified name when available) */\n agentType: string;\n /** STI type discriminator (same as agentType) */\n _meta_type?: string;\n /** UI slot definitions from manifest */\n slots?: AgentUISlots;\n /** Admin route declarations from manifest */\n adminRoutes?: AgentAdminRoute[];\n /** How this agent was resolved for the tenant */\n source?: 'explicit' | 'inherited';\n /** Which tenant the binding came from */\n sourceTenantId?: string;\n /** Merged permissions from manifest + tenant overrides */\n permissions?: Record<string, boolean>;\n /** Agent icon from manifest */\n icon?: string;\n /**\n * Tenant-level config overrides, **secret-sanitized** for client transport.\n *\n * SECURITY (#1553, follow-up to #1552): the raw `TenantAgent.config` is the\n * tenant's own override blob and is `@field({ sensitive: true })` (stripped\n * from the generated CRUD api/mcp surfaces). This hand-written admin\n * serialization runs it through `sanitizeConfig()` from\n * `@happyvertical/smrt-config` before it leaves the server, so secret-shaped\n * keys (apiKey/token/password/…) are dropped and secret-shaped values\n * (`sk-…`, `AKIA…`, `Bearer …`, URL credentials, PEM blocks) are masked —\n * non-secret config still reaches the authorized admin UI for display.\n *\n * This is **display-only**: do not edit-round-trip it back to the server\n * (a masked value would overwrite the real secret). Best practice remains to\n * reference secrets by id via `@happyvertical/smrt-secrets` so only an opaque\n * handle is ever stored in tenant config.\n */\n config?: Record<string, unknown>;\n}\n\n/**\n * Convert a ResolvedAgentAvailability to a serializable shape for the UI.\n *\n * @param resolved - Output from TenantAgentCollection.resolveForTenant()\n * @returns Serialized agent data safe for JSON transport\n */\nexport function serializeResolvedAgent(\n resolved: ResolvedAgentAvailability,\n): SerializedAgent {\n const manifest = resolved.manifest;\n\n return {\n id: resolved.agentId || `${resolved.sourceTenantId}:${resolved.agentType}`,\n name: manifest?.name || resolved.agentClass,\n agentClass: resolved.agentClass,\n agentType: resolved.agentType,\n _meta_type: resolved.agentType,\n slots: manifest?.uiSlots as AgentUISlots | undefined,\n adminRoutes: manifest?.adminRoutes as AgentAdminRoute[] | undefined,\n source: resolved.source,\n sourceTenantId: resolved.sourceTenantId,\n permissions: resolved.permissions,\n icon: manifest?.icon,\n // Secret-sanitize before the blob crosses into the client payload (#1553).\n config: sanitizeConfig(resolved.config) as SerializedAgent['config'],\n };\n}\n","import { createHash, randomUUID } from 'node:crypto';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport type { DataSurfaceActionResult } from '@happyvertical/smrt-types';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type {\n DataSurfaceActionStateStore,\n DataSurfaceIdempotencyRecord,\n DataSurfaceIdempotencyRecoveryEvidence,\n DataSurfaceIdempotencyReservation,\n DataSurfacePreviewTokenRecord,\n} from './data-surface-actions.js';\n\nconst TOKEN_TABLE = '_smrt_data_surface_action_tokens';\nconst IDEMPOTENCY_TABLE = '_smrt_data_surface_action_idempotency';\n\nconst INTERNAL_SURFACE = {\n api: false,\n cli: false,\n mcp: false,\n} as const;\n\n@smrt({ tableName: '_smrt_data_surface_action_tokens', ...INTERNAL_SURFACE })\nexport class DataSurfaceActionTokenState extends SmrtObject {\n @field({ type: 'text', required: true, unique: true })\n tokenHash: string = '';\n\n @field({ type: 'json', required: true })\n record: DataSurfacePreviewTokenRecord = emptyTokenRecord();\n\n @field({ type: 'text', nullable: true })\n consumedBy: string | null = null;\n}\n\n@smrt({\n tableName: '_smrt_data_surface_action_idempotency',\n ...INTERNAL_SURFACE,\n})\nexport class DataSurfaceActionIdempotencyState extends SmrtObject {\n @field({ type: 'text', required: true, unique: true })\n keyHash: string = '';\n\n @field({ type: 'text', required: true })\n status: 'reserved' | 'completed' = 'reserved';\n\n @field({ type: 'text', required: true })\n requestFingerprint: string = '';\n\n @field({ type: 'text', nullable: true })\n ownerHash: string | null = null;\n\n @field({ type: 'text', nullable: true })\n reservedAt: string | null = null;\n\n @field({ type: 'json', nullable: true })\n result: DataSurfaceActionResult | null = null;\n\n @field({ type: 'json', nullable: true })\n recovery: DataSurfaceIdempotencyRecoveryEvidence | null = null;\n}\n\nexport interface DataSurfaceIdempotencyRecoveryRequest {\n requestFingerprint: string;\n reservedAt: number;\n result: DataSurfaceActionResult;\n authorizedBy: string;\n evidence: string;\n}\n\nexport interface SqlDataSurfaceActionStateStoreOptions {\n db: DatabaseInterface;\n now?: () => number;\n authorizeRecovery?: (\n request: Readonly<DataSurfaceIdempotencyRecoveryRequest>,\n ) => boolean | Promise<boolean>;\n}\n\nexport class DataSurfaceActionStateCorruptionError extends Error {\n constructor(table: string) {\n super(`Malformed durable data-surface action state in ${table}`);\n this.name = 'DataSurfaceActionStateCorruptionError';\n }\n}\n\n/**\n * SQL-backed action state shared by server processes.\n *\n * Preview tokens and owner nonces are stored only as hashes. Runtime schema\n * creation remains the application's normal SMRT migration responsibility.\n * An orphaned reservation is never expired or released automatically: a host\n * may only reconcile it to a concrete terminal result after its live authority\n * callback accepts immutable evidence for the exact reservation timestamp.\n */\nexport class SqlDataSurfaceActionStateStore\n implements DataSurfaceActionStateStore\n{\n private readonly db: DatabaseInterface;\n private readonly now: () => number;\n private readonly authorizeRecovery?: SqlDataSurfaceActionStateStoreOptions['authorizeRecovery'];\n\n constructor(options: SqlDataSurfaceActionStateStoreOptions) {\n this.db = options.db;\n this.now = options.now ?? Date.now;\n this.authorizeRecovery = options.authorizeRecovery;\n }\n\n async putToken(\n token: string,\n record: DataSurfacePreviewTokenRecord,\n ): Promise<void> {\n const timestamp = new Date(this.now()).toISOString();\n await this.db.query(\n `INSERT INTO ${TOKEN_TABLE}\n (id, slug, context, created_at, updated_at, token_hash, record, consumed_by)\n VALUES (?, ?, '', ?, ?, ?, ?, NULL)\n ON CONFLICT(token_hash) DO NOTHING`,\n randomUUID(),\n `action-token-${randomUUID()}`,\n timestamp,\n timestamp,\n secretHash(token),\n JSON.stringify(record),\n );\n }\n\n async getToken(\n token: string,\n ): Promise<DataSurfacePreviewTokenRecord | undefined> {\n const found = await this.db.query(\n `SELECT record, consumed_by FROM ${TOKEN_TABLE} WHERE token_hash = ? LIMIT 1`,\n secretHash(token),\n );\n const row = found.rows[0] as Record<string, unknown> | undefined;\n if (!row) return undefined;\n const record = tokenRecord(parseObject(row.record, TOKEN_TABLE));\n return {\n ...record,\n ...(typeof row.consumed_by === 'string'\n ? { consumedBy: row.consumed_by }\n : {}),\n };\n }\n\n async markTokenConsumed(\n token: string,\n idempotencyKey: string,\n ): Promise<boolean> {\n const updated = await this.db.query(\n `UPDATE ${TOKEN_TABLE}\n SET consumed_by = ?, updated_at = ?\n WHERE token_hash = ? AND consumed_by IS NULL\n RETURNING token_hash`,\n secretHash(idempotencyKey),\n new Date(this.now()).toISOString(),\n secretHash(token),\n );\n return updated.rows.length === 1;\n }\n\n async consumeTokenAndReserveIdempotency(\n token: string,\n idempotencyKey: string,\n scope: string,\n reservation: DataSurfaceIdempotencyReservation,\n ): Promise<DataSurfaceIdempotencyRecord | undefined> {\n const transaction = this.db.transaction;\n if (!transaction) {\n throw new Error(\n 'Durable data-surface action state requires database transactions',\n );\n }\n return (await transaction.call(this.db, async (tx) => {\n const timestamp = new Date(this.now()).toISOString();\n const consumed = await tx.query(\n `UPDATE ${TOKEN_TABLE}\n SET consumed_by = ?, updated_at = ?\n WHERE token_hash = ?\n AND (consumed_by IS NULL OR consumed_by = ?)\n RETURNING token_hash`,\n secretHash(idempotencyKey),\n timestamp,\n secretHash(token),\n secretHash(idempotencyKey),\n );\n if (consumed.rows.length !== 1) return undefined;\n await tx.query(\n `INSERT INTO ${IDEMPOTENCY_TABLE}\n (id, slug, context, created_at, updated_at, key_hash, status,\n request_fingerprint, owner_hash, reserved_at, result, recovery)\n VALUES (?, ?, '', ?, ?, ?, 'reserved', ?, ?, ?, NULL, NULL)\n ON CONFLICT(key_hash) DO NOTHING`,\n randomUUID(),\n `action-idempotency-${randomUUID()}`,\n timestamp,\n timestamp,\n secretHash(scope),\n reservation.requestFingerprint,\n secretHash(reservation.ownerToken),\n String(reservation.reservedAt),\n );\n const current = await this.getIdempotencyWithOwner(\n scope,\n reservation.ownerToken,\n tx,\n );\n if (!current) {\n throw new DataSurfaceActionStateCorruptionError(IDEMPOTENCY_TABLE);\n }\n return current;\n })) as DataSurfaceIdempotencyRecord | undefined;\n }\n\n async getIdempotency(\n key: string,\n ): Promise<DataSurfaceIdempotencyRecord | undefined> {\n const found = await this.db.query(\n `SELECT status, request_fingerprint, owner_hash, reserved_at, result, recovery\n FROM ${IDEMPOTENCY_TABLE} WHERE key_hash = ? LIMIT 1`,\n secretHash(key),\n );\n const row = found.rows[0] as Record<string, unknown> | undefined;\n return row ? idempotencyRecord(row) : undefined;\n }\n\n async reserveIdempotency(\n key: string,\n reservation: DataSurfaceIdempotencyReservation,\n ): Promise<DataSurfaceIdempotencyRecord> {\n const timestamp = new Date(this.now()).toISOString();\n await this.db.query(\n `INSERT INTO ${IDEMPOTENCY_TABLE}\n (id, slug, context, created_at, updated_at, key_hash, status,\n request_fingerprint, owner_hash, reserved_at, result, recovery)\n VALUES (?, ?, '', ?, ?, ?, 'reserved', ?, ?, ?, NULL, NULL)\n ON CONFLICT(key_hash) DO NOTHING`,\n randomUUID(),\n `action-idempotency-${randomUUID()}`,\n timestamp,\n timestamp,\n secretHash(key),\n reservation.requestFingerprint,\n secretHash(reservation.ownerToken),\n String(reservation.reservedAt),\n );\n const current = await this.getIdempotencyWithOwner(\n key,\n reservation.ownerToken,\n );\n if (!current)\n throw new DataSurfaceActionStateCorruptionError(IDEMPOTENCY_TABLE);\n return current;\n }\n\n async completeIdempotency(\n key: string,\n ownerToken: string,\n result: DataSurfaceActionResult,\n ): Promise<boolean> {\n const updated = await this.db.query(\n `UPDATE ${IDEMPOTENCY_TABLE}\n SET status = 'completed', result = ?, owner_hash = NULL,\n reserved_at = NULL, updated_at = ?\n WHERE key_hash = ? AND status = 'reserved' AND owner_hash = ?\n RETURNING key_hash`,\n JSON.stringify(result),\n new Date(this.now()).toISOString(),\n secretHash(key),\n secretHash(ownerToken),\n );\n return updated.rows.length === 1;\n }\n\n async releaseIdempotency(key: string, ownerToken: string): Promise<boolean> {\n const removed = await this.db.query(\n `DELETE FROM ${IDEMPOTENCY_TABLE}\n WHERE key_hash = ? AND status = 'reserved' AND owner_hash = ?\n RETURNING key_hash`,\n secretHash(key),\n secretHash(ownerToken),\n );\n return removed.rows.length === 1;\n }\n\n async reconcileIdempotency(\n key: string,\n request: DataSurfaceIdempotencyRecoveryRequest,\n ): Promise<boolean> {\n if (\n !request.requestFingerprint ||\n !Number.isSafeInteger(request.reservedAt) ||\n request.reservedAt < 0 ||\n !request.authorizedBy ||\n request.authorizedBy.length > 256 ||\n !request.evidence ||\n request.evidence.length > 2_048\n ) {\n return false;\n }\n if (\n !this.authorizeRecovery ||\n !(await this.authorizeRecovery(Object.freeze({ ...request })))\n ) {\n return false;\n }\n const recovery: DataSurfaceIdempotencyRecoveryEvidence = {\n authorizedBy: request.authorizedBy,\n evidence: request.evidence,\n reconciledAt: this.now(),\n };\n const updated = await this.db.query(\n `UPDATE ${IDEMPOTENCY_TABLE}\n SET status = 'completed', result = ?, recovery = ?, owner_hash = NULL,\n reserved_at = NULL, updated_at = ?\n WHERE key_hash = ? AND status = 'reserved'\n AND request_fingerprint = ? AND reserved_at = ?\n RETURNING key_hash`,\n JSON.stringify(request.result),\n JSON.stringify(recovery),\n new Date(recovery.reconciledAt).toISOString(),\n secretHash(key),\n request.requestFingerprint,\n String(request.reservedAt),\n );\n return updated.rows.length === 1;\n }\n\n private async getIdempotencyWithOwner(\n key: string,\n ownerToken: string,\n db: DatabaseInterface = this.db,\n ): Promise<DataSurfaceIdempotencyRecord | undefined> {\n const found = await db.query(\n `SELECT status, request_fingerprint, owner_hash, reserved_at, result, recovery\n FROM ${IDEMPOTENCY_TABLE} WHERE key_hash = ? LIMIT 1`,\n secretHash(key),\n );\n const row = found.rows[0] as Record<string, unknown> | undefined;\n if (!row) return undefined;\n const record = idempotencyRecord(row);\n if (\n record.status === 'reserved' &&\n row.owner_hash === secretHash(ownerToken)\n ) {\n return { ...record, ownerToken };\n }\n return record;\n }\n}\n\nexport function createSqlDataSurfaceActionStateStore(\n options: SqlDataSurfaceActionStateStoreOptions,\n): SqlDataSurfaceActionStateStore {\n return new SqlDataSurfaceActionStateStore(options);\n}\n\nfunction secretHash(value: string): string {\n return createHash('sha256').update(value).digest('hex');\n}\n\nfunction parseObject(value: unknown, table: string): Record<string, unknown> {\n let parsed = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value) as unknown;\n } catch {\n throw new DataSurfaceActionStateCorruptionError(table);\n }\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new DataSurfaceActionStateCorruptionError(table);\n }\n return parsed as Record<string, unknown>;\n}\n\nfunction idempotencyRecord(\n row: Record<string, unknown>,\n): DataSurfaceIdempotencyRecord {\n const requestFingerprint = row.request_fingerprint;\n if (typeof requestFingerprint !== 'string') {\n throw new DataSurfaceActionStateCorruptionError(IDEMPOTENCY_TABLE);\n }\n if (row.status === 'reserved') {\n const reservedAt = Number(row.reserved_at);\n if (\n typeof row.owner_hash !== 'string' ||\n !Number.isSafeInteger(reservedAt)\n ) {\n throw new DataSurfaceActionStateCorruptionError(IDEMPOTENCY_TABLE);\n }\n return {\n status: 'reserved',\n requestFingerprint,\n ownerToken: '',\n reservedAt,\n };\n }\n if (row.status !== 'completed') {\n throw new DataSurfaceActionStateCorruptionError(IDEMPOTENCY_TABLE);\n }\n const result = actionResult(parseObject(row.result, IDEMPOTENCY_TABLE));\n const recovery =\n row.recovery == null\n ? undefined\n : recoveryEvidence(parseObject(row.recovery, IDEMPOTENCY_TABLE));\n return {\n status: 'completed',\n requestFingerprint,\n result,\n ...(recovery ? { recovery } : {}),\n };\n}\n\nfunction tokenRecord(\n value: Record<string, unknown>,\n): DataSurfacePreviewTokenRecord {\n const stringKeys = [\n 'actorUserId',\n 'identityKey',\n 'actionId',\n 'actionFingerprint',\n 'queryFingerprint',\n 'selectionFingerprint',\n 'resolvedRowsFingerprint',\n 'requestFingerprint',\n ] as const;\n if (\n !Number.isSafeInteger(value.expiresAt) ||\n !Number.isSafeInteger(value.revision) ||\n stringKeys.some((key) => typeof value[key] !== 'string') ||\n !['tenantId', 'onBehalfOfUserId', 'actsAsProfileId', 'agentClass'].every(\n (key) => value[key] === null || typeof value[key] === 'string',\n )\n ) {\n throw new DataSurfaceActionStateCorruptionError(TOKEN_TABLE);\n }\n return value as unknown as DataSurfacePreviewTokenRecord;\n}\n\nfunction actionResult(value: Record<string, unknown>): DataSurfaceActionResult {\n if (\n value.version !== 1 ||\n typeof value.requestId !== 'string' ||\n typeof value.actionId !== 'string' ||\n value.phase !== 'apply' ||\n typeof value.ok !== 'boolean' ||\n !value.identity ||\n typeof value.identity !== 'object' ||\n Array.isArray(value.identity) ||\n (value.reason !== undefined && typeof value.reason !== 'string')\n ) {\n throw new DataSurfaceActionStateCorruptionError(IDEMPOTENCY_TABLE);\n }\n return value as unknown as DataSurfaceActionResult;\n}\n\nfunction recoveryEvidence(\n value: Record<string, unknown>,\n): DataSurfaceIdempotencyRecoveryEvidence {\n if (\n typeof value.authorizedBy !== 'string' ||\n typeof value.evidence !== 'string' ||\n !Number.isSafeInteger(value.reconciledAt)\n ) {\n throw new DataSurfaceActionStateCorruptionError(IDEMPOTENCY_TABLE);\n }\n return value as unknown as DataSurfaceIdempotencyRecoveryEvidence;\n}\n\nfunction emptyTokenRecord(): DataSurfacePreviewTokenRecord {\n return {\n expiresAt: 0,\n actorUserId: '',\n tenantId: null,\n onBehalfOfUserId: null,\n actsAsProfileId: null,\n agentClass: null,\n identityKey: '',\n actionId: '',\n actionFingerprint: '',\n revision: 0,\n queryFingerprint: '',\n selectionFingerprint: '',\n resolvedRowsFingerprint: '',\n requestFingerprint: '',\n };\n}\n"],"mappings":"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"}
|