@capybara-hq/kernel 0.1.0-rc.10 → 0.1.0-rc.12
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/admin/admin.schemas.d.ts +3 -0
- package/dist/agents/agents.schemas.d.ts +3 -0
- package/dist/agents/agents.service.js +11 -1
- package/dist/agents/definition.d.ts +1 -0
- package/dist/agents/definition.js +7 -3
- package/dist/agents/org-templates.js +4 -0
- package/dist/agents/pending-connectors.service.js +1 -1
- package/dist/catalog/catalog-content.d.ts +33 -1
- package/dist/catalog/catalog-content.js +65 -2
- package/dist/catalog/catalog-items.js +1 -0
- package/dist/catalog/catalog-scope.service.d.ts +29 -3
- package/dist/catalog/catalog-scope.service.js +82 -10
- package/dist/catalog/catalog.service.d.ts +7 -5
- package/dist/catalog/catalog.service.js +26 -5
- package/dist/catalog/claude/translate.js +3 -0
- package/dist/catalog/component-scope.controller.d.ts +18 -6
- package/dist/catalog/component-scope.controller.js +36 -13
- package/dist/catalog/component-scope.schemas.d.ts +4 -0
- package/dist/catalog/component-scope.service.d.ts +59 -9
- package/dist/catalog/component-scope.service.js +156 -27
- package/dist/catalog/component-state.d.ts +20 -3
- package/dist/catalog/component-state.js +40 -14
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/org-catalog.service.js +3 -0
- package/dist/catalog/owned-items.js +7 -0
- package/dist/catalog/platform-components.d.ts +23 -3
- package/dist/catalog/platform-components.js +118 -9
- package/dist/catalog/platform-migration.js +2 -1
- package/dist/catalog/plugin-import.d.ts +24 -4
- package/dist/catalog/plugin-import.js +41 -7
- package/dist/catalog/plugin-install.d.ts +20 -1
- package/dist/catalog/plugin-install.js +71 -1
- package/dist/catalog/plugin-package.d.ts +41 -4
- package/dist/catalog/plugin-package.js +127 -7
- package/dist/catalog/plugin-upgrade.d.ts +13 -2
- package/dist/catalog/plugin-upgrade.js +124 -6
- package/dist/catalog/unshare.js +1 -0
- package/dist/conversations/conversations.service.d.ts +9 -0
- package/dist/conversations/conversations.service.js +9 -2
- package/dist/conversations/events.d.ts +1 -0
- package/dist/db/kernel-schema.d.ts +54 -4
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +27 -0
- package/dist/http/api.module.js +7 -0
- package/dist/identity/accounts.d.ts +11 -4
- package/dist/identity/accounts.js +23 -10
- package/dist/identity/me.controller.d.ts +10 -10
- package/dist/identity/me.controller.js +8 -6
- package/dist/identity/me.schemas.d.ts +13 -3
- package/dist/identity/me.schemas.js +10 -2
- package/dist/identity/settings.d.ts +27 -0
- package/dist/identity/settings.js +64 -0
- package/dist/orgs/settings.service.d.ts +31 -0
- package/dist/orgs/settings.service.js +31 -1
- package/dist/platform/exclusions.js +26 -0
- package/dist/platform/operation.js +6 -2
- package/dist/platform/ops/admin.ops.d.ts +3 -1
- package/dist/platform/ops/admin.ops.js +25 -7
- package/dist/platform/ops/agents.ops.js +19 -6
- package/dist/platform/ops/components.ops.js +1 -0
- package/dist/platform/ops/org-settings.ops.d.ts +3 -1
- package/dist/platform/ops/org-settings.ops.js +33 -8
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/platform.ops.d.ts +3 -1
- package/dist/platform/ops/platform.ops.js +43 -16
- package/dist/platform/ops/themes.ops.d.ts +14 -0
- package/dist/platform/ops/themes.ops.js +47 -0
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +5 -0
- package/dist/platform/route-schemas.js +3 -0
- package/dist/runtime/subagents/definition.d.ts +3 -2
- package/dist/runtime/subagents/definition.js +2 -1
- package/dist/themes/render-css.d.ts +12 -0
- package/dist/themes/render-css.js +132 -0
- package/dist/themes/theme-delivery.service.d.ts +34 -0
- package/dist/themes/theme-delivery.service.js +111 -0
- package/dist/themes/theme-state.d.ts +95 -0
- package/dist/themes/theme-state.js +203 -0
- package/dist/themes/theme-usage.d.ts +61 -0
- package/dist/themes/theme-usage.js +98 -0
- package/dist/themes/themes-public.controller.d.ts +28 -0
- package/dist/themes/themes-public.controller.js +92 -0
- package/dist/themes/themes.controller.d.ts +13 -0
- package/dist/themes/themes.controller.js +38 -0
- package/dist/themes/themes.module.d.ts +3 -0
- package/dist/themes/themes.module.js +21 -0
- package/dist/themes/themes.schemas.d.ts +3 -0
- package/dist/themes/themes.schemas.js +2 -0
- package/dist/themes/themes.service.d.ts +50 -0
- package/dist/themes/themes.service.js +99 -0
- package/dist/tools/connector-account-policies.d.ts +51 -0
- package/dist/tools/connector-account-policies.js +165 -0
- package/dist/tools/connectors.controller.d.ts +35 -4
- package/dist/tools/connectors.controller.js +66 -7
- package/dist/tools/connectors.schemas.d.ts +11 -0
- package/dist/tools/connectors.schemas.js +11 -0
- package/dist/tools/connectors.service.d.ts +2 -0
- package/dist/tools/connectors.service.js +1 -0
- package/dist/tools/pipeline.d.ts +1 -1
- package/dist/tools/policy.d.ts +23 -1
- package/dist/tools/policy.js +99 -24
- package/dist/tools/tools.module.js +3 -0
- package/package.json +3 -3
- package/src/migrations/0102_themes.sql +64 -0
- package/src/migrations/0103_ui_theme_setting.sql +7 -0
- package/src/migrations/0104_connector_tool_account_policies.sql +16 -0
package/dist/tools/policy.js
CHANGED
|
@@ -2,6 +2,7 @@ import { sql } from "kysely";
|
|
|
2
2
|
import { roleAtLeast } from "../orgs/roles.js";
|
|
3
3
|
import { readOrgSettings } from "../orgs/settings.service.js";
|
|
4
4
|
import { R3_FIXED_ASK_TOOL_KEYS, R3_SHARED_AGENT_ONLY_TOOL_KEYS, SANDBOX_ASK_TOOL_NAMES, } from "./builtin-names.js";
|
|
5
|
+
import { personalAuth } from "./connector-account-policies.js";
|
|
5
6
|
import { normalizeStoredDefinitionIn } from "./legacy-data.js";
|
|
6
7
|
export { R3_FIXED_ASK_TOOL_KEYS, R3_SHARED_AGENT_ONLY_TOOL_KEYS } from "./builtin-names.js";
|
|
7
8
|
const RANK = { allow: 0, ask: 1, deny: 2 };
|
|
@@ -35,17 +36,51 @@ export function isFixedAsk(tool, visibility, skillWritePolicy) {
|
|
|
35
36
|
// 私有 agent:缺省 / allow 不问(R4),负责人设为 ask(D10)时与共享 agent 一样固定询问
|
|
36
37
|
return !(builtinOnly && visibility === "private" && skillWritePolicy !== "ask");
|
|
37
38
|
}
|
|
38
|
-
const
|
|
39
|
+
const asSetting = (v) => v === "allow" || v === "ask" || v === "deny" ? v : undefined;
|
|
40
|
+
/** The stricter of the settings that are set (none set: undefined). */
|
|
41
|
+
function combine(...xs) {
|
|
42
|
+
let out;
|
|
43
|
+
for (const x of xs)
|
|
44
|
+
if (x !== undefined)
|
|
45
|
+
out = out === undefined ? x : stricter(out, x);
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
39
48
|
/**
|
|
40
|
-
* An agent's
|
|
41
|
-
* (`Platform:<operation>`), on that key, the stricter of the two
|
|
49
|
+
* An agent's setting for a call: its policy on the tool key and, for a per-call key
|
|
50
|
+
* (`Platform:<operation>`), on that key, the stricter of the two; undefined when neither is set.
|
|
51
|
+
* `allow` counts only for a connector tool ({@link connectorPolicy}); elsewhere an agent's policy
|
|
52
|
+
* can only tighten ({@link tighteningOf}).
|
|
42
53
|
*/
|
|
43
|
-
function
|
|
44
|
-
const own =
|
|
54
|
+
function settingOf(policies, toolKey, policyKey) {
|
|
55
|
+
const own = asSetting(policies?.[toolKey]);
|
|
45
56
|
if (policyKey === toolKey)
|
|
46
57
|
return own;
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
return combine(own, asSetting(policies?.[policyKey]));
|
|
59
|
+
}
|
|
60
|
+
/** An agent setting as a tightening (`allow` tightens nothing). */
|
|
61
|
+
const tighteningOf = (s) => s === "ask" || s === "deny" ? s : undefined;
|
|
62
|
+
/**
|
|
63
|
+
* A personal-credential connector tool's policy for one call (maintainer decisions 2026-11-09;
|
|
64
|
+
* an org-credential connector's tool keeps the org default with the agent's tightening only),
|
|
65
|
+
* highest first:
|
|
66
|
+
* 1. the org's default `deny` (a tool the org switched off never gets here: it is unavailable);
|
|
67
|
+
* 2. the member's own `deny` for calls with their connection (`member`): a floor no agent lifts;
|
|
68
|
+
* 3. the agent's setting (`agent`, from its tools page): `allow` / `ask` / `deny`;
|
|
69
|
+
* 4. the member's own `allow` / `ask`;
|
|
70
|
+
* 5. the org's default (`connector_tools.default_policy`, the annotation default unless an org
|
|
71
|
+
* admin changed it: `readOnlyHint: true` allows, anything else asks).
|
|
72
|
+
* Fixed asks (R3, `requiresUserInteraction`), role escalation and grants apply after this.
|
|
73
|
+
*/
|
|
74
|
+
export function connectorPolicy(input) {
|
|
75
|
+
if (input.orgDefault === "deny")
|
|
76
|
+
return { policy: "deny", source: "org" };
|
|
77
|
+
if (input.member === "deny")
|
|
78
|
+
return { policy: "deny", source: "member" };
|
|
79
|
+
if (input.agent !== undefined)
|
|
80
|
+
return { policy: input.agent, source: "agent" };
|
|
81
|
+
if (input.member !== undefined)
|
|
82
|
+
return { policy: input.member, source: "member" };
|
|
83
|
+
return { policy: input.orgDefault, source: "org" };
|
|
49
84
|
}
|
|
50
85
|
/**
|
|
51
86
|
* 执行时的策略判定(spec 3.6 R5:在动作执行那一刻判定)。每次调用都实时读取:
|
|
@@ -58,7 +93,7 @@ function overrideOf(policies, toolKey, policyKey) {
|
|
|
58
93
|
* parent's current version still tightens it (sub-agents spec §5.3, §9); its "this conversation"
|
|
59
94
|
* grants are the root conversation's (agent map spec §7); an org agent sub-agent (§5.5): `ctx.agentId` is the
|
|
60
95
|
* dispatched agent (its current version, its "always" grants) and the parent agent's current
|
|
61
|
-
* policies apply on top ({@link
|
|
96
|
+
* policies apply on top ({@link parentAgentSetting});
|
|
62
97
|
* - 授权表(`conversation_tool_grants` / `tool_grants`),`spec_hash` 与当前定义不一致视为无效(D8),
|
|
63
98
|
* `connector_id` 与工具的来源连接器不一致也无效(删除后用同一 slug 重新安装的连接器不继承旧授权);
|
|
64
99
|
* - 工具声明了 `requiredRole`(R1)时,发起人在组织中的当前角色:不是成员 → 拒绝;角色不足 → 按角色升级的审批
|
|
@@ -75,11 +110,15 @@ export function createDecidePolicy(db) {
|
|
|
75
110
|
let connectorDefault = call?.policy ?? tool.defaultPolicy;
|
|
76
111
|
let connectorId = null;
|
|
77
112
|
let hashCurrent = true;
|
|
113
|
+
/** The member's own setting for a call with their connection (a personal-credential connector). */
|
|
114
|
+
let memberSetting;
|
|
115
|
+
/** A personal-credential connector: calls use the acting account's own connection. */
|
|
116
|
+
let personal = false;
|
|
78
117
|
if (tool.source.kind === "connector") {
|
|
79
118
|
connectorId = tool.source.connectorId;
|
|
80
119
|
const app = await db
|
|
81
120
|
.selectFrom("connectors")
|
|
82
|
-
.select(["slug", "status", "deleted_at"])
|
|
121
|
+
.select(["slug", "status", "deleted_at", "auth"])
|
|
83
122
|
.where("id", "=", tool.source.connectorId)
|
|
84
123
|
.where("org_id", "=", ctx.orgId)
|
|
85
124
|
.executeTakeFirst();
|
|
@@ -105,6 +144,19 @@ export function createDecidePolicy(db) {
|
|
|
105
144
|
return { unavailable: "Tool is pending review" };
|
|
106
145
|
connectorDefault = row.default_policy;
|
|
107
146
|
hashCurrent = row.spec_hash === tool.specHash;
|
|
147
|
+
// The call is made with the acting account's own connection (the credential the pipeline
|
|
148
|
+
// injects for `ctx.accountId`): that account's settings apply, never another's
|
|
149
|
+
personal = personalAuth(app.auth);
|
|
150
|
+
if (personal) {
|
|
151
|
+
const mine = await db
|
|
152
|
+
.selectFrom("connector_tool_account_policies")
|
|
153
|
+
.select("policy")
|
|
154
|
+
.where("connector_id", "=", tool.source.connectorId)
|
|
155
|
+
.where("account_id", "=", ctx.accountId)
|
|
156
|
+
.where("tool_name", "=", tool.source.name)
|
|
157
|
+
.executeTakeFirst();
|
|
158
|
+
memberSetting = mine?.policy;
|
|
159
|
+
}
|
|
108
160
|
}
|
|
109
161
|
// 沙箱工具的组织默认(M5 T8):组织设置 sandboxToolPolicy 为 ask 时,有副作用的沙箱工具至少 ask
|
|
110
162
|
// `orgAsk`: the org setting, not the tool's own default, is what makes it ask
|
|
@@ -116,7 +168,7 @@ export function createDecidePolicy(db) {
|
|
|
116
168
|
}
|
|
117
169
|
}
|
|
118
170
|
// 运行所用版本可能是加 toolPolicies 字段之前保存的:缺省为空
|
|
119
|
-
const
|
|
171
|
+
const runSetting = settingOf(agentDef.toolPolicies, tool.key, policyKey);
|
|
120
172
|
const current = await db
|
|
121
173
|
.selectFrom("agents")
|
|
122
174
|
.innerJoin("agent_versions", (j) => j
|
|
@@ -130,12 +182,33 @@ export function createDecidePolicy(db) {
|
|
|
130
182
|
? undefined
|
|
131
183
|
: await normalizeStoredDefinitionIn(db, ctx.orgId, current.definition);
|
|
132
184
|
const currentPolicies = currentDef?.toolPolicies;
|
|
133
|
-
const
|
|
134
|
-
|
|
185
|
+
const currentSetting = settingOf(currentPolicies, tool.key, policyKey);
|
|
186
|
+
// the run's version, the agent's current version and (a sub-agent) its parent agent's
|
|
187
|
+
// current version: the stricter of the ones that are set
|
|
188
|
+
// (an `allow` the owner removed since the run started no longer applies: removing it tightens)
|
|
189
|
+
const runKept = runSetting === "allow" && current !== undefined && currentSetting === undefined
|
|
190
|
+
? undefined
|
|
191
|
+
: runSetting;
|
|
192
|
+
let agentSetting = combine(runKept, currentSetting);
|
|
135
193
|
if (ctx.parentConversationId !== undefined && ctx.parentAgentDiffers !== false) {
|
|
136
|
-
|
|
194
|
+
agentSetting = combine(agentSetting, await parentAgentSetting(db, tool.key, policyKey, ctx));
|
|
195
|
+
}
|
|
196
|
+
let agentOverride = tighteningOf(agentSetting);
|
|
197
|
+
// A personal-credential connector's tool: the levels of `connectorPolicy` decide its base
|
|
198
|
+
// policy (an agent's `allow` counts here, below the org's and the member's deny). A connector
|
|
199
|
+
// with one org credential has no member level and its calls act as the whole org: there the
|
|
200
|
+
// agent's setting only tightens the org default, as for every other tool (review 2026-11-09)
|
|
201
|
+
let decidedBy = null;
|
|
202
|
+
if (tool.source.kind === "connector" && personal) {
|
|
203
|
+
const r = connectorPolicy({
|
|
204
|
+
orgDefault: connectorDefault,
|
|
205
|
+
member: memberSetting,
|
|
206
|
+
agent: agentSetting,
|
|
207
|
+
});
|
|
208
|
+
connectorDefault = r.policy;
|
|
209
|
+
decidedBy = r.source;
|
|
210
|
+
agentOverride = undefined;
|
|
137
211
|
}
|
|
138
|
-
const agentOverride = strictest === "allow" ? undefined : strictest;
|
|
139
212
|
let escalateTo = null;
|
|
140
213
|
if (tool.requiredRole !== undefined) {
|
|
141
214
|
const m = await db
|
|
@@ -184,15 +257,17 @@ export function createDecidePolicy(db) {
|
|
|
184
257
|
// default
|
|
185
258
|
policy: escalateTo !== null
|
|
186
259
|
? "role"
|
|
187
|
-
: agentOverride === "ask"
|
|
260
|
+
: agentOverride === "ask" || (decidedBy === "agent" && connectorDefault === "ask")
|
|
188
261
|
? "agent"
|
|
189
|
-
:
|
|
190
|
-
? "
|
|
191
|
-
:
|
|
192
|
-
? "
|
|
193
|
-
:
|
|
194
|
-
? "
|
|
195
|
-
:
|
|
262
|
+
: decidedBy === "member" && connectorDefault === "ask"
|
|
263
|
+
? "member"
|
|
264
|
+
: tool.source.kind === "connector" && connectorDefault === "ask"
|
|
265
|
+
? "connector"
|
|
266
|
+
: fixedAsk
|
|
267
|
+
? "fixed"
|
|
268
|
+
: orgAsk
|
|
269
|
+
? "org"
|
|
270
|
+
: "default",
|
|
196
271
|
};
|
|
197
272
|
return { ask };
|
|
198
273
|
};
|
|
@@ -203,7 +278,7 @@ export function createDecidePolicy(db) {
|
|
|
203
278
|
* policy for the same key applies on top, so the parent's owner can tighten a running child too.
|
|
204
279
|
* For a template or general-purpose child the parent conversation has the same agent, already read.
|
|
205
280
|
*/
|
|
206
|
-
async function
|
|
281
|
+
async function parentAgentSetting(db, toolKey, policyKey, ctx) {
|
|
207
282
|
const row = await db
|
|
208
283
|
.selectFrom("conversations as c")
|
|
209
284
|
.innerJoin("agents as a", "a.id", "c.agent_id")
|
|
@@ -216,7 +291,7 @@ async function parentAgentOverride(db, toolKey, policyKey, ctx) {
|
|
|
216
291
|
// stored raw: an rc version's keys read as current keys, so its deny keeps applying (§8.3)
|
|
217
292
|
const policies = (await normalizeStoredDefinitionIn(db, ctx.orgId, row.definition))
|
|
218
293
|
.toolPolicies;
|
|
219
|
-
return
|
|
294
|
+
return settingOf(policies, toolKey, policyKey);
|
|
220
295
|
}
|
|
221
296
|
/**
|
|
222
297
|
* A grant matching the current definition hash and source connector, keyed by the call's policy key
|
|
@@ -26,6 +26,7 @@ import { ApprovalsService } from "./approvals.service.js";
|
|
|
26
26
|
import { Breaker } from "./breaker.js";
|
|
27
27
|
import { BuiltinTools } from "./builtins/builtin-tools.js";
|
|
28
28
|
import { WebPages } from "./builtins/web/page-cache.js";
|
|
29
|
+
import { ConnectorAccountPolicies } from "./connector-account-policies.js";
|
|
29
30
|
import { ConnectorContent } from "./connector-content.js";
|
|
30
31
|
import { ConnectorsService } from "./connectors.service.js";
|
|
31
32
|
import { Credentials } from "./credentials.js";
|
|
@@ -86,6 +87,7 @@ ToolsModule = __decorate([
|
|
|
86
87
|
ConnectorContent,
|
|
87
88
|
ToolPipeline,
|
|
88
89
|
ConnectorsService,
|
|
90
|
+
ConnectorAccountPolicies,
|
|
89
91
|
OAuthFlow,
|
|
90
92
|
ConversationToolInfo,
|
|
91
93
|
OrgExtensionTools,
|
|
@@ -103,6 +105,7 @@ ToolsModule = __decorate([
|
|
|
103
105
|
ConnectorContent,
|
|
104
106
|
ToolPipeline,
|
|
105
107
|
ConnectorsService,
|
|
108
|
+
ConnectorAccountPolicies,
|
|
106
109
|
OAuthFlow,
|
|
107
110
|
ConversationToolInfo,
|
|
108
111
|
OrgExtensionTools,
|
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.12",
|
|
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.8"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@langchain/langgraph-checkpoint-validation": "^1.2.0",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@types/ws": "^8.18.2",
|
|
75
75
|
"@types/yauzl": "3.4.0",
|
|
76
76
|
"ws": "^8.22.0",
|
|
77
|
-
"@capybara-hq/testing": "0.1.0-rc.
|
|
77
|
+
"@capybara-hq/testing": "0.1.0-rc.11"
|
|
78
78
|
},
|
|
79
79
|
"scripts": {
|
|
80
80
|
"build": "tsc -b"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
-- Themes as a platform component kind (themes spec 2026-11-08-themes-design.md §6, §7): rows and
|
|
2
|
+
-- versions shaped like platform agent templates, with the owner columns of org-owned items; the
|
|
3
|
+
-- `theme` kind in the component scope, switch and install component tables; the person's pick on
|
|
4
|
+
-- the account. Expand-only: the only dropped objects are the three kind checks, re-added wider in
|
|
5
|
+
-- the next statement each.
|
|
6
|
+
|
|
7
|
+
CREATE TABLE IF NOT EXISTS platform_themes (
|
|
8
|
+
id text PRIMARY KEY,
|
|
9
|
+
catalog_item_id uuid REFERENCES catalog_items(id) ON DELETE SET NULL,
|
|
10
|
+
plugin_name text,
|
|
11
|
+
name text NOT NULL,
|
|
12
|
+
description text,
|
|
13
|
+
description_zh text,
|
|
14
|
+
current_version integer NOT NULL CHECK (current_version >= 1),
|
|
15
|
+
scope_mode text NOT NULL DEFAULT 'follow' CHECK (scope_mode IN ('follow', 'own')),
|
|
16
|
+
scope text NOT NULL DEFAULT 'optional' CHECK (scope IN ('all', 'optional', 'named')),
|
|
17
|
+
disabled boolean NOT NULL DEFAULT false,
|
|
18
|
+
shown_to_others boolean NOT NULL DEFAULT true,
|
|
19
|
+
scope_version integer NOT NULL DEFAULT 0,
|
|
20
|
+
-- The owning org (NULL = the platform), the org it was created in (no FK, immutable) and the
|
|
21
|
+
-- share switch, as on the other platform components (0084).
|
|
22
|
+
owner_org_id text REFERENCES orgs(id) ON DELETE SET NULL,
|
|
23
|
+
origin_org_id text,
|
|
24
|
+
shareable boolean NOT NULL DEFAULT false,
|
|
25
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
26
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
27
|
+
deleted_at timestamptz
|
|
28
|
+
);
|
|
29
|
+
CREATE UNIQUE INDEX IF NOT EXISTS platform_themes_live_name_origin_uq
|
|
30
|
+
ON platform_themes ((coalesce(plugin_name, '')), name, (coalesce(origin_org_id, '')))
|
|
31
|
+
WHERE deleted_at IS NULL;
|
|
32
|
+
|
|
33
|
+
-- One version of a theme: `definition` is the parsed theme file (`ParsedTheme`); fonts and logo
|
|
34
|
+
-- live under `object_prefix` in `deployment/` (NULL for a theme without assets).
|
|
35
|
+
CREATE TABLE IF NOT EXISTS platform_theme_versions (
|
|
36
|
+
theme_id text NOT NULL REFERENCES platform_themes(id) ON DELETE CASCADE,
|
|
37
|
+
version integer NOT NULL CHECK (version >= 1),
|
|
38
|
+
definition jsonb NOT NULL,
|
|
39
|
+
object_prefix text,
|
|
40
|
+
catalog_version text,
|
|
41
|
+
updated_on_own boolean NOT NULL DEFAULT false,
|
|
42
|
+
created_by text,
|
|
43
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
44
|
+
PRIMARY KEY (theme_id, version)
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
-- 0081 declared these checks inline, so they carry the default names.
|
|
48
|
+
-- capybara:allow-destructive the check is added back with 'theme' in the next statement; existing rows satisfy it
|
|
49
|
+
ALTER TABLE component_scope_orgs DROP CONSTRAINT IF EXISTS component_scope_orgs_kind_check;
|
|
50
|
+
ALTER TABLE component_scope_orgs ADD CONSTRAINT component_scope_orgs_kind_check
|
|
51
|
+
CHECK (kind IN ('skill', 'agent_template', 'connector_template', 'theme'));
|
|
52
|
+
-- capybara:allow-destructive the check is added back with 'theme' in the next statement; existing rows satisfy it
|
|
53
|
+
ALTER TABLE component_org_switches DROP CONSTRAINT IF EXISTS component_org_switches_kind_check;
|
|
54
|
+
ALTER TABLE component_org_switches ADD CONSTRAINT component_org_switches_kind_check
|
|
55
|
+
CHECK (kind IN ('skill', 'agent_template', 'connector_template', 'theme'));
|
|
56
|
+
-- NOT VALID as in 0053: existing rows were checked by the narrower constraint already.
|
|
57
|
+
-- capybara:allow-destructive the check is added back with 'theme' in the next statement; existing rows satisfy it
|
|
58
|
+
ALTER TABLE plugin_install_components DROP CONSTRAINT IF EXISTS plugin_install_components_kind_check;
|
|
59
|
+
ALTER TABLE plugin_install_components ADD CONSTRAINT plugin_install_components_kind_check
|
|
60
|
+
CHECK (kind IN ('extension', 'connector', 'skill', 'plugin', 'agent_template', 'theme')) NOT VALID;
|
|
61
|
+
|
|
62
|
+
-- The person's theme (§7): one value across all their orgs; NULL follows the org. No FK: a pick
|
|
63
|
+
-- that is not on in the current org (or no longer exists) is skipped, never an error.
|
|
64
|
+
ALTER TABLE accounts ADD COLUMN IF NOT EXISTS theme text;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- The platform default theme setting `uiTheme` (themes spec §7) always has a row: the guards that
|
|
2
|
+
-- refuse taking the default theme away from an org read it FOR SHARE, and the setting's write
|
|
3
|
+
-- locks it FOR UPDATE before checking the chosen theme, so the two serialize on this row.
|
|
4
|
+
-- `{"id": null}` is the built-in theme (the default when the key is missing).
|
|
5
|
+
INSERT INTO deployment_settings (key, value)
|
|
6
|
+
VALUES ('uiTheme', '{"id": null}'::jsonb)
|
|
7
|
+
ON CONFLICT (key) DO NOTHING;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-- A member's own tool policies for their own connection of a personal-credential connector
|
|
2
|
+
-- (maintainer decision 2026-11-09, the connector card's 权限): one row per account, connector and
|
|
3
|
+
-- tool name. They apply to every agent the account uses; an agent's tool policy overrides them, and
|
|
4
|
+
-- a tool the org switched off (or set to deny) stays denied whatever they say.
|
|
5
|
+
CREATE TABLE IF NOT EXISTS capybara.connector_tool_account_policies (
|
|
6
|
+
org_id text NOT NULL REFERENCES capybara.orgs(id) ON DELETE CASCADE,
|
|
7
|
+
connector_id text NOT NULL REFERENCES capybara.connectors(id) ON DELETE CASCADE,
|
|
8
|
+
account_id text NOT NULL REFERENCES capybara.accounts(id) ON DELETE CASCADE,
|
|
9
|
+
tool_name text NOT NULL,
|
|
10
|
+
policy text NOT NULL CHECK (policy IN ('allow', 'ask', 'deny')),
|
|
11
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
12
|
+
PRIMARY KEY (connector_id, account_id, tool_name)
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX IF NOT EXISTS connector_tool_account_policies_account
|
|
16
|
+
ON capybara.connector_tool_account_policies (account_id);
|