
文档教程【免费下载链接】bookThe canonical reference for Astrid: kernel, capsules, host ABI, IPC, and the security model.项目地址https://gitcode.com/gh_mirrors/book269/book点击查看免费下载这篇技术指南以 Unicity Astrid OS 官方参考书The Unicity Astrid OS Book中的 附录Host ABI 错误码 为骨架结合内核宿主实现与 SDK 包装层系统讲解 Astrid 宿主 ABIhost ABI中error-code变体的完整设计它是什么、从哪里生成、每个包有哪些错误臂arm、各自在什么条件下被触发以及胶囊capsule开发者应如何正确地匹配与处理这些错误。读完本文你将能基于错误码类型而不是字符串解析来编写健壮的胶囊错误处理逻辑并理解 Astrid 为什么把错误类型化作为 ABI 稳定契约的一部分。error-code所有可失败宿主函数的统一返回类型Astrid 的宿主 ABI 是胶囊访问宿主操作系统文件、网络、总线、密钥存储、时钟等的唯一合法路径整个接口面都用 WIT 定义、按域划分包、每个包冻结在1.0.0版本见 The Syscall Surface。在这个契约体系中error-code是一个统一的错误变体约定每个可失败的宿主函数都返回result_, error-code。其中unknown(string)臂携带一段宿主格式化host-formatted的细节字符串是兜底catch-all分支——用于 WIT 契约没有预料到的情形其余命名的臂让胶囊可以不解析文本就精确匹配某个具体失败例如not-found、capability-denied、timeout、cas-mismatch。也就是说错误码设计的第一原则是可枚举的错误必须是类型而不是字符串。胶囊代码可以match一个 Rust 枚举而无需做任何字符串比较相关内容可参考 The Syscall Surface 的 Error Type Design 一节。这份附录从哪里来由 WIT 源文件生成本仓库中的src/appendix/error-codes.md不是手写文档而是由 tools/gen-appendices.sh 从权威源自动生成的。脚本注释明确写道These appendices are GENERATED, not hand-written. Do not edit the output files. Edit the source of truth (the Rust constants and the WIT files) and re-run this script.生成逻辑在脚本第 67-93 行读取wit/host/*.wit即unicity-astrid/wit仓库中host/目录下每个域的 WIT 文件用 Perl 正则抽取每个文件中variant error-code { ... }块文件名去掉.wit后缀即得包名如fs1.0.0.wit→fs1.0.0按包名排序后把每个变体臂以逗号分隔打印成##pkg 小节。运行方式在包含core/、wit/、capsules/的多仓工作树根目录下bash astrid-book/tools/gen-appendices.sh因此本文列出的错误臂清单与wit/host/*.wit中的variant error-code定义严格一一对应。如果你在源码中看到一个错误臂它在宿主实现和 SDK 绑定中都以同名 Rust 枚举变体存在。跨包的三个通用设计模式在进入逐包清单之前先看三个跨所有包的共同约定详细论述见 The Syscall Surfacecapability-denied永远是独立臂绝不折叠进unknown。胶囊捕获错误时可以直接按此分支处理无需字符串匹配。能力检查发生在每个调用的入口而非加载时所以能力被撤销后下一次调用立即生效。unknown(string)是唯一的兜底臂且其内容是尽力而为的。契约明确astrid:fs的错误字符串从不包含宿主真实路径、IP 地址、UUID 或能力名。to-debug-stringastrid:io/error也只为人类可读的诊断服务不承诺可解析格式。资源特定错误是一等臂first-class arm。例如 fs 的boundary-escape、net/http 的airlock-rejected、kv 的cas-mismatch都是为了让调用方无需解析文本即可处理。此外每个包都各自定义自己的error-code变体而不是共享一个全局错误枚举——这保证包的演进是局部的符合 WIT 契约与版本冻结纪律见 WIT Contracts and the Three-Repo Flow。逐包错误码清单与触发语义以下是附录中全部 12 个包的完整错误臂清单并补充每个错误臂在实际宿主实现中的触发条件与来源依据。approval1.0.0人工审批human-in-the-loopinvalid-input, timeout, store-unavailable, unknown(string)invalid-inputaction字符串超过MAX_ACTION_LEN256 字符上限时宿主入口即拒绝target-resource超过 1024 只做截断因为它是仅用于展示/审计的字段timeout审批调用阻塞等待前端用户响应60 秒超时未收到响应即返回胶囊卸载导致的取消同样归入超时store-unavailableAllowanceStore预授权快速路径不可用时返回。详见 Host Packages: Approval, Identity, Uplink。elicit1.0.0生命周期内的交互输入收集not-in-lifecycle, timeout, cancelled, invalid-input, store-unavailable, unknown(string)not-in-lifecycleelicit 被生命周期门HostState::lifecycle_phase约束只能在#[astrid::install]/#[astrid::upgrade]钩子中调用从 run loop、interceptor 或 tool 上下文调用立即返回此错误——这是该包区别于其他包的标志性错误臂timeout宿主最多阻塞 120 秒等待用户输入cancelled用户响应中value和values均为空时返回表示流程被中止invalid-inputselect类型要求非空options列表空列表直接拒绝。fs1.0.0虚拟文件系统not-found, access, capability-denied, boundary-escape, invalid-path, would-block, is-directory, not-directory, not-empty, too-large, quota, cross-vfs, already-exists, closed, unknown(string)这是错误臂最多的包之一每个臂对应一类可预测的路径/文件失败完整契约见 Host Packages: Filesystem, IO, and Storagenot-found目标路径不存在access权限不足非能力层面的访问拒绝capability-deniedCapsule.toml [capabilities]缺少fs_read/fs_write安全门在 VFS 分发之前就拒绝发生在任何路径解析之前boundary-escape..组件解析后越出 VFS 作用域这也是fs-hard-link的两个端点与process的cwd防穿越共用的一等臂invalid-path路径携带 NUL 字节、控制字符、非 UTF-8-NFC 字符串、超长字符串或不带 VFS schemeworkspace://、home://、tmp://的绝对路径would-block非阻塞操作在资源未就绪时返回对应astrid:io的轮询语义is-directory/not-directory路径类型与操作不匹配如对目录调用读文件not-empty删除非空目录fs-remove-dir-all目前是 stub返回unknown见下too-large单次read-file/write-file/fs-append超过 10 MBMAX_GUEST_PAYLOAD_LENfile-handle.read-at/write-at超过 1 MB或fs-readdir结果超过 4096 条quota超出 per-principal 配额cross-vfs跨越不同 VFS scheme 的操作如把workspace://文件硬链接到home://already-existsfs-mkdir是严格语义目标已存在即失败fs-mkdir-all才幂等closed句柄或流已关闭unknown(string)兜底。值得注意部分 WIT 已定义但宿主尚未落地的函数fs-open及其整个file-handle资源、fs-stat-symlink、fs-append、fs-copy、fs-rename、fs-remove-dir-all、fs-canonicalize、fs-read-link、fs-hard-link当前统一返回Err(ErrorCode::Unknown(... port pending))。胶囊应把它们当临时性失败处理简单读写模式优先回退到read-file/write-file。http1.0.0出站 HTTP带 SSRF 防护capability-denied, invalid-request, dns-error, airlock-rejected, tls-error, timeout, connection-error, body-too-large, closed, quota, protocol(string), unknown(string)airlock-rejectedSSRF 气闸拦截——DNS 解析在连接前由宿主完成私网10.0.0.0/8等、回环、链路本地、组播、未指定地址段全部被拒绝IPv4-mapped IPv6 也检查tls-errorTLS 握手失败HTTP 协议层由宿主实现包括 TLS、重定向、头归一化timeouthttp-request整体 30 秒超时body-too-large响应体超过 10 MB 上限protocol(string)这是唯一携带字符串参数的协议级错误臂携带如无效方法等协议细节quota同时并发 HTTP 流超过每胶囊 4 条的上限。identity1.0.0外部平台身份映射capability-denied, invalid-input, user-not-found, link-not-found, already-linked, store-unavailable, unknown(string)capability-denied身份操作受能力层级门控resolvelinkadmin默认CapsuleSecurityGate对所有身份操作 fail-closed空identity列表意味着所有调用都返回此错误invalid-inputastrid-user-id无法解析为uuid::Uuid时立即返回user-not-found/link-not-found/already-linked身份存储层的三种业务状态。其中link-not-found是权威信号而不是found: bool字段SDK 把它翻译成Ok(None)以便调用方使用惯用的Option语义。io1.0.0基础 I/O 原语poll / streamsinvalid-input, closed, too-large, cancelled, unknown(string)astrid:io是wasi:io形状的 Astrid 自研实现错误臂最少但语义关键cancelledpollable.block()与poll.poll()与胶囊的取消令牌竞速胶囊卸载时阻塞调用立即返回cancelled而不是让宿主任务空悬在永不完成的 future 上too-large单次poll超过 256 个 pollable 的上限closed流被关闭也作为 EOF 信号使用或胶囊卸载后所有流操作统一返回closedinvalid-input非法参数。流层还有一个独立的stream-error变体last-operation-failed(error)/closed其中error资源可向下转型downcast到域特定的error-code例如把 TCP 读失败转型为net的connection-reset或timeout。ipc1.0.0事件总线发布/订阅capability-denied, invalid-input, closed, rate-limited, backpressure, quota, timeout, unknown(string)invalid-input话题违反语法——段匹配[a-z0-9._-]、最多 8 段、总长不超过 256 字节foo.*.bar这类中间段通配符被subscribe拒绝quota每胶囊最多 128 个订阅超出即返回timeoutsubscription.recv(timeout-ms)超过宿主上限60,000 ms或等待超时rate-limited/backpressure总线层的流控与背压信号见 Per-Principal Routing and Backpressureclosed订阅句柄已关闭capability-denied发布/订阅表[publish]/[subscribe]未声明对应话题。kv1.0.0持久化键值存储invalid-key, too-large, quota, cas-mismatch, unknown(string)invalid-key键违反约束——非 UTF-8 NFC、含 NUL 字节或控制字符、超过 256 字节too-large值超过 1 MiB或kv-list-keys结果超过 1024 条契约刻意用too-large推动调用方改用分页 APIkv-list-keys-pagequotaper-(principal, capsule)累计配额由服务端强制耗尽即返回cas-mismatchCAS 期望值不匹配。这是并发协调的关键错误臂——内核在 Tokio 线程池上分发调用共享键上的读-改-写必须靠 CAS 保证原子性存储后端见 KV Storage。SDK 把cas-mismatch翻译回Ok(false)让常规的输掉竞争后重试循环用布尔分支即可。net1.0.0Unix 套接字、TCP、UDP、DNSwould-block, closed, capability-denied, airlock-rejected, connection-refused, connection-reset, timeout, address-in-use, address-not-available, name-unresolvable, invalid-handle, not-tcp, quota, unknown(string)airlock-rejectedSSRF 气闸拦截与 http 共享同一套地址过滤逻辑would-block非阻塞操作未就绪connection-refused/connection-reset/timeout连接层的三类标准失败可经astrid:io/error向下转型从流错误中还原address-in-use/address-not-available绑定端口/地址失败name-unresolvableDNS 解析失败注意解析成功但全部候选被气闸过滤时返回的是空列表而不是这个错误invalid-handle句柄无效not-tcp在 Unix 域套接字流上调用 TCP 专属 socket 选项set_nodelay、set_keepalive等时返回——因为TcpStream是 Unix 连接与出站 TCP 的共享类型quota每胶囊 8 个并发 TCP 流、4 个 TCP 监听器、4 个 UDP 套接字。process1.0.0宿主进程派生仅桌面内核capability-denied, invalid-input, boundary-escape, quota, too-large, closed, cancelled, wait-timeout, unknown(string)capability-denied缺少host_process能力或命令不在清单允许的可执行名列表中boundary-escapecwd字段含绝对路径或..穿越沙箱以工作区目录为界命令经bwrap/sandbox-exec包装quota每胶囊最多 8 个并发后台进程too-largestdout/stderr 1 MiB 环形缓冲区溢出类上限cancelled同步spawn阻塞期间胶囊被取消wait-timeoutwait(Some(duration))在期限内子进程未退出closed进程已被回收os_pid等调用返回。sys1.0.0系统运行原语日志、时钟、熵、配置、能力查询capability-denied, config-key-reserved, too-large, registry-unavailable, cancelled, unknown(string)这个包值得单独展开因为它承载一个显式的 fail-closed 哨兵config-key-reserved胶囊试图读取保留的内部配置键如ASTRID_SOCKET_PATH归属内核注入另有常量env::CONFIG_SOCKET_PATHtoo-largerandom-bytes单次请求超过 4096 字节SDK 的 shim 会循环补齐更大请求registry-unavailable能力注册表无法被查询时返回。它特意不折叠进unknown因为下游调用方必须能区分能力不存在应返回allowed: falsefail-closed与注册表本身不可达。依赖其他胶囊能力做条件行为的胶囊必须把registry-unavailable视作拒绝而非批准cancelledsleep-ns在胶囊卸载期间被取消单次睡眠上限 60 秒。uplink1.0.0平台桥接注册与消息注入capability-denied, invalid-input, invalid-profile, unknown-uplink, no-session, quota, unknown(string)capability-denied缺少uplink true能力标志HostState::has_uplink_capability是首道检查任何其他检查之前invalid-input注册时name/platform为空或uplink-id无法解析为 UUIDinvalid-profileuplink-profile不是chat/interactive/notify/bridge之一unknown-uplinkuplink-id未匹配到HostState::registered_uplinks中的描述符no-session目标 principal 无活动会话quota资源限制错误映射而来。注意一个易混淆点uplink-send在 WIT 层面不返回no-session——会话不存在时宿主用try_send通道错误返回Ok(false)表示消息被有意丢弃这是正常流而非异常。错误臂的横向分类如何在实战中对号入座把 12 个包的错误臂合并归类可以提炼出五条处理主线类别代表错误臂处理建议能力与策略capability-denied所有需要能力的包、config-key-reserved、registry-unavailable多数是配置/清单错误属于调用方修清单后重试registry-unavailable必须按拒绝处理配额与资源上限quota、too-large、rate-limited、backpressure表示达到硬上限应退避重试或改用分页/流式 API如kv-list-keys-page、splice生命周期与关闭cancelled、closed、not-in-lifecycle、wait-timeout表示宿主正在卸载、流已 EOF 或调用上下文不合法按可预期状态处理而非当作异常网络与远程connection-refused、connection-reset、timeout、dns-error、tls-error、name-unresolvable、airlock-rejected、address-in-use可重试类与硬拒绝类要区分airlock-rejected是策略拒绝重试无用数据与并发cas-mismatch、already-exists、user-not-found、link-not-found、invalid-key、invalid-path多为业务状态SDK 已尽量翻译成Ok(false)/Ok(None)等惯用形态SDK 侧的落地错误臂如何变成 Rust 类型astrid-sys通过wit_bindgen::generate!从 WIT 生成类型化绑定每个域的error-code变体成为 Rust 枚举astrid-sdk再把每个宿主调用包成Result_, SysError错误臂经Debug格式化映射为SysError::HostError(String)。更重要的是一些语义映射约定SDK 层把是错误改写成是结果identity的link-not-found→Ok(None)uplink-send的无会话丢弃 →Ok(false)kv的cas-mismatch→Ok(false)配合循环重试写 CAS 模式loop { let current kv::get_bytes_opt(counter)?; let new_val compute_new(current); if kv::cas(counter, current.as_deref(), new_val)? { break; } }来自 Host Packages: Filesystem, IO, and Storage 的 SDK 示例。这意味着胶囊代码在绝大多数常规路径上可以享受Optionbool级别的简洁语义只有真正需要区分失败种类的场景如把流错误向下转型到connection-resetvstimeout才需要触碰原始错误臂。实践要点总结优先匹配命名臂capability-denied、quota、timeout、cas-mismatch等都有明确语义直接match枚举变体。不要解析unknown(string)的文本它尽力而为、不属于契约fs 的错误字符串保证不含真实路径、IP、UUID 或能力名。注意 stub 返回值fs 的部分函数当前返回unknown(... port pending)应视为临时性失败并回退到read-file/write-file。fail-closed 永远是默认registry-unavailable视作拒绝空identity列表、无uplink标志、无能力声明都意味着调用直接失败。错误码是 ABI 契约的一部分附录由wit/host/*.wit生成、随版本冻结新功能走新版本文件如ipc1.1.0.wit而不是改动既有变体。因此按类型匹配的代码在 ABI 演进后依然成立。延伸阅读附录Host ABI Error Codes本文骨架生成源附录生成脚本 tools/gen-appendices.shThe Syscall Surface错误类型设计、零 WASI 导入Host Packages: Filesystem, IO, and Storagefs/kv/io 错误触发细节Host Packages: IPC, Net, HTTP, Sys, ProcessHost Packages: Approval, Identity, UplinkWIT Contracts and the Three-Repo Flow版本冻结与多版本共存KV Storagekv 后端与 CAS 实现赞分享文档教程【免费下载链接】bookThe canonical reference for Astrid: kernel, capsules, host ABI, IPC, and the security model.项目地址https://gitcode.com/gh_mirrors/book269/book点击查看免费下载相关推荐Astrid Host ABI 系统调用面The Syscall SurfaceWIT 契约、零 WASI 导入与能力门控全解析Astrid Host ABI 系统调用面The Syscall SurfaceWIT 契约、零 WASI 导入与能力门控全解析 导读 本文深入解析 Un文档教程Astrid Host ABI 实战指南astrid:fs / astrid:kv / astrid:io 文件、键值与流式 I/O 三包全解Astrid Host ABI 实战指南astrid:fs / astrid:kv / astrid:io 文件、键值与流式 I/O 三包全解 导读 本篇围绕文档教程Angular NG8024 错误完全指南Host 指令组合中的绑定别名冲突Conflicting Host Directive BindingAngular NG8024 错误完全指南Host 指令组合中的绑定别名冲突Conflicting Host Directive Binding 本文面向前端Web框架上一篇Fate/Grand AutomataFGO安卓版智能自动化战斗工具详解下一篇OBS虚拟摄像头终极指南如何将专业直播画面变成万能视频源创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考