@vertesia/common 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/lib/api-contract/components.generated.json +904 -378
  2. package/lib/api-schemas/account.d.ts +5 -0
  3. package/lib/api-schemas/account.d.ts.map +1 -1
  4. package/lib/api-schemas/account.js +7 -0
  5. package/lib/api-schemas/account.js.map +1 -1
  6. package/lib/api-schemas/agent-runs.d.ts +410 -145
  7. package/lib/api-schemas/agent-runs.d.ts.map +1 -1
  8. package/lib/api-schemas/app-runtime.d.ts +1169 -406
  9. package/lib/api-schemas/app-runtime.d.ts.map +1 -1
  10. package/lib/api-schemas/app-runtime.js +6 -0
  11. package/lib/api-schemas/app-runtime.js.map +1 -1
  12. package/lib/api-schemas/apps.d.ts +5 -0
  13. package/lib/api-schemas/apps.d.ts.map +1 -1
  14. package/lib/api-schemas/apps.js +6 -3
  15. package/lib/api-schemas/apps.js.map +1 -1
  16. package/lib/api-schemas/content.d.ts +418 -145
  17. package/lib/api-schemas/content.d.ts.map +1 -1
  18. package/lib/api-schemas/content.js +3 -0
  19. package/lib/api-schemas/content.js.map +1 -1
  20. package/lib/api-schemas/document-processing.d.ts +246 -87
  21. package/lib/api-schemas/document-processing.d.ts.map +1 -1
  22. package/lib/api-schemas/embeddings.d.ts +250 -0
  23. package/lib/api-schemas/embeddings.d.ts.map +1 -1
  24. package/lib/api-schemas/embeddings.js +163 -0
  25. package/lib/api-schemas/embeddings.js.map +1 -1
  26. package/lib/api-schemas/environment.d.ts +2 -2
  27. package/lib/api-schemas/events.d.ts +738 -261
  28. package/lib/api-schemas/events.d.ts.map +1 -1
  29. package/lib/api-schemas/files.d.ts +1 -0
  30. package/lib/api-schemas/files.d.ts.map +1 -1
  31. package/lib/api-schemas/files.js +1 -0
  32. package/lib/api-schemas/files.js.map +1 -1
  33. package/lib/api-schemas/interaction.d.ts +3518 -1260
  34. package/lib/api-schemas/interaction.d.ts.map +1 -1
  35. package/lib/api-schemas/interaction.js +2 -0
  36. package/lib/api-schemas/interaction.js.map +1 -1
  37. package/lib/api-schemas/project-configuration.d.ts +825 -290
  38. package/lib/api-schemas/project-configuration.d.ts.map +1 -1
  39. package/lib/api-schemas/project-configuration.js +5 -3
  40. package/lib/api-schemas/project-configuration.js.map +1 -1
  41. package/lib/api-schemas/project.d.ts +1233 -435
  42. package/lib/api-schemas/project.d.ts.map +1 -1
  43. package/lib/api-schemas/prompt.d.ts +1 -0
  44. package/lib/api-schemas/prompt.d.ts.map +1 -1
  45. package/lib/api-schemas/prompt.js +1 -0
  46. package/lib/api-schemas/prompt.js.map +1 -1
  47. package/lib/api-schemas/registry.d.ts +12751 -4412
  48. package/lib/api-schemas/registry.d.ts.map +1 -1
  49. package/lib/api-schemas/registry.js +52 -34
  50. package/lib/api-schemas/registry.js.map +1 -1
  51. package/lib/api-schemas/store.d.ts +4130 -1480
  52. package/lib/api-schemas/store.d.ts.map +1 -1
  53. package/lib/api-schemas/store.js +3 -0
  54. package/lib/api-schemas/store.js.map +1 -1
  55. package/lib/api-schemas/user.d.ts +28 -12
  56. package/lib/api-schemas/user.d.ts.map +1 -1
  57. package/lib/api-schemas/user.js +23 -17
  58. package/lib/api-schemas/user.js.map +1 -1
  59. package/lib/api-schemas/view-execution.d.ts +2 -0
  60. package/lib/api-schemas/view-execution.d.ts.map +1 -1
  61. package/lib/api-schemas/views.d.ts +7 -0
  62. package/lib/api-schemas/views.d.ts.map +1 -1
  63. package/lib/api-schemas/workflow-runs.d.ts +164 -58
  64. package/lib/api-schemas/workflow-runs.d.ts.map +1 -1
  65. package/lib/apps.d.ts +6 -0
  66. package/lib/apps.d.ts.map +1 -1
  67. package/lib/embeddings.d.ts +18 -1
  68. package/lib/embeddings.d.ts.map +1 -1
  69. package/lib/index.d.ts +2 -1
  70. package/lib/index.d.ts.map +1 -1
  71. package/lib/index.js +1 -0
  72. package/lib/index.js.map +1 -1
  73. package/lib/interaction.d.ts +2 -7
  74. package/lib/interaction.d.ts.map +1 -1
  75. package/lib/interaction.js.map +1 -1
  76. package/lib/principal-context.d.ts +21 -12
  77. package/lib/principal-context.d.ts.map +1 -1
  78. package/lib/project-values.d.ts +1 -0
  79. package/lib/project-values.d.ts.map +1 -1
  80. package/lib/project-values.js +1 -0
  81. package/lib/project-values.js.map +1 -1
  82. package/lib/project.d.ts.map +1 -1
  83. package/lib/project.js +10 -0
  84. package/lib/project.js.map +1 -1
  85. package/lib/store/intake-policy-schema.generated.d.ts.map +1 -1
  86. package/lib/store/intake-policy-schema.generated.js +104 -31
  87. package/lib/store/intake-policy-schema.generated.js.map +1 -1
  88. package/lib/store/rendering.d.ts +1 -0
  89. package/lib/store/rendering.d.ts.map +1 -1
  90. package/lib/store/rendering.js +4 -0
  91. package/lib/store/rendering.js.map +1 -1
  92. package/lib/user.d.ts +2 -1
  93. package/lib/user.d.ts.map +1 -1
  94. package/lib/user.js.map +1 -1
  95. package/lib/vertesia-common.js +2 -2
  96. package/lib/vertesia-common.js.map +1 -1
  97. package/package.json +4 -4
  98. package/src/api-contract/components.generated.json +904 -378
  99. package/src/api-schemas/account.ts +8 -0
  100. package/src/api-schemas/app-runtime.ts +7 -0
  101. package/src/api-schemas/apps.ts +6 -3
  102. package/src/api-schemas/content.ts +4 -0
  103. package/src/api-schemas/embeddings.ts +184 -0
  104. package/src/api-schemas/files.ts +1 -0
  105. package/src/api-schemas/indexing.contract.test.ts +40 -1
  106. package/src/api-schemas/interaction.ts +2 -0
  107. package/src/api-schemas/llumiverse.contract.test.ts +70 -39
  108. package/src/api-schemas/mcp-api-key.contract.test.ts +39 -0
  109. package/src/api-schemas/project-configuration.ts +5 -3
  110. package/src/api-schemas/project.contract.test.ts +30 -0
  111. package/src/api-schemas/prompt.ts +1 -0
  112. package/src/api-schemas/registry.ts +76 -35
  113. package/src/api-schemas/store.contract.test.ts +25 -25
  114. package/src/api-schemas/store.ts +4 -0
  115. package/src/api-schemas/user.contract.test.ts +24 -18
  116. package/src/api-schemas/user.ts +24 -18
  117. package/src/api-schemas/views.contract.test.ts +3 -10
  118. package/src/apps.ts +6 -0
  119. package/src/embeddings.ts +34 -0
  120. package/src/index.ts +2 -1
  121. package/src/interaction.ts +2 -6
  122. package/src/principal-context.ts +22 -12
  123. package/src/project-values.ts +1 -0
  124. package/src/project.ts +10 -0
  125. package/src/roles.test.ts +1 -0
  126. package/src/store/intake-policy-schema.generated.ts +109 -31
  127. package/src/store/rendering.ts +9 -0
  128. package/src/user.ts +8 -1
@@ -77,7 +77,12 @@ import {
77
77
  RoleDefinitionArraySchema,
78
78
  SystemRoleDefinitionArraySchema,
79
79
  } from './access-control.js';
80
- import { AccountSchema, StripeBillingStatusResponseSchema, UpdateAccountPayloadSchema } from './account.js';
80
+ import {
81
+ AccountApiVersionPolicySchema,
82
+ AccountSchema,
83
+ StripeBillingStatusResponseSchema,
84
+ UpdateAccountPayloadSchema,
85
+ } from './account.js';
81
86
  import { type JsonObject, toOpenApiComponents } from './adapter.js';
82
87
  import * as AgentCommunicationSchemas from './agent-communication.js';
83
88
  import * as AgentRunSchemas from './agent-runs.js';
@@ -364,6 +369,22 @@ import {
364
369
  WorkflowExecutionStatusSchema,
365
370
  } from './document-processing.js';
366
371
  import {
372
+ EmbeddingBatchApplyRequestSchema,
373
+ EmbeddingBatchApplyResponseSchema,
374
+ EmbeddingBatchCapabilityRequestSchema,
375
+ EmbeddingBatchCapabilityResponseSchema,
376
+ EmbeddingBatchCreateRequestSchema,
377
+ EmbeddingBatchJobRequestSchema,
378
+ EmbeddingBatchJobResponseSchema,
379
+ EmbeddingBatchPrepareRequestSchema,
380
+ EmbeddingBatchPrepareResponseSchema,
381
+ EmbeddingBatchProviderStateSchema,
382
+ EmbeddingBatchRenditionPageRequestSchema,
383
+ EmbeddingBatchRenditionPageResponseSchema,
384
+ EmbeddingBatchRunStateSchema,
385
+ EmbeddingBatchRunSummarySchema,
386
+ EmbeddingBatchSubjobSchema,
387
+ EmbeddingBatchUpdateRequestSchema,
367
388
  EmbeddingsApiAudioInputSchema,
368
389
  EmbeddingsApiImageInputSchema,
369
390
  EmbeddingsApiInputSchema,
@@ -373,6 +394,7 @@ import {
373
394
  EmbeddingsApiVideoInputSchema,
374
395
  EmbeddingsStatusResponseSchema,
375
396
  ProjectConfigurationEmbeddingEnablePayloadSchema,
397
+ RecalculateEmbeddingsQuerySchema,
376
398
  } from './embeddings.js';
377
399
  import {
378
400
  EnableEnvironmentModelPayloadSchema,
@@ -809,6 +831,7 @@ import * as WorkflowRunSchemas from './workflow-runs.js';
809
831
  * group approaches the proven-safe size.
810
832
  */
811
833
  const IAM_AND_ACCOUNT_SCHEMAS = {
834
+ AccountApiVersionPolicy: AccountApiVersionPolicySchema,
812
835
  Account: AccountSchema,
813
836
  UpdateAccountPayload: UpdateAccountPayloadSchema,
814
837
  StripeBillingStatusResponse: StripeBillingStatusResponseSchema,
@@ -1205,6 +1228,12 @@ const EXECUTION_RUN_SCHEMAS = {
1205
1228
  RunSearchQuery: RunSearchQuerySchema,
1206
1229
  RunListQuery: RunListQuerySchema,
1207
1230
  RunSearchPayload: RunSearchPayloadSchema,
1231
+ } as const satisfies Record<string, z.ZodType>;
1232
+
1233
+ // Split out of EXECUTION_RUN_SCHEMAS rather than grown in place: one literal covering both halves
1234
+ // infers a type too large for tsc to serialize into the declaration file (TS7056). The split is
1235
+ // purely structural — `mergeComponentGroups` and `ApiSchemaMap` see the same component set.
1236
+ const INTERACTION_EXECUTION_SCHEMAS = {
1208
1237
  // Executing an interaction, synchronously or as a workflow.
1209
1238
  InteractionExecutionPayload: InteractionExecutionPayloadSchema,
1210
1239
  NamedInteractionExecutionPayload: NamedInteractionExecutionPayloadSchema,
@@ -1463,7 +1492,24 @@ const INDEXING_SCHEMAS = {
1463
1492
 
1464
1493
  const EMBEDDING_ADMIN_SCHEMAS = {
1465
1494
  EmbeddingsStatusResponse: EmbeddingsStatusResponseSchema,
1495
+ RecalculateEmbeddingsQuery: RecalculateEmbeddingsQuerySchema,
1466
1496
  ProjectConfigurationEmbeddingEnablePayload: ProjectConfigurationEmbeddingEnablePayloadSchema,
1497
+ EmbeddingBatchProviderState: EmbeddingBatchProviderStateSchema,
1498
+ EmbeddingBatchCapabilityRequest: EmbeddingBatchCapabilityRequestSchema,
1499
+ EmbeddingBatchCapabilityResponse: EmbeddingBatchCapabilityResponseSchema,
1500
+ EmbeddingBatchCreateRequest: EmbeddingBatchCreateRequestSchema,
1501
+ EmbeddingBatchJobRequest: EmbeddingBatchJobRequestSchema,
1502
+ EmbeddingBatchJobResponse: EmbeddingBatchJobResponseSchema,
1503
+ EmbeddingBatchRunState: EmbeddingBatchRunStateSchema,
1504
+ EmbeddingBatchRunSummary: EmbeddingBatchRunSummarySchema,
1505
+ EmbeddingBatchSubjob: EmbeddingBatchSubjobSchema,
1506
+ EmbeddingBatchPrepareRequest: EmbeddingBatchPrepareRequestSchema,
1507
+ EmbeddingBatchPrepareResponse: EmbeddingBatchPrepareResponseSchema,
1508
+ EmbeddingBatchRenditionPageRequest: EmbeddingBatchRenditionPageRequestSchema,
1509
+ EmbeddingBatchRenditionPageResponse: EmbeddingBatchRenditionPageResponseSchema,
1510
+ EmbeddingBatchUpdateRequest: EmbeddingBatchUpdateRequestSchema,
1511
+ EmbeddingBatchApplyRequest: EmbeddingBatchApplyRequestSchema,
1512
+ EmbeddingBatchApplyResponse: EmbeddingBatchApplyResponseSchema,
1467
1513
  } as const satisfies Record<string, z.ZodType>;
1468
1514
 
1469
1515
  const COMMAND_SCHEMAS = {
@@ -2256,6 +2302,7 @@ const API_SCHEMA_GROUPS = [
2256
2302
  INTERACTION_AUTHORING_SCHEMAS,
2257
2303
  AGENT_CONVERSATION_SCHEMAS,
2258
2304
  EXECUTION_RUN_SCHEMAS,
2305
+ INTERACTION_EXECUTION_SCHEMAS,
2259
2306
  PROMPT_AUTHORING_SCHEMAS,
2260
2307
  PROJECT_TOOL_SCHEMAS,
2261
2308
  REMOTE_MCP_SCHEMAS,
@@ -2318,6 +2365,7 @@ type ApiSchemaMap = typeof IAM_AND_ACCOUNT_SCHEMAS &
2318
2365
  typeof INTERACTION_AUTHORING_SCHEMAS &
2319
2366
  typeof AGENT_CONVERSATION_SCHEMAS &
2320
2367
  typeof EXECUTION_RUN_SCHEMAS &
2368
+ typeof INTERACTION_EXECUTION_SCHEMAS &
2321
2369
  typeof PROMPT_AUTHORING_SCHEMAS &
2322
2370
  typeof PROJECT_TOOL_SCHEMAS &
2323
2371
  typeof REMOTE_MCP_SCHEMAS &
@@ -2435,7 +2483,7 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
2435
2483
  'QuotaStandingWindow',
2436
2484
  'QuotaStandingAdmissionClass',
2437
2485
  'QuotaTierResponse',
2438
- // The IAM closure. PrincipalContext is composed into PrincipalIdentity rather than hoisted,
2486
+ // The IAM closure. AbacPrincipalContext is composed into PrincipalIdentity rather than hoisted,
2439
2487
  // so it has no component of its own to list.
2440
2488
  'User',
2441
2489
  'UpdateUserPayload',
@@ -2558,33 +2606,12 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
2558
2606
  //
2559
2607
  // `JSONSchema` is deliberately absent: it is OPEN by design and by long-standing publication —
2560
2608
  // a JSON Schema carries keywords the type never enumerated. `JSONSchemaProperties` is a map.
2561
- 'TextFallbackOptions',
2562
- 'AzureFoundryChatOptions',
2563
- 'ImagenOptions',
2564
- 'VertexAIClaudeOptions',
2565
- 'VertexAIGeminiOptions',
2566
- 'VertexAIGeminiOmniVideoOptions',
2567
- 'VertexAIGrokOptions',
2568
- 'NovaCanvasOptions',
2569
- 'BedrockConverseOptions',
2570
- 'BedrockNovaOptions',
2571
- 'BedrockMistralOptions',
2572
- 'BedrockAI21Options',
2573
- 'BedrockCohereCommandOptions',
2574
- 'BedrockClaudeOptions',
2575
- 'BedrockPalmyraOptions',
2576
- 'BedrockGptOssOptions',
2577
- 'TwelvelabsPegasusOptions',
2578
- 'BedrockMantleResponsesOptions',
2579
- 'BedrockMantleChatCompletionsOptions',
2580
- 'BedrockMantleClaudeOptions',
2581
- 'OpenAiThinkingOptions',
2582
- 'OpenAiTextOptions',
2583
- 'OpenAiDalleOptions',
2584
- 'OpenAiGptImageOptions',
2585
- 'XAIGrokImageOptions',
2586
- 'GroqOptions',
2587
- 'MistralTextOptions',
2609
+ // Derive membership so new provider schemas inherit this enforcement check automatically.
2610
+ ...ModelOptionsSchema.options.map((schema) => {
2611
+ const id = schema.meta()?.id;
2612
+ if (!id) throw new Error('Model option schemas must declare a component id');
2613
+ return id;
2614
+ }),
2588
2615
  // The app-manifest leaves. Every object among them is published closed today, the nested `git`
2589
2616
  // block included, and it is spelled `strictObject` so the emission carries it directly. The five
2590
2617
  // enums take no `additionalProperties` at all.
@@ -2752,6 +2779,8 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
2752
2779
  'DriftAnalysisResult',
2753
2780
  'DriftAnalysisProgress',
2754
2781
  'EmbeddingsStatusResponse',
2782
+ 'EmbeddingBatchRunSummary',
2783
+ 'RecalculateEmbeddingsQuery',
2755
2784
  'ProjectConfigurationEmbeddingEnablePayload',
2756
2785
  'GenericCommandResponse',
2757
2786
  'DriftAnalysisStatusResponse',
@@ -3384,13 +3413,25 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
3384
3413
  * divergence. Note that `.refine()` is silently DROPPED rather than rejected, so refinements must
3385
3414
  * not be used to express contract rules — they would be invisible to both the spec and AJV.
3386
3415
  */
3387
- function emitRawSchemas(): Record<string, unknown> {
3388
- return Object.fromEntries(
3389
- Object.entries(API_SCHEMAS).map(([name, schema]) => [
3390
- name,
3391
- z.toJSONSchema(schema, { target: 'draft-2020-12', io: 'input' }),
3392
- ]),
3416
+ function emitSchema(name: string, schema: z.ZodType): unknown {
3417
+ const emitted = z.toJSONSchema(schema, { target: 'draft-2020-12', io: 'input' }) as Record<string, unknown>;
3418
+ const rootRef = emitted.$ref;
3419
+ const defs = emitted.$defs;
3420
+ const expectedRef = `#/$defs/${name}`;
3421
+ if (rootRef !== expectedRef || !defs || typeof defs !== 'object' || Array.isArray(defs)) return emitted;
3422
+
3423
+ const root = (defs as Record<string, unknown>)[name];
3424
+ if (!root || typeof root !== 'object' || Array.isArray(root)) return emitted;
3425
+ const remainingDefs = Object.fromEntries(
3426
+ Object.entries(defs as Record<string, unknown>).filter(([id]) => id !== name),
3393
3427
  );
3428
+ return Object.keys(remainingDefs).length === 0
3429
+ ? root
3430
+ : { ...(root as Record<string, unknown>), $defs: remainingDefs };
3431
+ }
3432
+
3433
+ function emitRawSchemas(): Record<string, unknown> {
3434
+ return Object.fromEntries(Object.entries(API_SCHEMAS).map(([name, schema]) => [name, emitSchema(name, schema)]));
3394
3435
  }
3395
3436
 
3396
3437
  /**
@@ -6,7 +6,7 @@ import { ContentTypeIntakePolicySchema as GeneratedIntakePolicySchema } from '..
6
6
  import type { ContentObjectTypeRef, ContentTypeIntakePolicy, IntakePageRanges } from '../store/store.js';
7
7
  import type { JsonObject } from './adapter.js';
8
8
  import { ApiSchemaComponents, bundleCanonicalComponent, validateApiResponse } from './registry.js';
9
- import { ContentTypeIntakePolicySchema } from './store.js';
9
+ import { ContentTypeIntakePolicySchema, InteractionExecutionConfigurationSchema } from './store.js';
10
10
 
11
11
  /** Exact type identity — `extends` in both directions is too weak (any/unknown slip through). */
12
12
  type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
@@ -103,26 +103,15 @@ describe.skipIf(!publishedDocument)('gate — generated artifact = canonical com
103
103
  }
104
104
  });
105
105
 
106
- it('drops the discriminator hint the published component keeps, and only that', () => {
107
- // The one place the artifact and the component are allowed to differ, pinned from both sides
108
- // so neither can move alone. `synthesizeDiscriminator` restates `type` and `required` on the
109
- // union node for the generated Java/Go clients; the node has no `properties`, and Gemini
110
- // rejects the whole tool schema over it ("requires unspecified property '_option_id'") when
111
- // the artifact reaches Vertex inside `create_or_update_type`'s input schema.
112
- expect(published.ModelOptions).toMatchObject({
113
- discriminator: { propertyName: '_option_id' },
114
- type: 'object',
115
- required: ['_option_id'],
116
- });
117
-
106
+ it('preserves optional-ID anyOf semantics in the bundled option schema', () => {
118
107
  const bundled = ($defsOf(GeneratedIntakePolicySchema) as Record<string, Record<string, unknown>>).ModelOptions;
108
+ const component = published.ModelOptions as { anyOf: unknown[]; discriminator?: unknown; required?: string[] };
119
109
  expect(bundled.discriminator).toBeUndefined();
120
- expect(bundled.required).toBeUndefined();
121
- expect(bundled.type).toBeUndefined();
122
- // The branches are what carried the contract all along, so nothing was validated away.
123
- expect((bundled.oneOf as unknown[]).length).toBe(
124
- ((published.ModelOptions as { oneOf: unknown[] }).oneOf ?? []).length,
125
- );
110
+ expect(component.discriminator).toBeUndefined();
111
+ expect(bundled.required ?? []).not.toContain('_option_id');
112
+ expect(component.required ?? []).not.toContain('_option_id');
113
+ expect((bundled.anyOf as unknown[]).length).toBe(component.anyOf.length);
114
+ expect(bundled.oneOf).toBeUndefined();
126
115
  });
127
116
 
128
117
  it('registers the component the alias claims, under the id the alias name requires', () => {
@@ -385,8 +374,8 @@ describe('runtime tightenings — recorded as operation 25 of the 1.5 runbook',
385
374
 
386
375
  it('validates model_options against the union instead of accepting any object', () => {
387
376
  // Same class: `model_options` was `{type: object, additionalProperties: true}` in the
388
- // hand-written schema and `$ref: ModelOptions` in the published component. It now has to name
389
- // a driver through `_option_id`, which is the discriminator generated clients already use.
377
+ // hand-written schema and `$ref: ModelOptions` in the published component. The family hint
378
+ // is optional, but known field types and supplied IDs remain validated.
390
379
  expect(ApiSchemaComponents.ContentTypeIntakePolicy).toBeDefined();
391
380
  expect(
392
381
  validate({
@@ -394,11 +383,11 @@ describe('runtime tightenings — recorded as operation 25 of the 1.5 runbook',
394
383
  }),
395
384
  errors(),
396
385
  ).toBe(true);
397
- expect(validate({ extraction: { config: { model_options: { temperature: 0.5 } } } })).toBe(false);
386
+ expect(validate({ extraction: { config: { model_options: { temperature: 0.5 } } } })).toBe(true);
398
387
  expect(validate({ extraction: { config: { model_options: { _option_id: 'not-a-driver' } } } })).toBe(false);
399
- // The empty object is rejected for the same reason, which is why nothing may PUT it on the
400
- // wire — see `normalizeModelOptions`, which drops an options bag with no options in it.
401
- expect(validate({ extraction: { config: { model_options: {} } } })).toBe(false);
388
+ expect(validate({ extraction: { config: { model_options: {} } } })).toBe(true);
389
+ expect(validate({ extraction: { config: { model_options: { temperature: 'hot' } } } })).toBe(false);
390
+ expect(validate({ extraction: { config: { model_options: { unknown_option: true } } } })).toBe(false);
402
391
  });
403
392
 
404
393
  it('constrains the two config enums that were unconstrained strings', () => {
@@ -498,3 +487,14 @@ describe('the five content-type shapes are composed, not repeated', () => {
498
487
  ).toBe(true);
499
488
  });
500
489
  });
490
+
491
+ describe('inherited execution model configuration', () => {
492
+ it.each([true, false, undefined])('preserves inherit_model_config=%s in the wire contract', (inherit) => {
493
+ const config = { environment: 'parent-env', model: 'parent-model', inherit_model_config: inherit };
494
+ expect(InteractionExecutionConfigurationSchema.parse(config)).toEqual(config);
495
+ const schema = bundleCanonicalComponent('InteractionExecutionConfiguration');
496
+ const validateConfig = ajv.compile(schema);
497
+ expect(validateConfig(config), ajv.errorsText(validateConfig.errors)).toBe(true);
498
+ expect(validateConfig({ ...config, inherit_model_config: 'true' })).toBe(false);
499
+ });
500
+ });
@@ -80,6 +80,10 @@ export const InteractionExecutionConfigurationSchema = z
80
80
  id: z.string().optional(),
81
81
  environment: z.string().optional(),
82
82
  model: z.string().optional(),
83
+ inherit_model_config: z.boolean().optional().meta({
84
+ description:
85
+ 'Treat environment and model as inherited fallbacks after interaction settings, before project defaults.',
86
+ }),
83
87
  do_validate: z.boolean().optional(),
84
88
  run_data: RunDataStorageLevelSchema.optional(),
85
89
  configMode: ConfigModesSchema.optional(),
@@ -1,10 +1,10 @@
1
1
  import { Ajv2020 } from 'ajv/dist/2020.js';
2
2
  import { describe, expect, it } from 'vitest';
3
- import type { PrincipalContext, PrincipalIdentity } from '../principal-context.js';
3
+ import type { AbacPrincipalContext, PrincipalIdentity } from '../principal-context.js';
4
4
  import type { UpdateUserPayload, User } from '../user.js';
5
5
  import type { JsonObject } from './adapter.js';
6
6
  import { ApiSchemaComponents, apiComponentRef, validateApiRequest, validateApiResponse } from './registry.js';
7
- import type { PrincipalContextFromSchema, UserArrayFromSchema } from './user.js';
7
+ import type { AbacPrincipalContextFromSchema, UserArrayFromSchema } from './user.js';
8
8
 
9
9
  /** Exact type identity — `extends` in both directions is too weak (any/unknown slip through). */
10
10
  type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
@@ -27,19 +27,23 @@ const VALID_USER = {
27
27
  describe('gate 1 — the schema is the single source of truth for the public IAM types', () => {
28
28
  it('publishes the exact schema-derived type, not a hand-written twin', () => {
29
29
  assertType<Equals<UserArrayFromSchema, User[]>>(true);
30
- assertType<Equals<PrincipalContext, PrincipalContextFromSchema>>(true);
30
+ assertType<Equals<AbacPrincipalContext, AbacPrincipalContextFromSchema>>(true);
31
31
  expect(true).toBe(true);
32
32
  });
33
33
 
34
- it('derives the inherited principal fields rather than restating them', () => {
35
- // PrincipalIdentity used to `extends PrincipalContext`, so composing the schemas is what
36
- // keeps the five inherited fields from becoming a twin one level down — the failure mode
37
- // this batch was scoped to avoid.
38
- assertType<Equals<PrincipalIdentity['clearance'], PrincipalContext['clearance']>>(true);
39
- assertType<Equals<PrincipalIdentity['compartments'], PrincipalContext['compartments']>>(true);
40
- assertType<Equals<PrincipalIdentity['email'], PrincipalContext['email']>>(true);
41
- assertType<Equals<PrincipalIdentity['tags'], PrincipalContext['tags']>>(true);
42
- assertType<Equals<PrincipalIdentity['properties'], PrincipalContext['properties']>>(true);
34
+ it('derives the identity fields from the ABAC context rather than restating them', () => {
35
+ // PrincipalIdentity `extends AbacPrincipalContext`, so composing the schemas is what keeps
36
+ // the inherited fields from becoming a twin one level down — the failure mode this batch was
37
+ // scoped to avoid. `kind` and `id` are part of the ABAC context itself (resolvable as
38
+ // `$principal.*`), not identity-only metadata.
39
+ assertType<Equals<PrincipalIdentity['kind'], AbacPrincipalContext['kind']>>(true);
40
+ assertType<Equals<PrincipalIdentity['id'], AbacPrincipalContext['id']>>(true);
41
+ assertType<Equals<PrincipalIdentity['clearance'], AbacPrincipalContext['clearance']>>(true);
42
+ assertType<Equals<PrincipalIdentity['compartments'], AbacPrincipalContext['compartments']>>(true);
43
+ assertType<Equals<PrincipalIdentity['email'], AbacPrincipalContext['email']>>(true);
44
+ assertType<Equals<PrincipalIdentity['tags'], AbacPrincipalContext['tags']>>(true);
45
+ assertType<Equals<PrincipalIdentity['properties'], AbacPrincipalContext['properties']>>(true);
46
+ assertType<Equals<PrincipalIdentity['kind'], 'user' | 'apikey'>>(true);
43
47
  assertType<Equals<PrincipalIdentity['id'], string>>(true);
44
48
  expect(true).toBe(true);
45
49
  });
@@ -80,20 +84,22 @@ describe('gate 1 — the schema is the single source of truth for the public IAM
80
84
  });
81
85
 
82
86
  describe('gate 2 — the published components match the closure the types come from', () => {
83
- it('does not hoist PrincipalContext into a component of its own', () => {
87
+ it('does not hoist AbacPrincipalContext into a component of its own', () => {
84
88
  // It is a public TYPE but has never been a published component. Hoisting it would add a
85
89
  // $ref to PrincipalIdentity that every generated client would have to follow.
86
- expect(Object.keys(ApiSchemaComponents)).not.toContain('PrincipalContext');
90
+ expect(Object.keys(ApiSchemaComponents)).not.toContain('AbacPrincipalContext');
87
91
  const props = ApiSchemaComponents.PrincipalIdentity.properties as Record<string, JsonObject>;
92
+ expect(props.kind).toEqual({ type: 'string', enum: ['user', 'apikey'] });
88
93
  expect(props.clearance).toEqual({ type: 'number' });
89
94
  expect(props.id).toEqual({ type: 'string' });
90
95
  });
91
96
 
92
- it('publishes the composed property order, id last', () => {
93
- // `.extend()` appends, which is what `interface … extends …` produced and what the document
94
- // already carries.
97
+ it('publishes the composed property order — kind and id first', () => {
98
+ // `AbacPrincipalContext` lists its discriminators (kind, id) ahead of the merged BLP
99
+ // attributes; PrincipalIdentity `.extend({})`s it, adding nothing, so the order is the
100
+ // context's own.
95
101
  const props = ApiSchemaComponents.PrincipalIdentity.properties as JsonObject;
96
- expect(Object.keys(props)).toEqual(['clearance', 'compartments', 'email', 'tags', 'properties', 'id']);
102
+ expect(Object.keys(props)).toEqual(['kind', 'id', 'clearance', 'compartments', 'email', 'tags', 'properties']);
97
103
  });
98
104
 
99
105
  it('declares the timestamps the endpoint has always shipped', () => {
@@ -9,15 +9,22 @@ import { z } from 'zod';
9
9
  */
10
10
 
11
11
  /**
12
- * Not hoisted: no `id` in `.meta()`, so the adapter inlines it into `PrincipalIdentity` instead of
13
- * emitting a `PrincipalContext` component and a `$ref` the document has never published.
12
+ * The full principal context resolved at token-issue time — every field a rule can reference through
13
+ * `$principal.*`: the principal `kind`, its `id`, and the merged BLP attributes. This is the single
14
+ * source of truth the token server mirrors into the JWT, the shared `buildPrincipalContext`
15
+ * produces, and the UI condition editor offers. `kind` and `id` are first-class members here, not
16
+ * identity-only metadata: they are resolvable in ResourceSet/PrincipalSet conditions, so hiding them
17
+ * (as an earlier split of this schema did) under-declared what the server actually matches against.
14
18
  *
15
- * It still exists as a schema rather than being spelled out inside `PrincipalIdentitySchema`,
16
- * because `PrincipalContext` is a public type in its own right — consumed by PrincipalSet condition
17
- * evaluation and client-side ABAC tooling. Composing the two is what keeps the five inherited fields
18
- * from becoming a hand-written twin of the schema that publishes them.
19
+ * Not hoisted: no `id` in `.meta()`, so the adapter inlines it into `PrincipalIdentity` instead of
20
+ * emitting an `AbacPrincipalContext` component and a `$ref` the document has never published. It
21
+ * still exists as a schema in its own right because it is a public type composed into
22
+ * `PrincipalIdentitySchema` — composing is what keeps the shared fields from becoming a hand-written
23
+ * twin of the schema that publishes them.
19
24
  */
20
- export const PrincipalContextSchema = z.object({
25
+ export const AbacPrincipalContextSchema = z.object({
26
+ kind: z.enum(['user', 'apikey']),
27
+ id: z.string(),
21
28
  clearance: z.number(),
22
29
  compartments: z.array(z.string()),
23
30
  email: z.string().optional(),
@@ -26,19 +33,18 @@ export const PrincipalContextSchema = z.object({
26
33
  });
27
34
 
28
35
  /**
29
- * `.extend()` rather than a fresh object literal: it appends `id` after the inherited five, which is
30
- * both what `interface PrincipalIdentity extends PrincipalContext` produced and the property order
31
- * the document already publishes.
36
+ * Response shape of the `/iam/users/identity` endpoint. Extends {@link AbacPrincipalContextSchema}
37
+ * adding nothing today: the two are kept as distinct names so identity-only fields — ones that must
38
+ * NOT become resolvable as `$principal.*` — can be added here later without widening the ABAC
39
+ * surface. Invariant: the ABAC principal context is always a subset of the identity. At this
40
+ * endpoint `kind` is always `user`.
32
41
  */
33
- export const PrincipalIdentitySchema = PrincipalContextSchema.extend({
34
- id: z.string(),
35
- }).meta({
42
+ export const PrincipalIdentitySchema = AbacPrincipalContextSchema.extend({}).meta({
36
43
  id: 'PrincipalIdentity',
37
44
  description:
38
- "Response shape of the `/iam/users/identity` endpoint: the current principal's {@link " +
39
- 'PrincipalContext } plus its id. Distinct from `PrincipalContext` itself because the id is ' +
40
- 'identity metadata, not a merged BLP field — adding it to `PrincipalContext` would ' +
41
- 'unintentionally expose `$principal.id` to PrincipalSet rule evaluation.',
45
+ "Response shape of the `/iam/users/identity` endpoint: the current principal's full ABAC " +
46
+ 'context — its `kind` (always `user` here), `id`, and the merged BLP attributes a rule can ' +
47
+ 'reference through `$principal.*`.',
42
48
  });
43
49
 
44
50
  /**
@@ -194,7 +200,7 @@ export const SignupPayloadSchema = z
194
200
  * The public IAM types, inferred rather than written. `../principal-context.ts`, `../user.ts` and
195
201
  * `../common.ts` re-export these under their public names.
196
202
  */
197
- export type PrincipalContextFromSchema = z.infer<typeof PrincipalContextSchema>;
203
+ export type AbacPrincipalContextFromSchema = z.infer<typeof AbacPrincipalContextSchema>;
198
204
  export type PrincipalIdentityFromSchema = z.infer<typeof PrincipalIdentitySchema>;
199
205
  export type UserFromSchema = z.infer<typeof UserSchema>;
200
206
  export type UserArrayFromSchema = z.infer<typeof UserArraySchema>;
@@ -70,19 +70,12 @@ describe('ViewExperienceConfiguration', () => {
70
70
  ).toBe(false);
71
71
  });
72
72
 
73
- it('accepts View model options that name no driver, while the shared config still requires one', () => {
74
- // The regression: a View's `model_options` are authored in the editor and saved before any
75
- // driver is resolved, so they carry no `_option_id`. Validating them against the
76
- // `ModelOptions` driver union — every branch of which requires that discriminator — meant a
77
- // stored View could not satisfy its own response schema, and `GET /views` logged a contract
78
- // violation on every call.
73
+ it('accepts untagged View options and preserves the shared options schema reference', () => {
74
+ // View options and shared model options both permit an omitted family ID.
79
75
  const authored = { model_options: { temperature: 0.2, max_tokens: 1024 } };
80
76
  expect(validateApiResponse('ViewAgenticExecutionConfiguration', authored).valid).toBe(true);
81
77
 
82
- // The split is the point: agent runs, events and workflow runs record options a driver
83
- // already resolved, so the shared component keeps the union. Asserted on the published
84
- // schema because `InteractionExecutionConfiguration` is not itself a response slot — if it
85
- // ever stops pointing at `ModelOptions`, the relaxation leaked out of Views.
78
+ // Keep the shared component wired to the canonical options contract.
86
79
  const modelOptions = (name: string) =>
87
80
  (ApiSchemaComponents[name] as { properties: Record<string, unknown> }).properties.model_options;
88
81
  expect(modelOptions('InteractionExecutionConfiguration')).toEqual({
package/src/apps.ts CHANGED
@@ -688,6 +688,12 @@ export interface CompositeAppMenuNavItem {
688
688
  description?: string | null;
689
689
  /** When true, this item is excluded from the Composite App dashboard cards */
690
690
  hideFromDashboard?: boolean;
691
+ /**
692
+ * When true, this item navigates to the App Portal form of the URL
693
+ * (`/apps/<appName><route>`) instead of the Composite App form (`/app/<appName><route>`),
694
+ * so the app is opened standalone rather than inside the Composite App shell.
695
+ */
696
+ openInAppPortal?: boolean;
691
697
  /** Optional access control settings for this nav item */
692
698
  permissions?: CompositeAppNavItemPermissions;
693
699
  /** Ordered child nav-items */
package/src/embeddings.ts CHANGED
@@ -1,6 +1,22 @@
1
1
  import type { EmbeddingsResult } from '@llumiverse/common';
2
2
  import type { z } from 'zod';
3
3
  import type {
4
+ EmbeddingBatchApplyRequestSchema,
5
+ EmbeddingBatchApplyResponseSchema,
6
+ EmbeddingBatchCapabilityRequestSchema,
7
+ EmbeddingBatchCapabilityResponseSchema,
8
+ EmbeddingBatchCreateRequestSchema,
9
+ EmbeddingBatchJobRequestSchema,
10
+ EmbeddingBatchJobResponseSchema,
11
+ EmbeddingBatchPrepareRequestSchema,
12
+ EmbeddingBatchPrepareResponseSchema,
13
+ EmbeddingBatchProviderStateSchema,
14
+ EmbeddingBatchRenditionPageRequestSchema,
15
+ EmbeddingBatchRenditionPageResponseSchema,
16
+ EmbeddingBatchRunStateSchema,
17
+ EmbeddingBatchRunSummarySchema,
18
+ EmbeddingBatchSubjobSchema,
19
+ EmbeddingBatchUpdateRequestSchema,
4
20
  EmbeddingsApiAudioInputSchema,
5
21
  EmbeddingsApiImageInputSchema,
6
22
  EmbeddingsApiInputSchema,
@@ -8,6 +24,7 @@ import type {
8
24
  EmbeddingsApiSourceSchema,
9
25
  EmbeddingsApiTextInputSchema,
10
26
  EmbeddingsApiVideoInputSchema,
27
+ RecalculateEmbeddingsQuerySchema,
11
28
  } from './api-schemas/embeddings.js';
12
29
 
13
30
  /**
@@ -36,3 +53,20 @@ export type EmbeddingsApiRequest = z.infer<typeof EmbeddingsApiRequestSchema>;
36
53
  * that prefer to consume types from @vertesia/common.
37
54
  */
38
55
  export type EmbeddingsApiResult = EmbeddingsResult;
56
+ export type RecalculateEmbeddingsQuery = z.infer<typeof RecalculateEmbeddingsQuerySchema>;
57
+ export type EmbeddingBatchCapabilityRequest = z.infer<typeof EmbeddingBatchCapabilityRequestSchema>;
58
+ export type EmbeddingBatchCapabilityResponse = z.infer<typeof EmbeddingBatchCapabilityResponseSchema>;
59
+ export type EmbeddingBatchCreateRequest = z.infer<typeof EmbeddingBatchCreateRequestSchema>;
60
+ export type EmbeddingBatchJobRequest = z.infer<typeof EmbeddingBatchJobRequestSchema>;
61
+ export type EmbeddingBatchJobResponse = z.infer<typeof EmbeddingBatchJobResponseSchema>;
62
+ export type EmbeddingBatchProviderState = z.infer<typeof EmbeddingBatchProviderStateSchema>;
63
+ export type EmbeddingBatchRunState = z.infer<typeof EmbeddingBatchRunStateSchema>;
64
+ export type EmbeddingBatchRunSummary = z.infer<typeof EmbeddingBatchRunSummarySchema>;
65
+ export type EmbeddingBatchSubjob = z.infer<typeof EmbeddingBatchSubjobSchema>;
66
+ export type EmbeddingBatchPrepareRequest = z.infer<typeof EmbeddingBatchPrepareRequestSchema>;
67
+ export type EmbeddingBatchPrepareResponse = z.infer<typeof EmbeddingBatchPrepareResponseSchema>;
68
+ export type EmbeddingBatchRenditionPageRequest = z.infer<typeof EmbeddingBatchRenditionPageRequestSchema>;
69
+ export type EmbeddingBatchRenditionPageResponse = z.infer<typeof EmbeddingBatchRenditionPageResponseSchema>;
70
+ export type EmbeddingBatchUpdateRequest = z.infer<typeof EmbeddingBatchUpdateRequestSchema>;
71
+ export type EmbeddingBatchApplyRequest = z.infer<typeof EmbeddingBatchApplyRequestSchema>;
72
+ export type EmbeddingBatchApplyResponse = z.infer<typeof EmbeddingBatchApplyResponseSchema>;
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@ export * from './analytics.js';
8
8
  */
9
9
  export type { UserGroupArrayFromSchema } from './api-schemas/group.js';
10
10
  export type {
11
- PrincipalContextFromSchema,
11
+ AbacPrincipalContextFromSchema,
12
12
  UserArrayFromSchema,
13
13
  UserRefArrayFromSchema,
14
14
  } from './api-schemas/user.js';
@@ -51,6 +51,7 @@ export * from './schema-for-extraction.js';
51
51
  export * from './secrets.js';
52
52
  export * from './skill.js';
53
53
  export * from './store/index.js';
54
+ export * from './store/rendering.js';
54
55
  export type {
55
56
  ContentObjectExportArtifact,
56
57
  ContentObjectExportArtifactFile,
@@ -61,6 +61,7 @@ import type {
61
61
  ResolvedEnvironmentInfoSchema,
62
62
  ResolvedInteractionExecutionInfoSchema,
63
63
  ResolvedRuntimeConfigSchema,
64
+ ResolveInteractionQuerySchema,
64
65
  ResultStorageOptionsSchema,
65
66
  RunSourceSchema,
66
67
  SchemaRefSchema,
@@ -121,12 +122,7 @@ export interface ExecuteInteractionByEndpointHeaders {
121
122
  'x-interaction-tag'?: string;
122
123
  }
123
124
 
124
- export interface ResolveInteractionQuery {
125
- environment?: string;
126
- model?: string;
127
- hasImage?: boolean;
128
- hasVideo?: boolean;
129
- }
125
+ export type ResolveInteractionQuery = z.infer<typeof ResolveInteractionQuerySchema>;
130
126
 
131
127
  export type InCodePrompt = z.infer<typeof InCodePromptSchema>;
132
128
  export type InCodeInteraction = z.infer<typeof InCodeInteractionSchema>;
@@ -1,23 +1,33 @@
1
1
  import type { z } from 'zod';
2
- import type { PrincipalContextFromSchema, PrincipalIdentitySchema } from './api-schemas/user.js';
2
+ import type { AbacPrincipalContextFromSchema, PrincipalIdentitySchema } from './api-schemas/user.js';
3
3
 
4
4
  /**
5
- * Resolved per-user context consumed by PrincipalSet condition evaluation
6
- * (`matchConditions` / `resolveConditions`) and by ABAC client-side tooling.
5
+ * The resolved principal context matched by ResourceSet/PrincipalSet condition evaluation
6
+ * (`resolveConditions` / `matchConditions`) and offered by the UI condition editor. Every field is
7
+ * referenceable in a rule as `$principal.<field>`: the principal `kind`, its `id`, and the merged
8
+ * BLP attributes (clearance, compartments, email, tags, properties).
7
9
  *
8
- * Mirrors what the token server builds for `$principal.*` resolution at JWT
9
- * issue time, with the same defaults (clearance = 0, compartments = [],
10
- * tags = [], properties = {}). Lives in @vertesia/common so both server-side
11
- * builders and client-side consumers share the exact same shape.
10
+ * This is the single shape the token server writes into the JWT for `$principal.*` resolution at
11
+ * issue time, and the shared `buildPrincipalContext` in @vertesia/studio-utils produces — with the
12
+ * defaults that keep condition operators well-defined for absent values (clearance = 0,
13
+ * compartments = [], tags = [], properties = {}, id = '', email = '').
12
14
  *
13
- * Derived from `PrincipalContextSchema`, which is composed into `PrincipalIdentitySchema` rather
14
- * than published as a component of its own — the document has never carried a `PrincipalContext`
15
+ * Derived from `AbacPrincipalContextSchema`, which is composed into `PrincipalIdentitySchema` rather
16
+ * than published as a component of its own — the document has never carried an `AbacPrincipalContext`
15
17
  * schema, and inventing one would add a `$ref` to every generated client.
16
18
  */
17
- export type PrincipalContext = PrincipalContextFromSchema;
19
+ export type AbacPrincipalContext = AbacPrincipalContextFromSchema;
18
20
 
19
21
  /**
20
- * Response shape of the `/iam/users/identity` endpoint. Derived from `PrincipalIdentitySchema`,
21
- * where its published description lives — Zod reads `.meta()`, not TSDoc.
22
+ * The principal subject kind. A resolvable field of {@link AbacPrincipalContext}, so rules may match
23
+ * on `$principal.kind`.
24
+ */
25
+ export type PrincipalKind = AbacPrincipalContext['kind'];
26
+
27
+ /**
28
+ * Response shape of the `/iam/users/identity` endpoint. Extends {@link AbacPrincipalContext} with
29
+ * identity-only fields (none today) — the invariant is that the ABAC context is always a subset of
30
+ * the identity, so a field added here never widens the `$principal.*` surface. Derived from
31
+ * `PrincipalIdentitySchema`, where its published description lives — Zod reads `.meta()`, not TSDoc.
22
32
  */
23
33
  export type PrincipalIdentity = z.infer<typeof PrincipalIdentitySchema>;
@@ -24,6 +24,7 @@ export enum ResourceVisibility {
24
24
  export enum SystemRoles {
25
25
  owner = 'owner', // all permissions
26
26
  admin = 'admin', // all permissions
27
+ app_admin = 'app_admin', // all permissions but studio:access — admin driving a custom admin UI
27
28
  manager = 'manager', // all permissions but manage_account, manage_billing
28
29
  developer = 'developer', // all permissions but manage_account, manage_billing, manage_roles, delete
29
30
  application = 'application', // executor + request_pk