@vertesia/common 1.5.0-dev.20260804.124748Z → 1.5.0-dev.20260807.073259Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Progress.d.ts.map +1 -1
- package/lib/Progress.js.map +1 -1
- package/lib/access-control-values.d.ts +2 -2
- package/lib/access-control-values.d.ts.map +1 -1
- package/lib/account-values.d.ts +1 -1
- package/lib/account-values.d.ts.map +1 -1
- package/lib/api-schemas/access-control.d.ts +19 -19
- package/lib/api-schemas/adapter.d.ts +1 -0
- package/lib/api-schemas/adapter.d.ts.map +1 -1
- package/lib/api-schemas/adapter.js +1 -1
- package/lib/api-schemas/adapter.js.map +1 -1
- package/lib/api-schemas/agent-runs.d.ts +660 -515
- package/lib/api-schemas/agent-runs.d.ts.map +1 -1
- package/lib/api-schemas/agent-runs.js +11 -2
- package/lib/api-schemas/agent-runs.js.map +1 -1
- package/lib/api-schemas/analytics.d.ts +12 -12
- package/lib/api-schemas/apikey.d.ts +10 -10
- package/lib/api-schemas/app-lifecycle.d.ts +186 -152
- package/lib/api-schemas/app-lifecycle.d.ts.map +1 -1
- package/lib/api-schemas/app-lifecycle.js +51 -0
- package/lib/api-schemas/app-lifecycle.js.map +1 -1
- package/lib/api-schemas/app-runtime.d.ts +4493 -2122
- package/lib/api-schemas/app-runtime.d.ts.map +1 -1
- package/lib/api-schemas/app-runtime.js +93 -1
- package/lib/api-schemas/app-runtime.js.map +1 -1
- package/lib/api-schemas/apps.d.ts +43 -19
- package/lib/api-schemas/apps.d.ts.map +1 -1
- package/lib/api-schemas/apps.js +63 -3
- package/lib/api-schemas/apps.js.map +1 -1
- package/lib/api-schemas/audit-trail.d.ts +129 -129
- package/lib/api-schemas/bulk-operation.d.ts +10 -10
- package/lib/api-schemas/content.d.ts +542 -398
- package/lib/api-schemas/content.d.ts.map +1 -1
- package/lib/api-schemas/content.js +12 -0
- package/lib/api-schemas/content.js.map +1 -1
- package/lib/api-schemas/cost-analytics.d.ts +12 -12
- package/lib/api-schemas/dashboard.d.ts +10 -10
- package/lib/api-schemas/data-store.d.ts +556 -556
- package/lib/api-schemas/document-processing.d.ts +280 -196
- package/lib/api-schemas/document-processing.d.ts.map +1 -1
- package/lib/api-schemas/embeddings.d.ts +12 -12
- package/lib/api-schemas/environment.d.ts +20 -18
- package/lib/api-schemas/environment.d.ts.map +1 -1
- package/lib/api-schemas/events.d.ts +988 -698
- package/lib/api-schemas/events.d.ts.map +1 -1
- package/lib/api-schemas/events.js +59 -3
- package/lib/api-schemas/events.js.map +1 -1
- package/lib/api-schemas/files.d.ts +1 -1
- package/lib/api-schemas/group.d.ts +3 -3
- package/lib/api-schemas/indexing.d.ts +3 -3
- package/lib/api-schemas/integrations.d.ts +4 -4
- package/lib/api-schemas/interaction.d.ts +3894 -2752
- package/lib/api-schemas/interaction.d.ts.map +1 -1
- package/lib/api-schemas/interaction.js +6 -0
- package/lib/api-schemas/interaction.js.map +1 -1
- package/lib/api-schemas/invites.d.ts +9 -9
- package/lib/api-schemas/oauth-server.d.ts +36 -36
- package/lib/api-schemas/parameters.js.map +1 -1
- package/lib/api-schemas/process.d.ts +47 -47
- package/lib/api-schemas/project-configuration.d.ts +944 -664
- package/lib/api-schemas/project-configuration.d.ts.map +1 -1
- package/lib/api-schemas/project.d.ts +1403 -983
- package/lib/api-schemas/project.d.ts.map +1 -1
- package/lib/api-schemas/registry.d.ts +19119 -13557
- package/lib/api-schemas/registry.d.ts.map +1 -1
- package/lib/api-schemas/registry.js +170 -18
- package/lib/api-schemas/registry.js.map +1 -1
- package/lib/api-schemas/secrets.d.ts +4 -4
- package/lib/api-schemas/store.d.ts +4624 -3224
- package/lib/api-schemas/store.d.ts.map +1 -1
- package/lib/api-schemas/sts.d.ts +46 -36
- package/lib/api-schemas/sts.d.ts.map +1 -1
- package/lib/api-schemas/sts.js +11 -0
- package/lib/api-schemas/sts.js.map +1 -1
- package/lib/api-schemas/task.d.ts +30 -30
- package/lib/api-schemas/tools.d.ts +9 -9
- package/lib/api-schemas/user.d.ts +6 -6
- package/lib/api-schemas/view-execution.d.ts +626 -570
- package/lib/api-schemas/view-execution.d.ts.map +1 -1
- package/lib/api-schemas/views.d.ts +1293 -1125
- package/lib/api-schemas/views.d.ts.map +1 -1
- package/lib/api-schemas/workflow-runs.d.ts +325 -268
- package/lib/api-schemas/workflow-runs.d.ts.map +1 -1
- package/lib/apps.d.ts +38 -24
- package/lib/apps.d.ts.map +1 -1
- package/lib/apps.js +4 -0
- package/lib/apps.js.map +1 -1
- package/lib/audit-trail.d.ts +3 -3
- package/lib/audit-trail.d.ts.map +1 -1
- package/lib/data-platform.d.ts +31 -31
- package/lib/data-platform.d.ts.map +1 -1
- package/lib/environment.d.ts +3 -3
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/platform-event-validation.d.ts.map +1 -1
- package/lib/platform-event-validation.js +15 -2
- package/lib/platform-event-validation.js.map +1 -1
- package/lib/platform-event.d.ts +31 -3
- package/lib/platform-event.d.ts.map +1 -1
- package/lib/platform-event.js.map +1 -1
- package/lib/project.d.ts +1 -1
- package/lib/schema-for-extraction.js.map +1 -1
- package/lib/store/agent-approval.d.ts +1 -1
- package/lib/store/agent-approval.d.ts.map +1 -1
- package/lib/store/intake-policy-schema.generated.d.ts.map +1 -1
- package/lib/store/intake-policy-schema.generated.js +36 -0
- package/lib/store/intake-policy-schema.generated.js.map +1 -1
- package/lib/store/process-schema.d.ts +1 -1
- package/lib/store/process-schema.d.ts.map +1 -1
- package/lib/store/process-validation.js.map +1 -1
- package/lib/store/schedule.d.ts +6 -6
- package/lib/store/schedule.d.ts.map +1 -1
- package/lib/store/store.d.ts +3 -3
- package/lib/store/store.d.ts.map +1 -1
- package/lib/store/workflow.d.ts +6 -0
- package/lib/store/workflow.d.ts.map +1 -1
- package/lib/store/workflow.js +8 -0
- package/lib/store/workflow.js.map +1 -1
- package/lib/sts-errors.d.ts +7 -0
- package/lib/sts-errors.d.ts.map +1 -0
- package/lib/sts-errors.js +11 -0
- package/lib/sts-errors.js.map +1 -0
- package/lib/sts-token-types.d.ts +2 -1
- package/lib/sts-token-types.d.ts.map +1 -1
- package/lib/sts-token-types.js.map +1 -1
- package/lib/user.d.ts +1 -1
- package/lib/user.d.ts.map +1 -1
- package/lib/user.js +1 -1
- package/lib/user.js.map +1 -1
- package/lib/versions.d.ts +10 -0
- package/lib/versions.d.ts.map +1 -1
- package/lib/versions.js +10 -0
- package/lib/versions.js.map +1 -1
- package/lib/vertesia-common.js +3 -3
- package/lib/vertesia-common.js.map +1 -1
- package/lib/view-configuration-validation.js.map +1 -1
- package/lib/view-query-validation.js.map +1 -1
- package/lib/view-validation-helpers.d.ts +1 -1
- package/lib/view-validation-helpers.d.ts.map +1 -1
- package/lib/views-schema.d.ts +51 -51
- package/lib/views-schema.d.ts.map +1 -1
- package/lib/views-validation.js.map +1 -1
- package/lib/views.d.ts +2 -2
- package/lib/views.d.ts.map +1 -1
- package/lib/workflow-analytics.d.ts +10 -3
- package/lib/workflow-analytics.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api-schemas/adapter.ts +1 -1
- package/src/api-schemas/agent-runs.ts +12 -2
- package/src/api-schemas/api-discriminators.test.ts +84 -0
- package/src/api-schemas/app-delete-summary.contract.test.ts +67 -0
- package/src/api-schemas/app-lifecycle.ts +59 -0
- package/src/api-schemas/app-runtime.ts +103 -0
- package/src/api-schemas/apps.ts +72 -3
- package/src/api-schemas/content.ts +13 -0
- package/src/api-schemas/events.ts +63 -3
- package/src/api-schemas/interaction.contract.test.ts +27 -0
- package/src/api-schemas/interaction.ts +7 -0
- package/src/api-schemas/mcp-api-key.contract.test.ts +86 -0
- package/src/api-schemas/registry.ts +200 -18
- package/src/api-schemas/store.contract.test.ts +21 -0
- package/src/api-schemas/sts.contract.test.ts +33 -1
- package/src/api-schemas/sts.ts +13 -0
- package/src/apps.test.ts +82 -0
- package/src/apps.ts +50 -16
- package/src/index.ts +1 -0
- package/src/platform-event-validation.test.ts +26 -0
- package/src/platform-event-validation.ts +15 -2
- package/src/platform-event.ts +43 -0
- package/src/store/intake-policy-schema.generated.ts +36 -0
- package/src/store/workflow.ts +9 -0
- package/src/sts-errors.ts +13 -0
- package/src/sts-token-types.ts +2 -0
- package/src/user.ts +1 -1
- package/src/versions.test.ts +13 -0
- package/src/versions.ts +12 -0
- package/src/workflow-analytics.ts +10 -3
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { type ApiComponentName, ApiSchemaComponents, validateApiResponse } from './registry.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The build-time half of `discriminator: true`.
|
|
6
|
+
*
|
|
7
|
+
* AJV applies its discriminator rules when it COMPILES a schema, not when it validates one, and it
|
|
8
|
+
* signals a union it cannot handle by throwing. Left unchecked that turns into a 500 on the first
|
|
9
|
+
* request to whichever endpoint publishes the offending component — a failure mode that depends on
|
|
10
|
+
* traffic and would reach a deployed environment before anyone saw it. Compiling every registered
|
|
11
|
+
* component here moves that to the build, and names the component when it happens.
|
|
12
|
+
*
|
|
13
|
+
* The rules a union has to satisfy, all of which `synthesizeDiscriminator` in the adapter already
|
|
14
|
+
* enforces before emitting a discriminator: `oneOf` members resolving to object schemas, a tag
|
|
15
|
+
* property present and REQUIRED in every branch, and a `const` or single-valued `enum` for the tag
|
|
16
|
+
* in each. A hand-written `.meta({ discriminator })` gets no such check when it is written, which
|
|
17
|
+
* is the case this test exists for.
|
|
18
|
+
*
|
|
19
|
+
* Generating a validator for each of the ~1000 components is real work: well under a second on a
|
|
20
|
+
* developer machine, ~8s on a loaded CI runner, past vitest's 5s default, hence the explicit budget
|
|
21
|
+
* below. It is generous on purpose — an unsupported discriminator makes AJV THROW during
|
|
22
|
+
* compilation, so a genuine regression is caught by the try/catch and never by the clock.
|
|
23
|
+
*/
|
|
24
|
+
const COMPILE_ALL_TIMEOUT_MS = 60_000;
|
|
25
|
+
|
|
26
|
+
describe('published discriminators', () => {
|
|
27
|
+
it(
|
|
28
|
+
'compiles every registered component under AJV discriminator support',
|
|
29
|
+
() => {
|
|
30
|
+
const failures: string[] = [];
|
|
31
|
+
for (const name of Object.keys(ApiSchemaComponents)) {
|
|
32
|
+
try {
|
|
33
|
+
// Compilation is the subject; the value only has to reach the validator. An
|
|
34
|
+
// invalid result is expected and irrelevant.
|
|
35
|
+
validateApiResponse(name as ApiComponentName, undefined);
|
|
36
|
+
} catch (err: unknown) {
|
|
37
|
+
failures.push(`${name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
expect(failures, `components AJV could not compile:\n${failures.join('\n')}`).toEqual([]);
|
|
41
|
+
},
|
|
42
|
+
COMPILE_ALL_TIMEOUT_MS,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
it('keeps discriminator mapping in the published components for generated clients', () => {
|
|
46
|
+
// AJV's copy drops `mapping`; the OpenAPI document must not. A Java or Go client reads the
|
|
47
|
+
// mapping to pick a concrete subtype, so losing it here would be a silent codegen
|
|
48
|
+
// regression that no schema assertion elsewhere would catch.
|
|
49
|
+
const union = ApiSchemaComponents.ToolCollectionObject as {
|
|
50
|
+
discriminator?: { propertyName?: string; mapping?: Record<string, string> };
|
|
51
|
+
};
|
|
52
|
+
expect(union.discriminator?.propertyName).toBe('type');
|
|
53
|
+
expect(union.discriminator?.mapping).toMatchObject({
|
|
54
|
+
mcp: '#/components/schemas/MCPToolCollectionObject',
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('reports only the tagged branch when a legacy MCP collection is missing its id', () => {
|
|
59
|
+
// The `hubspot-mcp-dev` shape: created before the write path required `id`, still served by
|
|
60
|
+
// the five-level resolution chain in fetch-tools.ts. Without discriminator support AJV also
|
|
61
|
+
// reported `oauth_app` as an undeclared property and `type` as not matching a constant —
|
|
62
|
+
// both from the vertesia_sdk branch this value never claimed to be.
|
|
63
|
+
const legacy = {
|
|
64
|
+
type: 'mcp',
|
|
65
|
+
name: 'HubSpot',
|
|
66
|
+
namespace: 'hubspot',
|
|
67
|
+
description: 'HubSpot MCP',
|
|
68
|
+
auth: 'oauth',
|
|
69
|
+
url: 'https://mcp.hubspot.com',
|
|
70
|
+
oauth_app: 'hubspot',
|
|
71
|
+
};
|
|
72
|
+
const result = validateApiResponse('ToolCollectionObject', legacy);
|
|
73
|
+
expect(result.valid).toBe(false);
|
|
74
|
+
if (result.valid) return;
|
|
75
|
+
expect(result.errors).toEqual(["/ must have required property 'id'"]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('rejects a value whose tag names no branch', () => {
|
|
79
|
+
const result = validateApiResponse('ToolCollectionObject', { type: 'nonesuch', url: 'https://example.com' });
|
|
80
|
+
expect(result.valid).toBe(false);
|
|
81
|
+
if (result.valid) return;
|
|
82
|
+
expect(result.errors.join('; ')).toContain('tag');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { AppDeleteSummary } from '../apps.js';
|
|
3
|
+
import { AppDeleteSummarySchema } from './app-lifecycle.js';
|
|
4
|
+
import { validateApiResponse } from './registry.js';
|
|
5
|
+
|
|
6
|
+
/** Exact type identity — `extends` in both directions is too weak (any/unknown slip through). */
|
|
7
|
+
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
8
|
+
function assertType<T extends true>(_ok: T): void {}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `DeleteApp` published `CountResult` while returning this shape. Response validation therefore
|
|
12
|
+
* reported a missing `count` and every field below as unexpected — and where the check fails closed
|
|
13
|
+
* (local development) that surfaced as a 500 raised AFTER the app had already been deleted, which is
|
|
14
|
+
* the worst possible moment for it. These assertions pin the component to what the handler builds.
|
|
15
|
+
*/
|
|
16
|
+
const REAL_SUMMARY: AppDeleteSummary = {
|
|
17
|
+
confirmed: true,
|
|
18
|
+
app_id: '68b1779130afe5403a1589bc',
|
|
19
|
+
app_name: 'acme-app',
|
|
20
|
+
versions: 2,
|
|
21
|
+
installations: 1,
|
|
22
|
+
storage_prefix: 'apps/acme-app',
|
|
23
|
+
deleted: true,
|
|
24
|
+
warnings: [],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
describe('AppDeleteSummary — as the DeleteApp response is validated', () => {
|
|
28
|
+
it('accepts what the handler returns after a confirmed delete', () => {
|
|
29
|
+
expect(validateApiResponse('AppDeleteSummary', REAL_SUMMARY).valid).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('accepts the dry-run preview, which is the same shape with deleted: false', () => {
|
|
33
|
+
const preview = { ...REAL_SUMMARY, confirmed: false, deleted: false };
|
|
34
|
+
expect(validateApiResponse('AppDeleteSummary', preview).valid).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('accepts a git-backed app, whose summary carries the repo URL', () => {
|
|
38
|
+
const withRepo = { ...REAL_SUMMARY, git_repo_url: 'https://git.example.com/acme/acme-app.git' };
|
|
39
|
+
expect(validateApiResponse('AppDeleteSummary', withRepo).valid).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('accepts the warnings a partially-degraded cascade collects', () => {
|
|
43
|
+
const warned = {
|
|
44
|
+
...REAL_SUMMARY,
|
|
45
|
+
warnings: ['git repo delete failed: 502', 'version cleanup failed: timeout'],
|
|
46
|
+
};
|
|
47
|
+
expect(validateApiResponse('AppDeleteSummary', warned).valid).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('is NOT interchangeable with CountResult, the component this endpoint used to publish', () => {
|
|
51
|
+
// The regression in one line: neither validates as the other, so the mismatch was total.
|
|
52
|
+
expect(validateApiResponse('CountResult', REAL_SUMMARY).valid).toBe(false);
|
|
53
|
+
expect(validateApiResponse('AppDeleteSummary', { count: 1 }).valid).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('rejects an undeclared field, so the component cannot silently drift from the handler', () => {
|
|
57
|
+
expect(validateApiResponse('AppDeleteSummary', { ...REAL_SUMMARY, secrets_purged: 3 }).valid).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('keeps the public type derived from the schema rather than hand-written beside it', () => {
|
|
61
|
+
assertType<Equals<AppDeleteSummary, ReturnType<typeof AppDeleteSummarySchema.parse>>>(true);
|
|
62
|
+
// Every field the handler always sets is required; only git_repo_url is optional.
|
|
63
|
+
expect(AppDeleteSummarySchema.safeParse({ ...REAL_SUMMARY, warnings: undefined }).success).toBe(false);
|
|
64
|
+
const { git_repo_url: _omitted, ...withoutRepo } = { ...REAL_SUMMARY, git_repo_url: 'https://x' };
|
|
65
|
+
expect(AppDeleteSummarySchema.safeParse(withoutRepo).success).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -180,6 +180,8 @@ export const AppPackageScopeSchema = z
|
|
|
180
180
|
'settings',
|
|
181
181
|
'widgets',
|
|
182
182
|
'activities',
|
|
183
|
+
'hooks',
|
|
184
|
+
'subscriptions',
|
|
183
185
|
'all',
|
|
184
186
|
])
|
|
185
187
|
.meta({ id: 'AppPackageScope' });
|
|
@@ -324,6 +326,35 @@ export const DeleteAppVersionResponseSchema = z
|
|
|
324
326
|
})
|
|
325
327
|
.meta({ id: 'DeleteAppVersionResponse' });
|
|
326
328
|
|
|
329
|
+
export const AppDeleteSummarySchema = z
|
|
330
|
+
.strictObject({
|
|
331
|
+
confirmed: z.boolean().meta({
|
|
332
|
+
description:
|
|
333
|
+
'Whether `?confirm=true` was sent. Without it the endpoint reports what WOULD be removed and ' +
|
|
334
|
+
'deletes nothing — `deleted` stays false.',
|
|
335
|
+
}),
|
|
336
|
+
app_id: z.string(),
|
|
337
|
+
app_name: z.string(),
|
|
338
|
+
versions: z.number().meta({ description: 'AppVersion records the cascade covers.' }),
|
|
339
|
+
installations: z.number().meta({ description: 'AppInstallation records the cascade covers.' }),
|
|
340
|
+
storage_prefix: z.string(),
|
|
341
|
+
git_repo_url: z.string().optional(),
|
|
342
|
+
deleted: z.boolean().meta({
|
|
343
|
+
description: 'Whether the app record itself was removed. False for a dry run.',
|
|
344
|
+
}),
|
|
345
|
+
warnings: z.array(z.string()).meta({
|
|
346
|
+
description:
|
|
347
|
+
'Cascade steps that failed without aborting the deletion. Credential cleanup is NOT among them — ' +
|
|
348
|
+
'a failed API key purge fails the request outright and keeps the app row.',
|
|
349
|
+
}),
|
|
350
|
+
})
|
|
351
|
+
.meta({
|
|
352
|
+
id: 'AppDeleteSummary',
|
|
353
|
+
description:
|
|
354
|
+
'Result of `DELETE /apps/:id`. Doubles as the dry-run preview: without `?confirm=true` the same ' +
|
|
355
|
+
'shape comes back with `deleted: false` describing what the cascade would remove.',
|
|
356
|
+
});
|
|
357
|
+
|
|
327
358
|
export const AppRepoBranchSchema = z
|
|
328
359
|
.strictObject({
|
|
329
360
|
name: z.string(),
|
|
@@ -469,6 +500,28 @@ export const OAuthClientCredentialsMapSchema = z
|
|
|
469
500
|
|
|
470
501
|
export const AppOAuthCollectionParamsSchema = OAuthClientCredentialsMapSchema.meta({ id: 'AppOAuthCollectionParams' });
|
|
471
502
|
|
|
503
|
+
export const McpApiKeyCredentialSchema = z
|
|
504
|
+
.strictObject({
|
|
505
|
+
// Matches SetMcpApiKeyRequest, including the `\S` pattern — see the note there on why the
|
|
506
|
+
// trim alone does not survive into the AJV-enforced JSON Schema.
|
|
507
|
+
api_key: z
|
|
508
|
+
.string()
|
|
509
|
+
.trim()
|
|
510
|
+
.min(1)
|
|
511
|
+
.regex(/\S/, 'API key must not be blank')
|
|
512
|
+
.meta({
|
|
513
|
+
description:
|
|
514
|
+
'The key the installer holds for this collection. Surrounding whitespace is stripped. Stored ' +
|
|
515
|
+
'encrypted in the installing project and never returned.',
|
|
516
|
+
}),
|
|
517
|
+
})
|
|
518
|
+
.meta({ id: 'McpApiKeyCredential' });
|
|
519
|
+
|
|
520
|
+
export const AppApiKeyCollectionParamsSchema = z
|
|
521
|
+
.object({})
|
|
522
|
+
.catchall(McpApiKeyCredentialSchema)
|
|
523
|
+
.meta({ id: 'AppApiKeyCollectionParams' });
|
|
524
|
+
|
|
472
525
|
export const AppInspectionIssueSchema = z
|
|
473
526
|
.strictObject({
|
|
474
527
|
severity: z.enum(['error', 'warning']),
|
|
@@ -775,6 +828,12 @@ export const AppInstallationPayloadSchema = z
|
|
|
775
828
|
description:
|
|
776
829
|
'OAuth credentials for named providers, keyed by the provider key from oauth_providers. Collected from the user at install time for providers with required_at_install. Separate from oauth_params to avoid key collisions between provider keys and collection ids.',
|
|
777
830
|
}).optional(),
|
|
831
|
+
api_key_params: AppApiKeyCollectionParamsSchema.meta({
|
|
832
|
+
description:
|
|
833
|
+
"API keys for auth: 'api_key' collections, keyed by collection.id. Collected from the user at " +
|
|
834
|
+
'install time for collections with api_key_config.required_at_install. Each key is stored in the ' +
|
|
835
|
+
"installing project's encrypted secret store, replacing any key already held for that collection.",
|
|
836
|
+
}).optional(),
|
|
778
837
|
})
|
|
779
838
|
.meta({ id: 'AppInstallationPayload' });
|
|
780
839
|
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
import type { JSONSchema } from '@llumiverse/common';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import type { CompositeAppMenuNavItem } from '../apps.js';
|
|
6
|
+
import type { PlatformEvent } from '../platform-event.js';
|
|
6
7
|
import type { InCodeProcessDefinition } from '../store/process.js';
|
|
8
|
+
import { SystemRolesSchema } from './apikey.js';
|
|
7
9
|
import {
|
|
8
10
|
AgentToolDefinitionSchema,
|
|
9
11
|
AppInstallationOAuthBindingSchema,
|
|
10
12
|
AppInstallationProviderBindingSchema,
|
|
11
13
|
AppVersionRecordSchema,
|
|
14
|
+
EventRefSchema,
|
|
12
15
|
} from './app-lifecycle.js';
|
|
13
16
|
import {
|
|
14
17
|
AppAccessControlSchema,
|
|
@@ -19,12 +22,14 @@ import {
|
|
|
19
22
|
MCPOAuthConfigSchema,
|
|
20
23
|
ToolCollectionObjectSchema,
|
|
21
24
|
} from './apps.js';
|
|
25
|
+
import { AuditMeterSchema } from './audit-trail.js';
|
|
22
26
|
import {
|
|
23
27
|
DashboardDataSourceSchema,
|
|
24
28
|
DashboardLayoutSchema,
|
|
25
29
|
DashboardPanelSchema,
|
|
26
30
|
DashboardQuerySchema,
|
|
27
31
|
} from './dashboard.js';
|
|
32
|
+
import { EventPrioritySchema, EventSubscriptionFilterSchema } from './events.js';
|
|
28
33
|
import { StringValueMapSchema } from './files.js';
|
|
29
34
|
import { RemoteActivityDefinitionSchema } from './integrations.js';
|
|
30
35
|
import { CatalogInteractionRefSchema } from './interaction.js';
|
|
@@ -804,6 +809,99 @@ export const CompositeAppConfigSchema = z
|
|
|
804
809
|
'CompositeApp shell configuration. This is the main configuration interface for storing CompositeApp settings. Used as the MongoDB model for persisting CompositeApp configurations.',
|
|
805
810
|
});
|
|
806
811
|
|
|
812
|
+
export const AppPackageEventHookSchema = z
|
|
813
|
+
.strictObject({
|
|
814
|
+
name: z.string().meta({ description: 'Registered event hook name.' }),
|
|
815
|
+
path: z.string().meta({ description: 'Authenticated endpoint that receives the event delivery envelope.' }),
|
|
816
|
+
description: z.string().meta({ description: 'Optional description of the event hook behavior.' }).optional(),
|
|
817
|
+
})
|
|
818
|
+
.meta({
|
|
819
|
+
id: 'AppPackageEventHook',
|
|
820
|
+
description: 'An authenticated event hook exposed by the app runtime.',
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
export const AppPackageHooksSchema = z
|
|
824
|
+
.strictObject({
|
|
825
|
+
install: z.string().meta({ description: 'Authenticated endpoint for the app install hook.' }).optional(),
|
|
826
|
+
uninstall: z.string().meta({ description: 'Authenticated endpoint for the app uninstall hook.' }).optional(),
|
|
827
|
+
events: z
|
|
828
|
+
.array(AppPackageEventHookSchema)
|
|
829
|
+
.meta({ description: 'Named event hooks exposed by the app runtime.' })
|
|
830
|
+
.optional(),
|
|
831
|
+
})
|
|
832
|
+
.meta({
|
|
833
|
+
id: 'AppPackageHooks',
|
|
834
|
+
description:
|
|
835
|
+
'Lifecycle and event hooks exposed by the app runtime. Lifecycle entries are informational; Studio invokes their conventional sibling endpoints directly.',
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
const AppEventHookPlatformEventSchema = EventRefSchema.extend({
|
|
839
|
+
timestamp: z.string(),
|
|
840
|
+
source: z.string(),
|
|
841
|
+
audit_trail: z.boolean().optional(),
|
|
842
|
+
replay_of: z.string().optional(),
|
|
843
|
+
replay_root_event_id: z.string().optional(),
|
|
844
|
+
replayed_by: z.string().optional(),
|
|
845
|
+
request_id: z.string().nullable().optional(),
|
|
846
|
+
status: z.number().optional(),
|
|
847
|
+
success: z.boolean().optional(),
|
|
848
|
+
principal_id: z.string().nullable().optional(),
|
|
849
|
+
principal_type: z.string().nullable().optional(),
|
|
850
|
+
effective_principal_id: z.string().nullable().optional(),
|
|
851
|
+
roles: z.array(z.string()).optional(),
|
|
852
|
+
account_name: z.string().nullable().optional(),
|
|
853
|
+
project_name: z.string().nullable().optional(),
|
|
854
|
+
provider: z.string().nullable().optional(),
|
|
855
|
+
meters: z.array(AuditMeterSchema).optional(),
|
|
856
|
+
resource_data: z.record(z.string(), z.unknown()).optional(),
|
|
857
|
+
resource_version: z.string().optional(),
|
|
858
|
+
details: z.record(z.string(), z.unknown()).optional(),
|
|
859
|
+
}) satisfies z.ZodType<PlatformEvent>;
|
|
860
|
+
|
|
861
|
+
export const AppEventHookDeliverySchema = z
|
|
862
|
+
.strictObject({
|
|
863
|
+
id: z.string().meta({ description: 'Event-delivery intent id.' }),
|
|
864
|
+
subscription_id: z.string().meta({ description: 'Event subscription id.' }),
|
|
865
|
+
attempt: z.number().finite().meta({ description: 'Current delivery attempt number.' }),
|
|
866
|
+
})
|
|
867
|
+
.meta({
|
|
868
|
+
id: 'AppEventHookDelivery',
|
|
869
|
+
description: 'Delivery metadata accompanying an app event-hook invocation.',
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
export const AppEventHookPayloadSchema = z
|
|
873
|
+
.strictObject({
|
|
874
|
+
event: AppEventHookPlatformEventSchema,
|
|
875
|
+
delivery: AppEventHookDeliverySchema,
|
|
876
|
+
})
|
|
877
|
+
.meta({
|
|
878
|
+
id: 'AppEventHookPayload',
|
|
879
|
+
description: 'Canonical platform event envelope delivered to an authenticated app event hook.',
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
export const AppEventSubscriptionDefinitionSchema = z
|
|
883
|
+
.strictObject({
|
|
884
|
+
id: z
|
|
885
|
+
.string()
|
|
886
|
+
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
|
|
887
|
+
.meta({ description: 'Stable app-local subscription id in kebab case.' }),
|
|
888
|
+
name: z.string().meta({ description: 'Human-readable subscription name.' }),
|
|
889
|
+
description: z.string().meta({ description: 'Optional description of the subscription behavior.' }).optional(),
|
|
890
|
+
hook: z.string().meta({ description: 'Name of an event hook registered by the same app package.' }),
|
|
891
|
+
filter: EventSubscriptionFilterSchema,
|
|
892
|
+
run_as_role: SystemRolesSchema.meta({
|
|
893
|
+
description:
|
|
894
|
+
'Identity used for event delivery. Use automation for the standard event-triggered execution identity.',
|
|
895
|
+
}),
|
|
896
|
+
enabled: z.boolean().meta({ description: 'Whether the installed subscription is enabled.' }).optional(),
|
|
897
|
+
priority: EventPrioritySchema.meta({ description: 'Delivery priority for matching events.' }).optional(),
|
|
898
|
+
})
|
|
899
|
+
.meta({
|
|
900
|
+
id: 'AppEventSubscriptionDefinition',
|
|
901
|
+
description:
|
|
902
|
+
'An app-owned event subscription. Studio derives its project scope and delivery target from the app installation and referenced event hook.',
|
|
903
|
+
});
|
|
904
|
+
|
|
807
905
|
export const AppPackageSchema = z
|
|
808
906
|
.strictObject({
|
|
809
907
|
ui: AppUIConfigSchema.meta({ description: 'The UI configuration of the app' }).optional(),
|
|
@@ -850,6 +948,11 @@ export const AppPackageSchema = z
|
|
|
850
948
|
settings_schema: JSONSchemaRefSchema.meta({
|
|
851
949
|
description: 'A JSON chema for the app installation settings.',
|
|
852
950
|
}).optional(),
|
|
951
|
+
hooks: AppPackageHooksSchema.optional(),
|
|
952
|
+
subscriptions: z
|
|
953
|
+
.array(AppEventSubscriptionDefinitionSchema)
|
|
954
|
+
.meta({ description: 'Event subscriptions contributed by the app.' })
|
|
955
|
+
.optional(),
|
|
853
956
|
})
|
|
854
957
|
.meta({ id: 'AppPackage' });
|
|
855
958
|
|
package/src/api-schemas/apps.ts
CHANGED
|
@@ -112,9 +112,13 @@ export const AppUIConfigSchema = z
|
|
|
112
112
|
})
|
|
113
113
|
.meta({ id: 'AppUIConfig' });
|
|
114
114
|
|
|
115
|
-
export const ToolCollectionAuthTypeSchema = z
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
export const ToolCollectionAuthTypeSchema = z.enum(['oauth', 'api_key', 'other']).meta({
|
|
116
|
+
id: 'ToolCollectionAuthType',
|
|
117
|
+
description:
|
|
118
|
+
"Authentication type for tool collections.\n- 'oauth': the runtime resolves a per-user or per-project " +
|
|
119
|
+
"OAuth access token\n- 'api_key': a static key held in the project's secret store is sent as the RFC 6750 " +
|
|
120
|
+
'bearer token (`Authorization: Bearer <key>`)',
|
|
121
|
+
});
|
|
118
122
|
|
|
119
123
|
export const MCPOAuthConfigSchema = z
|
|
120
124
|
.strictObject({
|
|
@@ -162,6 +166,33 @@ export const MCPOAuthConfigSchema = z
|
|
|
162
166
|
'oauth_bindings on AppInstallation.',
|
|
163
167
|
});
|
|
164
168
|
|
|
169
|
+
export const MCPApiKeyConfigSchema = z
|
|
170
|
+
.strictObject({
|
|
171
|
+
required_at_install: z
|
|
172
|
+
.boolean()
|
|
173
|
+
.optional()
|
|
174
|
+
.meta({
|
|
175
|
+
description:
|
|
176
|
+
'When true, the installer must supply the key in the install dialog. Use this for a manifest ' +
|
|
177
|
+
'published to projects that each hold their own key. Leave unset when the key was already ' +
|
|
178
|
+
'stored by whoever registered the server.',
|
|
179
|
+
}),
|
|
180
|
+
instructions: z
|
|
181
|
+
.string()
|
|
182
|
+
.optional()
|
|
183
|
+
.meta({
|
|
184
|
+
description:
|
|
185
|
+
'Shown in the install dialog above the key field — typically where to generate the key on the ' +
|
|
186
|
+
'remote service.',
|
|
187
|
+
}),
|
|
188
|
+
})
|
|
189
|
+
.meta({
|
|
190
|
+
id: 'MCPApiKeyConfig',
|
|
191
|
+
description:
|
|
192
|
+
"Install-time provisioning blueprint for an `auth: 'api_key'` MCP collection. Declares whether the " +
|
|
193
|
+
'installer is prompted for the key. Never holds the key itself — manifests are shareable documents.',
|
|
194
|
+
});
|
|
195
|
+
|
|
165
196
|
/**
|
|
166
197
|
* The two collection kinds share a base interface, so their published components both begin with
|
|
167
198
|
* `url` and `auth`. Spreading one shape is what keeps that true of the emission as well.
|
|
@@ -211,6 +242,11 @@ export const MCPToolCollectionObjectSchema = z
|
|
|
211
242
|
'required_at_install params. The created app is recorded in AppInstallation.oauth_bindings. ' +
|
|
212
243
|
'Mutually exclusive with oauth_provider.',
|
|
213
244
|
}),
|
|
245
|
+
api_key_config: MCPApiKeyConfigSchema.optional().meta({
|
|
246
|
+
description:
|
|
247
|
+
"Install-time provisioning blueprint for auth: 'api_key' collections. Only meaningful alongside " +
|
|
248
|
+
"auth: 'api_key'; ignored otherwise.",
|
|
249
|
+
}),
|
|
214
250
|
oauth_provider: z
|
|
215
251
|
.string()
|
|
216
252
|
.optional()
|
|
@@ -371,6 +407,39 @@ export const McpOAuthTokenRequestSchema = z
|
|
|
371
407
|
})
|
|
372
408
|
.meta({ id: 'McpOAuthTokenRequest' });
|
|
373
409
|
|
|
410
|
+
export const SetMcpApiKeyRequestSchema = z
|
|
411
|
+
.strictObject({
|
|
412
|
+
// `.regex(/\S/)` rather than `.trim().min(1)` alone: request bodies are validated by AJV
|
|
413
|
+
// against the EMITTED JSON Schema, where a Zod transform like `.trim()` leaves no trace —
|
|
414
|
+
// `minLength: 1` on its own happily accepts " ". The pattern emits and is enforced, so a
|
|
415
|
+
// whitespace-only key is rejected at the boundary instead of becoming an encrypted empty
|
|
416
|
+
// key that still reports `configured: true`. The trim still normalizes for Zod consumers.
|
|
417
|
+
api_key: z
|
|
418
|
+
.string()
|
|
419
|
+
.trim()
|
|
420
|
+
.min(1)
|
|
421
|
+
.regex(/\S/, 'API key must not be blank')
|
|
422
|
+
.meta({
|
|
423
|
+
description:
|
|
424
|
+
'The static key issued by the remote MCP server. Surrounding whitespace is stripped. Stored ' +
|
|
425
|
+
'encrypted in the project secret store and sent as the RFC 6750 bearer token on every request ' +
|
|
426
|
+
'to the collection URL. Never returned by the API.',
|
|
427
|
+
}),
|
|
428
|
+
})
|
|
429
|
+
.meta({ id: 'SetMcpApiKeyRequest' });
|
|
430
|
+
|
|
431
|
+
export const McpApiKeyStatusSchema = z
|
|
432
|
+
.strictObject({
|
|
433
|
+
configured: z.boolean().meta({ description: 'Whether a key is stored for this collection.' }),
|
|
434
|
+
// Always present — null when unset, never absent. `.nullable()` rather than `.nullish()`
|
|
435
|
+
// so the published contract says so and generated clients do not treat it as optional.
|
|
436
|
+
hint: z
|
|
437
|
+
.string()
|
|
438
|
+
.nullable()
|
|
439
|
+
.meta({ description: 'Last few characters of the stored key, for display only. Null when unset.' }),
|
|
440
|
+
})
|
|
441
|
+
.meta({ id: 'McpApiKeyStatus', description: 'Whether an API key is configured for an MCP tool collection' });
|
|
442
|
+
|
|
374
443
|
export const OAuthAuthStatusSchema = z
|
|
375
444
|
.strictObject({
|
|
376
445
|
collection_id: z.string(),
|
|
@@ -787,6 +787,19 @@ export const ContentObjectApiResponseSchema = z
|
|
|
787
787
|
parts_etag: z.string().optional(),
|
|
788
788
|
transcript: z.looseObject({}).optional(),
|
|
789
789
|
security: StringArrayMapSchema.optional(),
|
|
790
|
+
sensitivity: z
|
|
791
|
+
.number()
|
|
792
|
+
.meta({
|
|
793
|
+
description:
|
|
794
|
+
'BLP sensitivity level — set directly or inherited from collections (max across collections).',
|
|
795
|
+
})
|
|
796
|
+
.optional(),
|
|
797
|
+
compartments: z
|
|
798
|
+
.array(z.string())
|
|
799
|
+
.meta({
|
|
800
|
+
description: 'Compartments — set directly or inherited from collections (union across collections).',
|
|
801
|
+
})
|
|
802
|
+
.optional(),
|
|
790
803
|
inherited_properties: z.array(InheritedPropertyMetadataSchema).optional(),
|
|
791
804
|
})
|
|
792
805
|
.meta({ id: 'ContentObjectApiResponse' });
|
|
@@ -184,6 +184,17 @@ export const WebhookEventDeliveryTargetSchema = z
|
|
|
184
184
|
})
|
|
185
185
|
.meta({ id: 'WebhookEventDeliveryTarget' });
|
|
186
186
|
|
|
187
|
+
export const AppEventDeliveryTargetSchema = z
|
|
188
|
+
.strictObject({
|
|
189
|
+
type: z.literal('app'),
|
|
190
|
+
app_id: z.string(),
|
|
191
|
+
installation_id: z.string(),
|
|
192
|
+
hook: z.string(),
|
|
193
|
+
url: z.string(),
|
|
194
|
+
timeout_ms: z.number().optional(),
|
|
195
|
+
})
|
|
196
|
+
.meta({ id: 'AppEventDeliveryTarget' });
|
|
197
|
+
|
|
187
198
|
export const WorkflowEventDeliveryTargetSchema = z
|
|
188
199
|
.strictObject({
|
|
189
200
|
type: z.literal('workflow'),
|
|
@@ -432,6 +443,17 @@ export const WebhookEventDeliveryTargetInputSchema = z
|
|
|
432
443
|
})
|
|
433
444
|
.meta({ id: 'WebhookEventDeliveryTargetInput' });
|
|
434
445
|
|
|
446
|
+
export const AppEventDeliveryTargetInputSchema = z
|
|
447
|
+
.strictObject({
|
|
448
|
+
type: z.literal('app'),
|
|
449
|
+
app_id: z.string(),
|
|
450
|
+
installation_id: z.string(),
|
|
451
|
+
hook: z.string(),
|
|
452
|
+
url: z.string(),
|
|
453
|
+
timeout_ms: z.number().optional(),
|
|
454
|
+
})
|
|
455
|
+
.meta({ id: 'AppEventDeliveryTargetInput' });
|
|
456
|
+
|
|
435
457
|
export const WorkflowEventDeliveryTargetInputSchema = z
|
|
436
458
|
.strictObject({
|
|
437
459
|
type: z.literal('workflow'),
|
|
@@ -615,7 +637,7 @@ export const EventDeliveryQueueSubscriptionSummarySchema = z
|
|
|
615
637
|
.strictObject({
|
|
616
638
|
subscription_id: z.string(),
|
|
617
639
|
subscription_name: z.string(),
|
|
618
|
-
target_type: z.enum(['workflow', 'webhook', 'agent', 'process']),
|
|
640
|
+
target_type: z.enum(['workflow', 'webhook', 'app', 'agent', 'process']),
|
|
619
641
|
total: z.number(),
|
|
620
642
|
queued: z.number(),
|
|
621
643
|
deferred: z.number(),
|
|
@@ -632,12 +654,45 @@ export const EventDeliveryQueueSubscriptionSummarySchema = z
|
|
|
632
654
|
export const EventDeliveryQueueSummaryPayloadSchema = z
|
|
633
655
|
.strictObject({
|
|
634
656
|
subscription_id: z.string().optional(),
|
|
635
|
-
target_type: z.array(z.enum(['workflow', 'webhook', 'agent', 'process'])).optional(),
|
|
657
|
+
target_type: z.array(z.enum(['workflow', 'webhook', 'app', 'agent', 'process'])).optional(),
|
|
636
658
|
sort_by: EventDeliveryQueueSortFieldSchema.optional(),
|
|
637
659
|
sort_order: z.enum(['asc', 'desc']).optional(),
|
|
638
660
|
})
|
|
639
661
|
.meta({ id: 'EventDeliveryQueueSummaryPayload' });
|
|
640
662
|
|
|
663
|
+
export const CancelEventDeliveryIntentsPayloadSchema = z
|
|
664
|
+
.strictObject({
|
|
665
|
+
subscription_id: z
|
|
666
|
+
.string()
|
|
667
|
+
.min(1)
|
|
668
|
+
.meta({ description: 'Restrict cancellation to one subscription.' })
|
|
669
|
+
.optional(),
|
|
670
|
+
target_type: z
|
|
671
|
+
.array(z.enum(['workflow', 'webhook', 'app', 'agent', 'process']))
|
|
672
|
+
.min(1)
|
|
673
|
+
.meta({ description: 'Restrict cancellation to one or more delivery target types.' })
|
|
674
|
+
.optional(),
|
|
675
|
+
})
|
|
676
|
+
.meta({ id: 'CancelEventDeliveryIntentsPayload' });
|
|
677
|
+
|
|
678
|
+
export const CancelEventDeliveryIntentsResponseSchema = z
|
|
679
|
+
.strictObject({
|
|
680
|
+
environment: z.string().meta({ description: 'Deployment environment whose queue was changed.' }),
|
|
681
|
+
cleared_through: z.string().meta({
|
|
682
|
+
description: 'Server-side watermark; intents created after this time were not changed.',
|
|
683
|
+
format: 'date-time',
|
|
684
|
+
}),
|
|
685
|
+
cancelled: z
|
|
686
|
+
.number()
|
|
687
|
+
.int()
|
|
688
|
+
.nonnegative()
|
|
689
|
+
.meta({ description: 'Pending or retrying intents moved to the cancelled terminal state.' }),
|
|
690
|
+
active_untouched: z.number().int().nonnegative().meta({
|
|
691
|
+
description: 'Matching evaluating, starting, or running intents left for normal reconciliation.',
|
|
692
|
+
}),
|
|
693
|
+
})
|
|
694
|
+
.meta({ id: 'CancelEventDeliveryIntentsResponse' });
|
|
695
|
+
|
|
641
696
|
export const EventIngestChannelMutationResponseSchema = z
|
|
642
697
|
.strictObject({
|
|
643
698
|
channel: EventIngestChannelSchema,
|
|
@@ -724,7 +779,7 @@ export const EventDeliveryIntentSummarySchema = z
|
|
|
724
779
|
event_id: z.string(),
|
|
725
780
|
subscription_id: z.string(),
|
|
726
781
|
subscription_name: z.string(),
|
|
727
|
-
target_type: z.enum(['workflow', 'webhook', 'agent', 'process']),
|
|
782
|
+
target_type: z.enum(['workflow', 'webhook', 'app', 'agent', 'process']),
|
|
728
783
|
workflow_class: nullableStringSchema.optional(),
|
|
729
784
|
priority: EventPrioritySchema,
|
|
730
785
|
status: EventDeliveryIntentStatusSchema,
|
|
@@ -812,6 +867,7 @@ export const EventDeliveryTargetSchema: z.ZodType = z
|
|
|
812
867
|
.discriminatedUnion('type', [
|
|
813
868
|
WorkflowEventDeliveryTargetSchema,
|
|
814
869
|
WebhookEventDeliveryTargetSchema,
|
|
870
|
+
AppEventDeliveryTargetSchema,
|
|
815
871
|
AgentEventDeliveryTargetSchema,
|
|
816
872
|
z.lazy(() => ProcessEventDeliveryTargetSchema) as unknown as z.ZodObject,
|
|
817
873
|
])
|
|
@@ -821,6 +877,7 @@ export const EventDeliveryTargetInputSchema: z.ZodType = z
|
|
|
821
877
|
.discriminatedUnion('type', [
|
|
822
878
|
WorkflowEventDeliveryTargetInputSchema,
|
|
823
879
|
WebhookEventDeliveryTargetInputSchema,
|
|
880
|
+
AppEventDeliveryTargetInputSchema,
|
|
824
881
|
AgentEventDeliveryTargetSchema,
|
|
825
882
|
z.lazy(() => ProcessEventDeliveryTargetSchema) as unknown as z.ZodObject,
|
|
826
883
|
])
|
|
@@ -841,6 +898,9 @@ export const EventSubscriptionSchema: z.ZodType = z
|
|
|
841
898
|
protected: z.boolean(),
|
|
842
899
|
enabled: z.boolean(),
|
|
843
900
|
priority: EventPrioritySchema.optional(),
|
|
901
|
+
app_installation_id: z.string().optional(),
|
|
902
|
+
app_id: z.string().optional(),
|
|
903
|
+
app_subscription_id: z.string().optional(),
|
|
844
904
|
created_by: z.string().optional(),
|
|
845
905
|
updated_by: z.string().optional(),
|
|
846
906
|
created_at: z.string().optional(),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { AsyncConversationExecutionPayload } from '../interaction.js';
|
|
3
|
+
import { AsyncConversationExecutionPayloadSchema } from './interaction.js';
|
|
4
|
+
|
|
5
|
+
describe('AsyncConversationExecutionPayload contract', () => {
|
|
6
|
+
it('retains an immutable app-version execution target', () => {
|
|
7
|
+
const payload: AsyncConversationExecutionPayload = {
|
|
8
|
+
type: 'conversation',
|
|
9
|
+
interaction: 'sys:AppTester',
|
|
10
|
+
app_version: '20260804T022611971Z',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
expect(AsyncConversationExecutionPayloadSchema.parse(payload)).toMatchObject({
|
|
14
|
+
app_version: '20260804T022611971Z',
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('rejects a non-string app-version target', () => {
|
|
19
|
+
expect(() =>
|
|
20
|
+
AsyncConversationExecutionPayloadSchema.parse({
|
|
21
|
+
type: 'conversation',
|
|
22
|
+
interaction: 'sys:AppTester',
|
|
23
|
+
app_version: 42,
|
|
24
|
+
}),
|
|
25
|
+
).toThrow();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -1996,6 +1996,13 @@ export const AsyncConversationExecutionPayloadSchema = z
|
|
|
1996
1996
|
description:
|
|
1997
1997
|
'The interaction name and suffixed by an optional tag or version separated from the name using a @ character If no version/tag part is specified then the latest version is used. Example: ReviewContract, ReviewContract@draft, ReviewContract@1, ReviewContract@some-tag',
|
|
1998
1998
|
}),
|
|
1999
|
+
app_version: z
|
|
2000
|
+
.string()
|
|
2001
|
+
.meta({
|
|
2002
|
+
description:
|
|
2003
|
+
'Immutable app-version target inherited by this conversation execution. The workflow applies it to app-owned resource resolution; callers normally set the x-vertesia-app-version header instead of populating this field directly.',
|
|
2004
|
+
})
|
|
2005
|
+
.optional(),
|
|
1999
2006
|
data: z
|
|
2000
2007
|
.unknown()
|
|
2001
2008
|
.meta({
|