import { type Brand } from '../im/lark/lark-hosts.js'; export type { Brand }; export interface RequiredScope { /** 飞书 scope 名 (`im:message` 等) */ name: string; /** 给用户看的中文说明 */ desc: string; /** * `critical` = 不开通 botmux 核心功能无法工作 (收发消息). * 非 critical 的 scope 缺失只 WARN, 不阻断启动. */ critical: boolean; } export type CriticalScopeReadbackResult = { ok: true; granted: string[]; missingCritical: RequiredScope[]; } | { ok: false; error: 'invalid_credentials' | 'need_self_manage' | 'network' | 'unknown'; message: string; }; /** * botmux 运行所需的 scope. 这里**只用于检测/提示**, 不用于自动申请——飞书 * `scope.apply` 只能提交"已声明但未授权"的, 没法给应用 manifest 加新声明. * scope 选择必须用户去开放平台勾. * * **每个 name 必须是 lark-scopes.json manifest 里真实存在的 scope**, 否则 * `application/v6/applications/{id}` 返回的授权列表里永远找不到, 会把 * 已正确授权的用户误报"缺权限"。`test/setup-verify-permissions.test.ts` 里 * 的 manifest 一致性测试用 lark-scopes.json 兜底防止这类裸名再溜进来。 */ export declare const BOTMUX_REQUIRED_SCOPES: RequiredScope[]; export declare const DOC_FEATURE_SCOPES: RequiredScope[]; export declare const DOC_WATCH_SCOPES: RequiredScope[]; /** 文档评论入口需要订阅的事件——飞书无「列出已订阅事件」的 API,无法自检,仅在 * 启动就绪检查里据此提醒管理员去开发者后台订阅。 */ export declare const DOC_COMMENT_EVENT = "drive.notice.comment_add_v1"; /** VC meeting agent 所需的 app 权限。只有 bot 显式启用 vcMeetingAgent 时才检查。 */ export declare const VC_MEETING_FEATURE_SCOPES: RequiredScope[]; /** Realtime voice is only required when vcMeetingAgent.realtimeVoice.enabled is true. */ export declare const VC_MEETING_REALTIME_VOICE_SCOPES: RequiredScope[]; /** VC bot push 事件。开放平台当前没有公开 API 可列出已订阅事件,只能给管理员检查清单。 */ export declare const VC_MEETING_BOT_EVENTS: readonly ["vc.bot.meeting_invited_v1", "vc.bot.meeting_activity_v1", "vc.bot.meeting_ended_v1", "vc.meeting.participant_meeting_joined_v1"]; export interface RemainingStep { title: string; /** 飞书开放平台深链, 用户点了直接到对应页 */ url: string; } export declare function buildScopeDeepLink(appId: string, scopeName: string, brand?: Brand): string; export declare function buildEventSubDeepLink(appId: string, brand?: Brand): string; export declare function buildAppHomeDeepLink(appId: string, brand?: Brand): string; export type CredentialValidation = { ok: true; tenantAccessToken: string; tokenExpiresIn: number; } | { ok: false; error: 'invalid_credentials' | 'network' | 'unknown'; message: string; }; /** * 用 AppID/Secret 取一次 tenant_access_token, 验证凭证可用. * * Secret 不进 error.message: 错误信息只来自飞书返回的 msg 字段或 axios 错误类型. * * Codex review #3: 加 AbortController + 总超时. 网络半挂时 `botmux setup` / * `botmux start` 不能无限卡住; 超时归类为 network, 这样 setup 走"凭证校验失败 * 不写盘" 路径, start 走"network 只 WARN 继续"路径. */ export declare function validateCredentials(appId: string, appSecret: string, brand?: Brand, opts?: { budgetMs?: number; signal?: AbortSignal; }): Promise; /** * Runtime-proven scope readback used by Dashboard VC validation and daemon * startup checks: tenant token followed by Get application info. Unlike the * legacy grant_status helper below, this endpoint returns the effective scope * names directly in data.app.scopes. */ export declare function readCriticalScopesFromApplicationInfo(appId: string, appSecret: string, brand?: Brand, opts?: { budgetMs?: number; }): Promise; export type ScopeCheckResult = { ok: true; granted: string[]; missingCritical: RequiredScope[]; missingOptional: RequiredScope[]; } | { ok: false; /** * - `need_self_manage`: 调 scope.list 被拒, 应用缺 `application:application:self_manage` * (鸡生蛋: 没这个 scope 就查不到 scope 列表) * - `network` / `unknown`: 其它失败 */ error: 'need_self_manage' | 'network' | 'unknown'; message: string; }; /** * 列出应用的 scope grant 状态, 比对 BOTMUX_REQUIRED_SCOPES. * * **不在主路径使用** — 待 spike 用真实/可复现 mock 证明 grant_status 含义和 * 状态闭环后再启用. 当前主路径只输出"剩余步骤 + 深链", 不做 grant_status 判定. * * scope.list 返回 shape (SDK type): * `{ data: { scopes: [{ scope_name, grant_status, scope_type }] } }` * grant_status 含义未在官方文档明确, 但社区 SDK / 实测一般约定: * 1 = 已申请未生效, 2 = 已生效. 启用前 spike 务必确认这个映射. */ export declare function checkRequiredScopes(appId: string, appSecret: string, brand?: Brand): Promise; /** * 触发管理员审批 (把"已声明但未授权"的 scope 提交). * * **不在主路径使用** — 见模块顶部注释. 文档表明它无法添加新 scope 到 manifest, * 所以即使调成功也不能绕过"用户去开放平台勾 scope". 留作 spike 验证状态闭环 * 后的可选自动触发能力. * * 文档/SDK 显示无请求体. 错误码: * - 212001: 剩余权限为高敏, 无法申请 * - 212002: 无可申请的 scope (manifest 全部已授权或为空) * - 212003: 申请次数超限 (同租户同版本 > 10 次) * - 212004: 重复申请 */ export interface ApplyScopesResult { /** * - `submitted`: 申请已提交 (code=0). 是否被管理员审批通过需另查 `scope.list`. * - `nothing_to_apply`: 212002, manifest 没有"已声明但未授权"的 scope. * - `already_applied`: 212004, 重复申请. * - `over_limit`: 212003, 同租户同版本 > 10 次申请. * - `super_scope_only`: 212001, 剩余为高敏权限不可申请. * - `timeout`: 调用本身没在 budgetMs 内返回. * - `error`: 其它失败. */ status: 'submitted' | 'nothing_to_apply' | 'already_applied' | 'over_limit' | 'super_scope_only' | 'timeout' | 'error'; code?: number; msg?: string; } export declare function applyScopesUnverified(appId: string, appSecret: string, opts?: { brand?: Brand; budgetMs?: number; signal?: AbortSignal; }): Promise; /** * setup 后 "还要手动点的步骤" 结构化数据. 跟 cli.ts 的 printRemainingSteps + README * "5 分钟快速接入" 一致: 主线就两步 (权限申请 + 按需重定向 URL); PersonalAgent * 应用默认订阅事件 + bot 能力, 不在主线提示, 收不到消息时见 README 的 fallback * 自查清单. */ export declare function buildRemainingSteps(appId: string, brand?: Brand): RemainingStep[]; //# sourceMappingURL=verify-permissions.d.ts.map