@happyvertical/smrt-agents 0.44.0 → 0.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-agents",
5
- "packageVersion": "0.44.0",
5
+ "packageVersion": "0.44.1",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-agents:Agent": {
8
8
  "name": "agent",
@@ -351,7 +351,13 @@
351
351
  "delete": {
352
352
  "name": "delete",
353
353
  "async": true,
354
- "parameters": [],
354
+ "parameters": [
355
+ {
356
+ "name": "options",
357
+ "type": "SmrtDeleteOptions",
358
+ "optional": true
359
+ }
360
+ ],
355
361
  "returnType": "Promise<void>",
356
362
  "isStatic": false,
357
363
  "isPublic": true
@@ -2119,6 +2125,7 @@
2119
2125
  "moduleType": "smrt",
2120
2126
  "smrtDependencies": [
2121
2127
  "@happyvertical/smrt-core",
2128
+ "@happyvertical/smrt-playbooks",
2122
2129
  "@happyvertical/smrt-reports",
2123
2130
  "@happyvertical/smrt-secrets",
2124
2131
  "@happyvertical/smrt-tenancy",
@@ -0,0 +1,61 @@
1
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
2
+ import { PlaybookIntentResolver, PlaybookOperationClassifier, PlaybookOperationStep } from '@happyvertical/smrt-playbooks';
3
+ import { OperationPermissionCollectionInput } from '@happyvertical/smrt-users';
4
+ import { PrincipalRun } from './execute-as-principal.js';
5
+ import { PrincipalTool } from './invoke-agent.js';
6
+ /** Tool name + permission slug, gated by the persona's `allowedTools`. */
7
+ export declare const PLAYBOOK_PREFLIGHT_TOOL_SLUG = "playbooks.preflight";
8
+ /** Provider function name offered to the model. */
9
+ export declare const PLAYBOOK_PREFLIGHT_FUNCTION_NAME = "playbook_preflight";
10
+ /**
11
+ * Resolves the REST/permission collection slug a qualified model reference maps
12
+ * to (`@happyvertical/smrt-commerce:Order` → `orders`), falling back to the
13
+ * lower-cased class name for a model this process has not registered.
14
+ */
15
+ export declare function playbookStepCollection(model: string): string;
16
+ /** Default persona tool slug gating an operation step: `<collection>.<action>`. */
17
+ export declare function playbookStepToolSlug(step: PlaybookOperationStep): string;
18
+ export interface CreatePlaybookPreflightToolOptions {
19
+ /** Database handle used to resolve the caller's override layers. */
20
+ db?: SmrtClassOptions['db'];
21
+ /** Tenant scope for resolution. Defaults to the live run's tenant. */
22
+ tenantId?: string | null;
23
+ /**
24
+ * Maps an operation step to the persona tool slug that gates it. Defaults to
25
+ * {@link playbookStepToolSlug}.
26
+ */
27
+ toolSlug?: (step: PlaybookOperationStep) => string;
28
+ /**
29
+ * Maps an operation step to the permission-catalog collection. Defaults to
30
+ * the registered collection slug for the step's model.
31
+ */
32
+ collection?: (step: PlaybookOperationStep) => OperationPermissionCollectionInput;
33
+ /** Host classification source for operation steps. */
34
+ classifier?: PlaybookOperationClassifier;
35
+ /** Host intent registry (the #2588 seam). */
36
+ intents?: PlaybookIntentResolver;
37
+ /** Override the tool description offered to the model. */
38
+ description?: string;
39
+ }
40
+ /**
41
+ * Builds the **playbook preflight** tool.
42
+ *
43
+ * Offered through the conversational tool loop and gated by the persona's
44
+ * `allowedTools` like any other tool. Its handler re-asserts that gate, resolves
45
+ * the requested playbook through the caller's own layer chain on the `server`
46
+ * plane, and reports a per-step verdict. A playbook the chain cannot resolve —
47
+ * unknown key or unauthorized key alike — returns the single uniform
48
+ * "unavailable" report, so the tool is not an enumeration oracle.
49
+ */
50
+ export declare function createPlaybookPreflightTool(options?: CreatePlaybookPreflightToolOptions): PrincipalTool;
51
+ /**
52
+ * Filters a candidate playbook listing down to what the caller could plausibly
53
+ * run, so a tool list does not advertise a playbook that dies at step four.
54
+ *
55
+ * **This filter is a listing convenience, never an authorization decision.** A
56
+ * key it lets through is still authorized step by step at execution, and a key
57
+ * it hides is still denied at execution — nothing downstream may treat presence
58
+ * in this list as permission. Ordering is preserved so a listing is stable.
59
+ */
60
+ export declare function filterPlaybooksByPreflight(run: PrincipalRun, keys: readonly string[], options?: CreatePlaybookPreflightToolOptions): Promise<string[]>;
61
+ //# sourceMappingURL=playbook-preflight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playbook-preflight.d.ts","sourceRoot":"","sources":["../src/playbook-preflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAK3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,kCAAkC,EAExC,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,mBAAmB,CAAC;AAE7E,0EAA0E;AAC1E,eAAO,MAAM,4BAA4B,wBAAwB,CAAC;AAElE,mDAAmD;AACnD,eAAO,MAAM,gCAAgC,uBAAuB,CAAC;AAErE;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW5D;AAED,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAExE;AAED,MAAM,WAAW,kCAAkC;IACjD,oEAAoE;IACpE,EAAE,CAAC,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,MAAM,CAAC;IACnD;;;OAGG;IACH,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,qBAAqB,KACxB,kCAAkC,CAAC;IACxC,sDAAsD;IACtD,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA6DD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kCAAuC,GAC/C,aAAa,CAuCf;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,MAAM,EAAE,CAAC,CASnB"}
@@ -16,6 +16,8 @@ export interface DataSurfaceActionRowOutcome {
16
16
  rowId: DataSurfaceRowId;
17
17
  status: 'accepted' | 'skipped' | 'failed';
18
18
  reason?: string;
19
+ /** Serializable per-row result returned by the action implementation. */
20
+ metadata?: DataSurfaceJsonObject;
19
21
  }
20
22
  export interface ResolvedDataSurfaceSelection {
21
23
  /** Fresh server-side revision of the selected surface/query. */
@@ -1 +1 @@
1
- {"version":3,"file":"data-surface-actions.d.ts","sourceRoot":"","sources":["../../src/server/data-surface-actions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-surface-actions.d.ts","sourceRoot":"","sources":["../../src/server/data-surface-actions.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -277,10 +277,9 @@ function outcomesDetails(outcomes, extra = {}) {
277
277
  accepted: outcomes.filter(({ status }) => status === "accepted").length,
278
278
  skipped: outcomes.filter(({ status }) => status === "skipped").length,
279
279
  failed: outcomes.filter(({ status }) => status === "failed").length,
280
- outcomes: outcomes.map(({ rowId, status, reason }) => ({
281
- rowId,
282
- status,
283
- ...reason ? { reason } : {}
280
+ outcomes: outcomes.map(({ metadata, ...outcome }) => ({
281
+ ...metadata ?? {},
282
+ ...outcome
284
283
  })),
285
284
  ...extra
286
285
  };
@@ -403,10 +402,11 @@ function createDataSurfaceActionAdapter(options) {
403
402
  });
404
403
  continue;
405
404
  }
406
- await invocation.action.apply(invocation, rowId);
405
+ const applied = await invocation.action.apply(invocation, rowId);
407
406
  outcomes.push({
408
407
  rowId,
409
- status: "accepted"
408
+ status: "accepted",
409
+ ...applied !== null && typeof applied === "object" && !Array.isArray(applied) ? { metadata: applied } : {}
410
410
  });
411
411
  } catch (error) {
412
412
  outcomes.push({
@@ -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}\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(({ rowId, status, reason }) => ({\n rowId,\n status,\n ...(reason ? { reason } : {}),\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 await invocation.action.apply(invocation, rowId);\n outcomes.push({ rowId, status: 'accepted' });\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/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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"}