feat: release Dever 0.1.5 with direct workers and long transactions
This commit is contained in:
1 parent
89629c2197
commit
a900d7e8db
153 files changed
+3676
-3708
No files matched your search
+28
-9
@@ -148,7 +148,7 @@ cmd version = app.version
|
||||
|
||||
command Port 只有一个操作,操作名由业务决定;输入固定为 `args: List<Text>`,可选第二项 `stdin: Bytes?`,输出固定为 `output: dever.process.Output`,错误为 `dever.process.Error`。只需 argv 时可省略整项 stdin 参数。Output 有 `code: Int`、`stdout: Bytes`、`stderr: Bytes`;二进制输出不做隐式文本转换,正常非零退出码也是结果。每次调用启动一次进程,不重试,不使用 shell;空格、引号、`$()` 等按参数原样传递。未提供 stdin 时立即发送 EOF。启动失败、超时和输出超限产生源位置 runtime fault。
|
||||
|
||||
调用限额只从 `config/setting.json` 读取:`{"adapter":{"media.tool":{"command":{"timeout_ms":30000,"output_limit":1048576}}}}`。示例值就是默认值;timeout_ms 最大 3600000,output_limit 为 stdout/stderr 合计字节数、最大 8388608,均必须为正数。argv 含终止符总计最多 65536 字节且不含 NUL,stdin 最多 8388608 字节。超时、取消和退出会回收本次沙箱进程树。需要文件、网络或子进程时仍在声明中写 `allow file/network/process` 并使用已有部署授权;command 不接受 `setting` 或 `lib` 声明。
|
||||
调用限额只从 `config/setting.json` 读取:`{"adapter":{"media.tool":{"command":{"timeout_ms":30000,"output_limit":1048576}}}}`。示例值就是默认值;timeout_ms 最大 3600000,output_limit 为 stdout/stderr 合计字节数、最大 8388608,均必须为正数。argv 含终止符总计最多 65536 字节且不含 NUL,stdin 最多 8388608 字节。超时、取消和退出会回收本次受管进程组;不保证清理主动脱离进程组的守护程序。需要文件、网络或子进程时仍在声明中写 `allow file/network/process`,实际权限继承所在容器;command 不接受 `setting` 或 `lib` 声明。
|
||||
|
||||
`run/build` 离线嵌入 ELF 和相邻 `bin/lib/` 下显式随附的普通动态库文件;静态程序可直接使用,动态程序使用签名发行包的 GNU loader 和 OS 库。不扫描宿主库,不接受符号链接或 lib 子目录;缺库、错架构、SONAME/版本不匹配、越界搜索路径在构建期失败。Linux x86_64 与 ARM64 必须提供各自架构的二进制和库,Dever 不转换第三方二进制。单独使用 command 不需要 `dever lib` 或 `dever.lock`;资源可随 Dever Package 分发,Package 自身仍须锁定。测试继续用 Port fake,不执行真实命令。
|
||||
|
||||
@@ -165,7 +165,7 @@ external exec "worker/mail" {
|
||||
}
|
||||
```
|
||||
|
||||
entry 是所属领域目录内的可移植相对路径;上例构建时收集 `module/notification/mail/worker/mail`,将全部候选 exec Worker 的字节、SHA-256 和可执行位嵌入程序。入口原子提取到私有 `data/cache/lib/<bundle>`,每次启动 Worker 重新验证精确资源清单、摘要和 Unix 所有权/权限;不扫描其他 bundle,不依赖部署目录保留源码 Worker。路径不接受绝对形式、`.`、`..`、反斜杠或盘符,也不通过 shell、`PATH`、环境变量或外部命令字符串查找。capability 名称为 `network`、`file`、`process`、`gpu`;重复值和未知值在检查期拒绝。Worker 握手必须精确回显已编译的 Port、Adapter、schema、操作和 capability 集合。Linux 的文件、网络、进程权限还由统一 OS 沙箱执行;文件授权仅来自 `config/setting.json` 的 Adapter 配置。GPU 与其他 OS 沙箱尚不支持,明确失败。宿主必须允许所需 namespace 和 seccomp;不会自动放宽 AppArmor 等主机策略。
|
||||
entry 是所属领域目录内的可移植相对路径;上例构建时收集 `module/notification/mail/worker/mail`,将全部候选 exec Worker 的字节、SHA-256 和可执行位嵌入程序。入口原子提取到私有 `data/cache/lib/<bundle>`,每次启动 Worker 重新验证精确资源清单、摘要和 Unix 所有权/权限;不扫描其他 bundle,不依赖部署目录保留源码 Worker。路径不接受绝对形式、`.`、`..`、反斜杠或盘符,也不通过 shell、`PATH`、环境变量或外部命令字符串查找。capability 名称为 `network`、`file`、`process`、`gpu`;重复值和未知值在检查期拒绝。Worker 握手必须精确回显已编译的 Port、Adapter、schema、操作和 capability 集合。Linux Worker 直接执行,不创建内层 OS 沙箱。`allow` 是编译期效果及协议声明,不限制操作系统访问;实际文件、网络、GPU 权限由所在容器的用户、挂载、网络和设备策略决定。旧 Adapter `files` / `gpu` 授权字段已删除,真实路径通过业务 setting 传入。GPU 继承父容器设备和必要驱动环境,不重挂载设备,不修改主机安全策略。仅执行可信代码;配置与受管 C ABI 用法见 `sdk/README.md`。
|
||||
|
||||
`external` 只在 Adapter role 中有意义,且一个文件只能包含该声明和至多一个 `setting`。它完整实现且只能实现同领域一个 Port identity;不能同时写 Dever Adapter 函数或 helper。应用测试仍必须提供 case-local Dever Port fake,不启动生产 Worker,也不读取生产 Adapter setting。reference 后端明确不执行外部程序,正式执行只走 native 后端。
|
||||
|
||||
@@ -188,7 +188,7 @@ Go Worker 使用锁定的目标专用 build pack 内的 compiler、linker 和标
|
||||
|
||||
显式 `dever lib add/update` 可用签名 build pack 构建 PEP 517 sdist、执行 npm registry 包的 `preinstall/install/postinstall` 和原生 addon 编译。build pack 必须提供目标运行时、头文件、编译器、sysroot、固定 shell 和工具闭包;缺少的工具或库明确报错,不寻找宿主环境。Python 的静态与动态 build requirements 使用独立精确锁,console scripts 安装到隔离构建 prefix;metadata 与 wheel hook 分进程执行,最终 wheel 必须匹配父进程保存的 metadata。npm publishing hooks 不作为 registry 安装钩子执行,可选依赖构建失败会裁剪其不可用闭包,必需依赖失败则整个准备失败。
|
||||
|
||||
源码构建收据绑定源码摘要、运行时、工具包、固定 frontend、构建依赖与输出摘要;npm 还绑定完整安装图。`run/build` 离线消费已锁定输出,不再次执行上述安装钩子或源码构建。Node addon 在仅有目标 Node 和运行库的独立沙箱中逐个验证;所有 `.node` 文件必须有成功或明确拒绝记录,运行树只安装成功项,其他平台/ABI 的变体保留在原锁定归档中。本次源码生成的 addon 验证失败会使准备失败,不能改用纯 JavaScript 回退并声称原生构建成功。Linux 构建使用只读工具与输入、独占可写工作区并禁止网络。构建期限为五分钟,stdout/stderr 各限 16 MiB;工作区每 250 ms 检查 512 MiB/65,536 项预算并在超限时回收子进程,这不是内核磁盘 quota,检查间隔内可暂时超限。最终安装树仍限 256 MiB/65,536 项。普通 Worker 的能力由同一 OS 沙箱执行,其他平台不能借宿主工具绕过缺失的发行支持。
|
||||
源码构建收据绑定源码摘要、运行时、工具包、固定 frontend、构建依赖与输出摘要;npm 还绑定完整安装图。`run/build` 离线消费已锁定输出,不再次执行上述安装钩子或源码构建。Node addon 在仅有目标 Node 和运行库的独立进程中逐个验证;所有 `.node` 文件必须有成功或明确拒绝记录,运行树只安装成功项,其他平台/ABI 的变体保留在原锁定归档中。本次源码生成的 addon 验证失败会使准备失败,不能改用纯 JavaScript 回退并声称原生构建成功。Linux 构建使用明确的签名工具与输入、独立临时工作区;构建钩子直接继承容器权限,不再宣称文件/网络隔离。构建期限为五分钟,stdout/stderr 各限 16 MiB;工作区每 250 ms 检查 512 MiB/65,536 项预算并在超限时回收子进程,这不是内核磁盘 quota,检查间隔内可暂时超限。最终安装树仍限 256 MiB/65,536 项。普通 Worker 由同一进程监管执行;其他平台不能借宿主工具绕过缺失的发行支持。
|
||||
|
||||
Dever Package 的请求放在 `config/setting.json.package`:`registry` 是显式 HTTPS registry origin,`use` 是 `name@version-range` 数组。`dever package add/update` 解析版本和传递依赖;Package 与 Lib 共用 `dever.lock` 和机器摘要缓存。Package 的源码归属于 `module/<name>/`,Worker 资源归属于同组件路径或 `worker/<name>/`;其他组件路径不能混入归档,也不能与项目本地组件重名。`check/test/run/build` 自动加载锁定源码,无须增加 import 或注册方法;缺失的锁定 Worker 必须失败,不能使用项目同名文件替代。`remove` 离线裁剪已验证锁,不重新选择剩余依赖版本。
|
||||
|
||||
@@ -1054,11 +1054,11 @@ public post greeting = app.greet
|
||||
cmd greeting = app.greet
|
||||
```
|
||||
|
||||
前两项对应 `GET`、`POST /user/account/greeting`;CMD 名称为 `user.account.greeting`,输入是单个 JSON 对象,输出同样使用 `{"code":0,"message":"ok","data":...}`。HTTP 声明默认要求认证,只有明确的登录、健康检查等单条 HTTP 声明可加 `public`;`public cmd` 和 `public rest` 非法。public 入口忽略浏览器自动携带的旧 Cookie,使过期会话不会阻止重新登录;客户端显式提交的无效 Authorization 仍返回 401,不能降级成匿名请求。`get/post/put/delete <action> = app.<function>` 只绑定本领域无歧义的 App 函数,继承其输入输出签名,输出名不必叫 `response`。GET 的完整调用链不能写数据库或入队 Job;普通写 HTTP/CMD/Job 调用链在入口建立事务。含 password hash/verify 的 HTTP 调用链不建立覆盖密码计算的外层事务,其写入必须全部进入显式短 `transaction`,且事务内禁止密码计算;短事务必须重查写入依赖的账户、租户或成员状态。API role 不写函数体或旧 `get_` 前缀。GET/DELETE 从 query 读取标量输入,POST/PUT 从 `Content-Type: application/json` 的对象正文读取;命令也读取严格 JSON 对象。缺少必填值、额外或重复字段均拒绝。输入输出使用同一静态 wire codec,当前不支持 Choice、Bytes 等类型。
|
||||
前两项对应 `GET`、`POST /user/account/greeting`;CMD 名称为 `user.account.greeting`,输入是单个 JSON 对象,输出同样使用 `{"code":0,"message":"ok","data":...}`。HTTP 声明默认要求认证,只有明确的登录、健康检查等单条 HTTP 声明可加 `public`;`public cmd` 和 `public rest` 非法。public 入口忽略浏览器自动携带的旧 Cookie,使过期会话不会阻止重新登录;客户端显式提交的无效 Authorization 仍返回 401,不能降级成匿名请求。`get/post/put/delete <action> = app.<function>` 只绑定本领域无歧义的 App 函数,继承其输入输出签名,输出名不必叫 `response`。GET 的完整调用链不能写数据库或入队 Job。普通写 HTTP/CMD/Job 由入口建立整体事务;涉及外部 I/O、Worker、等待、并发或密码计算的写入口必须显式加 `long`,并将写库与入队放进 `transaction` 函数。`long` 不建立入口级事务,已提交阶段不因后续失败撤销;写入时须在事务内重查账户、租户或成员状态。编译器只验证声明,不根据调用图自动切换事务模式。API role 不写函数体或旧 `get_` 前缀。GET/DELETE 从 query 读取标量输入,POST/PUT 从 `Content-Type: application/json` 的对象正文读取;命令也读取严格 JSON 对象。缺少必填值、额外或重复字段均拒绝。输入输出使用同一静态 wire codec,当前不支持 Choice、Bytes 等类型。
|
||||
|
||||
简单领域使用 `api.dever`;复杂领域可同时使用 `api.dever` 与 `api/<scope>/<resource>.dever`,topic 依次进入 URL,例如 `module/user/account/api/admin/session.dever` 中的 `get status = app.status` 对应 `/user/account/admin/session/status`。`sites.<key>.path` 匹配这里的 API 父目录:`admin` 匹配 `api/admin/**`,不匹配同级文件 `api/admin.dever`,也不改写 URL。每条 HTTP API 必须且只能归属一个站点;目录遗漏、path 前缀重叠和同一路径同方法重复都会在运行前报错。`rest` 可为同领域唯一 Model 生成 GET 列表/详情、POST、PUT、DELETE;多 Model 时写 `rest model` 或 `rest model.<topic>` 消歧。列表只接受有界 `page`、`size` 和至多一个显式 `search` 条件,不开放任意查询。自动 REST 只序列化公开字段;`private owner user_id: ... = dever.auth.user_id()` 在创建时写入可信身份,并把同一 owner 条件放入全部读写 SQL。客户端不能提交 owner 或无 `input` 的服务端字段。需要不同资源策略或跨 Model 编排时仍使用 App,不把业务规则塞进 REST 声明。
|
||||
|
||||
HTTP 绑定的 App 调用链可用 `dever.api.request_id()`、`method()`、`path()`、`client_address()`、`header(name)`、`cookie(name)`、`secret_cookie(name)` 读取请求元数据,并用 `set_header(name, value)`、`set_cookie(name, value, options)`、`set_secret_cookie(name, secret, options)` 设置响应元数据;无需传递 Context 参数。`client_address()` 只返回直接 TCP peer 的地址,不信任转发 Header。`secure_cookie_options()` 提供 `Path=/`、`SameSite=Lax`、`Secure`、`HttpOnly` 的起点,业务可构造 `CookieOptions` 调整 Domain 和 Max-Age。Secret Cookie 使用 `v1.` 加无填充 base64url 存储原始 Secret 字节,读写不会把 Secret 转成业务 Text;非此格式的值读作缺席。敏感请求头不能经 `header` 读为 Text,Secret Cookie 必须使用 Secure 与 HttpOnly;响应 Header 不允许覆盖 Set-Cookie、Content-Type、Content-Length 等运行时字段或注入换行。Header/Cookie 先暂存在请求作用域,只有 handler 成功、响应序列化成功且数据库提交成功后才发布;失败和回滚会丢弃它们。Cookie 写请求和使用 Cookie 认证的非安全方法必须携带 Origin,并要求 Origin 与 Host 都精确匹配 `sites.<key>.origin` 配置的外部 HTTP/HTTPS scheme、规范化主机和有效端口;运行时不从内部明文监听协议猜外部 HTTPS,也不信任转发 Header。CMD/Job 调用链不能使用 HTTP 请求能力,脱离请求的并发任务也不能调用这些能力。
|
||||
HTTP 绑定的 App 调用链可用 `dever.api.request_id()`、`method()`、`path()`、`client_address()`、`header(name)`、`cookie(name)`、`secret_cookie(name)` 读取请求元数据,并用 `set_header(name, value)`、`set_cookie(name, value, options)`、`set_secret_cookie(name, secret, options)` 设置响应元数据;无需传递 Context 参数。`client_address()` 只返回直接 TCP peer 的地址,不信任转发 Header。`secure_cookie_options()` 提供 `Path=/`、`SameSite=Lax`、`Secure`、`HttpOnly` 的起点,业务可构造 `CookieOptions` 调整 Domain 和 Max-Age。Secret Cookie 使用 `v1.` 加无填充 base64url 存储原始 Secret 字节,读写不会把 Secret 转成业务 Text;非此格式的值读作缺席。敏感请求头不能经 `header` 读为 Text,Secret Cookie 必须使用 Secure 与 HttpOnly;响应 Header 不允许覆盖 Set-Cookie、Content-Type、Content-Length 等运行时字段或注入换行。Header/Cookie 先暂存在请求作用域,只有 handler 成功并且响应序列化成功后才发布;失败会丢弃待发布元数据;普通入口回滚未提交事务,`long` 入口不会撤销先前已经提交的 App 事务。Cookie 写请求和使用 Cookie 认证的非安全方法必须携带 Origin,并要求 Origin 与 Host 都精确匹配 `sites.<key>.origin` 配置的外部 HTTP/HTTPS scheme、规范化主机和有效端口;运行时不从内部明文监听协议猜外部 HTTPS,也不信任转发 Header。CMD/Job 调用链不能使用 HTTP 请求能力,脱离请求的并发任务也不能调用这些能力。
|
||||
|
||||
POST App 可以直接接收一个顶层 `Upload` 及普通标量,此时请求必须是 `multipart/form-data`。Runtime 按 `http.upload` 的总大小、单文件、字段、part、header 和 filename 上限流式写入 `data/tmp`;filename 仅作展示值,不能成为路径。`Upload` 是 affine 请求资源,不能嵌套、复制、作为输出或进入 GET/CMD/helper;App 可读取 metadata 后显式 `close_upload`,或一次性传给同领域 Port,再由 Adapter 调用 `dever.storage.put`。未消费资源及解析失败、handler 失败和取消路径会清理临时文件。
|
||||
|
||||
@@ -1205,7 +1205,26 @@ transaction register(email: Text, display_name: Text) (account: model.Account) {
|
||||
}
|
||||
```
|
||||
|
||||
编译器沿完整调用图推导数据库 effect。最外层 transaction 成功时提交;error、fault 或取消时先回滚再传播原失败。同一连接的嵌套 transaction 复用外层事务。无数据库操作、跨连接,或在事务中通过 `run`、`parallel`、流式游标、Channel 启动可逃逸工作都会在构建前被拒绝。`blocking(call())` 可以在事务中使用,但仍须满足其目标非挂起、无数据库和无并发的既有检查,调用者会等待它完成。
|
||||
编译器沿完整调用图推导数据库 effect。普通写 HTTP、CMD 和 Job 在入口建立整体事务,响应编码成功后才提交;同一入口内的显式 `transaction` 复用外层事务。`long` 入口不建立整体事务,业务写库和持久入队必须跨入显式 `transaction`;自动 REST 写操作保持原来的事务边界。最外层 transaction 成功时提交;error、fault 或取消时先回滚当前事务再传播原失败。同一连接的嵌套 transaction 复用外层事务。无数据库操作、跨连接,以及事务内的并发、流式游标、HTTP、文件传输、外部 Worker 和密码计算都会在构建前被拒绝。`blocking(call())` 仅在目标不包含这些操作并满足原有非挂起、无数据库约束时可用。事务外可以等待或编排多个独立事务;写入前需在事务内重新核验状态。`long` 中先前已经提交的事务不会因为后续阶段或响应序列化失败而回滚;重试的幂等性、失败状态和外部产物清理由业务定义,数据库回滚不撤销外部调用。
|
||||
|
||||
`long` 只修饰 HTTP、CMD 或 Job 入口,不修饰 App 函数、`transaction` 或 `rest`;与 `public` 同用时写 `public long`。声明形式如下(App 与请求类型按各自领域定义):
|
||||
|
||||
```dever
|
||||
post create = app.create
|
||||
long post generate = app.generate
|
||||
long cmd generate = app.generate
|
||||
public long post login = app.login
|
||||
```
|
||||
|
||||
Job 保留原来的重试和超时声明:
|
||||
|
||||
```dever
|
||||
long job generate(input: app.Request) () retry(3) timeout(30000) {
|
||||
app.run(input)
|
||||
}
|
||||
```
|
||||
|
||||
`long` 表示入口不自动持有整体事务,不代表允许长事务、自动异步、自动延长超时或按运行秒数分类。普通自动事务中出现外部操作,或 `long` 调用链存在事务外写库,均在编译期报 C014;仅添加外部调用不能静默改变原子性。GET 即使声明 `long` 也不能写库或入队。
|
||||
|
||||
数据库错误默认传播,保留 `dever.database.Error` 的类别和消息:Pool、PoolExhausted、Connection、Timeout、Cancelled、Database、Constraint、NotFound、InvalidData、Migration。要主动捕获一个返回 Account 的 App 调用,可以声明下面的结果类型;`result(load_account(...))` 的成功载荷和完整错误集合必须与调用一致。
|
||||
|
||||
@@ -1429,7 +1448,7 @@ Dever 用分句、类型化失败和集合操作表达控制流程。以下写
|
||||
|
||||
- `if`/`else`、`switch`、`match` 和条件表达式;条件永久使用 function 分句。
|
||||
- `for`、`while`、`break`、`continue` 和用户递归;重复使用集合/Stream 组合器。
|
||||
- class、继承、interface、method、annotation、macro、unsafe 和 FFI。
|
||||
- class、继承、interface、method、annotation、macro、unsafe 和进程内裸指针 FFI;受管 C ABI 通过隔离的 `external exec` Worker 提供,不新增业务源码中的指针类型。
|
||||
- lambda、闭包、一般化一等 function、用户泛型 type/function。
|
||||
- exception、`throw` 和 `catch`;可恢复错误使用推导式默认传播、`result(call)` 和 `fail(...)`。
|
||||
|
||||
@@ -1442,10 +1461,10 @@ Linux x86_64 已提供签名安装包、机器共享编译服务和配套 skill
|
||||
- 通用动态 Json 值、Set 和 BigInt;持久化 JSON 使用 Model 的 `Json` 字段,普通 JSON 处理使用 `dever.json.Document`。
|
||||
- CONNECT、非空 trailer、服务器推送、WebSocket-over-HTTP/2,以及 WebSocket 子协议、压缩扩展和关闭帧元数据。
|
||||
- table/field 多租户隔离模式,以及按租户业务配置动态选择已编译 Adapter;当前只支持 database 隔离和进程级 Adapter 选择。
|
||||
- GPU capability、macOS/Windows 外部程序沙箱和完整宿主发行;当前也不提供 ARM64 宿主编译器安装包。
|
||||
- 跨 GPU 厂商的设备验收、macOS/Windows 受管外部程序和完整宿主发行;当前也不提供 ARM64 宿主编译器安装包。GPU 支持不包含驱动安装、设备调度、模型分发或自动放宽容器权限。
|
||||
- 编译器自举。
|
||||
|
||||
未支持的能力明确失败,不使用默认值或关闭隔离来继续运行。具体安装与沙箱条件见 [安装指引](skills/references/install.md)。
|
||||
未支持的能力明确失败,不使用默认值伪装支持。具体安装与执行条件见 [安装指引](skills/references/install.md)。
|
||||
|
||||
## 17. 开发建议
|
||||
|
||||
|
||||
Reference in new issue
Block a user