@vertesia/common 1.5.0-dev.20260804.124748Z → 1.5.0-dev.20260806.125520Z
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.js.map +1 -1
- package/lib/api-schemas/agent-runs.d.ts +520 -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 +4022 -2127
- 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 +402 -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 +196 -196
- package/lib/api-schemas/embeddings.d.ts +12 -12
- package/lib/api-schemas/environment.d.ts +18 -18
- package/lib/api-schemas/events.d.ts +723 -685
- 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 +2744 -2742
- 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 +662 -662
- package/lib/api-schemas/project.d.ts +979 -979
- package/lib/api-schemas/registry.d.ts +14782 -13734
- package/lib/api-schemas/registry.d.ts.map +1 -1
- package/lib/api-schemas/registry.js +22 -2
- 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 +3203 -3203
- 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 +569 -569
- package/lib/api-schemas/views.d.ts +1124 -1124
- package/lib/api-schemas/workflow-runs.d.ts +269 -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/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/agent-runs.ts +12 -2
- 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 +25 -0
- 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/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
|
@@ -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({
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { McpApiKeyStatus } from '../apps.js';
|
|
3
|
+
import { AppInstallationPayloadSchema } from './app-lifecycle.js';
|
|
4
|
+
import { McpApiKeyStatusSchema, SetMcpApiKeyRequestSchema } from './apps.js';
|
|
5
|
+
import { validateApiRequest } from './registry.js';
|
|
6
|
+
|
|
7
|
+
/** Exact type identity — `extends` in both directions is too weak (any/unknown slip through). */
|
|
8
|
+
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
9
|
+
function assertType<T extends true>(_ok: T): void {}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Request bodies are enforced by AJV against the EMITTED JSON Schema, not by parsing with Zod. A
|
|
13
|
+
* Zod-only assertion would pass on transforms (`.trim()`) that leave no trace in the emission and
|
|
14
|
+
* therefore never run at the endpoint — so the blank-key cases below go through `validateApiRequest`,
|
|
15
|
+
* which is the path `validatedBody` actually takes.
|
|
16
|
+
*/
|
|
17
|
+
describe('SetMcpApiKeyRequest — as enforced at the endpoint (AJV)', () => {
|
|
18
|
+
it('accepts a real key', () => {
|
|
19
|
+
expect(validateApiRequest('SetMcpApiKeyRequest', { api_key: 'sk-live-abcdef' }).valid).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('rejects a whitespace-only key', () => {
|
|
23
|
+
expect(validateApiRequest('SetMcpApiKeyRequest', { api_key: ' ' }).valid).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('rejects a tab/newline-only key', () => {
|
|
27
|
+
expect(validateApiRequest('SetMcpApiKeyRequest', { api_key: '\t\n ' }).valid).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('rejects an empty key', () => {
|
|
31
|
+
expect(validateApiRequest('SetMcpApiKeyRequest', { api_key: '' }).valid).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('rejects a missing key', () => {
|
|
35
|
+
expect(validateApiRequest('SetMcpApiKeyRequest', {}).valid).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('rejects unknown properties', () => {
|
|
39
|
+
expect(validateApiRequest('SetMcpApiKeyRequest', { api_key: 'sk-live', collection_id: 'x' }).valid).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('still normalizes surrounding whitespace for Zod consumers', () => {
|
|
43
|
+
expect(SetMcpApiKeyRequestSchema.parse({ api_key: ' sk-live-abcdef ' }).api_key).toBe('sk-live-abcdef');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('AppInstallationPayload.api_key_params — as enforced at the endpoint (AJV)', () => {
|
|
48
|
+
const APP_ID = '68b1779130afe5403a1589bc';
|
|
49
|
+
|
|
50
|
+
it('accepts a key per collection', () => {
|
|
51
|
+
const result = validateApiRequest('AppInstallationPayload', {
|
|
52
|
+
app_id: APP_ID,
|
|
53
|
+
api_key_params: { acme_mcp: { api_key: 'sk-install-abcdef' } },
|
|
54
|
+
});
|
|
55
|
+
expect(result.valid).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('rejects a whitespace-only key on the install path too', () => {
|
|
59
|
+
const result = validateApiRequest('AppInstallationPayload', {
|
|
60
|
+
app_id: APP_ID,
|
|
61
|
+
api_key_params: { acme_mcp: { api_key: ' ' } },
|
|
62
|
+
});
|
|
63
|
+
expect(result.valid).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('stays optional — installs with no api_key collections send nothing', () => {
|
|
67
|
+
expect(validateApiRequest('AppInstallationPayload', { app_id: APP_ID }).valid).toBe(true);
|
|
68
|
+
expect(AppInstallationPayloadSchema.parse({ app_id: APP_ID }).api_key_params).toBeUndefined();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('McpApiKeyStatus', () => {
|
|
73
|
+
it('publishes hint as required-but-nullable, not optional', () => {
|
|
74
|
+
// Every response sets `hint`, so the field must not be optional in the generated clients.
|
|
75
|
+
assertType<Equals<McpApiKeyStatus, { configured: boolean; hint: string | null }>>(true);
|
|
76
|
+
expect(McpApiKeyStatusSchema.safeParse({ configured: false }).success).toBe(false);
|
|
77
|
+
expect(McpApiKeyStatusSchema.safeParse({ configured: false, hint: null }).success).toBe(true);
|
|
78
|
+
expect(McpApiKeyStatusSchema.safeParse({ configured: true, hint: 'sk-l...3456' }).success).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('never carries the key itself', () => {
|
|
82
|
+
expect(McpApiKeyStatusSchema.safeParse({ configured: true, hint: null, api_key: 'sk-live' }).success).toBe(
|
|
83
|
+
false,
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
});
|