@vertesia/common 1.6.0-dev.20260918.115658Z → 1.6.0-dev.20260923.085325Z

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 (107) hide show
  1. package/lib/api-contract/components.generated.json +3085 -2649
  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 +930 -300
  7. package/lib/api-schemas/agent-runs.d.ts.map +1 -1
  8. package/lib/api-schemas/app-lifecycle.d.ts +4 -0
  9. package/lib/api-schemas/app-lifecycle.d.ts.map +1 -1
  10. package/lib/api-schemas/app-lifecycle.js +10 -0
  11. package/lib/api-schemas/app-lifecycle.js.map +1 -1
  12. package/lib/api-schemas/app-runtime.d.ts +1342 -420
  13. package/lib/api-schemas/app-runtime.d.ts.map +1 -1
  14. package/lib/api-schemas/app-runtime.js +14 -0
  15. package/lib/api-schemas/app-runtime.js.map +1 -1
  16. package/lib/api-schemas/content.d.ts +465 -150
  17. package/lib/api-schemas/content.d.ts.map +1 -1
  18. package/lib/api-schemas/document-processing.d.ts +279 -90
  19. package/lib/api-schemas/document-processing.d.ts.map +1 -1
  20. package/lib/api-schemas/environment.d.ts +2 -2
  21. package/lib/api-schemas/events.d.ts +837 -270
  22. package/lib/api-schemas/events.d.ts.map +1 -1
  23. package/lib/api-schemas/interaction.d.ts +4260 -1290
  24. package/lib/api-schemas/interaction.d.ts.map +1 -1
  25. package/lib/api-schemas/interaction.js +1 -0
  26. package/lib/api-schemas/interaction.js.map +1 -1
  27. package/lib/api-schemas/oauth-server.d.ts +27 -0
  28. package/lib/api-schemas/oauth-server.d.ts.map +1 -1
  29. package/lib/api-schemas/oauth-server.js +32 -0
  30. package/lib/api-schemas/oauth-server.js.map +1 -1
  31. package/lib/api-schemas/process.d.ts +186 -60
  32. package/lib/api-schemas/process.d.ts.map +1 -1
  33. package/lib/api-schemas/project-configuration.d.ts +937 -300
  34. package/lib/api-schemas/project-configuration.d.ts.map +1 -1
  35. package/lib/api-schemas/project-configuration.js +6 -0
  36. package/lib/api-schemas/project-configuration.js.map +1 -1
  37. package/lib/api-schemas/project.d.ts +1416 -450
  38. package/lib/api-schemas/project.d.ts.map +1 -1
  39. package/lib/api-schemas/prompt.d.ts +1 -0
  40. package/lib/api-schemas/prompt.d.ts.map +1 -1
  41. package/lib/api-schemas/prompt.js +1 -0
  42. package/lib/api-schemas/prompt.js.map +1 -1
  43. package/lib/api-schemas/registry.d.ts +12043 -30352
  44. package/lib/api-schemas/registry.d.ts.map +1 -1
  45. package/lib/api-schemas/registry.js +42 -33
  46. package/lib/api-schemas/registry.js.map +1 -1
  47. package/lib/api-schemas/store.d.ts +4650 -1500
  48. package/lib/api-schemas/store.d.ts.map +1 -1
  49. package/lib/api-schemas/sts.d.ts +10 -0
  50. package/lib/api-schemas/sts.d.ts.map +1 -1
  51. package/lib/api-schemas/sts.js +14 -0
  52. package/lib/api-schemas/sts.js.map +1 -1
  53. package/lib/api-schemas/user.d.ts +28 -12
  54. package/lib/api-schemas/user.d.ts.map +1 -1
  55. package/lib/api-schemas/user.js +23 -17
  56. package/lib/api-schemas/user.js.map +1 -1
  57. package/lib/api-schemas/workflow-runs.d.ts +186 -60
  58. package/lib/api-schemas/workflow-runs.d.ts.map +1 -1
  59. package/lib/apps.d.ts +2 -1
  60. package/lib/apps.d.ts.map +1 -1
  61. package/lib/apps.js.map +1 -1
  62. package/lib/index.d.ts +2 -2
  63. package/lib/index.d.ts.map +1 -1
  64. package/lib/index.js.map +1 -1
  65. package/lib/oauth-server.d.ts +5 -1
  66. package/lib/oauth-server.d.ts.map +1 -1
  67. package/lib/principal-context.d.ts +21 -12
  68. package/lib/principal-context.d.ts.map +1 -1
  69. package/lib/project.d.ts.map +1 -1
  70. package/lib/project.js +10 -0
  71. package/lib/project.js.map +1 -1
  72. package/lib/store/intake-policy-schema.generated.d.ts.map +1 -1
  73. package/lib/store/intake-policy-schema.generated.js +166 -32
  74. package/lib/store/intake-policy-schema.generated.js.map +1 -1
  75. package/lib/sts-token-types.d.ts +3 -1
  76. package/lib/sts-token-types.d.ts.map +1 -1
  77. package/lib/user.d.ts +2 -1
  78. package/lib/user.d.ts.map +1 -1
  79. package/lib/user.js.map +1 -1
  80. package/lib/vertesia-common.js +2 -2
  81. package/lib/vertesia-common.js.map +1 -1
  82. package/package.json +6 -6
  83. package/src/api-contract/components.generated.json +3085 -2649
  84. package/src/api-schemas/account.ts +8 -0
  85. package/src/api-schemas/app-lifecycle.ts +11 -0
  86. package/src/api-schemas/app-runtime.ts +15 -0
  87. package/src/api-schemas/interaction.ts +1 -0
  88. package/src/api-schemas/llumiverse.contract.test.ts +70 -40
  89. package/src/api-schemas/oauth-server.ts +36 -0
  90. package/src/api-schemas/project-configuration.ts +6 -0
  91. package/src/api-schemas/project.contract.test.ts +15 -0
  92. package/src/api-schemas/prompt.ts +1 -0
  93. package/src/api-schemas/registry-groups.test.ts +9 -1
  94. package/src/api-schemas/registry.ts +100 -32
  95. package/src/api-schemas/store.contract.test.ts +6 -6
  96. package/src/api-schemas/sts.ts +16 -0
  97. package/src/api-schemas/user.contract.test.ts +24 -18
  98. package/src/api-schemas/user.ts +24 -18
  99. package/src/api-schemas/views.contract.test.ts +3 -10
  100. package/src/apps.ts +3 -0
  101. package/src/index.ts +9 -2
  102. package/src/oauth-server.ts +11 -0
  103. package/src/principal-context.ts +22 -12
  104. package/src/project.ts +10 -0
  105. package/src/store/intake-policy-schema.generated.ts +166 -32
  106. package/src/sts-token-types.ts +5 -0
  107. package/src/user.ts +8 -1
@@ -124,3 +124,19 @@ export const IssueTokenForbiddenResponseSchema = z
124
124
  export const IssueTokenUnavailableResponseSchema = z
125
125
  .strictObject({ error: z.string(), message: z.string() })
126
126
  .meta({ id: 'IssueTokenUnavailableResponse' });
127
+
128
+ export const AppSessionTokenRequestSchema = z
129
+ .strictObject({
130
+ app_name: z.string().min(1),
131
+ scopes: z.array(z.string()).optional(),
132
+ ttl_seconds: z.number().int().min(1).max(900).optional(),
133
+ })
134
+ .meta({ id: 'AppSessionTokenRequest' });
135
+
136
+ export const AppSessionTokenResponseSchema = z
137
+ .strictObject({
138
+ token: z.string(),
139
+ token_type: z.literal('Bearer'),
140
+ expires_in: z.number().int(),
141
+ })
142
+ .meta({ id: 'AppSessionTokenResponse' });
@@ -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
@@ -51,6 +51,7 @@ import type {
51
51
  StartAppDevelopmentTaskRequestSchema,
52
52
  StartAppScaffoldRequestSchema,
53
53
  StartAppScaffoldResponseSchema,
54
+ UpdateAppInstallationOAuthApprovalPayloadSchema,
54
55
  UpdateAppInstallationToolAllowlistPayloadSchema,
55
56
  UpsertAppVersionRequestSchema,
56
57
  ValidateUrlRequestSchema,
@@ -752,3 +753,5 @@ export type ValidateUrlResponse = z.infer<typeof ValidateUrlResponseSchema>;
752
753
  * already deleted. Deriving the type is what keeps the two from drifting again.
753
754
  */
754
755
  export type AppDeleteSummary = z.infer<typeof AppDeleteSummarySchema>;
756
+
757
+ export type UpdateAppInstallationOAuthApprovalPayload = z.infer<typeof UpdateAppInstallationOAuthApprovalPayloadSchema>;
package/src/index.ts CHANGED
@@ -1,4 +1,11 @@
1
- export type { VertexAIGeminiOmniVideoOptions, VideoResult } from '@llumiverse/common';
1
+ export type {
2
+ AudioResult,
3
+ OpenAiAudioOptions,
4
+ OpenAiSpeechOptions,
5
+ OpenAiTranscriptionOptions,
6
+ VertexAIGeminiOmniVideoOptions,
7
+ VideoResult,
8
+ } from '@llumiverse/common';
2
9
  export * from './access-control.js';
3
10
  export * from './analytics.js';
4
11
  /**
@@ -8,7 +15,7 @@ export * from './analytics.js';
8
15
  */
9
16
  export type { UserGroupArrayFromSchema } from './api-schemas/group.js';
10
17
  export type {
11
- PrincipalContextFromSchema,
18
+ AbacPrincipalContextFromSchema,
12
19
  UserArrayFromSchema,
13
20
  UserRefArrayFromSchema,
14
21
  } from './api-schemas/user.js';
@@ -6,6 +6,7 @@ import type {
6
6
  CreateOAuthClientPayloadSchema,
7
7
  ListOAuthGrantsQuerySchema,
8
8
  OAuthAuthorizationDecisionResponseSchema,
9
+ OAuthAuthorizationRequestGeneratedAppSchema,
9
10
  OAuthAuthorizationRequestSchema,
10
11
  OAuthAuthorizationRequestStatusSchema,
11
12
  OAuthAuthorizationServerMetadataSchema,
@@ -28,6 +29,9 @@ import type {
28
29
  OAuthGrantSortOrderSchema,
29
30
  OAuthGrantStatusSchema,
30
31
  OAuthGrantTypeSchema,
32
+ OAuthLoginDecisionResponseSchema,
33
+ OAuthLoginPayloadSchema,
34
+ OAuthLoginUserNotFoundResponseSchema,
31
35
  OAuthProjectBindingModeSchema,
32
36
  OAuthRegistrationSourceSchema,
33
37
  OAuthResponseTypeSchema,
@@ -92,3 +96,10 @@ export type OAuthAuthorizationDecisionResponse = z.infer<typeof OAuthAuthorizati
92
96
  export type OAuthDeviceAuthorizationRequest = z.infer<typeof OAuthDeviceAuthorizationRequestSchema>;
93
97
  export type OAuthDeviceAuthorizationResponse = z.infer<typeof OAuthDeviceAuthorizationResponseSchema>;
94
98
  export type OAuthTokenResponse = z.infer<typeof OAuthTokenResponseSchema>;
99
+
100
+ export type OAuthAuthorizationRequestGeneratedApp = z.infer<typeof OAuthAuthorizationRequestGeneratedAppSchema>;
101
+
102
+ export type OAuthLoginPayload = z.infer<typeof OAuthLoginPayloadSchema>;
103
+ export type OAuthLoginDecisionResponse = z.infer<typeof OAuthLoginDecisionResponseSchema>;
104
+
105
+ export type OAuthLoginUserNotFoundResponse = z.infer<typeof OAuthLoginUserNotFoundResponseSchema>;
@@ -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>;
package/src/project.ts CHANGED
@@ -118,6 +118,16 @@ export const SYSTEM_INTERACTION_CATEGORIES: Record<string, SystemInteractionCate
118
118
  ContentSearchAgent: SystemInteractionCategory.analysis,
119
119
  ContentSearchReranker: SystemInteractionCategory.analysis,
120
120
  StudioAssistant: SystemInteractionCategory.agent,
121
+ // App development runs as an orchestrator plus five specialist sub-agents. Categorising them
122
+ // lets `defaults.system.agent` apply: an in-code sub-agent is launched without an environment
123
+ // or model of its own, so without a category it resolves to the project BASE default rather
124
+ // than the agent default, and a task started on a chosen model ran its sub-agents on another.
125
+ AppDevelopmentOrchestrator: SystemInteractionCategory.agent,
126
+ AppSolutionArchitect: SystemInteractionCategory.agent,
127
+ AppDesigner: SystemInteractionCategory.agent,
128
+ AppDeveloper: SystemInteractionCategory.agent,
129
+ AppReviewer: SystemInteractionCategory.agent,
130
+ AppTester: SystemInteractionCategory.agent,
121
131
  };
122
132
 
123
133
  /**