@jskit-ai/kernel 0.1.245 → 0.1.247

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 (102) 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 +19 -62
  15. package/internal/node/installedPackages.test.js +33 -0
  16. package/package.json +2 -4
  17. package/server/actions/actionCatalogue.js +13 -34
  18. package/{shared → server}/actions/actionContributorHelpers.js +0 -5
  19. package/{shared → server}/actions/actionDefinitions.js +24 -131
  20. package/{shared → server}/actions/actionDefinitions.test.js +75 -21
  21. package/server/actions/actionEvents.js +97 -2
  22. package/server/actions/actionEvents.test.js +79 -0
  23. package/{shared → server}/actions/executionContext.js +3 -13
  24. package/server/actions/idempotency.js +24 -0
  25. package/server/actions/pipeline.js +87 -0
  26. package/{shared → server}/actions/policies.js +20 -33
  27. package/{shared → server}/actions/policies.test.js +6 -6
  28. package/{shared → server}/actions/registry.js +3 -22
  29. package/{shared → server}/actions/registry.test.js +70 -32
  30. package/server/actions/requestMeta.js +17 -0
  31. package/server/http/capabilityHttpRuntime.js +1 -1
  32. package/server/http/capabilityHttpRuntime.test.js +56 -0
  33. package/server/http/errorHandling.js +291 -0
  34. package/server/{runtime/fastifyBootstrap.test.js → http/errorHandling.test.js} +72 -120
  35. package/server/http/lib/routeRegistration.js +36 -150
  36. package/server/http/lib/routeTransport.js +2 -0
  37. package/server/http/lib/routeValidator.js +5 -47
  38. package/server/http/lib/routeValidator.test.js +15 -17
  39. package/server/http/lib/router.js +10 -94
  40. package/server/platform/providerRuntime/capabilityProviderLoader.js +2 -1
  41. package/server/platform/providerRuntime/helpers.js +1 -34
  42. package/server/runtime/integers.js +1 -5
  43. package/server/runtime/serviceAuthorization.js +4 -9
  44. package/server/support/appConfig.js +2 -1
  45. package/server/support/appConfigFiles.js +1 -38
  46. package/server/support/appConfigFiles.test.js +3 -39
  47. package/server/support/index.js +1 -20
  48. package/shared/capabilities/defineProvider.js +1 -1
  49. package/shared/capabilities/index.js +1 -1
  50. package/shared/index.js +1 -1
  51. package/shared/support/index.js +1 -4
  52. package/shared/support/mobileConfig.js +99 -0
  53. package/shared/support/mobileConfig.test.js +113 -0
  54. package/shared/support/normalize.js +0 -108
  55. package/shared/support/normalize.test.js +0 -134
  56. package/shared/{actions/actionContributorHelpers.test.js → support/permissions.test.js} +1 -1
  57. package/shared/support/returnToPath.js +1 -20
  58. package/shared/support/returnToPath.test.js +1 -36
  59. package/shared/support/shellLayoutTargets.js +2 -140
  60. package/shared/support/shellLayoutTargets.test.js +1 -110
  61. package/shared/support/sorting.js +1 -9
  62. package/shared/surface/apiPaths.js +1 -82
  63. package/shared/surface/paths.js +38 -171
  64. package/shared/surface/registry.js +2 -1
  65. package/shared/surface/runtime.js +18 -109
  66. package/shared/surface/runtime.test.js +57 -0
  67. package/shared/validators/index.js +1 -4
  68. package/shared/validators/jsonRestSchemaSupport.js +0 -9
  69. package/shared/validators/recordIdParamsValidator.js +0 -6
  70. package/shared/validators/schemaDefinitions.js +4 -30
  71. package/shared/validators/schemaPayloadValidation.js +2 -6
  72. package/test/barrelExposure.test.js +3 -7
  73. package/test/exportsContract.test.js +1 -3
  74. package/client/mobileLaunchRouting.js +0 -231
  75. package/client/mobileLaunchRouting.test.js +0 -230
  76. package/server/http/lib/controller.js +0 -183
  77. package/server/http/lib/controller.test.js +0 -143
  78. package/server/http/lib/index.js +0 -5
  79. package/server/runtime/canonicalJson.js +0 -74
  80. package/server/runtime/entityChangeEvents.js +0 -307
  81. package/server/runtime/entityChangeEvents.test.js +0 -274
  82. package/server/runtime/fastifyBootstrap.js +0 -553
  83. package/server/runtime/moduleConfig.js +0 -223
  84. package/server/runtime/moduleConfig.test.js +0 -165
  85. package/server/runtime/pagination.js +0 -13
  86. package/server/runtime/realtimeNormalization.js +0 -21
  87. package/server/runtime/routeUtils.js +0 -20
  88. package/server/runtime/securityAudit.js +0 -269
  89. package/server/runtime/securityAudit.test.js +0 -41
  90. package/server/support/pageTargets.js +0 -772
  91. package/server/support/pageTargets.test.js +0 -659
  92. package/server/support/shellOutlets.js +0 -576
  93. package/server/support/shellOutlets.test.js +0 -336
  94. package/server/surface/index.js +0 -18
  95. package/shared/actions/audit.js +0 -7
  96. package/shared/actions/idempotency.js +0 -62
  97. package/shared/actions/observability.js +0 -10
  98. package/shared/actions/pipeline.js +0 -309
  99. package/shared/actions/requestMeta.js +0 -36
  100. package/shared/actions/textNormalization.js +0 -3
  101. package/shared/actions/withActionDefaults.js +0 -34
  102. /package/{shared → server}/actions/executionContext.test.js +0 -0
@@ -1,8 +1,8 @@
1
- import { readFile, realpath } from "node:fs/promises";
1
+ import { realpath } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { normalizeObject } from "../../shared/support/normalize.js";
4
4
  import { sortStrings } from "../../shared/support/sorting.js";
5
- import { fileExists } from "./fileSystem.js";
5
+ import { fileExists, readJsonFile } from "./fileSystem.js";
6
6
 
7
7
  const ROOT_DEPENDENCY_SECTIONS = Object.freeze([
8
8
  "dependencies",
@@ -18,14 +18,6 @@ const JSKIT_PACKAGE_CONFIG_KEYS = Object.freeze([
18
18
  "vite"
19
19
  ]);
20
20
 
21
- async function readJsonFile(filePath, fallback = {}) {
22
- try {
23
- return JSON.parse(await readFile(filePath, "utf8"));
24
- } catch {
25
- return fallback;
26
- }
27
- }
28
-
29
21
  function collectRootDependencySpecifiers(packageJson = {}) {
30
22
  const specifiers = new Map();
31
23
  for (const sectionName of ROOT_DEPENDENCY_SECTIONS) {
@@ -42,7 +34,7 @@ function collectRootDependencySpecifiers(packageJson = {}) {
42
34
 
43
35
  function collectPackageDependencyIds(packageJson = {}) {
44
36
  const dependencyIds = new Set();
45
- for (const sectionName of ["dependencies", "optionalDependencies", "peerDependencies"]) {
37
+ for (const sectionName of ROOT_DEPENDENCY_SECTIONS) {
46
38
  for (const packageId of Object.keys(normalizeObject(packageJson?.[sectionName]))) {
47
39
  const normalizedPackageId = String(packageId || "").trim();
48
40
  if (normalizedPackageId) {
@@ -175,56 +167,27 @@ async function discoverInstalledPackages({ appRoot } = {}) {
175
167
  const rootPackageJson = await readJsonFile(path.resolve(normalizedAppRoot, "package.json"), {});
176
168
  const directSpecifiers = collectRootDependencySpecifiers(rootPackageJson);
177
169
  const directPackageIds = new Set(directSpecifiers.keys());
178
- const runtimeRootPackageIds = new Set(
179
- ["dependencies", "optionalDependencies", "peerDependencies"]
180
- .flatMap((sectionName) => Object.keys(normalizeObject(rootPackageJson?.[sectionName])))
181
- );
182
170
  const visited = new Set();
171
+ // Breadth-first walk of the dependency graph; the queue stays ordered by packageId.
183
172
  const queue = [];
184
- const queued = new Map();
173
+ const queued = new Set();
185
174
  const packages = [];
186
175
 
187
- const sortQueue = () => {
188
- queue.sort((left, right) => {
189
- if (left.traverseDependencies !== right.traverseDependencies) {
190
- return left.traverseDependencies ? -1 : 1;
191
- }
192
- return left.packageId.localeCompare(right.packageId);
193
- });
194
- };
195
- const enqueue = ({ packageId, parentPackageRoot = "", traverseDependencies = false }) => {
196
- const normalizedPackageId = String(packageId || "").trim();
197
- if (!normalizedPackageId || visited.has(normalizedPackageId)) {
176
+ const enqueue = ({ packageId, parentPackageRoot = "" }) => {
177
+ if (!packageId || visited.has(packageId) || queued.has(packageId)) {
198
178
  return;
199
179
  }
200
- const existing = queued.get(normalizedPackageId);
201
- if (existing) {
202
- if (traverseDependencies && !existing.traverseDependencies) {
203
- existing.traverseDependencies = true;
204
- existing.parentPackageRoot = parentPackageRoot || existing.parentPackageRoot;
205
- sortQueue();
206
- }
207
- return;
208
- }
209
- const entry = {
210
- packageId: normalizedPackageId,
211
- parentPackageRoot,
212
- traverseDependencies: Boolean(traverseDependencies)
213
- };
214
- queue.push(entry);
215
- queued.set(normalizedPackageId, entry);
216
- sortQueue();
180
+ queue.push({ packageId, parentPackageRoot });
181
+ queued.add(packageId);
182
+ queue.sort((left, right) => left.packageId.localeCompare(right.packageId));
217
183
  };
218
184
 
219
185
  for (const packageId of sortStrings([...directPackageIds])) {
220
- enqueue({
221
- packageId,
222
- traverseDependencies: runtimeRootPackageIds.has(packageId)
223
- });
186
+ enqueue({ packageId });
224
187
  }
225
188
 
226
189
  while (queue.length > 0) {
227
- const { packageId, parentPackageRoot, traverseDependencies } = queue.shift();
190
+ const { packageId, parentPackageRoot } = queue.shift();
228
191
  queued.delete(packageId);
229
192
  if (!packageId || visited.has(packageId)) {
230
193
  continue;
@@ -244,26 +207,20 @@ async function discoverInstalledPackages({ appRoot } = {}) {
244
207
  }
245
208
 
246
209
  const packageJson = await readJsonFile(packageJsonPath, {});
247
- const manifestPackageId = String(packageJson.name || "").trim();
248
- if (manifestPackageId && manifestPackageId !== packageId) {
210
+ const packageMetadata = createPackageMetadata(packageJson);
211
+ // An npm alias ("alias": "npm:real@1") installs another package under the alias name,
212
+ // which is only an error for JSKIT packages.
213
+ if (packageMetadata && packageMetadata.packageId !== packageId) {
249
214
  throw new Error(
250
- `Installed package manifest mismatch: expected ${packageId}, received ${manifestPackageId}.`
215
+ `Installed package manifest mismatch: expected ${packageId}, received ${packageMetadata.packageId}.`
251
216
  );
252
217
  }
253
218
 
254
219
  const dependencyIds = collectPackageDependencyIds(packageJson);
255
- if (traverseDependencies) {
256
- for (const dependencyId of dependencyIds) {
257
- const normalizedDependencyId = String(dependencyId || "").trim();
258
- enqueue({
259
- packageId: normalizedDependencyId,
260
- parentPackageRoot: roots.packageRoot,
261
- traverseDependencies: true
262
- });
263
- }
220
+ for (const dependencyId of dependencyIds) {
221
+ enqueue({ packageId: dependencyId, parentPackageRoot: roots.packageRoot });
264
222
  }
265
223
 
266
- const packageMetadata = createPackageMetadata(packageJson);
267
224
  if (!packageMetadata) {
268
225
  continue;
269
226
  }
@@ -115,3 +115,36 @@ test("discoverInstalledPackages excludes development-only packages from runtime
115
115
  const packages = await discoverInstalledPackages({ appRoot });
116
116
  assert.deepEqual(packages.map((entry) => entry.packageId), ["@example/runtime"]);
117
117
  });
118
+
119
+ test("discoverInstalledPackages walks npm alias dependencies but rejects aliased JSKIT packages", async (context) => {
120
+ const appRoot = await mkdtemp(path.join(tmpdir(), "jskit-installed-package-alias-"));
121
+ context.after(() => rm(appRoot, { recursive: true, force: true }));
122
+ const aliasRoot = path.join(appRoot, "node_modules", "@example", "sdk-v0_3");
123
+ const runtimeRoot = path.join(appRoot, "node_modules", "@example", "runtime");
124
+ await mkdir(aliasRoot, { recursive: true });
125
+ await mkdir(runtimeRoot, { recursive: true });
126
+ await writeFile(
127
+ path.join(appRoot, "package.json"),
128
+ JSON.stringify({ dependencies: { "@example/sdk-v0_3": "npm:@example/sdk@0.3.0" } })
129
+ );
130
+ await writeFile(
131
+ path.join(aliasRoot, "package.json"),
132
+ JSON.stringify({ name: "@example/sdk", version: "0.3.0", dependencies: { "@example/runtime": "1.0.0" } })
133
+ );
134
+ await writeFile(
135
+ path.join(runtimeRoot, "package.json"),
136
+ JSON.stringify({ name: "@example/runtime", version: "1.0.0", jskit: { kind: "runtime" } })
137
+ );
138
+
139
+ const packages = await discoverInstalledPackages({ appRoot });
140
+ assert.deepEqual(packages.map((entry) => entry.packageId), ["@example/runtime"]);
141
+
142
+ await writeFile(
143
+ path.join(aliasRoot, "package.json"),
144
+ JSON.stringify({ name: "@example/sdk", version: "0.3.0", jskit: { kind: "runtime" } })
145
+ );
146
+ await assert.rejects(
147
+ () => discoverInstalledPackages({ appRoot }),
148
+ /Installed package manifest mismatch: expected @example\/sdk-v0_3, received @example\/sdk\./
149
+ );
150
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/kernel",
3
- "version": "0.1.245",
3
+ "version": "0.1.247",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "json-rest-schema": "^1.0.17"
@@ -25,18 +25,16 @@
25
25
  "./client/moduleBootstrap": "./client/moduleBootstrap.js",
26
26
  "./client/vite": "./client/vite/index.js",
27
27
  "./server/actions": "./server/actions/index.js",
28
+ "./server/actions/actionContributorHelpers": "./server/actions/actionContributorHelpers.js",
28
29
  "./server/features": "./server/features/index.js",
29
30
  "./server/http": "./server/http/index.js",
30
31
  "./server/platform": "./server/platform/index.js",
31
32
  "./server/runtime": "./server/runtime/index.js",
32
- "./server/runtime/entityChangeEvents": "./server/runtime/entityChangeEvents.js",
33
33
  "./server/runtime/errors": "./server/runtime/errors.js",
34
34
  "./server/runtime/requestUrl": "./server/runtime/requestUrl.js",
35
35
  "./server/support": "./server/support/index.js",
36
36
  "./shared": "./shared/index.js",
37
37
  "./shared/capabilities": "./shared/capabilities/index.js",
38
- "./shared/actions/actionContributorHelpers": "./shared/actions/actionContributorHelpers.js",
39
- "./shared/actions/textNormalization": "./shared/actions/textNormalization.js",
40
38
  "./shared/validators": "./shared/validators/index.js",
41
39
  "./shared/validators/inputNormalization": "./shared/validators/inputNormalization.js",
42
40
  "./shared/support": "./shared/support/index.js",
@@ -1,4 +1,4 @@
1
- import { createActionRegistry } from "../../shared/actions/registry.js";
1
+ import { createActionRegistry } from "./registry.js";
2
2
  import { isRecord } from "../../shared/support/normalize.js";
3
3
 
4
4
  function normalizeRegistration(value) {
@@ -9,21 +9,12 @@ function normalizeRegistration(value) {
9
9
  return value;
10
10
  }
11
11
 
12
- function createActionCatalogue({
13
- idempotencyAdapter,
14
- auditAdapter,
15
- observabilityAdapter,
16
- events,
17
- logger = null
18
- } = {}) {
12
+ function createActionCatalogue({ events, logger = null } = {}) {
19
13
  const contributors = [];
20
14
  const contextContributors = [];
21
15
  const contextContributorIds = new Set();
22
16
  let registry = createActionRegistry({
23
17
  contributors,
24
- idempotencyAdapter,
25
- auditAdapter,
26
- observabilityAdapter,
27
18
  events,
28
19
  logger
29
20
  });
@@ -36,9 +27,6 @@ function createActionCatalogue({
36
27
  const nextContributors = [...contributors, normalizeRegistration(contributor)];
37
28
  const nextRegistry = createActionRegistry({
38
29
  contributors: nextContributors,
39
- idempotencyAdapter,
40
- auditAdapter,
41
- observabilityAdapter,
42
30
  events,
43
31
  logger
44
32
  });
@@ -104,40 +92,31 @@ function createActionCatalogue({
104
92
  return Object.freeze(enriched);
105
93
  }
106
94
 
107
- async function execute(payload = {}) {
95
+ async function run(method, payload = {}) {
108
96
  const source = payload && typeof payload === "object" ? payload : {};
109
97
  const input = source.input && typeof source.input === "object" ? source.input : {};
98
+ const version = source.version == null ? null : source.version;
110
99
  const context = await buildExecutionContext({
111
100
  actionId: source.actionId,
112
- version: source.version == null ? null : source.version,
101
+ version,
113
102
  input,
114
103
  context: source.context
115
104
  });
116
- return currentRegistry().execute({
105
+ return currentRegistry()[method]({
117
106
  actionId: source.actionId,
118
- version: source.version == null ? null : source.version,
107
+ version,
119
108
  input,
120
109
  context,
121
110
  deps: isRecord(source.deps) ? source.deps : {}
122
111
  });
123
112
  }
124
113
 
125
- async function executeStream(payload = {}) {
126
- const source = payload && typeof payload === "object" ? payload : {};
127
- const input = source.input && typeof source.input === "object" ? source.input : {};
128
- const context = await buildExecutionContext({
129
- actionId: source.actionId,
130
- version: source.version == null ? null : source.version,
131
- input,
132
- context: source.context
133
- });
134
- return currentRegistry().executeStream({
135
- actionId: source.actionId,
136
- version: source.version == null ? null : source.version,
137
- input,
138
- context,
139
- deps: isRecord(source.deps) ? source.deps : {}
140
- });
114
+ function execute(payload) {
115
+ return run("execute", payload);
116
+ }
117
+
118
+ function executeStream(payload) {
119
+ return run("executeStream", payload);
141
120
  }
142
121
 
143
122
  function listDefinitions() {
@@ -1,6 +1,4 @@
1
1
  import { createSchema } from "json-rest-schema";
2
- import { normalizeObject, normalizePositiveInteger as toPositiveInteger } from "../support/normalize.js";
3
- import { hasPermission } from "../support/permissions.js";
4
2
 
5
3
  function requireServiceMethod(service, methodName, contributorId, { serviceLabel } = {}) {
6
4
  if (!service || typeof service[methodName] !== "function") {
@@ -19,10 +17,7 @@ const emptyInputValidator = Object.freeze({
19
17
  });
20
18
 
21
19
  export {
22
- normalizeObject,
23
- toPositiveInteger,
24
20
  requireServiceMethod,
25
21
  resolveRequest,
26
- hasPermission,
27
22
  emptyInputValidator
28
23
  };
@@ -1,9 +1,7 @@
1
- import {
2
- normalizeSingleSchemaDefinition
3
- } from "../validators/index.js";
4
- import { isRecord as isPlainObject, normalizePositiveInteger } from "../support/normalize.js";
5
- import { normalizePermissionList } from "../support/permissions.js";
6
- import { normalizeText } from "./textNormalization.js";
1
+ import { normalizeSingleSchemaDefinition } from "../../shared/validators/index.js";
2
+ import { isRecord as isPlainObject, normalizePositiveInteger, normalizeText } from "../../shared/support/normalize.js";
3
+ import { normalizePermissionList } from "../../shared/support/permissions.js";
4
+ import { ARCHITECTURE_ID_PATTERN } from "../../shared/capabilities/defineProvider.js";
7
5
 
8
6
  const ACTION_KINDS = Object.freeze(["query", "command", "stream"]);
9
7
  const ACTION_IDEMPOTENCY_POLICIES = Object.freeze(["none", "optional", "required", "domain_native"]);
@@ -12,7 +10,6 @@ const ACTION_PERMISSION_REQUIRE_MODES = Object.freeze(["none", "authenticated",
12
10
  const ACTION_KIND_SET = new Set(ACTION_KINDS);
13
11
  const ACTION_IDEMPOTENCY_SET = new Set(ACTION_IDEMPOTENCY_POLICIES);
14
12
  const ACTION_PERMISSION_REQUIRE_SET = new Set(ACTION_PERMISSION_REQUIRE_MODES);
15
- const ACTION_DOMAIN_PATTERN = /^[a-z][a-z0-9_.-]*$/;
16
13
 
17
14
  class ActionRuntimeError extends Error {
18
15
  constructor(status, message, options = {}) {
@@ -38,10 +35,10 @@ function normalizeActionDomain(value, { context = "domain", errorCode = "ACTION_
38
35
  code: errorCode
39
36
  });
40
37
  }
41
- if (!ACTION_DOMAIN_PATTERN.test(domain)) {
38
+ if (!ARCHITECTURE_ID_PATTERN.test(domain)) {
42
39
  throw createActionRuntimeError(
43
40
  500,
44
- `${context} must match ${ACTION_DOMAIN_PATTERN.toString()} (lowercase letters, digits, _, -, .).`,
41
+ `${context} must match ${ARCHITECTURE_ID_PATTERN.toString()} (lowercase letters, digits, _, -, .).`,
45
42
  {
46
43
  code: errorCode
47
44
  }
@@ -51,23 +48,13 @@ function normalizeActionDomain(value, { context = "domain", errorCode = "ACTION_
51
48
  return domain;
52
49
  }
53
50
 
54
- function normalizeStringArray(value, { fieldName, allowedSet, allowEmpty = false } = {}) {
51
+ function normalizeStringArray(value, fieldName) {
55
52
  const source = Array.isArray(value) ? value : [];
56
53
  const normalized = Array.from(
57
- new Set(
58
- source
59
- .map((entry) => normalizeText(entry).toLowerCase())
60
- .filter(Boolean)
61
- .filter((entry) => {
62
- if (!(allowedSet instanceof Set)) {
63
- return true;
64
- }
65
- return allowedSet.has(entry);
66
- })
67
- )
54
+ new Set(source.map((entry) => normalizeText(entry).toLowerCase()).filter(Boolean))
68
55
  );
69
56
 
70
- if (!allowEmpty && normalized.length < 1) {
57
+ if (normalized.length < 1) {
71
58
  throw createActionRuntimeError(500, `Action definition ${fieldName} must include at least one value.`, {
72
59
  code: "ACTION_DEFINITION_INVALID"
73
60
  });
@@ -76,7 +63,7 @@ function normalizeStringArray(value, { fieldName, allowedSet, allowEmpty = false
76
63
  return normalized;
77
64
  }
78
65
 
79
- function normalizeSingleActionSchema(value, fieldName, { required = false, defaultMode = "" } = {}) {
66
+ function normalizeActionSchema(value, fieldName, { required = false, defaultMode = "" } = {}) {
80
67
  if (value == null) {
81
68
  if (!required) {
82
69
  return null;
@@ -87,6 +74,12 @@ function normalizeSingleActionSchema(value, fieldName, { required = false, defau
87
74
  });
88
75
  }
89
76
 
77
+ if (Array.isArray(value)) {
78
+ throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
79
+ code: "ACTION_DEFINITION_INVALID"
80
+ });
81
+ }
82
+
90
83
  if (!isPlainObject(value)) {
91
84
  throw createActionRuntimeError(500, `Action definition ${fieldName} must be a json-rest-schema schema definition.`, {
92
85
  code: "ACTION_DEFINITION_INVALID"
@@ -105,52 +98,6 @@ function normalizeSingleActionSchema(value, fieldName, { required = false, defau
105
98
  }
106
99
  }
107
100
 
108
- function normalizeActionInputDefinition(value, fieldName, { required = false } = {}) {
109
- if (value == null) {
110
- if (!required) {
111
- return null;
112
- }
113
-
114
- throw createActionRuntimeError(500, `Action definition ${fieldName} is required.`, {
115
- code: "ACTION_DEFINITION_INVALID"
116
- });
117
- }
118
-
119
- if (Array.isArray(value)) {
120
- throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
121
- code: "ACTION_DEFINITION_INVALID"
122
- });
123
- }
124
-
125
- return normalizeSingleActionSchema(value, fieldName, {
126
- required,
127
- defaultMode: "patch"
128
- });
129
- }
130
-
131
- function normalizeActionOutputDefinition(value, fieldName, { required = false } = {}) {
132
- if (value == null) {
133
- if (!required) {
134
- return null;
135
- }
136
-
137
- throw createActionRuntimeError(500, `Action definition ${fieldName} is required.`, {
138
- code: "ACTION_DEFINITION_INVALID"
139
- });
140
- }
141
-
142
- if (Array.isArray(value)) {
143
- throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
144
- code: "ACTION_DEFINITION_INVALID"
145
- });
146
- }
147
-
148
- return normalizeSingleActionSchema(value, fieldName, {
149
- required,
150
- defaultMode: "replace"
151
- });
152
- }
153
-
154
101
  function normalizeActionPermission(permission, actionId) {
155
102
  if (permission == null) {
156
103
  return Object.freeze({
@@ -190,42 +137,6 @@ function normalizeActionPermission(permission, actionId) {
190
137
  });
191
138
  }
192
139
 
193
- function normalizeAuditConfig(audit, { actionId }) {
194
- const source = audit && typeof audit === "object" ? audit : {};
195
- const actionName = normalizeText(source.actionName || actionId);
196
- const metadataBuilder = source.metadataBuilder;
197
- const piiTags = normalizeStringArray(source.piiTags, {
198
- fieldName: "audit.piiTags",
199
- allowEmpty: true
200
- });
201
-
202
- if (metadataBuilder != null && typeof metadataBuilder !== "function") {
203
- throw createActionRuntimeError(500, "Action definition audit.metadataBuilder must be a function when provided.", {
204
- code: "ACTION_DEFINITION_INVALID"
205
- });
206
- }
207
-
208
- return Object.freeze({
209
- actionName,
210
- metadataBuilder: typeof metadataBuilder === "function" ? metadataBuilder : null,
211
- piiTags
212
- });
213
- }
214
-
215
- function normalizeObservabilityConfig(observability) {
216
- const source = observability && typeof observability === "object" ? observability : {};
217
- const metricTags = normalizeStringArray(source.metricTags, {
218
- fieldName: "observability.metricTags",
219
- allowEmpty: true
220
- });
221
- const sampleRate = Number(source.sampleRate);
222
-
223
- return Object.freeze({
224
- metricTags,
225
- sampleRate: Number.isFinite(sampleRate) && sampleRate >= 0 && sampleRate <= 1 ? sampleRate : null
226
- });
227
- }
228
-
229
140
  function normalizeActionExtensions(value) {
230
141
  if (value == null) {
231
142
  return Object.freeze({});
@@ -286,13 +197,8 @@ function normalizeActionDefinition(definition, { contributorId = "", contributor
286
197
  });
287
198
  }
288
199
 
289
- const channels = normalizeStringArray(source.channels, {
290
- fieldName: "channels"
291
- });
292
-
293
- const surfaces = normalizeStringArray(source.surfaces, {
294
- fieldName: "surfaces"
295
- });
200
+ const channels = normalizeStringArray(source.channels, "channels");
201
+ const surfaces = normalizeStringArray(source.surfaces, "surfaces");
296
202
 
297
203
  const idempotency = normalizeText(source.idempotency || "none").toLowerCase();
298
204
  if (!ACTION_IDEMPOTENCY_SET.has(idempotency)) {
@@ -318,18 +224,15 @@ function normalizeActionDefinition(definition, { contributorId = "", contributor
318
224
  kind,
319
225
  channels,
320
226
  surfaces,
321
- input: normalizeActionInputDefinition(source.input, "input", {
322
- required: true
227
+ input: normalizeActionSchema(source.input, "input", {
228
+ required: true,
229
+ defaultMode: "patch"
323
230
  }),
324
- output: normalizeActionOutputDefinition(source.output, "output", {
325
- required: false
231
+ output: normalizeActionSchema(source.output, "output", {
232
+ defaultMode: "replace"
326
233
  }),
327
234
  idempotency,
328
235
  permission: normalizeActionPermission(source.permission, id),
329
- audit: normalizeAuditConfig(source.audit, {
330
- actionId: id
331
- }),
332
- observability: normalizeObservabilityConfig(source.observability),
333
236
  extensions: normalizeActionExtensions(source.extensions),
334
237
  events: normalizeActionEvents(source.events, id),
335
238
  execute: source.execute,
@@ -371,15 +274,7 @@ function createActionVersionKey(actionId, version) {
371
274
  }
372
275
 
373
276
  const __testables = {
374
- normalizeText,
375
- isPlainObject,
376
- normalizeStringArray,
377
- normalizeSingleActionSchema,
378
- normalizeActionInputDefinition,
379
- normalizeActionOutputDefinition,
380
- normalizeActionPermission,
381
- normalizeAuditConfig,
382
- normalizeObservabilityConfig,
277
+ normalizeActionSchema,
383
278
  normalizeActionExtensions
384
279
  };
385
280
 
@@ -388,8 +283,6 @@ export {
388
283
  createActionRuntimeError,
389
284
  normalizeActionDefinition,
390
285
  normalizeActionContributor,
391
- normalizeActionDomain,
392
286
  createActionVersionKey,
393
- isPlainObject,
394
287
  __testables
395
288
  };