Repository navigation
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:改为 multipartfile+ 必填
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-applicationapplication/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
payfeature。PayService/PayClient提供订单详情(get_order)、租户付费方案
列表(list_orders)与用户开通范围(check_user)。同一批补齐 platform spark
分析与可用范围(analytics_overview/query_analytics_data/credit_usage/
available_scopeget+update)以及 VCcountdown。发布顺序上openlark-pay
位于openlark-client之前。 -
client:HTTP 事件入站
event-http(#672,#667):新增HttpEventInbound
(根 crateevent-httpfeature,复用EventDispatcherHandler)。覆盖
encrypt_keyAES-256-CBC + PKCS7 解密、url_verificationChallenge,以及入站
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。HTTPevent-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-docsminutes/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):新增
CallbackEventHandlertrait(handle返回Option<serde_json::Value>)与
EventDispatcherHandler::register_callback(key, handler)。卡片回传交互
(card.action.trigger)等 callback 型事件的业务响应(如{"toast": {...}}/
{"card": {...}})现经 ACK 帧data字段以 base64(JSON) 写回服务端(3 秒内),
对齐官方 GoOnP2CardActionTrigger/ Pythonregister_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:删除 id7563551656446263298
(获取客户端设备认证信息 /
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、
Pythonbase64.b64encode、NodeBuffer.toString("base64"));Serialize/Deserialize
对称(往返一致),无业务数据时省略data字段(Python/Java/Node 行为),序列化失败
fallback 不再输出"data":[]。base64为websocketfeature 下的 optional 依赖。
type=card数据帧维持跳过(官方 Go/Python/Java/Node SDK 一律直接丢弃、不回 ACK),
由debug!升级为warn!并在代码注释记录官方依据;新版卡片回调
(card.action.trigger)官方路径是type=event帧 + payloadheader.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-communicationim/v1
message_cot leaf 不删不改),按「catalog 外 extra 实现」口径处理,不触发 missing 补齐。 - 可选:approval instance/task subscription 模块
docPath注释对齐新fullPathslug;
wire method/path 与 Request/Response 形状不变。
- 刷新
Fixed
-
release:
publish-workspace.sh识别已发布版本的 Cargo 新文案:
lark-websocket-protobuf0.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 缺口 |