@xemahq/kernel-contracts 0.50.0 → 0.57.0
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/dist/biome/lib/biome-manifest.d.ts +9 -0
- package/dist/biome/lib/biome-manifest.d.ts.map +1 -1
- package/dist/biome/lib/biome-manifest.js +2 -0
- package/dist/biome/lib/biome-manifest.js.map +1 -1
- package/dist/capability/index.d.ts +3 -1
- package/dist/capability/index.d.ts.map +1 -1
- package/dist/capability/index.js +3 -1
- package/dist/capability/index.js.map +1 -1
- package/dist/capability/lib/authority-effect.d.ts +8 -0
- package/dist/capability/lib/authority-effect.d.ts.map +1 -0
- package/dist/capability/lib/authority-effect.js +17 -0
- package/dist/capability/lib/authority-effect.js.map +1 -0
- package/dist/capability/lib/capability-contribution.d.ts +4 -0
- package/dist/capability/lib/capability-contribution.d.ts.map +1 -1
- package/dist/capability/lib/capability-contribution.js +4 -0
- package/dist/capability/lib/capability-contribution.js.map +1 -1
- package/dist/capability/lib/capability-domain.d.ts +8 -0
- package/dist/capability/lib/capability-domain.d.ts.map +1 -0
- package/dist/capability/lib/capability-domain.js +24 -0
- package/dist/capability/lib/capability-domain.js.map +1 -0
- package/dist/capability/lib/capability-reach.d.ts +13 -0
- package/dist/capability/lib/capability-reach.d.ts.map +1 -0
- package/dist/capability/lib/capability-reach.js +34 -0
- package/dist/capability/lib/capability-reach.js.map +1 -0
- package/dist/capability/lib/meta-tool.d.ts +51 -14
- package/dist/capability/lib/meta-tool.d.ts.map +1 -1
- package/dist/capability/lib/meta-tool.js +66 -12
- package/dist/capability/lib/meta-tool.js.map +1 -1
- package/dist/capability-projection/index.d.ts +4 -0
- package/dist/capability-projection/index.d.ts.map +1 -0
- package/dist/capability-projection/index.js +20 -0
- package/dist/capability-projection/index.js.map +1 -0
- package/dist/capability-projection/lib/capability-invocation-binding.d.ts +72 -0
- package/dist/capability-projection/lib/capability-invocation-binding.d.ts.map +1 -0
- package/dist/capability-projection/lib/capability-invocation-binding.js +101 -0
- package/dist/capability-projection/lib/capability-invocation-binding.js.map +1 -0
- package/dist/capability-projection/lib/capability-sync-manifest.d.ts +8 -0
- package/dist/capability-projection/lib/capability-sync-manifest.d.ts.map +1 -0
- package/dist/capability-projection/lib/capability-sync-manifest.js +8 -0
- package/dist/capability-projection/lib/capability-sync-manifest.js.map +1 -0
- package/dist/capability-projection/lib/projected-capability.d.ts +15 -0
- package/dist/capability-projection/lib/projected-capability.d.ts.map +1 -0
- package/dist/capability-projection/lib/projected-capability.js +17 -0
- package/dist/capability-projection/lib/projected-capability.js.map +1 -0
- package/dist/connector/lib/connector-adapter-contribution.d.ts +2 -0
- package/dist/connector/lib/connector-adapter-contribution.d.ts.map +1 -1
- package/dist/connector/lib/onboarding-manifest.d.ts +2 -0
- package/dist/connector/lib/onboarding-manifest.d.ts.map +1 -1
- package/dist/connector/lib/onboarding-manifest.js +1 -0
- package/dist/connector/lib/onboarding-manifest.js.map +1 -1
- package/dist/connector/lib/provider-descriptor.d.ts +2 -0
- package/dist/connector/lib/provider-descriptor.d.ts.map +1 -1
- package/dist/contribution/lib/contribution-kind.d.ts +1 -6
- package/dist/contribution/lib/contribution-kind.d.ts.map +1 -1
- package/dist/contribution/lib/contribution-kind.js +1 -6
- package/dist/contribution/lib/contribution-kind.js.map +1 -1
- package/dist/distribution/index.d.ts +1 -0
- package/dist/distribution/index.d.ts.map +1 -1
- package/dist/distribution/index.js +1 -0
- package/dist/distribution/index.js.map +1 -1
- package/dist/distribution/lib/distribution-lock.d.ts +6 -0
- package/dist/distribution/lib/distribution-lock.d.ts.map +1 -1
- package/dist/distribution/lib/distribution-lock.js +9 -1
- package/dist/distribution/lib/distribution-lock.js.map +1 -1
- package/dist/distribution/lib/first-party-capability-domains.d.ts +15 -0
- package/dist/distribution/lib/first-party-capability-domains.d.ts.map +1 -0
- package/dist/distribution/lib/first-party-capability-domains.js +52 -0
- package/dist/distribution/lib/first-party-capability-domains.js.map +1 -0
- package/dist/object/lib/xema-object-ref.d.ts +0 -5
- package/dist/object/lib/xema-object-ref.d.ts.map +1 -1
- package/dist/object/lib/xema-object-ref.js +12 -62
- package/dist/object/lib/xema-object-ref.js.map +1 -1
- package/dist/output-surface-inspect/index.d.ts +1 -0
- package/dist/output-surface-inspect/index.d.ts.map +1 -1
- package/dist/output-surface-inspect/index.js +1 -0
- package/dist/output-surface-inspect/index.js.map +1 -1
- package/dist/output-surface-inspect/lib/buffers.d.ts +52 -0
- package/dist/output-surface-inspect/lib/buffers.d.ts.map +1 -0
- package/dist/output-surface-inspect/lib/buffers.js +132 -0
- package/dist/output-surface-inspect/lib/buffers.js.map +1 -0
- package/dist/output-surface-inspect/lib/output-surface-inspect.d.ts +6 -1
- package/dist/output-surface-inspect/lib/output-surface-inspect.d.ts.map +1 -1
- package/dist/output-surface-inspect/lib/output-surface-inspect.js +12 -1
- package/dist/output-surface-inspect/lib/output-surface-inspect.js.map +1 -1
- package/dist/output-surface-inspect/lib/step-schema.d.ts +2 -1
- package/dist/output-surface-inspect/lib/step-schema.d.ts.map +1 -1
- package/dist/output-surface-inspect/lib/step-schema.js +9 -2
- package/dist/output-surface-inspect/lib/step-schema.js.map +1 -1
- package/dist/output-surface-inspect/runtime/index.d.ts +1 -0
- package/dist/output-surface-inspect/runtime/index.d.ts.map +1 -1
- package/dist/output-surface-inspect/runtime/index.js +1 -0
- package/dist/output-surface-inspect/runtime/index.js.map +1 -1
- package/dist/search/index.d.ts +1 -0
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -0
- package/dist/search/index.js.map +1 -1
- package/dist/search/lib/route-template.d.ts +31 -0
- package/dist/search/lib/route-template.d.ts.map +1 -0
- package/dist/search/lib/route-template.js +142 -0
- package/dist/search/lib/route-template.js.map +1 -0
- package/dist/search/lib/search-contribution.d.ts +4 -2
- package/dist/search/lib/search-contribution.d.ts.map +1 -1
- package/dist/search/lib/search-contribution.js +46 -4
- package/dist/search/lib/search-contribution.js.map +1 -1
- package/dist/search-source/lib/indexable-document.d.ts +22 -0
- package/dist/search-source/lib/indexable-document.d.ts.map +1 -1
- package/dist/search-source/lib/indexable-document.js +10 -1
- package/dist/search-source/lib/indexable-document.js.map +1 -1
- package/dist/search-source/lib/search-index-event.d.ts +10 -0
- package/dist/search-source/lib/search-index-event.d.ts.map +1 -1
- package/dist/search-source/lib/search-ref.d.ts.map +1 -1
- package/dist/search-source/lib/search-ref.js +11 -2
- package/dist/search-source/lib/search-ref.js.map +1 -1
- package/dist/search-source/lib/search-replay.d.ts +10 -0
- package/dist/search-source/lib/search-replay.d.ts.map +1 -1
- package/dist/service-registry/lib/service-descriptor.d.ts +1 -0
- package/dist/service-registry/lib/service-descriptor.d.ts.map +1 -1
- package/dist/space/lib/space-ref-parser.d.ts +6 -4
- package/dist/space/lib/space-ref-parser.d.ts.map +1 -1
- package/dist/space/lib/space-ref-parser.js +90 -126
- package/dist/space/lib/space-ref-parser.js.map +1 -1
- package/dist/space/lib/space-traversal.d.ts.map +1 -1
- package/dist/space/lib/space-traversal.js +9 -13
- package/dist/space/lib/space-traversal.js.map +1 -1
- package/dist/space/lib/space.d.ts +7 -0
- package/dist/space/lib/space.d.ts.map +1 -1
- package/dist/space/lib/space.js +48 -29
- package/dist/space/lib/space.js.map +1 -1
- package/dist/subject/lib/subject.d.ts +1 -0
- package/dist/subject/lib/subject.d.ts.map +1 -1
- package/dist/subject/lib/subject.js +1 -0
- package/dist/subject/lib/subject.js.map +1 -1
- package/dist/surface/index.d.ts +4 -0
- package/dist/surface/index.d.ts.map +1 -0
- package/dist/surface/index.js +20 -0
- package/dist/surface/index.js.map +1 -0
- package/dist/surface/lib/surface-contribution.d.ts +24 -0
- package/dist/surface/lib/surface-contribution.d.ts.map +1 -0
- package/dist/surface/lib/surface-contribution.js +23 -0
- package/dist/surface/lib/surface-contribution.js.map +1 -0
- package/dist/surface/lib/surface-kind.d.ts +23 -0
- package/dist/surface/lib/surface-kind.d.ts.map +1 -0
- package/dist/surface/lib/surface-kind.js +27 -0
- package/dist/surface/lib/surface-kind.js.map +1 -0
- package/dist/surface/lib/vista-surface.d.ts +11 -0
- package/dist/surface/lib/vista-surface.d.ts.map +1 -0
- package/dist/surface/lib/vista-surface.js +13 -0
- package/dist/surface/lib/vista-surface.js.map +1 -0
- package/dist/widget/lib/chat-widget-envelope.d.ts.map +1 -1
- package/dist/widget/lib/chat-widget-envelope.js.map +1 -1
- package/dist/workflow/lib/enums.d.ts.map +1 -1
- package/dist/workflow/lib/enums.js.map +1 -1
- package/package.json +1 -1
- package/src/biome/lib/biome-manifest.ts +41 -1
- package/src/capability/index.ts +3 -1
- package/src/capability/lib/authority-effect.ts +88 -0
- package/src/capability/lib/capability-contribution.ts +44 -0
- package/src/capability/lib/capability-domain.ts +51 -0
- package/src/capability/lib/capability-grant.ts +1 -1
- package/src/capability/lib/capability-reach.ts +119 -0
- package/src/capability/lib/meta-tool.ts +172 -39
- package/src/capability-projection/index.ts +3 -0
- package/src/capability-projection/lib/capability-invocation-binding.ts +223 -0
- package/src/capability-projection/lib/capability-sync-manifest.ts +52 -0
- package/src/capability-projection/lib/projected-capability.ts +63 -0
- package/src/connector/lib/onboarding-manifest.ts +16 -0
- package/src/contribution/lib/contribution-kind.ts +165 -61
- package/src/distribution/index.ts +1 -0
- package/src/distribution/lib/distribution-lock.ts +36 -0
- package/src/distribution/lib/first-party-capability-domains.ts +166 -0
- package/src/object/lib/xema-object-ref.ts +27 -82
- package/src/output-surface-inspect/index.ts +2 -0
- package/src/output-surface-inspect/lib/buffers.ts +252 -0
- package/src/output-surface-inspect/lib/output-surface-inspect.ts +65 -6
- package/src/output-surface-inspect/lib/step-schema.ts +36 -3
- package/src/output-surface-inspect/runtime/index.ts +1 -0
- package/src/search/index.ts +1 -0
- package/src/search/lib/route-template.ts +381 -0
- package/src/search/lib/search-contribution.ts +138 -31
- package/src/search-source/lib/indexable-document.ts +44 -0
- package/src/search-source/lib/search-ref.ts +22 -9
- package/src/service-registry/lib/service-descriptor.ts +16 -0
- package/src/space/lib/skill-mirror-path.ts +1 -1
- package/src/space/lib/space-ref-parser.ts +190 -165
- package/src/space/lib/space-traversal.ts +34 -17
- package/src/space/lib/space.ts +110 -35
- package/src/subject/lib/subject.ts +16 -0
- package/src/surface/index.ts +3 -0
- package/src/surface/lib/surface-contribution.ts +101 -0
- package/src/surface/lib/surface-kind.ts +65 -0
- package/src/surface/lib/vista-surface.ts +44 -0
- package/src/widget/lib/chat-widget-envelope.ts +6 -2
- package/src/workflow/lib/enums.ts +6 -7
- package/src/capability/lib/first-party-capability-domains.ts +0 -77
package/src/space/lib/space.ts
CHANGED
|
@@ -148,48 +148,123 @@ const REQUIRED_SEGMENTS: Readonly<Record<SpaceKind, readonly SegmentKey[]>> = {
|
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
151
|
+
* Structured, fail-fast error raised by every Space-ref grammar operation
|
|
152
|
+
* ({@link spaceRefToPath}, `parseSpaceRef`, `formatSpaceRef`). Carries a
|
|
153
|
+
* stable `code` so services can map it to a typed 400 without string-matching
|
|
154
|
+
* the message.
|
|
155
|
+
*/
|
|
156
|
+
export class SpaceRefParseError extends Error {
|
|
157
|
+
public readonly code = 'SPACE_REF_INVALID';
|
|
158
|
+
public readonly raw: string;
|
|
159
|
+
|
|
160
|
+
public constructor(message: string, raw: string) {
|
|
161
|
+
super(message);
|
|
162
|
+
this.name = 'SpaceRefParseError';
|
|
163
|
+
this.raw = raw;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* A single Space path segment id (an orgId, projectId, appId, sessionId,
|
|
169
|
+
* biomeId or userId). Deliberately value-identical to the `XemaObjectRef`
|
|
170
|
+
* slug-segment pattern so a Space path and an object ref agree on what a
|
|
171
|
+
* legal segment is: starts alphanumeric, then alphanumerics plus `_`, `.`,
|
|
172
|
+
* `-`. No `/`, no whitespace, no `@` — those are grammar separators and
|
|
173
|
+
* would make the ref ambiguous.
|
|
174
|
+
*/
|
|
175
|
+
export const SPACE_SEGMENT_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Fail-fast guard for a Space path segment id. Enforced by BOTH the renderer
|
|
179
|
+
* ({@link spaceRefToPath}) and the parser, which is what makes parse/format
|
|
180
|
+
* exact inverses: a ref that cannot be rendered can never be produced, and a
|
|
181
|
+
* string that cannot be parsed can never be rendered.
|
|
182
|
+
*/
|
|
183
|
+
export function assertValidSpaceSegmentId(
|
|
184
|
+
segment: keyof SpaceRef,
|
|
185
|
+
value: string,
|
|
186
|
+
raw: string,
|
|
187
|
+
): void {
|
|
188
|
+
if (!SPACE_SEGMENT_ID_PATTERN.test(value)) {
|
|
189
|
+
throw new SpaceRefParseError(
|
|
190
|
+
`Space segment "${String(segment)}" id "${value}" must match ${SPACE_SEGMENT_ID_PATTERN}.`,
|
|
191
|
+
raw,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function requireSpaceSegment(
|
|
197
|
+
ref: SpaceRef,
|
|
198
|
+
segment: SegmentKey,
|
|
199
|
+
raw: string,
|
|
200
|
+
): string {
|
|
201
|
+
const value = ref[segment];
|
|
202
|
+
if (value === undefined || value.length === 0) {
|
|
203
|
+
throw new SpaceRefParseError(
|
|
204
|
+
`SpaceKind.${ref.tier} requires "${segment}".`,
|
|
205
|
+
raw,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
assertValidSpaceSegmentId(segment, value, raw);
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Render a `SpaceRef` as its canonical XVFS path prefix. Returns a string
|
|
214
|
+
* that starts with `/`. Fails fast if a required segment is missing or its id
|
|
215
|
+
* violates {@link SPACE_SEGMENT_ID_PATTERN}.
|
|
216
|
+
*
|
|
217
|
+
* This is the SINGLE canonical Space grammar — the plural-head form shared by
|
|
218
|
+
* `XemaObjectRef`, search refs, the object-registry projection and (since the
|
|
219
|
+
* X9 convergence) `formatSpaceRef`/`parseSpaceRef`:
|
|
220
|
+
*
|
|
221
|
+
* ```
|
|
222
|
+
* /system
|
|
223
|
+
* /users/<userId>
|
|
224
|
+
* /biomes/<biomeId>
|
|
225
|
+
* /sessions/<sessionId>
|
|
226
|
+
* /orgs/<orgId>
|
|
227
|
+
* /orgs/<orgId>/projects/<projectId>
|
|
228
|
+
* /orgs/<orgId>/projects/<projectId>/apps/<appId>
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* `User`, `Biome` and `Session` are ROOT-addressable on purpose — that is
|
|
232
|
+
* exactly what {@link REQUIRED_SEGMENTS} already declares (they require only
|
|
233
|
+
* their own id), and it is what every real producer emits: a biome-contributed
|
|
234
|
+
* skill lives at `xema://biomes/<id>/skill/<slug>` and is org-less. A ref's
|
|
235
|
+
* ancestor segments are NOT part of its identity for those tiers.
|
|
154
236
|
*/
|
|
155
237
|
export function spaceRefToPath(ref: SpaceRef): string {
|
|
238
|
+
const raw = ref.path ?? `<SpaceKind.${ref.tier}>`;
|
|
156
239
|
switch (ref.tier) {
|
|
157
240
|
case SpaceKind.System:
|
|
158
241
|
return '/system';
|
|
159
242
|
case SpaceKind.Biome:
|
|
160
|
-
|
|
161
|
-
throw new Error('spaceRefToPath: SpaceKind.Biome requires biomeId');
|
|
162
|
-
}
|
|
163
|
-
return `/biomes/${ref.biomeId}`;
|
|
164
|
-
case SpaceKind.Org:
|
|
165
|
-
if (!ref.orgId) {
|
|
166
|
-
throw new Error('spaceRefToPath: SpaceKind.Org requires orgId');
|
|
167
|
-
}
|
|
168
|
-
return `/orgs/${ref.orgId}`;
|
|
169
|
-
case SpaceKind.Project:
|
|
170
|
-
if (!ref.orgId || !ref.projectId) {
|
|
171
|
-
throw new Error(
|
|
172
|
-
'spaceRefToPath: SpaceKind.Project requires orgId and projectId',
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
return `/orgs/${ref.orgId}/projects/${ref.projectId}`;
|
|
176
|
-
case SpaceKind.App:
|
|
177
|
-
if (!ref.orgId || !ref.projectId || !ref.appId) {
|
|
178
|
-
throw new Error(
|
|
179
|
-
'spaceRefToPath: SpaceKind.App requires orgId, projectId, and appId',
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
return `/orgs/${ref.orgId}/projects/${ref.projectId}/apps/${ref.appId}`;
|
|
183
|
-
case SpaceKind.Session:
|
|
184
|
-
if (!ref.sessionId) {
|
|
185
|
-
throw new Error('spaceRefToPath: SpaceKind.Session requires sessionId');
|
|
186
|
-
}
|
|
187
|
-
return `/sessions/${ref.sessionId}`;
|
|
243
|
+
return `/biomes/${requireSpaceSegment(ref, 'biomeId', raw)}`;
|
|
188
244
|
case SpaceKind.User:
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
245
|
+
return `/users/${requireSpaceSegment(ref, 'userId', raw)}`;
|
|
246
|
+
case SpaceKind.Session:
|
|
247
|
+
return `/sessions/${requireSpaceSegment(ref, 'sessionId', raw)}`;
|
|
248
|
+
case SpaceKind.Org:
|
|
249
|
+
return `/orgs/${requireSpaceSegment(ref, 'orgId', raw)}`;
|
|
250
|
+
case SpaceKind.Project: {
|
|
251
|
+
const orgId = requireSpaceSegment(ref, 'orgId', raw);
|
|
252
|
+
const projectId = requireSpaceSegment(ref, 'projectId', raw);
|
|
253
|
+
return `/orgs/${orgId}/projects/${projectId}`;
|
|
254
|
+
}
|
|
255
|
+
case SpaceKind.App: {
|
|
256
|
+
const orgId = requireSpaceSegment(ref, 'orgId', raw);
|
|
257
|
+
const projectId = requireSpaceSegment(ref, 'projectId', raw);
|
|
258
|
+
const appId = requireSpaceSegment(ref, 'appId', raw);
|
|
259
|
+
return `/orgs/${orgId}/projects/${projectId}/apps/${appId}`;
|
|
260
|
+
}
|
|
261
|
+
default: {
|
|
262
|
+
const exhaustive: never = ref.tier;
|
|
263
|
+
throw new SpaceRefParseError(
|
|
264
|
+
`spaceRefToPath: unhandled SpaceKind "${String(exhaustive)}".`,
|
|
265
|
+
raw,
|
|
266
|
+
);
|
|
267
|
+
}
|
|
193
268
|
}
|
|
194
269
|
}
|
|
195
270
|
|
|
@@ -45,11 +45,27 @@ export const SubjectKindSchema = z.nativeEnum(SubjectKind);
|
|
|
45
45
|
export interface ActingForRef {
|
|
46
46
|
kind: SubjectKind;
|
|
47
47
|
id: string;
|
|
48
|
+
/**
|
|
49
|
+
* The ISSUER-STAMPED OAuth client identity of this hop (`azp`, else
|
|
50
|
+
* `client_id`), when the issuer stamps it inside the hop's `act` object.
|
|
51
|
+
*
|
|
52
|
+
* `id` is the hop's `sub` — for a service-account token that is an opaque
|
|
53
|
+
* Keycloak UUID, which says nothing about WHICH service conveyed the call.
|
|
54
|
+
* The client id is the logical service name (`workflow-runtime-worker`,
|
|
55
|
+
* `agent-session-api`, …) that grants and audit trails are keyed by. It is
|
|
56
|
+
* never caller-supplied: an OAuth client cannot assert another client's id
|
|
57
|
+
* in a token the issuer signed.
|
|
58
|
+
*
|
|
59
|
+
* Absent when the issuer stamps neither claim on the hop — treat absence as
|
|
60
|
+
* "unknown", never as a match.
|
|
61
|
+
*/
|
|
62
|
+
clientId?: string;
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
export const ActingForRefSchema = z.object({
|
|
51
66
|
kind: SubjectKindSchema,
|
|
52
67
|
id: z.string().min(1),
|
|
68
|
+
clientId: z.string().min(1).optional(),
|
|
53
69
|
}) as z.ZodType<ActingForRef>;
|
|
54
70
|
|
|
55
71
|
/**
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manifest shape carried by every `ContributionKind.SurfaceKind` envelope.
|
|
5
|
+
*
|
|
6
|
+
* One contribution = one Vista surface kind. The shape is STRUCTURALLY
|
|
7
|
+
* IDENTICAL to `WidgetContributionManifest` (see
|
|
8
|
+
* `../../widget/lib/widget-contribution.ts`) — the two planes deliberately
|
|
9
|
+
* share one contribution pattern, so the generic
|
|
10
|
+
* `BootstrapContributionsService<TKind, TManifest>` template and the biome-host
|
|
11
|
+
* `KindParser` ingest a surface kind exactly the way a widget kind is ingested.
|
|
12
|
+
* Provenance (`biomeId`, `biomeVersion`) is stamped by the ingestion pipeline
|
|
13
|
+
* from the discovering biome's manifest — authors do NOT declare it inline.
|
|
14
|
+
*
|
|
15
|
+
* A biome contributes a surface kind so its frontend biome can register a
|
|
16
|
+
* renderer for it against the `<biomeId>:<kind>` slug. The `kind` here is the
|
|
17
|
+
* BARE, biome-local kind slug; the catalogue namespaces it at ingest so it can
|
|
18
|
+
* never shadow a first-party {@link SurfaceKind}.
|
|
19
|
+
*
|
|
20
|
+
* Validation is fail-fast: a contribution that violates any constraint is
|
|
21
|
+
* rejected at boot. `payloadSchema` is an opaque JSON Schema passed through
|
|
22
|
+
* verbatim (the catalogue surfaces it to the frontend — which derives the
|
|
23
|
+
* GENERIC schema-driven renderer from it — and to authoring tools; it is NOT a
|
|
24
|
+
* kernel-validated shape, because validating it as JSON Schema here would be
|
|
25
|
+
* either partial or pull in a JSON-Schema validator, violating the kernel-leaf
|
|
26
|
+
* invariant).
|
|
27
|
+
*
|
|
28
|
+
* Per the 2-file rule for a new `ContributionKind`, the kernel owns exactly
|
|
29
|
+
* this manifest schema plus the enum member; the per-kind ingestion PARSER
|
|
30
|
+
* lives in the consuming service (`biome-host-api`), not here.
|
|
31
|
+
*/
|
|
32
|
+
export interface SurfaceContributionManifest {
|
|
33
|
+
/**
|
|
34
|
+
* Biome-local kind slug (lowercase, hyphenated). Namespaced to
|
|
35
|
+
* `<biomeId>:<kind>` by the catalogue — a biome can never claim a bare
|
|
36
|
+
* first-party kind.
|
|
37
|
+
*/
|
|
38
|
+
readonly kind: string;
|
|
39
|
+
/** Monotonic schema version for this kind's payload. */
|
|
40
|
+
readonly version: number;
|
|
41
|
+
/** Human-readable display name surfaced in the catalogue (≤ 200 chars). */
|
|
42
|
+
readonly displayName: string;
|
|
43
|
+
/** One-line summary of WHAT the surface shows + WHEN to open it (≤ 1000 chars). */
|
|
44
|
+
readonly summary: string;
|
|
45
|
+
/** JSON Schema for the surface payload — passed through verbatim. */
|
|
46
|
+
readonly payloadSchema: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const SURFACE_KIND_SLUG_REGEX = /^[a-z][a-z0-9-]*$/;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Zod validator for {@link SurfaceContributionManifest}. The biome-host parser
|
|
53
|
+
* and the catalogue's register route BOTH route every candidate manifest
|
|
54
|
+
* through this before persisting, so a malformed contribution fails at the
|
|
55
|
+
* boundary instead of at render time.
|
|
56
|
+
*/
|
|
57
|
+
export const SurfaceContributionManifestSchema: z.ZodType<SurfaceContributionManifest> =
|
|
58
|
+
z.object({
|
|
59
|
+
kind: z
|
|
60
|
+
.string()
|
|
61
|
+
.min(1)
|
|
62
|
+
.max(100)
|
|
63
|
+
.regex(
|
|
64
|
+
SURFACE_KIND_SLUG_REGEX,
|
|
65
|
+
'Surface kind slug must be lowercase letters, digits, and hyphens (start with a letter).',
|
|
66
|
+
),
|
|
67
|
+
version: z.number().int().positive(),
|
|
68
|
+
displayName: z.string().min(1).max(200),
|
|
69
|
+
summary: z.string().min(1).max(1000),
|
|
70
|
+
payloadSchema: z.record(z.string(), z.unknown()),
|
|
71
|
+
}) as z.ZodType<SurfaceContributionManifest>;
|
|
72
|
+
|
|
73
|
+
/** Provenance of a surface-kind catalogue entry. Closed set. */
|
|
74
|
+
export enum SurfaceKindSource {
|
|
75
|
+
FirstParty = 'first-party',
|
|
76
|
+
Biome = 'biome',
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const SurfaceKindSourceSchema = z.nativeEnum(SurfaceKindSource);
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* A resolved surface-kind catalogue entry — what the surface-kind catalogue
|
|
83
|
+
* endpoint returns. It unifies the closed first-party set and the open
|
|
84
|
+
* biome-contributed set behind ONE shape the frontend consumes to know which
|
|
85
|
+
* kinds exist (and to register biome-contributed kinds into the open Vista
|
|
86
|
+
* registry with a generic schema-driven renderer).
|
|
87
|
+
*
|
|
88
|
+
* `source` discriminates provenance; `kind` is the FULLY-NAMESPACED slug the
|
|
89
|
+
* frontend registry keys by (a first-party kind is its bare enum value; a biome
|
|
90
|
+
* kind is `<biomeId>:<kind>`).
|
|
91
|
+
*/
|
|
92
|
+
export interface SurfaceKindCatalogueEntry {
|
|
93
|
+
readonly kind: string;
|
|
94
|
+
readonly version: number;
|
|
95
|
+
readonly displayName: string;
|
|
96
|
+
readonly summary: string;
|
|
97
|
+
readonly payloadSchema: Record<string, unknown>;
|
|
98
|
+
readonly source: SurfaceKindSource;
|
|
99
|
+
/** Present only for biome-contributed kinds. */
|
|
100
|
+
readonly biomeId?: string;
|
|
101
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `SurfaceKind` — the closed first-party set of render kinds a Vista tab can
|
|
5
|
+
* hold (Canopy Plane ④, "Vista: the render plane").
|
|
6
|
+
*
|
|
7
|
+
* Vista is the agent-driven, biome-extensible tabbed preview plane: the agent
|
|
8
|
+
* opens a tab by emitting a {@link VistaSurface} envelope, and the frontend
|
|
9
|
+
* resolves the envelope's `kind` to a renderer. Each first-party kind is a
|
|
10
|
+
* GENERIC, domain-agnostic presentation primitive — chosen to cover the
|
|
11
|
+
* broadest possible range of "thing the agent wants to show the user" without
|
|
12
|
+
* baking in any vertical semantics.
|
|
13
|
+
*
|
|
14
|
+
* ── Closed first-party set vs. open biome set ───────────────────────────────
|
|
15
|
+
* A biome contributes its OWN surface kind as a namespaced string
|
|
16
|
+
* (`<biomeId>:<kind>`) through a `ContributionKind.SurfaceKind` contribution —
|
|
17
|
+
* it never extends this enum. This is the same closed-enum + open-namespaced-
|
|
18
|
+
* string pattern as `ChatWidgetKind` (see `../../widget`): the frontend
|
|
19
|
+
* registry reserves every value below, so a biome can never shadow a
|
|
20
|
+
* first-party kind.
|
|
21
|
+
*
|
|
22
|
+
* Adding a first-party kind = one enum member here + a renderer registered
|
|
23
|
+
* into the frontend Vista registry's closed set.
|
|
24
|
+
*/
|
|
25
|
+
export enum SurfaceKind {
|
|
26
|
+
/** An external URL rendered in the preview chrome (address bar + frame). */
|
|
27
|
+
Url = 'url',
|
|
28
|
+
/** A first-party in-app web view (a host route rendered inside the tab). */
|
|
29
|
+
Web = 'web',
|
|
30
|
+
/** UNTRUSTED HTML rendered in an opaque-origin, script-sandboxed frame. */
|
|
31
|
+
Html = 'html',
|
|
32
|
+
/** A Markdown document. */
|
|
33
|
+
Markdown = 'markdown',
|
|
34
|
+
/** A source file with syntax highlighting. */
|
|
35
|
+
Code = 'code',
|
|
36
|
+
/** A unified diff (one or more files). */
|
|
37
|
+
Diff = 'diff',
|
|
38
|
+
/** A JSON document rendered as an inspectable tree. */
|
|
39
|
+
Json = 'json',
|
|
40
|
+
/** Generic columns + rows. The universal "show me structured records". */
|
|
41
|
+
Table = 'table',
|
|
42
|
+
/** A chart over labelled series. */
|
|
43
|
+
Chart = 'chart',
|
|
44
|
+
/** A PDF document (canvas-rendered, no script execution). */
|
|
45
|
+
Pdf = 'pdf',
|
|
46
|
+
/** A still image. */
|
|
47
|
+
Image = 'image',
|
|
48
|
+
/** Time-based media (audio/video). */
|
|
49
|
+
Media = 'media',
|
|
50
|
+
/** A Xema object rendered through its registered object view. */
|
|
51
|
+
Object = 'object',
|
|
52
|
+
/** A biome's REAL React route, reached through an `xema://biome/…` deeplink. */
|
|
53
|
+
BiomeRoute = 'biome-route',
|
|
54
|
+
/** A schema-driven form — the secure-elicitation surface. */
|
|
55
|
+
Form = 'form',
|
|
56
|
+
/** A runtime app (App Platform) rendered in its own frame. */
|
|
57
|
+
App = 'app',
|
|
58
|
+
/** A file tree / browser over a workspace or artifact set. */
|
|
59
|
+
Files = 'files',
|
|
60
|
+
/** A node-edge graph (e.g. the capability map). */
|
|
61
|
+
Graph = 'graph',
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Zod mirror of {@link SurfaceKind} for wire-boundary validation. */
|
|
65
|
+
export const SurfaceKindSchema = z.nativeEnum(SurfaceKind);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `VistaSurface` — one Vista tab. The agent opens/updates a tab by emitting
|
|
5
|
+
* this envelope; the frontend Vista registry resolves `kind` to a renderer and
|
|
6
|
+
* hands it the validated `payload`.
|
|
7
|
+
*
|
|
8
|
+
* `kind` is a first-party {@link SurfaceKind} value OR a namespaced biome
|
|
9
|
+
* string (`<biomeId>:<kind>`). `version` is the monotonic schema version for
|
|
10
|
+
* THIS kind — the frontend renders the registered renderer when `version <=
|
|
11
|
+
* supportedVersion`, else a safe fallback card. `payload` is the kind-specific
|
|
12
|
+
* payload (validated by the producer against the kind's JSON Schema; the
|
|
13
|
+
* frontend re-validates before render so a malformed payload renders the
|
|
14
|
+
* fallback rather than being dropped).
|
|
15
|
+
*
|
|
16
|
+
* Structurally this is `ChatWidgetEnvelope` plus the tab identity a preview
|
|
17
|
+
* plane needs (`tabId`, `title`, `pinned`) — deliberately so: the two planes
|
|
18
|
+
* share ONE contribution pattern, one registry core, and one three-layer
|
|
19
|
+
* renderer fallback.
|
|
20
|
+
*/
|
|
21
|
+
export interface VistaSurface {
|
|
22
|
+
/** Stable identity of the tab. Re-opening the same `tabId` replaces it. */
|
|
23
|
+
readonly tabId: string;
|
|
24
|
+
/** First-party {@link SurfaceKind} value, or a `<biomeId>:<kind>` slug. */
|
|
25
|
+
readonly kind: string;
|
|
26
|
+
/** Monotonic schema version for this kind's payload. */
|
|
27
|
+
readonly version: number;
|
|
28
|
+
/** Tab label. */
|
|
29
|
+
readonly title: string;
|
|
30
|
+
/** Kind-specific payload, validated + narrowed by the frontend registry. */
|
|
31
|
+
readonly payload: unknown;
|
|
32
|
+
/** A pinned tab survives the agent closing/replacing unpinned tabs. */
|
|
33
|
+
readonly pinned?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Zod validator for {@link VistaSurface}. */
|
|
37
|
+
export const VistaSurfaceSchema: z.ZodType<VistaSurface> = z.object({
|
|
38
|
+
tabId: z.string().min(1),
|
|
39
|
+
kind: z.string().min(1),
|
|
40
|
+
version: z.number().int().positive(),
|
|
41
|
+
title: z.string().min(1),
|
|
42
|
+
payload: z.unknown(),
|
|
43
|
+
pinned: z.boolean().optional(),
|
|
44
|
+
}) as z.ZodType<VistaSurface>;
|
|
@@ -31,8 +31,12 @@ export const ChatWidgetEnvelopeSchema: z.ZodType<ChatWidgetEnvelope> = z.object(
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Why a widget fell back to the safe card — populated on the FE resolved
|
|
34
|
-
* decision so the Studio debugger can see WHY.
|
|
35
|
-
*
|
|
34
|
+
* decision so the Studio debugger can see WHY. Closed set.
|
|
35
|
+
*
|
|
36
|
+
* This is the WIRE mirror. The FE runtime reason set is
|
|
37
|
+
* `ContributionFallbackReason` in `@xemahq/ui-kernel`, shared by every plane
|
|
38
|
+
* built on the two-layer contribution registry (ChatWidgets, Vista surfaces) —
|
|
39
|
+
* keep the two value-identical.
|
|
36
40
|
*/
|
|
37
41
|
export enum ChatWidgetFallbackReason {
|
|
38
42
|
UnknownKind = 'unknown-kind',
|
|
@@ -288,13 +288,12 @@ export enum BuiltInActionId {
|
|
|
288
288
|
* authorization decisions, so any cross-service side-effect routes
|
|
289
289
|
* through this action and the router's grant resolver decides.
|
|
290
290
|
*
|
|
291
|
-
* Inputs declare the `ref` (`<domain>:<resource>.<verb>@<major>`)
|
|
292
|
-
* the opaque `input` payload the bound implementation consumes
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* workflow run id so audit-log entries stitch back to the run.
|
|
291
|
+
* Inputs declare the `ref` (`<domain>:<resource>.<verb>@<major>`) and
|
|
292
|
+
* the opaque `input` payload the bound implementation consumes. The
|
|
293
|
+
* subject is not an input: the activity always derives it from the
|
|
294
|
+
* worker's own service identity — the identity whose bearer the
|
|
295
|
+
* router verifies — and stamps `correlationId` with the workflow run
|
|
296
|
+
* id so audit-log entries stitch back to the run.
|
|
298
297
|
*/
|
|
299
298
|
CAPABILITY_INVOKE = 'xema/capability',
|
|
300
299
|
/**
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
4
|
-
// ── The CLOSED set of first-party capability DOMAINS ──
|
|
5
|
-
//
|
|
6
|
-
// A capability ref is `<domain>:<resource>.<verb>@<major>`. A DOMAIN is
|
|
7
|
-
// "first-party" when a fixed in-the-box Xema platform service owns every ref
|
|
8
|
-
// under it — i.e. the capability-router's static dispatch table resolves it
|
|
9
|
-
// directly (never through an org-provisioned or contributed backing).
|
|
10
|
-
//
|
|
11
|
-
// This is the SINGLE SOURCE OF TRUTH for that membership. It exists so two
|
|
12
|
-
// services can agree without one reaching into the other's code:
|
|
13
|
-
//
|
|
14
|
-
// - `xema-capability-router` builds its static dispatch table from EXACTLY
|
|
15
|
-
// these keys and asserts the two agree at boot (fail-fast on drift).
|
|
16
|
-
// - `capability-registry-api` REFUSES an org `CapabilityProviderBinding`
|
|
17
|
-
// whose ref domain is in this set — an org admin must not be able to bind
|
|
18
|
-
// `kb:page.read@1` / `agent:invoke@1` / `artifact:blob.read@1` to a URL
|
|
19
|
-
// they control and silently shadow the platform data plane.
|
|
20
|
-
//
|
|
21
|
-
// Membership is the router's dispatch keys, in dispatch-registration order.
|
|
22
|
-
// Adding/removing a first-party domain is a coordinated change here PLUS the
|
|
23
|
-
// router's dispatch table — the boot assertion turns any divergence into a
|
|
24
|
-
// crash rather than a silent shadow window.
|
|
25
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
26
|
-
|
|
27
|
-
export const FIRST_PARTY_CAPABILITY_DOMAINS = [
|
|
28
|
-
'xema-shell',
|
|
29
|
-
'store',
|
|
30
|
-
'biome',
|
|
31
|
-
'connector',
|
|
32
|
-
'kb',
|
|
33
|
-
'agent',
|
|
34
|
-
'memory',
|
|
35
|
-
'model',
|
|
36
|
-
'model-resolution',
|
|
37
|
-
'mcp-tool',
|
|
38
|
-
'workflow',
|
|
39
|
-
'studio',
|
|
40
|
-
'interactive-session',
|
|
41
|
-
'agent-session',
|
|
42
|
-
'document',
|
|
43
|
-
'notification',
|
|
44
|
-
'space',
|
|
45
|
-
'mailops',
|
|
46
|
-
'workspace',
|
|
47
|
-
'worker-runtime',
|
|
48
|
-
'artifact',
|
|
49
|
-
'search',
|
|
50
|
-
'app',
|
|
51
|
-
] as const;
|
|
52
|
-
|
|
53
|
-
export type FirstPartyCapabilityDomain =
|
|
54
|
-
(typeof FIRST_PARTY_CAPABILITY_DOMAINS)[number];
|
|
55
|
-
|
|
56
|
-
export const FirstPartyCapabilityDomainSchema = z.enum(
|
|
57
|
-
FIRST_PARTY_CAPABILITY_DOMAINS as unknown as [
|
|
58
|
-
FirstPartyCapabilityDomain,
|
|
59
|
-
...FirstPartyCapabilityDomain[],
|
|
60
|
-
],
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
const FIRST_PARTY_CAPABILITY_DOMAIN_SET: ReadonlySet<string> = new Set(
|
|
64
|
-
FIRST_PARTY_CAPABILITY_DOMAINS,
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* `true` iff `domain` is a first-party platform capability domain. O(1)
|
|
69
|
-
* membership over the closed set above. The write-path shadow refusal and the
|
|
70
|
-
* router's binding-skip defense-in-depth both branch on this — never on an
|
|
71
|
-
* ad-hoc string compare or a hand-maintained second list.
|
|
72
|
-
*/
|
|
73
|
-
export function isFirstPartyCapabilityDomain(
|
|
74
|
-
domain: string,
|
|
75
|
-
): domain is FirstPartyCapabilityDomain {
|
|
76
|
-
return FIRST_PARTY_CAPABILITY_DOMAIN_SET.has(domain);
|
|
77
|
-
}
|