@aalis/api-authority 0.5.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/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/index.d.ts +264 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ace Nyan <ace@acenyan.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @aalis/api-authority
|
|
2
|
+
|
|
3
|
+
类型/接口/能力声明包(只导出 `type` 与 `*Capabilities`,不含运行时逻辑)
|
|
4
|
+
|
|
5
|
+
## 角色
|
|
6
|
+
|
|
7
|
+
类型/接口/能力声明包(只导出 `type` 与 `*Capabilities`,不含运行时逻辑)
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @aalis/api-authority
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 使用
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import type { /* ... */ } from '@aalis/api-authority';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
本包为 *-api 类型包;实现见对应的运行时插件。
|
|
22
|
+
|
|
23
|
+
## 许可
|
|
24
|
+
|
|
25
|
+
见仓库根目录 LICENSE。
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/** 细粒度能力标识,如 tool:file.write、command:shutdown */
|
|
2
|
+
export type CapabilityId = string;
|
|
3
|
+
/**
|
|
4
|
+
* 能力默认可见性(轴 A · 授权:谁默认能用):
|
|
5
|
+
* - public:所有人默认拥有(除非被显式 deny),如查天气、查状态。
|
|
6
|
+
* - restricted:默认禁止,须被 owner/上层委托授予,如关机、写 users.json。
|
|
7
|
+
*/
|
|
8
|
+
export type CapabilityVisibility = 'public' | 'restricted';
|
|
9
|
+
/**
|
|
10
|
+
* 能力确认要求(轴 B · 确认:是否需「人确认」这一步,与 visibility 正交、owner 也生效):
|
|
11
|
+
* - 缺省/undefined:无需确认(不提醒)。
|
|
12
|
+
* - 'session':执行前需人确认;可「本会话」记住(回复 YS),会话内同能力不再追问。
|
|
13
|
+
* - 'always':每次都需确认,不接受会话记忆(最危险操作)。
|
|
14
|
+
*
|
|
15
|
+
* 与 visibility 正交:visibility 管「授权(能不能)」,confirm 管「意图确认(是不是你本人此刻要)/防注入减速带」。
|
|
16
|
+
* 即便 owner=`*`,命中 confirm 的能力仍须确认 —— 抵御 owner 会话内提示注入借权静默调高危。
|
|
17
|
+
*/
|
|
18
|
+
export type CapabilityConfirm = 'session' | 'always';
|
|
19
|
+
/**
|
|
20
|
+
* 能力风险等级(可选声明糖):插件自分类风险,框架展开为 (visibility, confirm) 默认:
|
|
21
|
+
* - safe → (public, 无确认) 查天气/算术等
|
|
22
|
+
* - sensitive → (restricted, 无确认) owner 顺手的中危
|
|
23
|
+
* - dangerous → (restricted, 'session') owner 也确认 —— shell / 写删 / 改系统 等
|
|
24
|
+
*
|
|
25
|
+
* 显式 visibility / confirm 覆盖 risk 推导值;三者皆不声明 → visibility 默认 public(保持向后兼容)。
|
|
26
|
+
*/
|
|
27
|
+
export type CapabilityRisk = 'safe' | 'sensitive' | 'dangerous';
|
|
28
|
+
/** 操作在注册时可声明的能力策略(可见性 / 确认 / 风险糖) */
|
|
29
|
+
export interface CapabilityPolicyDecl {
|
|
30
|
+
visibility?: CapabilityVisibility;
|
|
31
|
+
confirm?: CapabilityConfirm;
|
|
32
|
+
risk?: CapabilityRisk;
|
|
33
|
+
}
|
|
34
|
+
/** 未登记外部身份的默认等级。 */
|
|
35
|
+
export declare const DEFAULT_AUTHORITY = 0;
|
|
36
|
+
/** 无 risk 声明、仅标 `visibility:'restricted'` 的操作的兜底最低等级。 */
|
|
37
|
+
export declare const RESTRICTED_LEVEL = 2;
|
|
38
|
+
/**
|
|
39
|
+
* `(risk, visibility)` → 操作最低等级。**这是契约语义,不是某个实现的细节** —— 任何需要
|
|
40
|
+
* 判断「两个能力声明谁更严」的地方都必须用它,否则会得到与实际裁决不一致的答案。
|
|
41
|
+
*
|
|
42
|
+
* 关键性质:**risk 一旦存在就完全遮蔽 visibility**。于是「未声明 risk」在合并两份声明时
|
|
43
|
+
* 不能当成最弱 —— 对一个 `visibility:'restricted'` 的能力来说,不声明 risk 反而意味着更严
|
|
44
|
+
* (兜底到 RESTRICTED_LEVEL),而补上一个 `risk:'safe'` 会把门槛降到 0。
|
|
45
|
+
*
|
|
46
|
+
* 曾按「visibility / confirm / risk 三轴各自独立取最严」来合并同名指令的多份声明,实测
|
|
47
|
+
* 不单调:给 `{visibility:'restricted'}` 的 /shutdown 压一层 `{risk:'safe'}`,门槛从 2 掉到 0,
|
|
48
|
+
* 而 visibility 那一栏仍显示 restricted —— 提权成功且症状被藏起来。正解是拿本函数给每份
|
|
49
|
+
* 声明各自定级、取最严的**那一份**,不跨声明混轴。
|
|
50
|
+
*/
|
|
51
|
+
export declare function capabilityMinLevel(opts: {
|
|
52
|
+
risk?: CapabilityRisk;
|
|
53
|
+
visibility?: CapabilityVisibility;
|
|
54
|
+
}): number;
|
|
55
|
+
/**
|
|
56
|
+
* risk → 默认 (visibility, confirm);无 risk 返回空对象。
|
|
57
|
+
* 供需要保留「未声明=继承」语义的注册方(如 commands 沿 dot-path 继承)用 —— 不带兜底默认。
|
|
58
|
+
*/
|
|
59
|
+
export declare function riskDefaults(risk?: CapabilityRisk): {
|
|
60
|
+
visibility?: CapabilityVisibility;
|
|
61
|
+
confirm?: CapabilityConfirm;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* 把 (risk, visibility, confirm) 声明展开为生效的 (visibility, confirm)。纯函数。
|
|
65
|
+
* 优先级:显式 visibility/confirm > risk 推导 > defaultVisibility。
|
|
66
|
+
* @param defaultVisibility 三者皆缺省时的兜底可见性 —— tools/commands 传 'public',
|
|
67
|
+
* WebUI actions 传 'restricted'(actions 默认拒,与 tool/command 相反)。
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveCapabilityPolicy(decl: CapabilityPolicyDecl, defaultVisibility?: CapabilityVisibility): {
|
|
70
|
+
visibility: CapabilityVisibility;
|
|
71
|
+
confirm?: CapabilityConfirm;
|
|
72
|
+
};
|
|
73
|
+
/** 执行守卫上下文 —— 操作执行前权限检查的最小信息 */
|
|
74
|
+
export interface ExecutionGuardContext {
|
|
75
|
+
/** 操作名称(指令名 / 工具名) */
|
|
76
|
+
name: string;
|
|
77
|
+
/** 操作类型 */
|
|
78
|
+
type: 'command' | 'tool';
|
|
79
|
+
/** 操作主能力的生效可见性(轴 A;注册时已由 resolveCapabilityPolicy 展开 risk/默认)。无 risk 时作 minTier 兜底 */
|
|
80
|
+
visibility: CapabilityVisibility;
|
|
81
|
+
/** 操作原始风险声明(透传,供 authority 派生 minTier:safe→访客/sensitive→朋友/dangerous→信任);缺省回退 visibility */
|
|
82
|
+
risk?: CapabilityRisk;
|
|
83
|
+
/** 操作的生效确认要求(轴 B,与 visibility/档位 正交、owner 也生效);缺省=不确认 */
|
|
84
|
+
confirm?: CapabilityConfirm;
|
|
85
|
+
/** 会话 ID */
|
|
86
|
+
sessionId: string;
|
|
87
|
+
/** 来源平台 */
|
|
88
|
+
platform: string;
|
|
89
|
+
/** 用户 ID */
|
|
90
|
+
userId?: string;
|
|
91
|
+
/** 操作参数 */
|
|
92
|
+
args?: Record<string, unknown>;
|
|
93
|
+
/**
|
|
94
|
+
* 系统/受信源(如 scheduler,无人能点交互确认):仍走 authorize 评估调用者能力,
|
|
95
|
+
* 仅跳过受限被拒后的交互确认弹窗(requestAccess)。**不**绕过 authorize(防提权)。
|
|
96
|
+
*/
|
|
97
|
+
skipConfirm?: boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 执行守卫函数。返回 null 放行;返回 string 拦截(值为原因/提示)。
|
|
101
|
+
* 由 plugin-authority 通过 setExecutionGuard() 注入。
|
|
102
|
+
*/
|
|
103
|
+
export type ExecutionGuard = (ctx: ExecutionGuardContext) => Promise<string | null>;
|
|
104
|
+
/**
|
|
105
|
+
* 能力统一闸请求:一次敏感操作在边界处声明它触达的能力。
|
|
106
|
+
*
|
|
107
|
+
* 任何 surface(tool/command/WebUI action/REST/scheduler)的敏感操作都在操作边界
|
|
108
|
+
* 调用 authorize 过同一闸。
|
|
109
|
+
*/
|
|
110
|
+
export interface AuthorizeRequest {
|
|
111
|
+
/** 操作主能力(tool:<name> / command:<name>) */
|
|
112
|
+
capability: CapabilityId;
|
|
113
|
+
/** 主能力的默认可见性(操作声明;无 risk 时作 minTier 兜底) */
|
|
114
|
+
visibility: CapabilityVisibility;
|
|
115
|
+
/** 操作原始风险(透传,供 minTier 派生;缺省回退 visibility) */
|
|
116
|
+
risk?: CapabilityRisk;
|
|
117
|
+
}
|
|
118
|
+
/** 用户触达未授予的 restricted 能力时,向 owner/确认回调发起的请求 */
|
|
119
|
+
export interface AccessRequest {
|
|
120
|
+
/** 操作名称 */
|
|
121
|
+
name: string;
|
|
122
|
+
/** 操作类型 */
|
|
123
|
+
type: 'command' | 'tool';
|
|
124
|
+
/** 触达的(受限)能力 */
|
|
125
|
+
capability: CapabilityId;
|
|
126
|
+
args?: Record<string, unknown>;
|
|
127
|
+
sessionId: string;
|
|
128
|
+
platform: string;
|
|
129
|
+
userId?: string;
|
|
130
|
+
/**
|
|
131
|
+
* 请求性质:
|
|
132
|
+
* - 'grant'(缺省):非 owner 触达未授予的 restricted 能力,确认=授予。
|
|
133
|
+
* - 'confirm':调用者已有权限(含 owner),仅因能力标了 confirm 轴需「意图确认」。
|
|
134
|
+
* confirm='always' 时不接受会话记忆(每次都问)。
|
|
135
|
+
*/
|
|
136
|
+
confirm?: CapabilityConfirm;
|
|
137
|
+
}
|
|
138
|
+
/** 批准后授予的临时委托范围:once 不持久;session 为当前会话短时授予 */
|
|
139
|
+
export interface TemporaryGrantSpec {
|
|
140
|
+
scope: 'once' | 'session';
|
|
141
|
+
/** 授予秒数,仅 scope=session 时有效 */
|
|
142
|
+
durationSeconds?: number;
|
|
143
|
+
/** 最大使用次数,仅 scope=session 时有效 */
|
|
144
|
+
maxUses?: number;
|
|
145
|
+
}
|
|
146
|
+
export interface AccessDecision {
|
|
147
|
+
allowed: boolean;
|
|
148
|
+
grant?: TemporaryGrantSpec;
|
|
149
|
+
}
|
|
150
|
+
/** 一条生效中的临时能力委托 */
|
|
151
|
+
export interface TemporaryGrant {
|
|
152
|
+
id: string;
|
|
153
|
+
capability: CapabilityId;
|
|
154
|
+
name: string;
|
|
155
|
+
type: 'command' | 'tool';
|
|
156
|
+
sessionId: string;
|
|
157
|
+
platform: string;
|
|
158
|
+
userId?: string;
|
|
159
|
+
expiresAt: number;
|
|
160
|
+
maxUses?: number;
|
|
161
|
+
used: number;
|
|
162
|
+
createdAt: number;
|
|
163
|
+
}
|
|
164
|
+
/** 确认回调:boolean 为最简允许/拒绝;对象可附带临时委托范围 */
|
|
165
|
+
export type AccessConfirmHandler = (request: AccessRequest) => Promise<boolean | AccessDecision>;
|
|
166
|
+
/** 跨平台用户身份标识 */
|
|
167
|
+
export interface UserIdentity {
|
|
168
|
+
platform: string;
|
|
169
|
+
userId: string;
|
|
170
|
+
}
|
|
171
|
+
/** listUsers 返回的用户记录 */
|
|
172
|
+
export interface AuthorityUserEntry {
|
|
173
|
+
platform: string;
|
|
174
|
+
userId: string;
|
|
175
|
+
/** owner = ∞,拥有一切 */
|
|
176
|
+
isOwner: boolean;
|
|
177
|
+
/** 用户等级(整数,越大越高;owner 不入表,此处为非 owner 外部身份的登记等级;缺省 0,封禁=负数) */
|
|
178
|
+
level: number;
|
|
179
|
+
/** 可选备注(这人是谁) */
|
|
180
|
+
note?: string;
|
|
181
|
+
}
|
|
182
|
+
export interface AuthorityService {
|
|
183
|
+
/** 是否为 owner(owners 配置命中 → 拥有 `*`) */
|
|
184
|
+
isOwner(platform: string, userId?: string): boolean;
|
|
185
|
+
/**
|
|
186
|
+
* 统一权限闸 —— 任何 surface 的敏感操作在边界调用本方法。
|
|
187
|
+
* 数字等级裁决:deniedCapabilities(全局硬禁) > owner(∞) > 用户 level >= 操作 minLevel;
|
|
188
|
+
* minLevel 由 request.risk/visibility/config.authorityOverrides 派生。
|
|
189
|
+
* @returns null 放行;string 为拒绝原因(可直接展示)
|
|
190
|
+
*/
|
|
191
|
+
authorize(identity: UserIdentity | {
|
|
192
|
+
platform: string;
|
|
193
|
+
userId?: string;
|
|
194
|
+
}, request: AuthorizeRequest): string | null;
|
|
195
|
+
/**
|
|
196
|
+
* 设置 target 外部身份的等级(覆盖式整数;level=0 默认值且无备注则清记录)。
|
|
197
|
+
* 单 owner 终态:权限只由 owner 管理。调用方(WebUI action / CLI 指令)自行确保仅 owner 可达(防自授)。
|
|
198
|
+
*/
|
|
199
|
+
setUserLevel(target: UserIdentity, level: number): void;
|
|
200
|
+
/** 删除用户记录(等级一并清除,回退默认 0) */
|
|
201
|
+
removeUser(platform: string, userId: string): void;
|
|
202
|
+
/**
|
|
203
|
+
* 「未授权」分支专用闸:请求是否被 owner 预先放行(restrictedPolicy 白名单 / 该用户在本会话已有授予),
|
|
204
|
+
* 且不触犯硬禁 / 资源保护。**绝不询问发起者本人**(杜绝自我确认提权)。守卫 authorize 拒绝后调本方法。
|
|
205
|
+
*/
|
|
206
|
+
isPreApproved(request: AccessRequest): boolean;
|
|
207
|
+
/** 用户触达未授予的 restricted 能力时,过临时委托流程(白名单策略 → 会话临时授予 → 确认回调) */
|
|
208
|
+
requestAccess(request: AccessRequest): Promise<boolean>;
|
|
209
|
+
listTemporaryGrants(): TemporaryGrant[];
|
|
210
|
+
revokeTemporaryGrant(id: string): boolean;
|
|
211
|
+
setConfirmHandler(platform: string, handler: AccessConfirmHandler): void;
|
|
212
|
+
save(): void;
|
|
213
|
+
listUsers(): AuthorityUserEntry[];
|
|
214
|
+
}
|
|
215
|
+
declare module '@aalis/core' {
|
|
216
|
+
interface AalisConfig {
|
|
217
|
+
/** owner 列表(owner = `*`,拥有一切) */
|
|
218
|
+
owners?: UserIdentity[];
|
|
219
|
+
/** 全局能力封禁(glob):命中即拒,连 owner 都压过(系统级硬禁用,慎用)。 */
|
|
220
|
+
deniedCapabilities?: string[];
|
|
221
|
+
/**
|
|
222
|
+
* 管理员对单条操作的最低等级覆盖(能力键 `type:name`,如 `tool:weather` → 任意整数)。
|
|
223
|
+
* 让 owner 调某操作的门槛等级,无需改插件声明;优先于 risk/visibility 派生。
|
|
224
|
+
*/
|
|
225
|
+
authorityOverrides?: Record<string, number>;
|
|
226
|
+
/**
|
|
227
|
+
* 管理员对单条操作的确认要求覆盖(能力键 `type:name` → session/always/off)。
|
|
228
|
+
* 'off' 强制关闭确认(即便插件声明了 confirm,便于自动化);与等级正交,owner 也吃。
|
|
229
|
+
*/
|
|
230
|
+
confirmOverrides?: Record<string, CapabilityConfirm | 'off'>;
|
|
231
|
+
/**
|
|
232
|
+
* 受限能力的临时放行策略(替代旧 dangerousPolicy):
|
|
233
|
+
* allow 列出自动放行的 restricted 能力/操作名 glob(['*'] 全放);duration 放行时长(秒,0=永久)。
|
|
234
|
+
* 运行时启用时点(enabledAt)不持久化,是 plugin-authority 运行时状态。
|
|
235
|
+
*/
|
|
236
|
+
restrictedPolicy?: {
|
|
237
|
+
allow?: string[];
|
|
238
|
+
duration?: number;
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* auto 确认模式(owner 临时免 dangerous 二次确认,便于批处理;类 Claude Code auto):
|
|
242
|
+
* epoch ms 截止时间;-1=一直;0/缺省=关。仅跳过 owner 自己的 session 确认,不动等级/deny,always 不跳。
|
|
243
|
+
*/
|
|
244
|
+
autoConfirmUntil?: number;
|
|
245
|
+
/**
|
|
246
|
+
* 网络出口闸(SSRF 防护,粗粒度高效):限制由 LLM/用户 URL 触发的 safeFetch 能连到哪。
|
|
247
|
+
* 不影响你自己配置的固定本地服务(ollama/onebot daemon 走裸 fetch,不过 safeFetch)。
|
|
248
|
+
*/
|
|
249
|
+
network?: {
|
|
250
|
+
/** 拦私网/回环/链路本地/元数据段(默认 true)。 */
|
|
251
|
+
blockPrivate?: boolean;
|
|
252
|
+
/** 额外拒绝的 IPv4 CIDR,如 ["100.64.0.0/10"]。 */
|
|
253
|
+
denyCidrs?: string[];
|
|
254
|
+
/** 仅允许这些目标端口(非空生效),如 [80, 443]。 */
|
|
255
|
+
allowedPorts?: number[];
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
declare module '@aalis/core' {
|
|
260
|
+
interface ServiceTypeMap {
|
|
261
|
+
authority: AuthorityService;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// ----- 权限服务接口 + 执行守卫契约(纯能力委托模型)-----
|
|
2
|
+
//
|
|
3
|
+
// 模型:能力(capability)+ 默认可见性 public/restricted + owner 授予加减。
|
|
4
|
+
// - owner = `*`,可执行任意能力、可管理所有人的权限。
|
|
5
|
+
// - 用户有效能力 = owner ? 全部 : (所有 public ∪ 被授予的 restricted) − 被禁用的;deny 优先。
|
|
6
|
+
// - 单 owner 终态:权限只由 owner 管理(无委托树/子委托),故无子集约束。
|
|
7
|
+
//
|
|
8
|
+
// 任何需要「执行前权限校验」的服务(plugin-tools / plugin-commands 等)从本包导入
|
|
9
|
+
// ExecutionGuard / ExecutionGuardContext;消费权限服务的插件导入 AuthorityService。
|
|
10
|
+
const RISK_DEFAULTS = {
|
|
11
|
+
safe: { visibility: 'public' },
|
|
12
|
+
sensitive: { visibility: 'restricted' },
|
|
13
|
+
dangerous: { visibility: 'restricted', confirm: 'session' },
|
|
14
|
+
};
|
|
15
|
+
/** 未登记外部身份的默认等级。 */
|
|
16
|
+
export const DEFAULT_AUTHORITY = 0;
|
|
17
|
+
/** 无 risk 声明、仅标 `visibility:'restricted'` 的操作的兜底最低等级。 */
|
|
18
|
+
export const RESTRICTED_LEVEL = 2;
|
|
19
|
+
/**
|
|
20
|
+
* `(risk, visibility)` → 操作最低等级。**这是契约语义,不是某个实现的细节** —— 任何需要
|
|
21
|
+
* 判断「两个能力声明谁更严」的地方都必须用它,否则会得到与实际裁决不一致的答案。
|
|
22
|
+
*
|
|
23
|
+
* 关键性质:**risk 一旦存在就完全遮蔽 visibility**。于是「未声明 risk」在合并两份声明时
|
|
24
|
+
* 不能当成最弱 —— 对一个 `visibility:'restricted'` 的能力来说,不声明 risk 反而意味着更严
|
|
25
|
+
* (兜底到 RESTRICTED_LEVEL),而补上一个 `risk:'safe'` 会把门槛降到 0。
|
|
26
|
+
*
|
|
27
|
+
* 曾按「visibility / confirm / risk 三轴各自独立取最严」来合并同名指令的多份声明,实测
|
|
28
|
+
* 不单调:给 `{visibility:'restricted'}` 的 /shutdown 压一层 `{risk:'safe'}`,门槛从 2 掉到 0,
|
|
29
|
+
* 而 visibility 那一栏仍显示 restricted —— 提权成功且症状被藏起来。正解是拿本函数给每份
|
|
30
|
+
* 声明各自定级、取最严的**那一份**,不跨声明混轴。
|
|
31
|
+
*/
|
|
32
|
+
export function capabilityMinLevel(opts) {
|
|
33
|
+
if (opts.risk === 'dangerous')
|
|
34
|
+
return 2;
|
|
35
|
+
if (opts.risk === 'sensitive')
|
|
36
|
+
return 1;
|
|
37
|
+
if (opts.risk === 'safe')
|
|
38
|
+
return DEFAULT_AUTHORITY;
|
|
39
|
+
return opts.visibility === 'restricted' ? RESTRICTED_LEVEL : DEFAULT_AUTHORITY;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* risk → 默认 (visibility, confirm);无 risk 返回空对象。
|
|
43
|
+
* 供需要保留「未声明=继承」语义的注册方(如 commands 沿 dot-path 继承)用 —— 不带兜底默认。
|
|
44
|
+
*/
|
|
45
|
+
export function riskDefaults(risk) {
|
|
46
|
+
return risk ? RISK_DEFAULTS[risk] : {};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 把 (risk, visibility, confirm) 声明展开为生效的 (visibility, confirm)。纯函数。
|
|
50
|
+
* 优先级:显式 visibility/confirm > risk 推导 > defaultVisibility。
|
|
51
|
+
* @param defaultVisibility 三者皆缺省时的兜底可见性 —— tools/commands 传 'public',
|
|
52
|
+
* WebUI actions 传 'restricted'(actions 默认拒,与 tool/command 相反)。
|
|
53
|
+
*/
|
|
54
|
+
export function resolveCapabilityPolicy(decl, defaultVisibility = 'public') {
|
|
55
|
+
const base = riskDefaults(decl.risk);
|
|
56
|
+
return {
|
|
57
|
+
visibility: decl.visibility ?? base.visibility ?? defaultVisibility,
|
|
58
|
+
confirm: decl.confirm ?? base.confirm,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,2DAA2D;AAC3D,qCAAqC;AACrC,0EAA0E;AAC1E,iDAAiD;AACjD,EAAE;AACF,0DAA0D;AAC1D,uEAAuE;AA0CvE,MAAM,aAAa,GAA8F;IAC/G,IAAI,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE;IAC9B,SAAS,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE;IACvC,SAAS,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE;CAC5D,CAAC;AAEF,oBAAoB;AACpB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAkE;IACnG,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC;IACxC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC;IACxC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,iBAAiB,CAAC;IACnD,OAAO,IAAI,CAAC,UAAU,KAAK,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB,CAAC;AACjF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAqB;IAIhD,OAAO,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAA0B,EAC1B,oBAA0C,QAAQ;IAKlD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,IAAI,iBAAiB;QACnE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;KACtC,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aalis/api-authority",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/AalisLabs/Aalis.git",
|
|
8
|
+
"directory": "packages/api-authority"
|
|
9
|
+
},
|
|
10
|
+
"author": "Ace Nyan <ace@acenyan.com>",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/AalisLabs/Aalis/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/AalisLabs/Aalis#readme",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22.0.0",
|
|
23
|
+
"typescript": "^5.7.0",
|
|
24
|
+
"@aalis/core": "0.10.0"
|
|
25
|
+
},
|
|
26
|
+
"aalis": {
|
|
27
|
+
"types": true
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@aalis/core": ">=0.2.0 <1.0.0"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"aalis",
|
|
34
|
+
"aalis-api"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"dev": "tsc --watch"
|
|
39
|
+
}
|
|
40
|
+
}
|