@jskit-ai/kernel 0.1.245 → 0.1.246

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/client/appConfig.js +2 -1
  2. package/client/asyncModuleRecovery.js +2 -4
  3. package/client/index.d.ts +13 -75
  4. package/client/index.js +1 -1
  5. package/client/logging.js +8 -2
  6. package/client/moduleBootstrap.js +41 -33
  7. package/client/moduleBootstrap.test.js +35 -0
  8. package/client/shellBootstrap.js +1 -8
  9. package/client/shellBootstrap.test.js +32 -5
  10. package/client/shellRouting.js +16 -61
  11. package/client/shellRouting.test.js +30 -1
  12. package/client/vite/clientBootstrapPlugin.js +0 -6
  13. package/client/vite/clientBootstrapPlugin.test.js +2 -3
  14. package/internal/node/installedPackages.js +14 -58
  15. package/package.json +2 -4
  16. package/server/actions/actionCatalogue.js +13 -34
  17. package/{shared → server}/actions/actionContributorHelpers.js +0 -5
  18. package/{shared → server}/actions/actionDefinitions.js +24 -131
  19. package/{shared → server}/actions/actionDefinitions.test.js +75 -21
  20. package/server/actions/actionEvents.js +97 -2
  21. package/server/actions/actionEvents.test.js +79 -0
  22. package/{shared → server}/actions/executionContext.js +3 -13
  23. package/server/actions/idempotency.js +24 -0
  24. package/server/actions/pipeline.js +87 -0
  25. package/{shared → server}/actions/policies.js +20 -33
  26. package/{shared → server}/actions/policies.test.js +6 -6
  27. package/{shared → server}/actions/registry.js +3 -22
  28. package/{shared → server}/actions/registry.test.js +70 -32
  29. package/server/actions/requestMeta.js +17 -0
  30. package/server/http/capabilityHttpRuntime.js +1 -1
  31. package/server/http/capabilityHttpRuntime.test.js +56 -0
  32. package/server/http/errorHandling.js +291 -0
  33. package/server/{runtime/fastifyBootstrap.test.js → http/errorHandling.test.js} +72 -120
  34. package/server/http/lib/routeRegistration.js +36 -150
  35. package/server/http/lib/routeTransport.js +2 -0
  36. package/server/http/lib/routeValidator.js +5 -47
  37. package/server/http/lib/routeValidator.test.js +15 -17
  38. package/server/http/lib/router.js +10 -94
  39. package/server/platform/providerRuntime/capabilityProviderLoader.js +2 -1
  40. package/server/platform/providerRuntime/helpers.js +1 -34
  41. package/server/runtime/integers.js +1 -5
  42. package/server/runtime/serviceAuthorization.js +4 -9
  43. package/server/support/appConfig.js +2 -1
  44. package/server/support/appConfigFiles.js +1 -38
  45. package/server/support/appConfigFiles.test.js +3 -39
  46. package/server/support/index.js +1 -20
  47. package/shared/capabilities/defineProvider.js +1 -1
  48. package/shared/capabilities/index.js +1 -1
  49. package/shared/index.js +1 -1
  50. package/shared/support/index.js +1 -4
  51. package/shared/support/mobileConfig.js +99 -0
  52. package/shared/support/mobileConfig.test.js +113 -0
  53. package/shared/support/normalize.js +0 -108
  54. package/shared/support/normalize.test.js +0 -134
  55. package/shared/{actions/actionContributorHelpers.test.js → support/permissions.test.js} +1 -1
  56. package/shared/support/returnToPath.js +1 -20
  57. package/shared/support/returnToPath.test.js +1 -36
  58. package/shared/support/shellLayoutTargets.js +2 -140
  59. package/shared/support/shellLayoutTargets.test.js +1 -110
  60. package/shared/support/sorting.js +1 -9
  61. package/shared/surface/apiPaths.js +1 -82
  62. package/shared/surface/paths.js +38 -171
  63. package/shared/surface/registry.js +2 -1
  64. package/shared/surface/runtime.js +18 -109
  65. package/shared/surface/runtime.test.js +57 -0
  66. package/shared/validators/index.js +1 -4
  67. package/shared/validators/jsonRestSchemaSupport.js +0 -9
  68. package/shared/validators/recordIdParamsValidator.js +0 -6
  69. package/shared/validators/schemaDefinitions.js +4 -30
  70. package/shared/validators/schemaPayloadValidation.js +2 -6
  71. package/test/barrelExposure.test.js +3 -7
  72. package/test/exportsContract.test.js +1 -3
  73. package/client/mobileLaunchRouting.js +0 -231
  74. package/client/mobileLaunchRouting.test.js +0 -230
  75. package/server/http/lib/controller.js +0 -183
  76. package/server/http/lib/controller.test.js +0 -143
  77. package/server/http/lib/index.js +0 -5
  78. package/server/runtime/canonicalJson.js +0 -74
  79. package/server/runtime/entityChangeEvents.js +0 -307
  80. package/server/runtime/entityChangeEvents.test.js +0 -274
  81. package/server/runtime/fastifyBootstrap.js +0 -553
  82. package/server/runtime/moduleConfig.js +0 -223
  83. package/server/runtime/moduleConfig.test.js +0 -165
  84. package/server/runtime/pagination.js +0 -13
  85. package/server/runtime/realtimeNormalization.js +0 -21
  86. package/server/runtime/routeUtils.js +0 -20
  87. package/server/runtime/securityAudit.js +0 -269
  88. package/server/runtime/securityAudit.test.js +0 -41
  89. package/server/support/pageTargets.js +0 -772
  90. package/server/support/pageTargets.test.js +0 -659
  91. package/server/support/shellOutlets.js +0 -576
  92. package/server/support/shellOutlets.test.js +0 -336
  93. package/server/surface/index.js +0 -18
  94. package/shared/actions/audit.js +0 -7
  95. package/shared/actions/idempotency.js +0 -62
  96. package/shared/actions/observability.js +0 -10
  97. package/shared/actions/pipeline.js +0 -309
  98. package/shared/actions/requestMeta.js +0 -36
  99. package/shared/actions/textNormalization.js +0 -3
  100. package/shared/actions/withActionDefaults.js +0 -34
  101. /package/{shared → server}/actions/executionContext.test.js +0 -0
@@ -1,8 +1,103 @@
1
- import { resolveDefaultScope } from "../runtime/entityChangeEvents.js";
2
1
  import { normalizeObject, normalizeOpaqueId, normalizeText } from "../../shared/support/normalize.js";
3
2
 
4
3
  const ENTITY_CHANGE_OPERATIONS = new Set(["created", "updated", "deleted"]);
5
4
 
5
+ function resolveContextScope(context = {}) {
6
+ const sourceScope = normalizeObject(context?.scope || context?.requestMeta?.scope || context?.request?.scope);
7
+ const kind = normalizeText(sourceScope.kind).toLowerCase();
8
+ if (!kind) {
9
+ return null;
10
+ }
11
+ if (kind === "global") {
12
+ return {
13
+ kind: "global",
14
+ id: null
15
+ };
16
+ }
17
+
18
+ const scopeId = normalizeOpaqueId(sourceScope.id);
19
+ if (scopeId == null) {
20
+ return null;
21
+ }
22
+
23
+ const resolvedScope = {
24
+ kind,
25
+ id: scopeId
26
+ };
27
+
28
+ const scopeUserId = normalizeOpaqueId(sourceScope.userId);
29
+ if (scopeUserId != null) {
30
+ resolvedScope.userId = scopeUserId;
31
+ }
32
+
33
+ const scopedScopeId = normalizeOpaqueId(sourceScope.scopeId);
34
+ if (scopedScopeId != null) {
35
+ resolvedScope.scopeId = scopedScopeId;
36
+ }
37
+
38
+ return resolvedScope;
39
+ }
40
+
41
+ function resolveVisibilityScope(visibilityContext = {}) {
42
+ const visibility = normalizeText(visibilityContext.visibility).toLowerCase();
43
+ const scopeKind = normalizeText(visibilityContext.scopeKind || visibility).toLowerCase();
44
+ const scopeOwnerId = normalizeOpaqueId(visibilityContext.scopeOwnerId);
45
+ const userId = normalizeOpaqueId(visibilityContext.userId);
46
+ const requiresActorScope = visibilityContext.requiresActorScope === true;
47
+
48
+ if (requiresActorScope && userId == null) {
49
+ return null;
50
+ }
51
+
52
+ if (scopeKind && scopeOwnerId != null) {
53
+ const scope = {
54
+ kind: scopeKind,
55
+ id: scopeOwnerId
56
+ };
57
+ if (requiresActorScope) {
58
+ scope.scopeId = scopeOwnerId;
59
+ scope.userId = userId;
60
+ }
61
+ return scope;
62
+ }
63
+ if (scopeKind && scopeKind !== "user") {
64
+ return null;
65
+ }
66
+
67
+ if (!scopeKind && scopeOwnerId != null) {
68
+ return {
69
+ kind: "scope",
70
+ id: scopeOwnerId
71
+ };
72
+ }
73
+
74
+ if (scopeKind === "user" && userId != null) {
75
+ return {
76
+ kind: "user",
77
+ id: userId
78
+ };
79
+ }
80
+
81
+ return null;
82
+ }
83
+
84
+ function resolveEventScope(context = {}) {
85
+ const visibilityScope = resolveVisibilityScope(normalizeObject(context.visibilityContext));
86
+ if (visibilityScope) {
87
+ return visibilityScope;
88
+ }
89
+
90
+ const contextScope = resolveContextScope(context);
91
+ if (contextScope) {
92
+ return contextScope;
93
+ }
94
+
95
+ return {
96
+ kind: "global",
97
+ id: null
98
+ };
99
+ }
100
+
6
101
  function resolveValue(value, execution) {
7
102
  return typeof value === "function" ? value(execution) : value;
8
103
  }
@@ -53,7 +148,7 @@ function createEntityChangedActionEvent({
53
148
  entity: normalizedEntity,
54
149
  operation: normalizedOperation,
55
150
  entityId: normalizedEntityId,
56
- scope: resolveDefaultScope(normalizeObject(context.visibilityContext), { context }),
151
+ scope: resolveEventScope(context),
57
152
  actorId: normalizeOpaqueId(context?.actor?.id),
58
153
  commandId: normalizeText(requestMeta.commandId || requestMeta.idempotencyKey) || null,
59
154
  sourceClientId: normalizeText(requestMeta.sourceClientId) || null,
@@ -0,0 +1,79 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { createEntityChangedActionEvent } from "./actionEvents.js";
4
+
5
+ function buildEvent(context, { entityId = 11, realtime = null } = {}) {
6
+ return createEntityChangedActionEvent({
7
+ source: "workspace",
8
+ entity: "settings",
9
+ operation: "updated",
10
+ entityId,
11
+ realtime
12
+ })({ context });
13
+ }
14
+
15
+ test("entity-changed action events carry actor, command and source client", () => {
16
+ const event = buildEvent({
17
+ actor: { id: 17 },
18
+ requestMeta: { idempotencyKey: "cmd-1", sourceClientId: "client-a" },
19
+ visibilityContext: { scopeOwnerId: 23 }
20
+ }, {
21
+ entityId: 5,
22
+ realtime: { event: "settings.changed", payload: { reason: "edit" } }
23
+ });
24
+
25
+ assert.equal(event.type, "entity.changed");
26
+ assert.equal(event.entityId, "5");
27
+ assert.deepEqual(event.scope, { kind: "scope", id: "23" });
28
+ assert.equal(event.actorId, "17");
29
+ assert.equal(event.commandId, "cmd-1");
30
+ assert.equal(event.sourceClientId, "client-a");
31
+ assert.deepEqual(event.realtime, { event: "settings.changed", audience: "event_scope", payload: { reason: "edit" } });
32
+ });
33
+
34
+ test("entity-changed action events skip missing entity identifiers", () => {
35
+ assert.equal(buildEvent({}, { entityId: null }), null);
36
+ });
37
+
38
+ test("entity-changed action events fall back to the context scope when visibility has no owner", () => {
39
+ const event = buildEvent({
40
+ scope: { kind: "workspace", id: 23 },
41
+ visibilityContext: { visibility: "workspace" }
42
+ });
43
+
44
+ assert.deepEqual(event.scope, { kind: "workspace", id: "23" });
45
+ });
46
+
47
+ test("entity-changed action events keep actor-scoped ownership only with an explicit user", () => {
48
+ assert.deepEqual(buildEvent({
49
+ actor: { id: "user_17" },
50
+ visibilityContext: {
51
+ scopeKind: "workspace_user",
52
+ scopeOwnerId: "workspace_23",
53
+ userId: "user_17",
54
+ requiresActorScope: true
55
+ }
56
+ }).scope, {
57
+ kind: "workspace_user",
58
+ id: "workspace_23",
59
+ scopeId: "workspace_23",
60
+ userId: "user_17"
61
+ });
62
+
63
+ assert.deepEqual(buildEvent({
64
+ actor: { id: "user_17" },
65
+ visibilityContext: {
66
+ scopeKind: "workspace_user",
67
+ scopeOwnerId: "workspace_23",
68
+ requiresActorScope: true
69
+ }
70
+ }).scope, { kind: "global", id: null });
71
+
72
+ assert.deepEqual(buildEvent({
73
+ visibilityContext: {
74
+ scopeKind: "workspace_user",
75
+ scopeOwnerId: "workspace_23",
76
+ requiresActorScope: false
77
+ }
78
+ }).scope, { kind: "workspace_user", id: "workspace_23" });
79
+ });
@@ -1,6 +1,6 @@
1
1
  import { normalizeRequestMeta } from "./requestMeta.js";
2
- import { normalizeLowerText, normalizeText } from "./textNormalization.js";
3
- import { normalizePermissionList } from "../support/permissions.js";
2
+ import { normalizeLowerText, normalizeText } from "../../shared/support/normalize.js";
3
+ import { normalizePermissionList } from "../../shared/support/permissions.js";
4
4
 
5
5
  function copyRecord(value) {
6
6
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -73,14 +73,4 @@ function normalizeExecutionContext(context = {}) {
73
73
  });
74
74
  }
75
75
 
76
- const __testables = {
77
- normalizeText,
78
- normalizeLowerText,
79
- normalizePermissions: normalizePermissionList,
80
- copyRecord,
81
- normalizeActor,
82
- normalizeRequestMeta,
83
- normalizeTimeMeta
84
- };
85
-
86
- export { normalizeExecutionContext, __testables };
76
+ export { normalizeExecutionContext };
@@ -0,0 +1,24 @@
1
+ import { createActionRuntimeError } from "./actionDefinitions.js";
2
+ import { normalizeText } from "../../shared/support/normalize.js";
3
+
4
+ function ensureIdempotencyKeyIfRequired(definition, context) {
5
+ if (definition.idempotency !== "required") {
6
+ return;
7
+ }
8
+
9
+ const key = normalizeText(context?.requestMeta?.idempotencyKey || context?.requestMeta?.commandId);
10
+ if (key) {
11
+ return;
12
+ }
13
+
14
+ throw createActionRuntimeError(400, "Validation failed.", {
15
+ code: "ACTION_IDEMPOTENCY_KEY_REQUIRED",
16
+ details: {
17
+ fieldErrors: {
18
+ idempotencyKey: "Idempotency key is required for this action."
19
+ }
20
+ }
21
+ });
22
+ }
23
+
24
+ export { ensureIdempotencyKeyIfRequired };
@@ -0,0 +1,87 @@
1
+ import {
2
+ ensureActionChannelAllowed,
3
+ ensureActionSurfaceAllowed,
4
+ ensureActionPermissionAllowed,
5
+ normalizeActionInput,
6
+ normalizeActionOutput
7
+ } from "./policies.js";
8
+ import { ensureIdempotencyKeyIfRequired } from "./idempotency.js";
9
+ import { normalizeExecutionContext } from "./executionContext.js";
10
+
11
+ async function publishActionEvents(events, builders, execution) {
12
+ if (!Array.isArray(builders) || builders.length === 0) return;
13
+ if (!events || typeof events.publish !== "function") {
14
+ throw new TypeError("Action event publishing requires runtime.events.publish().");
15
+ }
16
+ for (const builder of builders) {
17
+ const built = await builder(execution);
18
+ const values = Array.isArray(built) ? built : [built];
19
+ for (const event of values) {
20
+ if (event != null) await events.publish(event);
21
+ }
22
+ }
23
+ }
24
+
25
+ function logActionExecution(logger, { definition, context, outcome, startedAt, errorCode = null }) {
26
+ if (!logger || typeof logger.debug !== "function") {
27
+ return;
28
+ }
29
+ logger.debug(
30
+ {
31
+ action: definition?.id,
32
+ version: definition?.version,
33
+ channel: context?.channel,
34
+ surface: context?.surface,
35
+ requestId: context?.requestMeta?.requestId || null,
36
+ durationMs: Date.now() - startedAt,
37
+ outcome,
38
+ errorCode
39
+ },
40
+ "action.execution"
41
+ );
42
+ }
43
+
44
+ async function executeActionPipeline({
45
+ definition,
46
+ input,
47
+ context,
48
+ deps = {},
49
+ events,
50
+ logger = console
51
+ } = {}) {
52
+ const normalizedContext = normalizeExecutionContext(context);
53
+ const startedAt = Date.now();
54
+
55
+ try {
56
+ ensureActionChannelAllowed(definition, normalizedContext);
57
+ ensureActionSurfaceAllowed(definition, normalizedContext);
58
+ ensureActionPermissionAllowed(definition, normalizedContext);
59
+
60
+ const normalizedInput = await normalizeActionInput(definition, input);
61
+ ensureIdempotencyKeyIfRequired(definition, normalizedContext);
62
+
63
+ const executionResult = await definition.execute(normalizedInput, normalizedContext, deps);
64
+ const normalizedResult = await normalizeActionOutput(definition, executionResult);
65
+
66
+ await publishActionEvents(events, definition.events, Object.freeze({
67
+ definition,
68
+ input: normalizedInput,
69
+ result: normalizedResult,
70
+ context: normalizedContext
71
+ }));
72
+
73
+ logActionExecution(logger, { definition, context: normalizedContext, outcome: "success", startedAt });
74
+ return normalizedResult;
75
+ } catch (error) {
76
+ logActionExecution(logger, {
77
+ definition,
78
+ context: normalizedContext,
79
+ outcome: "failure",
80
+ startedAt,
81
+ errorCode: String(error?.code || "ACTION_EXECUTION_FAILED").trim()
82
+ });
83
+ throw error;
84
+ }
85
+ }
86
+
87
+ export { executeActionPipeline };
@@ -1,10 +1,7 @@
1
1
  import { createActionRuntimeError } from "./actionDefinitions.js";
2
- import { normalizeLowerText, normalizeText } from "./textNormalization.js";
3
- import { hasPermission, normalizePermissionList } from "../support/permissions.js";
4
- import { isRecord, normalizeOpaqueId } from "../support/normalize.js";
5
- import {
6
- validateSchemaPayload
7
- } from "../validators/schemaPayloadValidation.js";
2
+ import { hasPermission, normalizePermissionList } from "../../shared/support/permissions.js";
3
+ import { isRecord, normalizeLowerText, normalizeOpaqueId } from "../../shared/support/normalize.js";
4
+ import { validateSchemaPayload } from "../../shared/validators/schemaPayloadValidation.js";
8
5
 
9
6
  function createActionValidationError({
10
7
  status = 400,
@@ -22,13 +19,12 @@ function createActionValidationError({
22
19
 
23
20
  function ensureActionChannelAllowed(definition, context) {
24
21
  const channel = normalizeLowerText(context?.channel);
25
- const allowedChannels = Array.isArray(definition?.channels) ? definition.channels : [];
26
22
 
27
- if (!channel || !allowedChannels.includes(channel)) {
23
+ if (!channel || !definition.channels.includes(channel)) {
28
24
  throw createActionRuntimeError(403, "Forbidden.", {
29
25
  code: "ACTION_CHANNEL_FORBIDDEN",
30
26
  details: {
31
- actionId: definition?.id,
27
+ actionId: definition.id,
32
28
  channel
33
29
  }
34
30
  });
@@ -37,13 +33,13 @@ function ensureActionChannelAllowed(definition, context) {
37
33
 
38
34
  function ensureActionSurfaceAllowed(definition, context) {
39
35
  const surface = normalizeLowerText(context?.surface);
40
- const allowedSurfaces = Array.isArray(definition?.surfaces) ? definition.surfaces : [];
36
+ const allowedSurfaces = definition.surfaces;
41
37
 
42
38
  if (!allowedSurfaces.includes("*") && (!surface || !allowedSurfaces.includes(surface))) {
43
39
  throw createActionRuntimeError(403, "Forbidden.", {
44
40
  code: "ACTION_SURFACE_FORBIDDEN",
45
41
  details: {
46
- actionId: definition?.id,
42
+ actionId: definition.id,
47
43
  surface
48
44
  }
49
45
  });
@@ -51,8 +47,8 @@ function ensureActionSurfaceAllowed(definition, context) {
51
47
  }
52
48
 
53
49
  function ensureActionPermissionAllowed(definition, context) {
54
- const permission = isRecord(definition?.permission) ? definition.permission : { require: "none" };
55
- const mode = normalizeLowerText(permission.require || "none");
50
+ const { permission } = definition;
51
+ const mode = permission.require;
56
52
 
57
53
  if (mode === "none") {
58
54
  return;
@@ -63,7 +59,7 @@ function ensureActionPermissionAllowed(definition, context) {
63
59
  throw createActionRuntimeError(401, permission.message || "Authentication required.", {
64
60
  code: permission.code || "ACTION_AUTHENTICATION_REQUIRED",
65
61
  details: {
66
- actionId: definition?.id
62
+ actionId: definition.id
67
63
  }
68
64
  });
69
65
  }
@@ -72,7 +68,7 @@ function ensureActionPermissionAllowed(definition, context) {
72
68
  return;
73
69
  }
74
70
 
75
- const requiredPermissions = normalizePermissionList(permission.permissions);
71
+ const requiredPermissions = permission.permissions;
76
72
  if (requiredPermissions.length < 1) {
77
73
  return;
78
74
  }
@@ -87,7 +83,7 @@ function ensureActionPermissionAllowed(definition, context) {
87
83
  throw createActionRuntimeError(403, permission.message || "Forbidden.", {
88
84
  code: permission.code || "ACTION_PERMISSION_DENIED",
89
85
  details: {
90
- actionId: definition?.id,
86
+ actionId: definition.id,
91
87
  permission: requiredPermission
92
88
  }
93
89
  });
@@ -101,19 +97,18 @@ function ensureActionPermissionAllowed(definition, context) {
101
97
  throw createActionRuntimeError(403, permission.message || "Forbidden.", {
102
98
  code: permission.code || "ACTION_PERMISSION_DENIED",
103
99
  details: {
104
- actionId: definition?.id,
100
+ actionId: definition.id,
105
101
  requiredPermissions
106
102
  }
107
103
  });
108
104
  }
109
105
  }
110
106
 
111
- async function normalizeActionInput(definition, input, context) {
107
+ async function normalizeActionInput(definition, input) {
112
108
  try {
113
- return validateSchemaPayload(definition?.input, input, {
109
+ return validateSchemaPayload(definition.input, input, {
114
110
  phase: "input",
115
- definition,
116
- context
111
+ context: `Action ${definition.id} input`
117
112
  });
118
113
  } catch (error) {
119
114
  if (isRecord(error?.fieldErrors) || isRecord(error?.details?.fieldErrors)) {
@@ -137,16 +132,15 @@ async function normalizeActionInput(definition, input, context) {
137
132
  }
138
133
  }
139
134
 
140
- async function normalizeActionOutput(definition, output, context) {
141
- if (!definition?.output) {
135
+ async function normalizeActionOutput(definition, output) {
136
+ if (!definition.output) {
142
137
  return output;
143
138
  }
144
139
 
145
140
  try {
146
141
  return validateSchemaPayload(definition.output, output, {
147
142
  phase: "output",
148
- definition,
149
- context
143
+ context: `Action ${definition.id} output`
150
144
  });
151
145
  } catch (error) {
152
146
  if (isRecord(error?.fieldErrors) || isRecord(error?.details?.fieldErrors)) {
@@ -182,17 +176,10 @@ async function normalizeActionOutput(definition, output, context) {
182
176
  }
183
177
  }
184
178
 
185
- const __testables = {
186
- normalizeText,
187
- normalizeLowerText,
188
- validateSchemaPayload
189
- };
190
-
191
179
  export {
192
180
  ensureActionChannelAllowed,
193
181
  ensureActionSurfaceAllowed,
194
182
  ensureActionPermissionAllowed,
195
183
  normalizeActionInput,
196
- normalizeActionOutput,
197
- __testables
184
+ normalizeActionOutput
198
185
  };
@@ -20,7 +20,7 @@ test("plain json-rest-schema action schemas validate input without reshaping it"
20
20
  }
21
21
  };
22
22
 
23
- const result = await normalizeActionInput(definition, { workspaceSlug: " ACME " }, {});
23
+ const result = await normalizeActionInput(definition, { workspaceSlug: " ACME " });
24
24
  assert.deepEqual(result, { workspaceSlug: "ACME" });
25
25
  });
26
26
 
@@ -41,7 +41,7 @@ test("json-rest-schema input validation surfaces plain field keys", async () =>
41
41
  };
42
42
 
43
43
  await assert.rejects(
44
- () => normalizeActionInput(definition, { name: "too long" }, {}),
44
+ () => normalizeActionInput(definition, { name: "too long" }),
45
45
  (error) => {
46
46
  const fieldErrors = error.details?.fieldErrors || {};
47
47
  assert.equal(typeof fieldErrors.name, "string");
@@ -67,11 +67,11 @@ test("action output validation preserves valid json-rest-schema output", async (
67
67
  };
68
68
 
69
69
  await assert.rejects(
70
- () => normalizeActionOutput(definition, { ok: 2 }, {}),
70
+ () => normalizeActionOutput(definition, { ok: 2 }),
71
71
  (error) => error?.code === "ACTION_OUTPUT_VALIDATION_FAILED"
72
72
  );
73
73
 
74
- const result = await normalizeActionOutput(definition, { ok: true }, {});
74
+ const result = await normalizeActionOutput(definition, { ok: true });
75
75
  assert.deepEqual(result, { ok: true });
76
76
  });
77
77
 
@@ -94,7 +94,7 @@ test("json-rest-schema action validators normalize action input", async () => {
94
94
  }
95
95
  };
96
96
 
97
- const result = await normalizeActionInput(definition, { name: " Acme " }, {});
97
+ const result = await normalizeActionInput(definition, { name: " Acme " });
98
98
  assert.deepEqual(result, { name: "Acme" });
99
99
  });
100
100
 
@@ -118,7 +118,7 @@ test("json-rest-schema action validators surface field errors", async () => {
118
118
  };
119
119
 
120
120
  await assert.rejects(
121
- () => normalizeActionInput(definition, { name: " " }, {}),
121
+ () => normalizeActionInput(definition, { name: " " }),
122
122
  (error) => {
123
123
  assert.equal(error.code, "ACTION_VALIDATION_FAILED");
124
124
  assert.equal(error.details?.fieldErrors?.name, "Name is required.");
@@ -111,9 +111,6 @@ function resolveActionDefinition(index, actionId, version) {
111
111
 
112
112
  function createActionRegistry({
113
113
  contributors = [],
114
- idempotencyAdapter,
115
- auditAdapter,
116
- observabilityAdapter,
117
114
  events,
118
115
  logger = console
119
116
  } = {}) {
@@ -122,19 +119,14 @@ function createActionRegistry({
122
119
 
123
120
  async function execute({ actionId, version = null, input = {}, context = {}, deps = {} } = {}) {
124
121
  const definition = resolveActionDefinition(index, actionId, version);
125
- const execution = await executeActionPipeline({
122
+ return executeActionPipeline({
126
123
  definition,
127
124
  input,
128
125
  context,
129
126
  deps,
130
- idempotencyAdapter,
131
- auditAdapter,
132
- observabilityAdapter,
133
127
  events,
134
128
  logger
135
129
  });
136
-
137
- return execution.result;
138
130
  }
139
131
 
140
132
  async function executeStream({ actionId, version = null, input = {}, context = {}, deps = {} } = {}) {
@@ -150,19 +142,14 @@ function createActionRegistry({
150
142
  });
151
143
  }
152
144
 
153
- const execution = await executeActionPipeline({
145
+ return executeActionPipeline({
154
146
  definition,
155
147
  input,
156
148
  context,
157
149
  deps,
158
- idempotencyAdapter,
159
- auditAdapter,
160
- observabilityAdapter,
161
150
  events,
162
151
  logger
163
152
  });
164
-
165
- return execution.result;
166
153
  }
167
154
 
168
155
  function listDefinitions() {
@@ -181,10 +168,4 @@ function createActionRegistry({
181
168
  });
182
169
  }
183
170
 
184
- const __testables = {
185
- normalizeContributors,
186
- buildDefinitionIndex,
187
- resolveActionDefinition
188
- };
189
-
190
- export { createActionRegistry, __testables };
171
+ export { createActionRegistry };