Files

58 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 按需复用的完整项目
这些项目随 skill 提供,都包含 `module/`、`test/` 和 `config/setting.json`。复制需要的项目到新目录,再替换业务内容,不要把整个 examples 放进 module。最小项目直接用 `dever new` 创建。
| 场景 | 项目资产 | 首次阅读 |
| --- | --- | --- |
| HTTP、受保护 REST、真实身份核验 | [http-rest](../assets/examples/http-rest/) | `config/setting.json`、`module/access/session/app.dever`、`module/content/article/` |
| 入队、持久 Job、隔离数据库与虚拟时钟 | [jobs](../assets/examples/jobs/) | `module/report/archive/`、`test/report/archive/queued.dever` |
| 外部能力、声明失败、每例独立 fake | [external-lib](../assets/examples/external-lib/) | [三语言接入说明](external-lib.md) |
| 筛选、映射、累计与逐项断言 | [collections](../assets/examples/collections/) | [集合与处理函数](language.md#集合与处理函数) |
| 普通二进制 Port、CMD 与 fake | [command](../assets/examples/command/) | [二进制调用说明](libraries.md#外部-lib-与普通二进制) |
复制后先运行 `dever fmt <root> --check` 和 `dever check <root>`,再按下面的命令运行相关测试。这些检查不准备 Worker、不连接部署数据库、不启动 HTTP/Job 服务。
文件要放在示例对应的角色中。遇到无法从业务入口调用到的代码报错(C016),接通真实调用或删除废弃代码,不添加假调用。
## HTTP 与 REST
`http-rest` 展示的是受保护内容资源和已有登录系统的 verify 接口,不包含账号注册、密码登录或签发凭据。匿名健康检查 `GET /system/health/admin/status/ready` 返回 `{"code":0,"message":"ok","data":true}`;它没有持久数据或租户依赖。
`module/content/article/api/admin/entries.dever` 的 `rest model` 生成 `/content/article/admin/entries` 下的资源接口;用 `dever api <root> --output <new-file>` 查看精确方法、路径和输入合同。REST 的权限键为 `content.article.admin.read/create/replace/delete`。例如创建正文包含 `title`、`body`,title 经同领域 pure Domain trim 后再应用 Model 长度约束。Model 自动提供 id/created_at,不手写 CRUD App。
配置中的 `admin.path = "admin"` 对应两个领域的 `api/admin/**`。
身份核验先读取 global Session,检查 UUID、subject、site、tenant key、过期与吊销状态,再检查用户、租户和成员关系。成功返回只有 id/user_id/tenant_id 的 Identity;失败返回 Unauthorized。不能原样回显 claims 冒充核验,也不从 verify 返回权限列表。
接入已有登录系统时,由它的认证流程创建 User、Tenant、Membership、Session,再按 provider 配置签发 subject/session/tenant。示例不会自动建默认用户、发演示 token 或绕过权限。
部署前替换 JWT 密钥,迁移租户数据库,再用 `dever tenant owner <root> <positive-tenant-id> admin <positive-user-id>` 建立初始 Owner。参数是数据库 ID,不是 token 的 tenant key。后续角色权限用核心 `dever.auth` 管理,不复制一套 RBAC 表。建 Owner 和迁移属于运维操作,不是普通测试。
这里开启 database 租户隔离:global 身份表在控制库,Article 在租户库,匿名 health 不触达 Article。不要添加 `tenant.mode/field/table` 或在缺少租户时回退控制库。站点没有使用 Cookie;如果改为 Cookie 登录,补充精确 `sites.admin.origin` 和 issue_cookie/clear_cookie 的同源合同。
定向测试:`dever test <root> --filter content.article.title --timeout-ms 5000`。该例验证标题规则,不证明 REST HTTP、JWT、权限或实际租户迁移已验收。
## 持久 Job
`jobs` 的 `report.archive.submit` CMD 接受一个 `input` record:
```sh
dever run <root> -- report.archive.submit '{"input":{"key":"report-2026-10","title":"Monthly report"}}'
```
这是会写示例数据库的显式运行命令,不是普通验证。CMD 只入队并退出;没有命令参数的服务启动才按配置 `runtime.mode = "worker"` 执行持久队列,不能为了跑测试启动它。
Job 声明 `database default`、同领域 App 参数类型、`retry(3)` 和 `timeout(30000)`,执行时只调用 App。
入队和入口写入在同一事务中;key 用来识别同一请求,重复提交不会创建另一个任务。Job 执行有自己的事务,Model 的 request_key 唯一约束防止重复档案。失败由核心队列重试,不另写循环、sleep 或第三方 Worker。
`dever test <root> --filter report.archive.queued --timeout-ms 5000` 使用运行器拥有的临时 SQLite。测试重复入队验证同一任务 ID,通过 `dever.test.drain_jobs(5)` 执行已到期任务,使用 `advance_clock(1000)` 推进虚拟时钟。既不使用配置里的 `data/jobs.db`,也不启动真实后台服务。
CMD/Test 的可信执行身份由核心建立为 System。若改为 HTTP 入队,只能从受保护写 API 到达;public 不得入队。核心在每次 User Job 尝试时重新验证会话、租户、组件与入队接口的精确权限,不保存角色快照。
## 来源与验证边界
集合项目可直接运行 `dever run <root> -- content.article.summarize '{"articles":[{"title":" First ","published":true},{"title":"Hidden","published":false}]}'`,结果包含 `titles: ["First"]` 和 `title_length: 5`。`dever test <root> --filter content.article --timeout-ms 5000` 同时运行集合业务和语法分句断言,无需数据库或服务。
这些项目保留了当前语言的角色边界、身份核验、Job 和 Port fake 用法,关键源码随 skill 提供。教程中的 dever 代码块必须有“源码”链接,内容与链接文件的连续片段逐字匹配,所属完整项目参加源码、业务入口、格式和测试检查。真实 Lib、数据库部署和 HTTP 仍需各自验收。