evolcore 0.0.10 → 0.0.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/CHANGELOG.md +44 -0
- package/README.md +3 -3
- package/bin/codex-managed-hook.mjs +80 -0
- package/dist/agents/baseagent.js +4 -0
- package/dist/agents/claude-runner.js +158 -44
- package/dist/agents/codex-app-server-client.js +153 -23
- package/dist/agents/codex-runner.js +331 -43
- package/dist/agents/ecagent-runner.js +53 -6
- package/dist/agents/gemini-runner.js +1 -0
- package/dist/agents/request-identity.js +55 -0
- package/dist/aun/aid/client.js +11 -21
- package/dist/aun/aid/managed-operation.js +107 -0
- package/dist/aun/msg/group.js +81 -12
- package/dist/aun/msg/managed-operation.js +804 -0
- package/dist/aun/msg/mention-schema.js +20 -0
- package/dist/aun/msg/p2p.js +7 -0
- package/dist/aun/outbox.js +28 -31
- package/dist/channels/aun.js +418 -235
- package/dist/channels/daemon.js +13 -0
- package/dist/cli/agent-command.js +72 -17
- package/dist/cli/agent.js +249 -22
- package/dist/cli/aun-commands.js +270 -69
- package/dist/cli/bench.js +12 -3
- package/dist/cli/daemon-commands.js +52 -33
- package/dist/cli/fs-command.js +60 -0
- package/dist/cli/handoff-command.js +3 -0
- package/dist/cli/index.js +106 -63
- package/dist/cli/init-cancel.js +208 -0
- package/dist/cli/init-channel.js +343 -195
- package/dist/cli/init.js +21 -9
- package/dist/cli/managed-command-guard.js +41 -0
- package/dist/cli/model.js +11 -4
- package/dist/cli/queue-command.js +11 -1
- package/dist/cli/response.js +71 -0
- package/dist/cli/restart-monitor.js +4 -18
- package/dist/cli/trigger-command.js +4 -0
- package/dist/config/builtin-roles.js +5 -0
- package/dist/config/contact-book-store.js +11 -3
- package/dist/config/contact-request-service.js +161 -15
- package/dist/config/gateway-config.js +26 -10
- package/dist/config/mention-mode.js +8 -24
- package/dist/core/agent-reload-coordinator.js +53 -0
- package/dist/core/auth/agent-delegation.js +0 -1
- package/dist/core/auth/operation-authorizer.js +62 -154
- package/dist/core/auth/operation-catalog.js +264 -22
- package/dist/core/bootstrap-messages.js +68 -0
- package/dist/core/bootstrap-service.js +144 -10
- package/dist/core/capability/providers/claude-capability-provider.js +9 -31
- package/dist/core/capability/providers/codex-capability-provider.js +4 -15
- package/dist/core/capability/skill-discovery.js +55 -0
- package/dist/core/channel-loader.js +24 -7
- package/dist/core/command/agent-control.js +14 -11
- package/dist/core/command/cli-intent-parser.js +9 -0
- package/dist/core/command/command-handler.js +467 -6
- package/dist/core/command/connect-menu.js +15 -0
- package/dist/core/command/group-menu.js +4 -4
- package/dist/core/command/menu-catalog.js +366 -0
- package/dist/core/command/menu-handler.js +213 -110
- package/dist/core/command/menu-protocol.js +71 -0
- package/dist/core/command/slash-gate.js +5 -2
- package/dist/core/command/slash-handler.js +45 -25
- package/dist/core/daemon-file-cache.js +2 -1
- package/dist/core/data-migration.js +9 -2
- package/dist/core/evolagent-registry.js +125 -35
- package/dist/core/evolagent.js +12 -5
- package/dist/core/handoff/dispatcher.js +5 -2
- package/dist/core/handoff/runtime.js +145 -21
- package/dist/core/handoff/store.js +24 -0
- package/dist/core/handoff/types.js +1 -0
- package/dist/core/inference/text-inference.js +38 -4
- package/dist/core/message/logical-queue-bridge.js +1 -0
- package/dist/core/message/mention-schema.js +126 -0
- package/dist/core/message/message-bridge.js +237 -79
- package/dist/core/message/message-log.js +23 -0
- package/dist/core/message/message-queue.js +20 -4
- package/dist/core/message/response-engine.js +54 -36
- package/dist/core/model/model-catalog.js +143 -24
- package/dist/core/model/model-diagnostics.js +28 -10
- package/dist/core/permission/ec-command-parser.js +156 -10
- package/dist/core/permission/index.js +1 -0
- package/dist/core/permission/readonly-shell-query.js +532 -0
- package/dist/core/permission/sandbox-runtime.js +22 -1
- package/dist/core/permission/shell-environment.js +46 -0
- package/dist/core/permission/tool-policy.js +292 -111
- package/dist/core/protected-paths.js +17 -9
- package/dist/core/runner-reload-transaction.js +57 -0
- package/dist/core/session/session-manager.js +21 -2
- package/dist/eck/manifest-engine.js +39 -13
- package/dist/index.js +644 -180
- package/dist/ipc.js +246 -19
- package/dist/response-system/coordinator.js +6 -4
- package/dist/response-system/engines/v1/proactive-flow.js +26 -8
- package/dist/response-system/modes/single-session/index.js +14 -1
- package/dist/response-system/selector.js +6 -5
- package/dist/trigger/anomaly-store.js +4 -0
- package/dist/trigger/script-executor.js +1 -0
- package/dist/utils/aid-bind.js +3 -8
- package/dist/utils/codex-app-server-registry.js +90 -0
- package/dist/utils/codex-cli.js +5 -1
- package/dist/utils/cross-platform.js +15 -0
- package/dist/utils/log-writer.js +6 -10
- package/dist/utils/logger.js +5 -5
- package/dist/utils/npm-ops.js +5 -12
- package/dist/utils/tool-summary.js +11 -0
- package/kits/docs/channels/aun.md +1 -1
- package/kits/docs/context-assembly.md +2 -2
- package/kits/docs/evolcore/agent.md +11 -6
- package/kits/docs/evolcore/aid.md +14 -0
- package/kits/docs/evolcore/msg.md +13 -0
- package/kits/docs/prompt-loading-architecture.md +1 -2
- package/kits/docs/venues/group.md +1 -1
- package/kits/eck_manifest.json +0 -12
- package/kits/rules/01-overview.md +9 -0
- package/kits/rules/04-relation.md +1 -1
- package/kits/rules/05-venue.md +2 -2
- package/kits/schemas/agent-config.schema.3.json +1 -1
- package/kits/schemas/agent-config.schema.4.json +1 -1
- package/kits/schemas/relation-config.schema.2.json +1 -1
- package/kits/schemas/role-config.schema.1.json +1 -1
- package/kits/schemas/single-session.schema.1.json +3 -3
- package/kits/schemas/single-session.schema.2.json +3 -3
- package/kits/templates/roles/admin.json +27 -0
- package/kits/templates/roles/member.json +44 -0
- package/kits/templates/roles/visitor.json +40 -2
- package/kits/templates/system-fragments/bootstrap.md +12 -6
- package/kits/templates/system-fragments/channel.md +6 -0
- package/kits/templates/system-fragments/session.md +2 -0
- package/package.json +3 -2
- package/skills/eclink/SKILL.md +15 -3
- package/skills/eclink/agents/openai.yaml +3 -3
- package/dist/core/command/evol-menu-version-gate.js +0 -39
|
@@ -5,68 +5,6 @@ import { isResolvedConfigMutation, } from '../../config/resolved-config-op.js';
|
|
|
5
5
|
import { normalizePeer } from '../model/config-scope.js';
|
|
6
6
|
import { getOperationMeta } from './operation-catalog.js';
|
|
7
7
|
import { formatPeerKey, parsePeerKey } from '../relation/peer-identity.js';
|
|
8
|
-
export const USER_PLANE_CAPABILITY_CEILING = {
|
|
9
|
-
allowOperations: new Set([
|
|
10
|
-
'model.list',
|
|
11
|
-
'model.current',
|
|
12
|
-
'model.use',
|
|
13
|
-
'model.effort',
|
|
14
|
-
'model.reset',
|
|
15
|
-
'permission.current',
|
|
16
|
-
'permission.answer',
|
|
17
|
-
'chatmode.current',
|
|
18
|
-
'chatmode.update',
|
|
19
|
-
'mentionmode.current',
|
|
20
|
-
'mentionmode.update',
|
|
21
|
-
'group.mentionmode.current',
|
|
22
|
-
'group.rulespolicy.current',
|
|
23
|
-
'session.list',
|
|
24
|
-
'session.create',
|
|
25
|
-
'session.rename',
|
|
26
|
-
'trigger.list',
|
|
27
|
-
'trigger.show',
|
|
28
|
-
'trigger.history',
|
|
29
|
-
'trigger.eventCatalog',
|
|
30
|
-
'trigger.create',
|
|
31
|
-
'trigger.update',
|
|
32
|
-
'trigger.setEnabled',
|
|
33
|
-
'trigger.cancel',
|
|
34
|
-
'trigger.delete',
|
|
35
|
-
'trigger.run',
|
|
36
|
-
'stats.summary',
|
|
37
|
-
'stats.session',
|
|
38
|
-
'stats.context',
|
|
39
|
-
'file.list',
|
|
40
|
-
'file.fetch',
|
|
41
|
-
'ec.msg.send',
|
|
42
|
-
'ec.msg.file',
|
|
43
|
-
'ec.group.send',
|
|
44
|
-
'ec.group.file',
|
|
45
|
-
'config.get',
|
|
46
|
-
'config.set',
|
|
47
|
-
'config.unset',
|
|
48
|
-
]),
|
|
49
|
-
denyOperations: new Set([
|
|
50
|
-
'role.assign',
|
|
51
|
-
'role.revoke',
|
|
52
|
-
'config.write',
|
|
53
|
-
'gateway.write',
|
|
54
|
-
'cli.exec.raw',
|
|
55
|
-
'shell.exec',
|
|
56
|
-
'rce.exec',
|
|
57
|
-
]),
|
|
58
|
-
denyNamespaces: new Set([
|
|
59
|
-
'role',
|
|
60
|
-
'connect',
|
|
61
|
-
'contact',
|
|
62
|
-
'agent',
|
|
63
|
-
'system',
|
|
64
|
-
'storage',
|
|
65
|
-
'aid',
|
|
66
|
-
]),
|
|
67
|
-
allowCategories: new Set(['read', 'write-own']),
|
|
68
|
-
denyCategories: new Set(['write-agent', 'process', 'dangerous']),
|
|
69
|
-
};
|
|
70
8
|
export function authorizeCommand(ctx) {
|
|
71
9
|
return authorizeCommandInternal(ctx);
|
|
72
10
|
}
|
|
@@ -84,68 +22,33 @@ export function authorizeResolvedConfigCommand(command, context) {
|
|
|
84
22
|
* enforced here.
|
|
85
23
|
*/
|
|
86
24
|
export function evaluateRoleOperationCapability(params) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
const roleDef = getRoleDefinition(params.role, params.selfAid);
|
|
96
|
-
if (!roleDef || roleDef.allowAccess === false) {
|
|
97
|
-
return {
|
|
98
|
-
allow: false,
|
|
99
|
-
operation: params.operation,
|
|
100
|
-
reason: `Role ${params.role} cannot access commands`,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
const matched = matchCommandPermission(params.operation, opMeta.category, roleDef.commandPermissions || {}, opMeta.dangerous);
|
|
104
|
-
if (!matched) {
|
|
105
|
-
return {
|
|
106
|
-
allow: false,
|
|
107
|
-
operation: params.operation,
|
|
108
|
-
reason: `Role ${params.role} has no permission for ${params.operation}`,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
const { permission, matchedRule } = matched;
|
|
112
|
-
if (!permission.allow) {
|
|
113
|
-
return {
|
|
114
|
-
allow: false,
|
|
115
|
-
operation: params.operation,
|
|
116
|
-
reason: permission.reason || `Role ${params.role} explicitly denies ${params.operation}`,
|
|
117
|
-
matchedRule,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
const scopes = permission.scopes || opMeta.defaultScopes;
|
|
121
|
-
if (!scopes.includes(params.scope)) {
|
|
122
|
-
return {
|
|
123
|
-
allow: false,
|
|
25
|
+
// Capability discovery has no concrete relation target. Use a synthetic
|
|
26
|
+
// self relation so target/current-relation constraints are evaluated as
|
|
27
|
+
// role capabilities without weakening the real authorization path.
|
|
28
|
+
const capabilitySelf = params.selfAid ?? 'capability.agentid.pub';
|
|
29
|
+
const capabilityPeer = formatPeerKey('aun', capabilitySelf);
|
|
30
|
+
const decision = authorizeCommand({
|
|
31
|
+
intent: {
|
|
124
32
|
operation: params.operation,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
if (opMeta.dangerous && !isExplicitDangerousGrant(matchedRule, permission)) {
|
|
146
|
-
return { allow: false, operation: params.operation, reason: 'Dangerous operation is not explicitly granted', matchedRule };
|
|
147
|
-
}
|
|
148
|
-
return { allow: true, operation: params.operation, matchedRule };
|
|
33
|
+
scope: params.scope,
|
|
34
|
+
source: 'menu',
|
|
35
|
+
args: {
|
|
36
|
+
self: capabilitySelf,
|
|
37
|
+
peer: capabilityPeer,
|
|
38
|
+
peerKey: capabilityPeer,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
selfAid: capabilitySelf,
|
|
42
|
+
peerKey: capabilityPeer,
|
|
43
|
+
role: params.role,
|
|
44
|
+
chatType: params.chatType,
|
|
45
|
+
isDaemonOwner: params.fromControlChannel && params.role === 'owner',
|
|
46
|
+
fromControlChannel: params.fromControlChannel,
|
|
47
|
+
source: 'menu',
|
|
48
|
+
});
|
|
49
|
+
return decision.allow
|
|
50
|
+
? { allow: true, operation: params.operation, matchedRule: decision.matchedRule }
|
|
51
|
+
: { allow: false, operation: params.operation, reason: decision.reason, matchedRule: decision.matchedRule };
|
|
149
52
|
}
|
|
150
53
|
function authorizeCommandInternal(ctx, resolvedConfigCommand) {
|
|
151
54
|
const { intent, role } = ctx;
|
|
@@ -208,11 +111,6 @@ function authorizeCommandInternal(ctx, resolvedConfigCommand) {
|
|
|
208
111
|
if (roleDef.allowAccess === false) {
|
|
209
112
|
return denyDecision(ctx, 'ROLE_ACCESS_DENIED', `Role ${role} is not allowed to access commands`, operation, intent.scope, opMeta.dangerous);
|
|
210
113
|
}
|
|
211
|
-
if (!isManagementRole(role)
|
|
212
|
-
&& !resolvedConfigCommand
|
|
213
|
-
&& !isUserPlaneOperationAllowed(operation, opMeta.category, opMeta.dangerous)) {
|
|
214
|
-
return denyDecision(ctx, 'NOT_ALLOWED', `Operation ${operation} is outside the user permission plane`, operation, intent.scope, opMeta.dangerous);
|
|
215
|
-
}
|
|
216
114
|
const matchResult = matchCommandPermission(operation, opMeta.category, roleDef.commandPermissions || {}, opMeta.dangerous);
|
|
217
115
|
if (!matchResult) {
|
|
218
116
|
return denyDecision(ctx, 'NO_PERMISSION', `Role ${role} has no permission for ${operation}`, operation, intent.scope, opMeta.dangerous);
|
|
@@ -261,7 +159,7 @@ function authorizeCommandInternal(ctx, resolvedConfigCommand) {
|
|
|
261
159
|
if (permission.constraints) {
|
|
262
160
|
const constraintCheck = checkConstraints(ctx, permission.constraints, resolvedConfigCommand);
|
|
263
161
|
if (!constraintCheck.ok) {
|
|
264
|
-
return denyDecision(ctx, 'ARGUMENT_MISMATCH', constraintCheck.reason || 'Command arguments do not satisfy permission constraints', operation, intent.scope, opMeta.dangerous, matchedRule);
|
|
162
|
+
return denyDecision(ctx, constraintCheck.code ?? 'ARGUMENT_MISMATCH', constraintCheck.reason || 'Command arguments do not satisfy permission constraints', operation, intent.scope, opMeta.dangerous, matchedRule);
|
|
265
163
|
}
|
|
266
164
|
}
|
|
267
165
|
return {
|
|
@@ -275,10 +173,9 @@ function authorizeCommandInternal(ctx, resolvedConfigCommand) {
|
|
|
275
173
|
};
|
|
276
174
|
}
|
|
277
175
|
function matchCommandPermission(operation, category, commandPerms, isDangerous) {
|
|
278
|
-
const namespace = operation.split('.')[0];
|
|
279
176
|
const matches = [];
|
|
280
177
|
for (const [rule, permission] of Object.entries(commandPerms)) {
|
|
281
|
-
const rank = getRuleRank(rule, permission, operation,
|
|
178
|
+
const rank = getRuleRank(rule, permission, operation, category, isDangerous);
|
|
282
179
|
if (rank > 0) {
|
|
283
180
|
matches.push({ permission, matchedRule: rule, rank });
|
|
284
181
|
}
|
|
@@ -288,12 +185,17 @@ function matchCommandPermission(operation, category, commandPerms, isDangerous)
|
|
|
288
185
|
matches.sort((a, b) => b.rank - a.rank);
|
|
289
186
|
return matches[0];
|
|
290
187
|
}
|
|
291
|
-
function getRuleRank(rule, permission, operation,
|
|
188
|
+
function getRuleRank(rule, permission, operation, category, isDangerous) {
|
|
292
189
|
const denyOffset = permission.allow ? 0 : 1;
|
|
293
190
|
if (rule === operation)
|
|
294
191
|
return 1000 + denyOffset;
|
|
295
|
-
if (rule
|
|
296
|
-
|
|
192
|
+
if (rule.endsWith('.*')) {
|
|
193
|
+
const prefix = rule.slice(0, -1);
|
|
194
|
+
if (operation.startsWith(prefix)) {
|
|
195
|
+
const depth = rule.slice(0, -2).split('.').length;
|
|
196
|
+
return 800 + Math.min((depth - 1) * 20, 180) + denyOffset;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
297
199
|
if (rule.startsWith('category:') && rule.slice('category:'.length) === category)
|
|
298
200
|
return 600 + denyOffset;
|
|
299
201
|
if (rule === 'dangerous:*' && isDangerous)
|
|
@@ -305,20 +207,6 @@ function getRuleRank(rule, permission, operation, namespace, category, isDangero
|
|
|
305
207
|
function isExplicitDangerousGrant(rule, permission) {
|
|
306
208
|
return permission.allow === true && permission.dangerous === true && (rule === 'dangerous:*' || !rule.includes('*') && !rule.startsWith('category:'));
|
|
307
209
|
}
|
|
308
|
-
function isUserPlaneOperationAllowed(operation, category, dangerous) {
|
|
309
|
-
const namespace = operation.split('.')[0];
|
|
310
|
-
if (dangerous)
|
|
311
|
-
return false;
|
|
312
|
-
if (USER_PLANE_CAPABILITY_CEILING.denyCategories.has(category))
|
|
313
|
-
return false;
|
|
314
|
-
if (!USER_PLANE_CAPABILITY_CEILING.allowCategories.has(category))
|
|
315
|
-
return false;
|
|
316
|
-
if (USER_PLANE_CAPABILITY_CEILING.denyOperations.has(operation))
|
|
317
|
-
return false;
|
|
318
|
-
if (USER_PLANE_CAPABILITY_CEILING.denyNamespaces.has(namespace))
|
|
319
|
-
return false;
|
|
320
|
-
return USER_PLANE_CAPABILITY_CEILING.allowOperations.has(operation);
|
|
321
|
-
}
|
|
322
210
|
function checkConstraints(ctx, constraints, resolvedConfigCommand) {
|
|
323
211
|
if (constraints.ownPeerOnly) {
|
|
324
212
|
const peerCheck = checkOwnPeer(ctx);
|
|
@@ -326,16 +214,17 @@ function checkConstraints(ctx, constraints, resolvedConfigCommand) {
|
|
|
326
214
|
return peerCheck;
|
|
327
215
|
}
|
|
328
216
|
if (constraints.ownAgentOnly || constraints.targetCurrentAgentOnly) {
|
|
329
|
-
const
|
|
330
|
-
|
|
217
|
+
const controlOwnerOverride = ctx.fromControlChannel && ctx.isDaemonOwner;
|
|
218
|
+
const targetAid = stringArg(ctx.intent.args.self) ?? stringArg(ctx.intent.args.aid);
|
|
219
|
+
if (!controlOwnerOverride && (!ctx.selfAid || !targetAid || targetAid !== ctx.selfAid)) {
|
|
331
220
|
return { ok: false, reason: 'Only the current agent can be targeted' };
|
|
332
221
|
}
|
|
333
222
|
}
|
|
334
223
|
if (constraints.requireAgentOwner && ctx.role !== 'owner') {
|
|
335
|
-
return { ok: false, reason: 'This command requires agent owner permission' };
|
|
224
|
+
return { ok: false, code: 'NO_PERMISSION', reason: 'This command requires agent owner permission' };
|
|
336
225
|
}
|
|
337
226
|
if (constraints.requireAgentAdmin && ctx.role !== 'owner' && ctx.role !== 'admin') {
|
|
338
|
-
return { ok: false, reason: 'This command requires agent admin permission' };
|
|
227
|
+
return { ok: false, code: 'NO_PERMISSION', reason: 'This command requires agent admin permission' };
|
|
339
228
|
}
|
|
340
229
|
if (constraints.privateOnly && ctx.chatType !== 'private') {
|
|
341
230
|
return { ok: false, reason: 'This command is only allowed in private chats' };
|
|
@@ -345,7 +234,7 @@ function checkConstraints(ctx, constraints, resolvedConfigCommand) {
|
|
|
345
234
|
const sameGroup = constraints.currentRelationOnly ? ' and may only target that same group' : '';
|
|
346
235
|
return {
|
|
347
236
|
ok: false,
|
|
348
|
-
reason: `Denied ${ctx.intent.operation}: role=${ctx.role}, source_chat=${ctx.chatType ?? 'unknown'}, target_group=${target}. This role may
|
|
237
|
+
reason: `Denied ${ctx.intent.operation}: role=${ctx.role}, source_chat=${ctx.chatType ?? 'unknown'}, target_group=${target}. This role may access group operations only from a group-chat task${sameGroup}; the target being a group is not sufficient.`,
|
|
349
238
|
};
|
|
350
239
|
}
|
|
351
240
|
if (constraints.requireDaemonOwner && !ctx.isDaemonOwner) {
|
|
@@ -516,7 +405,7 @@ function checkCurrentRelation(ctx, resolvedConfigCommand) {
|
|
|
516
405
|
const targetGroup = stringArg(ctx.intent.args.targetId) ?? peerIdFromArg(requestedPeer);
|
|
517
406
|
return {
|
|
518
407
|
ok: false,
|
|
519
|
-
reason: `Denied ${ctx.intent.operation}: role=${ctx.role}, current_group=${currentGroup}, target_group=${targetGroup}. This role may
|
|
408
|
+
reason: `Denied ${ctx.intent.operation}: role=${ctx.role}, current_group=${currentGroup}, target_group=${targetGroup}. This role may access only the current group; cross-group access requires admin or owner permission.`,
|
|
520
409
|
};
|
|
521
410
|
}
|
|
522
411
|
return { ok: false, reason: 'Only the current relation can be targeted' };
|
|
@@ -613,6 +502,25 @@ function checkOwnPeer(ctx) {
|
|
|
613
502
|
return { ok: true };
|
|
614
503
|
const requestedPeerId = argPeer ? peerIdFromArg(argPeer) : undefined;
|
|
615
504
|
const requestedPeerKeyId = argPeerKey ? peerIdFromArg(argPeerKey) : undefined;
|
|
505
|
+
if (ctx.chatType === 'group') {
|
|
506
|
+
if (!expectedPeerKey)
|
|
507
|
+
return { ok: false, reason: 'Cannot verify peer ownership' };
|
|
508
|
+
const candidateKeys = new Set();
|
|
509
|
+
if (argPeerKey)
|
|
510
|
+
candidateKeys.add(argPeerKey);
|
|
511
|
+
if (argPeer) {
|
|
512
|
+
candidateKeys.add(argPeer);
|
|
513
|
+
const channelType = parseChannelType(expectedPeerKey);
|
|
514
|
+
if (channelType)
|
|
515
|
+
candidateKeys.add(formatPeerKey(channelType, argPeer));
|
|
516
|
+
const legacyChannelType = parseLegacyChannelType(expectedPeerKey);
|
|
517
|
+
if (legacyChannelType)
|
|
518
|
+
candidateKeys.add(`${legacyChannelType}::${argPeer}`);
|
|
519
|
+
}
|
|
520
|
+
return candidateKeys.has(expectedPeerKey)
|
|
521
|
+
? { ok: true }
|
|
522
|
+
: { ok: false, reason: 'Only the current group relation can be targeted' };
|
|
523
|
+
}
|
|
616
524
|
if (ctx.actorId) {
|
|
617
525
|
if (requestedPeerId && requestedPeerId !== ctx.actorId) {
|
|
618
526
|
return { ok: false, reason: 'Only the actor peer can be targeted' };
|