Skip to content

Release v0.21.0

Latest

Choose a tag to compare

@github-actions github-actions released this 09 Oct 10:34
· 42 commits to main since this release
393f140

Content freeze for the 0.21 release window. Package identity and this dated
section are filled by the packaging change. GitHub Release body is extracted
from this section by .github/workflows/release.yml — this is the source of
truth for 0.21 notes. Consumer upgrade path: docs/migration-guide.md →
OpenLark 0.21.

Security

  • deps:传递依赖 rustls 升至 0.23.45(RUSTSEC-2026-0285,#665):
    lockfile-only 更新,修复 TLS 1.3 handshake encryption-level 公告。无 Cargo.toml
    直依赖变更,无公开 API 变化。

Changed (Breaking)

  • ai:对齐飞书 OCR/语音/翻译/合同抽取 OpenAPI 请求体:按官方文档重写
    openlark-ai 中 5 个字段硬错误接口的 Body/Response。

    • optical_char_recognition/.../basic_recognize:image(base64;文档标选填,
      SDK 建模为必填)替代错误的 file_token/recognition_model;响应为 text_list。
    • speech_to_text/.../file_recognize:speech.speech + config.{file_id,format,engine_type};
      响应为 recognition_text。
    • speech_to_text/.../stream_recognize:speech.speech +
      config.{stream_id,sequence_id,action,format,engine_type};响应含 recognition_text 等。
    • translation/.../text/translate:单字段 text + 可选 glossary[{from,to}],移除 texts;
      响应为 text。
    • document_ai/.../contract/field_extraction:改为 multipart file + 必填
      pdf_page_limit/ocr_mode(移除错误的 file_token/is_async)。
  • helpdesk:对齐飞书 Helpdesk OpenAPI 请求体:按官方文档重写
    openlark-helpdesk 中字段硬错误接口的 Body(嵌套包装与扁平字段)。

    • agent/schedules/patch:agent_schedule.{schedule[],agent_skill_ids};
      agent_schedule/create:agent_schedules[]。
    • agent_skill/create|patch:rules/agent_ids;patch 使用 agent_skill 包装。
    • agent/patch:status 改为整型。
    • category/create|patch:name/parent_id(create 必填)+ 可选 language;移除错误
      description/order。
    • faq/create|patch:请求体改为 faq{...} 包装(question 等)。
    • bot/message/create:msg_type/content/receiver_id/receive_type(移除 receive_id)。
    • ticket/message/create:msg_type/content 必填;answer_user_query:event_id/faqs;
      start_service:open_id/human_service/appointed_agents/customized_info。
    • notification/create|patch:按官方 Notification 扁平字段(job_name/push_content 等),
      移除错误 title/content。
    • ticket_customized_field/create|patch:对齐 key_name/display_name/field_type 等官方字段。
  • application:对齐飞书 app_badge/set OpenAPI 请求体:按官方文档重写
    openlark-application application/v6/app_badge/set(及历史 v1 同名模块)Body。

    • 移除错误推断字段 app_id / badge。
    • 官方字段:必填 user_id + version;可选 extra、pc/mobile
      (client_badge_num:web_app / gadget);查询参数 user_id_type。
    • 响应 data 为空对象,去掉错误的双重嵌套 Response { data: Option<Value> }。
  • user:对齐飞书 personal_settings system_status OpenAPI 请求/响应体:按官方文档重写
    openlark-user 全部 6 个 system_status 接口的 Body/Response。

    • batch_close:请求体字段 user_ids → user_list(string[],长度 1~50);响应为
      result_list[{user_id,result}];支持查询参数 user_id_type。
    • batch_open:补齐必填 body.user_list[{user_id,end_time}];响应为
      result_list[{user_id,end_time,result}]。
    • create:补齐 body(title/icon_key 必填,及 i18n_title/color/priority/sync_setting);
      响应为 system_status。
    • patch:补齐 body.system_status + update_fields;路径参数 setter 为 system_status_id;
      响应为 system_status。
    • list:补齐查询参数 page_size/page_token;响应为 items/has_more/page_token。
    • delete:路径参数 setter 为 system_status_id;响应 data 为空对象。
    • 移除错误的双重嵌套 Response { data: Option<Value> }(Transport 已解包外层 data)。
  • cardkit:对齐飞书 CardKit OpenAPI 请求体(#603):按官方文档重写
    openlark-cardkit 全量/局部更新、配置、组件增删改、流式文本与 id_convert 的 Body 字段。

    • 所有流式相关写接口补齐必填 sequence(及可选 uuid);路径参数 card_id/element_id 不再序列化进 JSON body。
    • CreateCardBody:type + data(字符串);移除错误的 card_content/card_type/template_id/temp*。
    • UpdateCardBody:card.{type,data} + sequence;移除 card_content/update_mask。
    • BatchUpdateCardBody:actions(字符串)替代 operations。
    • UpdateCardSettingsBody.settings、组件 element/partial_element/elements/content 均按文档使用字符串。
    • element.content 端点(PUT .../elements/:id/content)字段修正为 content: String + sequence。
    • ConvertCardIdBody 仅保留官方 message_id(旧 source_id_type/card_ids 为错误推断)。
    • 多数写接口响应 data 为空对象,对应 Response 结构同步收敛。

Added

  • pay:商店付费 crate openlark-pay(#660):新增 workspace 成员与根 crate
    pay feature。PayService / PayClient 提供订单详情(get_order)、租户付费方案
    列表(list_orders)与用户开通范围(check_user)。同一批补齐 platform spark
    分析与可用范围(analytics_overview / query_analytics_data / credit_usage /
    available_scope get+update)以及 VC countdown。发布顺序上 openlark-pay
    位于 openlark-client 之前。

  • client:HTTP 事件入站 event-http(#672,#667):新增 HttpEventInbound
    (根 crate event-http feature,复用 EventDispatcherHandler)。覆盖
    encrypt_key AES-256-CBC + PKCS7 解密、url_verification Challenge,以及入站
    X-Lark-Signature(SHA256(timestamp+nonce+encrypt_key+body))。这与
    openlark-webhook 出站自定义机器人不是同一能力。

  • communication:ImClient::send_card(#669):发送 msg_type=interactive
    卡片 JSON(非完整 Block Kit DSL)。HTTP 卡片回传 ACK 走 event-http 上既有的
    register_card_action_trigger,本票不另起 servlet。

  • websocket:高频 typed 事件(#668):EventDispatcherHandler 新增
    register_im_message_receive_v1 与 register_card_action_trigger,公开 payload
    为具名 struct(ImMessageReceiveV1 / CardActionTrigger / CardActionTriggerResponse),
    不是单独的 serde_json::Value。typed 方法写入既有 raw / callback map:
    register_raw 仍可用;card.action.trigger 仍走 callback ACK(toast / 卡片)。
    url.preview.get 本票不做 typed,继续 register_callback。HTTP event-http
    入站复用同一套 typed 注册。

  • workflow/docs:审批可发起定义搜索 + 妙记片段/上传(#648):
    catalog 同步 2026-08-31(1740→1743,+3 APIs)。
    openlark-workflow 新增 SearchLaunchableApprovalRequestV4
    (POST /open-apis/approval/v4/approvals/search_launchable);
    openlark-docs minutes/v1/minute 新增 MinuteClipRequest /
    MinuteUploadRequest(POST .../minutes/:minute_token/clip、
    POST .../minutes/upload)。三接口均为 User token only;
    新端点走 crate-private extra catalog,不扩展公开 ApprovalApiV4 /
    MinutesApiV1。现有审批定义 CRUD/订阅与妙记 get/search/artifacts
    等读接口未改。

  • meeting:VC 会议机器人加入/离开/发送会中消息(#645):
    catalog 同步 2026-08-24(1737→1740,+3 APIs)。openlark-meeting
    vc/v1/bot 新增 JoinBotRequest / LeaveBotRequest / SendBotMessageRequest,
    对应 POST /open-apis/vc/v1/bots/{join,leave,message}。凭证默认 User+Tenant。
    现有 events / user_active_meeting 读接口未改。

  • websocket:callback 型事件处理器业务响应通道(#632):新增
    CallbackEventHandler trait(handle 返回 Option<serde_json::Value>)与
    EventDispatcherHandler::register_callback(key, handler)。卡片回传交互
    (card.action.trigger)等 callback 型事件的业务响应(如 {"toast": {...}} /
    {"card": {...}})现经 ACK 帧 data 字段以 base64(JSON) 写回服务端(3 秒内),
    对齐官方 Go OnP2CardActionTrigger / Python register_p2_card_action_trigger
    的双 handler map 形态:callback 命中即短路,不再落 raw 处理器;payload_sender
    转发不受影响。既有 EventHandler / register_raw / do_without_validation
    签名不变,纯增量公开 API。

Changed

  • catalog:同步 2026-09-21 飞书 API 目录(#678):
    live 二次导出与 watch 快照一致(基准 1752 → 当前 1751;新增 0 / 删除 1 / 字段变化 0)。

    • 刷新 api_list_export.csv:删除 id 7563551656446263298
      (获取客户端设备认证信息 /
      GET:/open-apis/security_and_compliance/v2/device_records/mine)。
    • device_records.mine:live 目录列表已无。CSV 与 live 对齐移除该行;
      SDK 公开 API 默认冻结保留(openlark-security
      device_records.mine 不删不改),按「catalog 外 extra 实现」口径处理
      (#581 同款),不触发 missing 补齐。
  • websocket:SessionState 收敛 CloseIntent + harness 瘦身(#641):
    SessionState{Active,Closing,Closed} × CloseIntent{None,WithoutReason,WithReason}
    两个必须手工对齐的字段收为 SessionState::Closing(Option<WsCloseReason>)。
    stream 错误与 outcome 错误的 reason 保留镜像块收敛为单一
    fail_preserving_close_reason。两枚举均私有,InvalidStateKind /
    WsClientError 公开面不变。full_session_tests 删除被 #640 新层替代的
    15 个用例(1478 → ~622 行),保留 B 组 6 个墙钟测试与 C 组 3 个端点发现测试。

  • deps:升级 h2 0.4.14 → 0.4.16(RUSTSEC-2026-0258):修复空 DATA 帧无界排队。

  • tools:weekly/full 字段核对无 --crate 时扫描量为零(#638):
    新增 run_field_verify_ci.py 作为 weekly/full 唯一入口:显式 --crate
    产物仍在 output-dir 根(summary.json + <crate>.md);全仓按
    api_coverage.toml 逐 crate --crate(子目录)并合并 summary。coverage
    清单为空则非零退出。CLI 无 --crate 默认路径不改。

  • tools:Rust 合约提取收口为单一深 module(#636):verify_api_fields
    删除内嵌提取栈(~105 行,正则停在首个 }、不认 rename_all),改为库消费
    api_contracts.rust_source——extract_structs 成为唯一分组提取 interface,
    FieldInfo/StructFields 模型移入 models.py。共享层修复与增强(两 CLI 同时
    受益):struct 体改为括号配平提取(平衡花括号的 doc 注释不再截断字段);类型
    整行捕获修复 HashMap<String, String> 逗号截断(161 处);#[serde(rename)]
    可跨 doc 注解生效;std::option::Option 前缀识别为选填;__ 前缀内部字段
    全局跳过;新增 matches_struct_suffix 支持版本尾缀命名(*BodyV4/*ResponseV1,
    workflow 244 个字段恢复可见);multipart 表单字段(Meta struct/json! 字面量)
    以 MultipartForm 合成分组进入字段核对(二进制 file 通道除外——官方
    request_body 字段表不列它,live 实证)。响应对比改为 *Response 优先、
    *Result/*Resp/*ResponseData 兜底的确定性选择(auth 域 10 个
    *ResponseData 唯一响应 struct 的文件恢复对比能力)。提取语义测试迁入
    test_validate_api_contracts_rust_source.py 并补新语义正测;对拍验证:全仓
    新旧提取 diff 零意外回归,1,628 个 API quick 模式问题集零漂移;两个 multipart
    API live full 模式实跑通过。另发现既有 bug 另案跟踪(#638:weekly 门无
    --crate 调用时扫描量为零)。

  • websocket:Session 读写 seam 泛型化 + 内存 adapter,session 级测试下沉(#640,
    ADR-0006)
    :Session 泛型于底层字节流(Session<S: AsyncRead + AsyncWrite + Unpin + Send + 'static>,字段为 WebSocketStream<S> split 半部)——生产实例化
    MaybeTlsStream<TcpStream> 不变(client.rs 类型推断吃掉泛型,LarkWsClient::open
    签名零变化,公开 API 零变化)。新增 session_behavior_tests(#[cfg(test)]
    内联,tokio::io::duplex + from_raw_socket 双侧成帧):16 个用例覆盖状态机
    核心行为(close reason 保留、违约帧不覆盖原因、乱序/不完整/越界多包扣留、
    BacklogFull、串行派发、panic 传播、超大帧守卫(精确断言 Capacity(MessageTooLong),
    宽三选一在守卫失效时会被解码错误兜住)、malformed pong)与 callback ACK
    session 级 round-trip
    (base64 data 经真实 sink→对端逐字节验证,#634 缺口)。
    同步以 channel/gate 原语替代 thread::sleep 排序、负向断言以后到事件的 ACK 作
    正向同步点;串行派发用例以 500ms 有界反证窗口观察(「证明串行」的消极性质与
    零等待不可兼得)。full_session_tests 24 测原样保留作 parity。随附
    ADR-0006;ADR-0003 状态头回写 Accepted(实施早已落地,纯漂移修复)。

  • tools:删除休眠回归锁与平行 URL 解析器,fetch 栈就近 schema_cache(#635):
    删除 tools/check_api_urls.py(659 行激进 URL 解析器,与 rust_source 的对齐仅靠
    注释维持,零 CI/justfile 引用);删除 7 个休眠验收测试(~1,046 行,断言冻结在历史
    issue 事实上、无任何 runner 收集,含 test_p1_platform_clear_or_disprove /
    test_p2_selective_slice 两条文档化回归锁)及其 docs 提及;official.py 死代码清理
    (split_method_path、重复 re.sub 行);fetch_detail_payload 等取数栈自
    api_contracts/official.py 搬至 tools/schema_cache/fetch.py(唯一生产消费者是
    schema_cache,codegen/okr v2 批量预取不受影响),official.py 回归纯 catalog seam。

  • websocket:ACK data 对齐官方 base64 wire 格式 + card 帧文档化(#631):
    长连接数据帧应答(ACK)payload 的 data 字段由 serde 对 Vec<u8> 默认的 JSON 数组
    ([1,2,3])改为 base64 字符串,与官方 SDK 一致(Go []byte+json.Marshal、
    Python base64.b64encode、Node Buffer.toString("base64"));Serialize/Deserialize
    对称(往返一致),无业务数据时省略 data 字段(Python/Java/Node 行为),序列化失败
    fallback 不再输出 "data":[]。base64 为 websocket feature 下的 optional 依赖。
    type=card 数据帧维持跳过(官方 Go/Python/Java/Node SDK 一律直接丢弃、不回 ACK),
    由 debug! 升级为 warn! 并在代码注释记录官方依据;新版卡片回调
    (card.action.trigger)官方路径是 type=event 帧 + payload header.event_type,
    已由 EventDispatcherHandler 按 event_type 路由支持(补官方 schema 2.0 fixture 测试)。

  • tools:字段核对跳过多分表单内部元数据 / 放宽「代码更严」门禁:
    verify_api_fields 提取 Body 时跳过 serde 名以 __ 开头的字段(如 multipart
    __file_name);「文档选填但代码非 Option」由 warning 降为 info,不再阻断 --fetch-docs
    门禁(保留提示,避免有意更严建模被误拦)。

  • websocket protobuf 打包修复(#605):恢复 lark-websocket-protobuf 为 workspace
    权威发布源并准备 0.1.2;将 pbbp2.proto 的生成代码随 crate 提交和打包,移除默认
    build.rs、prost-build 与消费者侧 protoc 系统依赖。公开路径
    lark_websocket_protobuf::pbbp2::{Frame, Header} 和消息字段保持兼容;新增从 .crate
    解包后在无 protoc 环境构建的回归测试。实际 crates.io 发布仍需 owner 在合并后执行。

  • ADR-0002 lock-in(#584):代码迁移已在 main;本项补治理半边——
    docs/adr/0002-auth-concern-concentration.md 状态 → Accepted(残差空);
    ARCHITECTURE.md / openlark-core/AGENTS.md 鉴权归属对齐 auth/{policy,acquisition,app_ticket};
    新增结构回归锁 crates/openlark-core/tests/adr0002_locality_lock.rs
    (policy 不回迁 Transport、resend 不经 ad-hoc client、AuthHandler 不回迁 request_execution、
    无公开 resend escape hatch、ADR 状态)。无公开 API 变更。

  • catalog:同步 2026-07-27 飞书 API 目录(#581):
    live 二次导出复核与 issue 快照一致(基准 1739 → 当前 1736;新增 0 / 删除 3 / 字段变化 7)。

    • 刷新 api_list_export.csv:合并 approval subscription 文档路径重命名与 charging 回填、
      IM「搜索消息」与 VC bot 读接口的计费/supportAppTypes/name 元数据变化;url 列未改写。
    • message_cot(create/complete/update):live 目录列表已无,但官方 docPath 仍 HTTP 200。
      CSV 与 live 对齐移除三行;SDK 公开 API 默认冻结保留(openlark-communication im/v1
      message_cot leaf 不删不改),按「catalog 外 extra 实现」口径处理,不触发 missing 补齐。
    • 可选:approval instance/task subscription 模块 docPath 注释对齐新 fullPath slug;
      wire method/path 与 Request/Response 形状不变。

Fixed

  • release:publish-workspace.sh 识别已发布版本的 Cargo 新文案:
    lark-websocket-protobuf 0.1.2 已在 crates.io。Cargo 1.84+ 在真正上传前以
    already exists on crates.io index 失败(不再只靠服务端 is already uploaded)。
    脚本两种文案都继续后续 crate,避免 0.21 发布停在发布顺序的第一个包。

  • webhook:出站签名改为飞书空消息 HMAC(#686):sign 使用
    base64(HMAC-SHA256(key="{timestamp}\n{secret}", message="")),与自定义机器人
    官方算法一致。此前 key 与 message 对调,签名校验会被拒绝。

  • auth:tenant token 缓存键纳入租户上下文(#684):缓存键同时哈希
    tenant_key 与 app_ticket,票据轮换后不再复用旧 tenant token。

  • websocket:未处理事件不再物化整段 JSON(#683):分发器只解析事件信封以取得
    event_type,命中处理器后才把原始 payload 交给 handle,不再预先把整段事件
    解析成 serde_json::Value。

  • ai:合同抽取上传大小上限(#682):field_extraction 在发往 Transport 前拒绝
    达到 10MiB 边界的 file(上限 10 * 1024 * 1024 - 1 字节)。

  • api:必填列表非空校验 + 快速模式假阳性(#646):
    批量删除补充信息在空 user_ids 时于 Transport 前返回校验错误。
    detect_suspicious_patterns 认字段级 validate_required!(与
    validate_required_list! / {field}.is_empty() 同等效力);
    skip_serializing_if = "Vec::is_empty" 的可选列表不再报
    missing_list_validation。人员组成员 write 的空 add/remove 仍为合法 no-op。

Crate 级质量状态

质量状态维度:

  • typed coverage:来自 reports/api_validation/summary.json 的 typed API 覆盖率
  • contract tests:crate 内存在 request/response contract test
  • snapshot tests:crate 内存在 helper/output snapshot test
crate typed coverage 剩余缺口 contract tests snapshot tests 备注
openlark n/a n/a no no 非 typed API 覆盖统计对象
lark-websocket-protobuf n/a n/a no no 非 typed API 覆盖统计对象
openlark-core n/a n/a yes no 非 typed API 覆盖统计对象
openlark-client n/a n/a yes no 非 typed API 覆盖统计对象
openlark-capability-unique n/a n/a no no 非 typed API 覆盖统计对象
openlark-auth 100.0% 0 no no 无 typed API 缺口
openlark-security 100.0% 0 no no 无 typed API 缺口
openlark-communication 100.0% 0 yes yes 无 typed API 缺口
openlark-cardkit 100.0% 0 no no 无 typed API 缺口
openlark-webhook n/a n/a no no 非 typed API 覆盖统计对象
openlark-docs 100.0% 0 yes yes 无 typed API 缺口
openlark-hr 100.0% 0 yes no 无 typed API 缺口
openlark-ai 100.0% 0 no no 无 typed API 缺口
openlark-workflow 100.0% 0 yes yes 无 typed API 缺口
openlark-application 100.0% 0 yes no 无 typed API 缺口
openlark-platform 100.0% 0 yes no 无 typed API 缺口
openlark-meeting 100.0% 0 yes no 无 typed API 缺口
openlark-helpdesk 100.0% 0 yes no 无 typed API 缺口
openlark-mail 100.0% 0 yes no 无 typed API 缺口
openlark-bot 100.0% 0 no no 无 typed API 缺口
openlark-pay 0.0% 0 no no 无 typed API 缺口
openlark-analytics 100.0% 0 yes no 无 typed API 缺口
openlark-user 100.0% 0 yes no 无 typed API 缺口