@capybara-hq/kernel 0.1.0-rc.17 → 0.1.0-rc.19
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/catalog/component-scope.service.d.ts +4 -0
- package/dist/catalog/component-scope.service.js +4 -0
- package/dist/catalog/component-state.d.ts +2 -0
- package/dist/catalog/component-state.js +3 -0
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/client/client-access.service.d.ts +3 -2
- package/dist/client/client-access.service.js +12 -3
- package/dist/client/client-sign-in.service.d.ts +21 -0
- package/dist/client/client-sign-in.service.js +49 -0
- package/dist/client/client.controller.d.ts +7 -3
- package/dist/client/client.controller.js +17 -9
- package/dist/client/client.module.d.ts +2 -1
- package/dist/client/client.module.js +5 -3
- package/dist/client/client.schemas.d.ts +6 -0
- package/package.json +2 -2
|
@@ -77,6 +77,8 @@ export interface ComponentView {
|
|
|
77
77
|
en: string;
|
|
78
78
|
} | null;
|
|
79
79
|
description: string | null;
|
|
80
|
+
/** The description's Chinese text (null: show `description` in every locale). */
|
|
81
|
+
descriptionZh: string | null;
|
|
80
82
|
/** The plugin it came from (null: none). */
|
|
81
83
|
plugin: string | null;
|
|
82
84
|
itemId: string | null;
|
|
@@ -151,6 +153,8 @@ export interface OrgOfferedComponentView extends OrgComponentView {
|
|
|
151
153
|
en: string;
|
|
152
154
|
} | null;
|
|
153
155
|
description: string | null;
|
|
156
|
+
/** The description's Chinese text (null: show `description` in every locale). */
|
|
157
|
+
descriptionZh: string | null;
|
|
154
158
|
itemId: string | null;
|
|
155
159
|
version: string;
|
|
156
160
|
scopeMode: "follow" | "own";
|
|
@@ -211,6 +211,7 @@ let ComponentScopeService = class ComponentScopeService {
|
|
|
211
211
|
name: c.name,
|
|
212
212
|
displayName: c.displayName,
|
|
213
213
|
description: c.description,
|
|
214
|
+
descriptionZh: c.descriptionZh,
|
|
214
215
|
plugin: c.plugin,
|
|
215
216
|
itemId: c.itemId,
|
|
216
217
|
owner: ownerOf(c.ownerOrgId, owners),
|
|
@@ -269,6 +270,7 @@ let ComponentScopeService = class ComponentScopeService {
|
|
|
269
270
|
name: c.name,
|
|
270
271
|
displayName: c.displayName,
|
|
271
272
|
description: c.description,
|
|
273
|
+
descriptionZh: c.descriptionZh,
|
|
272
274
|
plugin: c.plugin,
|
|
273
275
|
itemId: c.itemId,
|
|
274
276
|
version: c.version,
|
|
@@ -373,6 +375,7 @@ let ComponentScopeService = class ComponentScopeService {
|
|
|
373
375
|
name: r.name,
|
|
374
376
|
displayName: null,
|
|
375
377
|
description: r.description,
|
|
378
|
+
descriptionZh: null,
|
|
376
379
|
plugin: r.plugin,
|
|
377
380
|
itemId: r.catalog_item_id,
|
|
378
381
|
owner: ownerOf(r.org_id, owners),
|
|
@@ -1097,6 +1100,7 @@ const virtualOf = (o) => ({
|
|
|
1097
1100
|
plugin: o.plugin,
|
|
1098
1101
|
version: String(o.version),
|
|
1099
1102
|
description: null,
|
|
1103
|
+
descriptionZh: null,
|
|
1100
1104
|
displayName: null,
|
|
1101
1105
|
itemId: null,
|
|
1102
1106
|
scopeMode: "own",
|
|
@@ -68,6 +68,8 @@ export interface ComponentRow extends ComponentScopeFacts {
|
|
|
68
68
|
/** The current version (a connector template: the catalog version that last changed it). */
|
|
69
69
|
version: string;
|
|
70
70
|
description: string | null;
|
|
71
|
+
/** The description's Chinese text (a theme's or skill's `description.zh`); null without one. */
|
|
72
|
+
descriptionZh: string | null;
|
|
71
73
|
/**
|
|
72
74
|
* A connector template's localized display name (its file's `displayName`); null for skills and
|
|
73
75
|
* agent templates, whose name is what they are shown by.
|
|
@@ -119,6 +119,7 @@ export async function loadComponents(db, kind, filter = {}) {
|
|
|
119
119
|
plugin: r.item_name,
|
|
120
120
|
version: r.current_version,
|
|
121
121
|
description: typeof file?.description === "string" ? file.description : null,
|
|
122
|
+
descriptionZh: null,
|
|
122
123
|
displayName: localizedName(file?.displayName),
|
|
123
124
|
originOrgId: null,
|
|
124
125
|
};
|
|
@@ -137,6 +138,7 @@ export async function loadComponents(db, kind, filter = {}) {
|
|
|
137
138
|
"p.plugin_name",
|
|
138
139
|
"p.name",
|
|
139
140
|
"p.description",
|
|
141
|
+
"p.description_zh",
|
|
140
142
|
"p.current_version",
|
|
141
143
|
"p.scope_mode",
|
|
142
144
|
"p.scope",
|
|
@@ -161,6 +163,7 @@ export async function loadComponents(db, kind, filter = {}) {
|
|
|
161
163
|
plugin: r.plugin_name,
|
|
162
164
|
version: String(r.current_version),
|
|
163
165
|
description: r.description,
|
|
166
|
+
descriptionZh: r.description_zh,
|
|
164
167
|
displayName: null,
|
|
165
168
|
originOrgId: r.origin_org_id,
|
|
166
169
|
}));
|
|
@@ -188,7 +188,7 @@ export declare function headsToResolve(entries: readonly MarketplaceEntry[], imp
|
|
|
188
188
|
/** The host versions (an entry's `minKernel` is judged against them). */
|
|
189
189
|
export declare const HOST_VERSIONS: {
|
|
190
190
|
readonly kernel: string;
|
|
191
|
-
readonly sdk: "0.1.0-rc.
|
|
191
|
+
readonly sdk: "0.1.0-rc.14";
|
|
192
192
|
};
|
|
193
193
|
/** Whether this deployment satisfies the entry's `minKernel`. */
|
|
194
194
|
export declare const entryCompatible: (e: Pick<MarketplaceEntry, "minKernel">) => boolean;
|
|
@@ -90,12 +90,13 @@ export declare class ClientAccess {
|
|
|
90
90
|
* build ({@link listed}: one per extension), in name order, minus the stopped ones; `components`
|
|
91
91
|
* are those whose slot the role may use (`canUseSlot`: its `minRole`, never `platform.page`). An
|
|
92
92
|
* extension with no component left is still listed (its stylesheets and entry still load).
|
|
93
|
+
* `signInId` gives each item the viewer's sign-in id for that plugin (`ClientSignIn`).
|
|
93
94
|
*/
|
|
94
|
-
orgSet(orgId: string, role: OrgRole): Promise<ClientExtensionsResponse>;
|
|
95
|
+
orgSet(orgId: string, role: OrgRole, signInId: (plugin: string) => string): Promise<ClientExtensionsResponse>;
|
|
95
96
|
/**
|
|
96
97
|
* The admin console's set (spec §9.6): the extensions with a served build (whatever their org
|
|
97
98
|
* enablement) with at least one `platform.page` component and an entry, only those components
|
|
98
99
|
* and no stylesheets (the admin console runs no org client code); with `plugin`, at most that one.
|
|
99
100
|
*/
|
|
100
|
-
platformSet(plugin?: string): Promise<ClientExtensionsResponse>;
|
|
101
|
+
platformSet(signInId: (plugin: string) => string, plugin?: string): Promise<ClientExtensionsResponse>;
|
|
101
102
|
}
|
|
@@ -234,8 +234,9 @@ let ClientAccess = class ClientAccess {
|
|
|
234
234
|
* build ({@link listed}: one per extension), in name order, minus the stopped ones; `components`
|
|
235
235
|
* are those whose slot the role may use (`canUseSlot`: its `minRole`, never `platform.page`). An
|
|
236
236
|
* extension with no component left is still listed (its stylesheets and entry still load).
|
|
237
|
+
* `signInId` gives each item the viewer's sign-in id for that plugin (`ClientSignIn`).
|
|
237
238
|
*/
|
|
238
|
-
async orgSet(orgId, role) {
|
|
239
|
+
async orgSet(orgId, role, signInId) {
|
|
239
240
|
const db = this.db.db;
|
|
240
241
|
const [kill, rows] = await Promise.all([
|
|
241
242
|
readClientExtensions(db, this.log),
|
|
@@ -253,6 +254,7 @@ let ClientAccess = class ClientAccess {
|
|
|
253
254
|
components: componentsOf(r.section)
|
|
254
255
|
.filter((c) => canUseSlot(c.slot, role))
|
|
255
256
|
.map((c) => ({ id: c.id, slot: c.slot.id })),
|
|
257
|
+
signInId: signInId(r.plugin),
|
|
256
258
|
}));
|
|
257
259
|
return { enabled: true, apiVersion: CLIENT_API_VERSION, items };
|
|
258
260
|
}
|
|
@@ -261,7 +263,7 @@ let ClientAccess = class ClientAccess {
|
|
|
261
263
|
* enablement) with at least one `platform.page` component and an entry, only those components
|
|
262
264
|
* and no stylesheets (the admin console runs no org client code); with `plugin`, at most that one.
|
|
263
265
|
*/
|
|
264
|
-
async platformSet(plugin) {
|
|
266
|
+
async platformSet(signInId, plugin) {
|
|
265
267
|
const db = this.db.db;
|
|
266
268
|
let q = this.listed(db);
|
|
267
269
|
if (plugin !== undefined)
|
|
@@ -278,7 +280,14 @@ let ClientAccess = class ClientAccess {
|
|
|
278
280
|
if (components.length === 0)
|
|
279
281
|
return [];
|
|
280
282
|
return [
|
|
281
|
-
{
|
|
283
|
+
{
|
|
284
|
+
plugin: r.plugin,
|
|
285
|
+
build: r.build,
|
|
286
|
+
entry: fileRef(r, r.entry),
|
|
287
|
+
styles: [],
|
|
288
|
+
components,
|
|
289
|
+
signInId: signInId(r.plugin),
|
|
290
|
+
},
|
|
282
291
|
];
|
|
283
292
|
});
|
|
284
293
|
return { enabled: true, apiVersion: CLIENT_API_VERSION, items };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Keyring } from "../ctx/secrets.js";
|
|
2
|
+
import type { UserPrincipal } from "../identity/principal.js";
|
|
3
|
+
/**
|
|
4
|
+
* The sign-in ids of the shell reads (client extensions spec §4.2, `ClientApi.signIn`): an opaque
|
|
5
|
+
* id per plugin that stays the same for one sign-in (one web session, across token refreshes and
|
|
6
|
+
* every tab of it) and changes on the next sign-in, so client code can do something once per
|
|
7
|
+
* sign-in. It is `HMAC-SHA256(key, "<sign-in>\0<plugin>")` truncated to 128 bits, the key derived
|
|
8
|
+
* from the master keyring: not a credential and not reversible to the session id. The plugin name
|
|
9
|
+
* is an input only so that the id is not the same string in every plugin; that is no isolation
|
|
10
|
+
* boundary: client code runs with full trust in the page (spec D2) and can read the whole shell
|
|
11
|
+
* read (or the query cache), which lists every plugin's id. Derived per request from the
|
|
12
|
+
* principal, no state. A personal token (no session) is its own sign-in. Rotating the master key
|
|
13
|
+
* changes every id once (client code then treats the session as a new sign-in); during a rolling
|
|
14
|
+
* restart old and new replicas answer different ids, so it may look like more than one.
|
|
15
|
+
*/
|
|
16
|
+
export declare class ClientSignIn {
|
|
17
|
+
private readonly key;
|
|
18
|
+
constructor(keyring: Keyring);
|
|
19
|
+
/** The id function of the caller's sign-in: plugin name → that plugin's sign-in id. */
|
|
20
|
+
of(principal: UserPrincipal): (plugin: string) => string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { createHmac } from "node:crypto";
|
|
11
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
12
|
+
import { KEYRING } from "../infra/tokens.js";
|
|
13
|
+
/** The HKDF purpose of the sign-in id key (`capybara:client-sign-in/v1`). */
|
|
14
|
+
const SIGN_IN_KEY_INFO = "client-sign-in/v1";
|
|
15
|
+
/** A sign-in id is 128 bits of the HMAC, base64url (22 characters). */
|
|
16
|
+
const SIGN_IN_ID_BYTES = 16;
|
|
17
|
+
/**
|
|
18
|
+
* The sign-in ids of the shell reads (client extensions spec §4.2, `ClientApi.signIn`): an opaque
|
|
19
|
+
* id per plugin that stays the same for one sign-in (one web session, across token refreshes and
|
|
20
|
+
* every tab of it) and changes on the next sign-in, so client code can do something once per
|
|
21
|
+
* sign-in. It is `HMAC-SHA256(key, "<sign-in>\0<plugin>")` truncated to 128 bits, the key derived
|
|
22
|
+
* from the master keyring: not a credential and not reversible to the session id. The plugin name
|
|
23
|
+
* is an input only so that the id is not the same string in every plugin; that is no isolation
|
|
24
|
+
* boundary: client code runs with full trust in the page (spec D2) and can read the whole shell
|
|
25
|
+
* read (or the query cache), which lists every plugin's id. Derived per request from the
|
|
26
|
+
* principal, no state. A personal token (no session) is its own sign-in. Rotating the master key
|
|
27
|
+
* changes every id once (client code then treats the session as a new sign-in); during a rolling
|
|
28
|
+
* restart old and new replicas answer different ids, so it may look like more than one.
|
|
29
|
+
*/
|
|
30
|
+
let ClientSignIn = class ClientSignIn {
|
|
31
|
+
key;
|
|
32
|
+
constructor(keyring) {
|
|
33
|
+
this.key = keyring.deriveKey(SIGN_IN_KEY_INFO).current;
|
|
34
|
+
}
|
|
35
|
+
/** The id function of the caller's sign-in: plugin name → that plugin's sign-in id. */
|
|
36
|
+
of(principal) {
|
|
37
|
+
const signIn = principal.via === "session" ? `session:${principal.sessionId}` : `pat:${principal.tokenId}`;
|
|
38
|
+
return (plugin) => createHmac("sha256", this.key)
|
|
39
|
+
.update(`${signIn}\0${plugin}`)
|
|
40
|
+
.digest()
|
|
41
|
+
.subarray(0, SIGN_IN_ID_BYTES)
|
|
42
|
+
.toString("base64url");
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
ClientSignIn = __decorate([
|
|
46
|
+
Injectable(),
|
|
47
|
+
__param(0, Inject(KEYRING))
|
|
48
|
+
], ClientSignIn);
|
|
49
|
+
export { ClientSignIn };
|
|
@@ -4,18 +4,21 @@ import { type OrgContext } from "../orgs/org.guard.js";
|
|
|
4
4
|
import { AdminClientQuery, type ClientExtensionsResponse, ReportBody } from "./client.schemas.js";
|
|
5
5
|
import { ClientAccess } from "./client-access.service.js";
|
|
6
6
|
import { ClientReports } from "./client-reports.service.js";
|
|
7
|
+
import { ClientSignIn } from "./client-sign-in.service.js";
|
|
7
8
|
/**
|
|
8
9
|
* The workspace shell read of client extensions (client extensions spec §9.2), `ui.use` (guest and
|
|
9
10
|
* up; a person, not a service token): `GET /api/v1/orgs/:orgId/ui/client` →
|
|
10
11
|
* {@link ClientExtensionsResponse}: the extensions enabled in the org that run with an approved
|
|
11
|
-
* client build, their file URLs and integrity,
|
|
12
|
+
* client build, their file URLs and integrity, the components the caller's role may use and the
|
|
13
|
+
* caller's sign-in id per plugin (`ClientSignIn`);
|
|
12
14
|
* `enabled: false` with no items under the kill switch. `no-store`: the set changes with an org
|
|
13
15
|
* switch, an upgrade or the kill switch.
|
|
14
16
|
*/
|
|
15
17
|
export declare class OrgClientController {
|
|
16
18
|
private readonly access;
|
|
17
19
|
private readonly reports;
|
|
18
|
-
|
|
20
|
+
private readonly signIn;
|
|
21
|
+
constructor(access: ClientAccess, reports: ClientReports, signIn: ClientSignIn);
|
|
19
22
|
list(principal: Principal, org: OrgContext): Promise<ClientExtensionsResponse>;
|
|
20
23
|
/**
|
|
21
24
|
* `POST /api/v1/orgs/:orgId/ui/client/reports` (spec §10.4), `ui.use`, a person, 20 per minute
|
|
@@ -34,7 +37,8 @@ export declare class OrgClientController {
|
|
|
34
37
|
export declare class AdminClientController {
|
|
35
38
|
private readonly access;
|
|
36
39
|
private readonly reports;
|
|
37
|
-
|
|
40
|
+
private readonly signIn;
|
|
41
|
+
constructor(access: ClientAccess, reports: ClientReports, signIn: ClientSignIn);
|
|
38
42
|
list(principal: Principal, q: z.infer<typeof AdminClientQuery>): Promise<ClientExtensionsResponse>;
|
|
39
43
|
/**
|
|
40
44
|
* `POST /api/v1/admin/ui/client/reports` (spec §10.4), super admins, 20 per minute per account:
|
|
@@ -16,6 +16,7 @@ import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
|
16
16
|
import { AdminClientQuery, ReportBody } from "./client.schemas.js";
|
|
17
17
|
import { ClientAccess } from "./client-access.service.js";
|
|
18
18
|
import { ClientReports } from "./client-reports.service.js";
|
|
19
|
+
import { ClientSignIn } from "./client-sign-in.service.js";
|
|
19
20
|
class AdminClientQueryDto extends createZodDto(AdminClientQuery, "AdminClientQuery") {
|
|
20
21
|
}
|
|
21
22
|
class ReportBodyDto extends createZodDto(ReportBody, "ClientReportBody") {
|
|
@@ -24,20 +25,23 @@ class ReportBodyDto extends createZodDto(ReportBody, "ClientReportBody") {
|
|
|
24
25
|
* The workspace shell read of client extensions (client extensions spec §9.2), `ui.use` (guest and
|
|
25
26
|
* up; a person, not a service token): `GET /api/v1/orgs/:orgId/ui/client` →
|
|
26
27
|
* {@link ClientExtensionsResponse}: the extensions enabled in the org that run with an approved
|
|
27
|
-
* client build, their file URLs and integrity,
|
|
28
|
+
* client build, their file URLs and integrity, the components the caller's role may use and the
|
|
29
|
+
* caller's sign-in id per plugin (`ClientSignIn`);
|
|
28
30
|
* `enabled: false` with no items under the kill switch. `no-store`: the set changes with an org
|
|
29
31
|
* switch, an upgrade or the kill switch.
|
|
30
32
|
*/
|
|
31
33
|
let OrgClientController = class OrgClientController {
|
|
32
34
|
access;
|
|
33
35
|
reports;
|
|
34
|
-
|
|
36
|
+
signIn;
|
|
37
|
+
constructor(access, reports, signIn) {
|
|
35
38
|
this.access = access;
|
|
36
39
|
this.reports = reports;
|
|
40
|
+
this.signIn = signIn;
|
|
37
41
|
}
|
|
38
42
|
async list(principal, org) {
|
|
39
|
-
requireUser(principal);
|
|
40
|
-
return this.access.orgSet(org.orgId, org.role);
|
|
43
|
+
const user = requireUser(principal);
|
|
44
|
+
return this.access.orgSet(org.orgId, org.role, this.signIn.of(user));
|
|
41
45
|
}
|
|
42
46
|
/**
|
|
43
47
|
* `POST /api/v1/orgs/:orgId/ui/client/reports` (spec §10.4), `ui.use`, a person, 20 per minute
|
|
@@ -69,7 +73,8 @@ __decorate([
|
|
|
69
73
|
OrgClientController = __decorate([
|
|
70
74
|
Controller("api/v1/orgs/:orgId/ui/client"),
|
|
71
75
|
__param(0, Inject(ClientAccess)),
|
|
72
|
-
__param(1, Inject(ClientReports))
|
|
76
|
+
__param(1, Inject(ClientReports)),
|
|
77
|
+
__param(2, Inject(ClientSignIn))
|
|
73
78
|
], OrgClientController);
|
|
74
79
|
export { OrgClientController };
|
|
75
80
|
/**
|
|
@@ -81,13 +86,15 @@ export { OrgClientController };
|
|
|
81
86
|
let AdminClientController = class AdminClientController {
|
|
82
87
|
access;
|
|
83
88
|
reports;
|
|
84
|
-
|
|
89
|
+
signIn;
|
|
90
|
+
constructor(access, reports, signIn) {
|
|
85
91
|
this.access = access;
|
|
86
92
|
this.reports = reports;
|
|
93
|
+
this.signIn = signIn;
|
|
87
94
|
}
|
|
88
95
|
async list(principal, q) {
|
|
89
|
-
requireUser(principal);
|
|
90
|
-
return this.access.platformSet(q.plugin);
|
|
96
|
+
const user = requireUser(principal);
|
|
97
|
+
return this.access.platformSet(this.signIn.of(user), q.plugin);
|
|
91
98
|
}
|
|
92
99
|
/**
|
|
93
100
|
* `POST /api/v1/admin/ui/client/reports` (spec §10.4), super admins, 20 per minute per account:
|
|
@@ -116,6 +123,7 @@ AdminClientController = __decorate([
|
|
|
116
123
|
Controller("api/v1/admin/ui/client"),
|
|
117
124
|
SuperAdmin(),
|
|
118
125
|
__param(0, Inject(ClientAccess)),
|
|
119
|
-
__param(1, Inject(ClientReports))
|
|
126
|
+
__param(1, Inject(ClientReports)),
|
|
127
|
+
__param(2, Inject(ClientSignIn))
|
|
120
128
|
], AdminClientController);
|
|
121
129
|
export { AdminClientController };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Client extensions (spec 2026-11-09-client-extensions-design.md): the client builds stored with
|
|
3
3
|
* extension packages ({@link ClientBuilds}) and who may load them ({@link ClientAccess}: the
|
|
4
|
-
* delivery route and the shell reads, whose controllers the api role lists
|
|
4
|
+
* delivery route and the shell reads, whose controllers the api role lists; {@link ClientSignIn}:
|
|
5
|
+
* the per-plugin sign-in ids of those reads).
|
|
5
6
|
*/
|
|
6
7
|
export declare class ClientModule {
|
|
7
8
|
}
|
|
@@ -9,18 +9,20 @@ import { StorageModule } from "../storage/storage.module.js";
|
|
|
9
9
|
import { ClientAccess } from "./client-access.service.js";
|
|
10
10
|
import { ClientBuilds } from "./client-builds.service.js";
|
|
11
11
|
import { ClientReports } from "./client-reports.service.js";
|
|
12
|
+
import { ClientSignIn } from "./client-sign-in.service.js";
|
|
12
13
|
/**
|
|
13
14
|
* Client extensions (spec 2026-11-09-client-extensions-design.md): the client builds stored with
|
|
14
15
|
* extension packages ({@link ClientBuilds}) and who may load them ({@link ClientAccess}: the
|
|
15
|
-
* delivery route and the shell reads, whose controllers the api role lists
|
|
16
|
+
* delivery route and the shell reads, whose controllers the api role lists; {@link ClientSignIn}:
|
|
17
|
+
* the per-plugin sign-in ids of those reads).
|
|
16
18
|
*/
|
|
17
19
|
let ClientModule = class ClientModule {
|
|
18
20
|
};
|
|
19
21
|
ClientModule = __decorate([
|
|
20
22
|
Module({
|
|
21
23
|
imports: [StorageModule],
|
|
22
|
-
providers: [ClientBuilds, ClientAccess, ClientReports],
|
|
23
|
-
exports: [ClientBuilds, ClientAccess, ClientReports],
|
|
24
|
+
providers: [ClientBuilds, ClientAccess, ClientReports, ClientSignIn],
|
|
25
|
+
exports: [ClientBuilds, ClientAccess, ClientReports, ClientSignIn],
|
|
24
26
|
})
|
|
25
27
|
], ClientModule);
|
|
26
28
|
export { ClientModule };
|
|
@@ -22,6 +22,12 @@ export interface ClientExtensionItem {
|
|
|
22
22
|
id: string;
|
|
23
23
|
slot: UiSlotId;
|
|
24
24
|
}[];
|
|
25
|
+
/**
|
|
26
|
+
* The viewer's sign-in id for this plugin (`ClientApi.signIn.id`, spec §4.2): opaque, the same
|
|
27
|
+
* for every read of one sign-in and different after the next one; a different string per plugin,
|
|
28
|
+
* not a secret between plugins (client code is full trust and reads the whole set).
|
|
29
|
+
*/
|
|
30
|
+
signInId: string;
|
|
25
31
|
}
|
|
26
32
|
/** The shell read (spec §9.2). */
|
|
27
33
|
export interface ClientExtensionsResponse {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capybara-hq/kernel",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.19",
|
|
4
4
|
"description": "Capybara kernel: config, database, plugin host and HTTP API of the Capybara agent platform",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"yaml": "^2.9.1",
|
|
66
66
|
"yauzl": "3.4.0",
|
|
67
67
|
"zod": "^4.6.7",
|
|
68
|
-
"@capybara-hq/plugin-sdk": "^0.1.0-rc.
|
|
68
|
+
"@capybara-hq/plugin-sdk": "^0.1.0-rc.14"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@langchain/langgraph-checkpoint-validation": "^1.2.0",
|