Web Device 在回放预渲染 HTML 之前、于 serve time 决定谁能读这一页。public 必须写在某一层策略上。没有集合、路径或 hatch 默认值的未标记记录是 404,站点管理员也不例外。
Connect 当前承认四种角色:guest、member、admin、owner。none 不是角色,而是硬拒绝。
先把集合设为 public,再收紧单条记录
常见写法:集合默认是 public,未标记的记录保持可读。再给少数受限记录打标。
# blocklet.yaml
collections:
articles:
access: public# content/articles/members-only/content.md
---
title: Members-only note
access: member
---本站 articles 集合已经有这个默认值。collections.<type>.access 是该类型详情的默认值,不设置 /articles/ 列表页。零配置的集合列表路由默认 public,除非你锁那条路由。因此类型级 member 默认不会关掉列表,只会关掉未标记的详情。
不要写 preview。未登录读者会看到正文的第一屏,然后是门。树的其余部分不会进入 HTML。Sitemap、llms.txt 和 MCP 会去掉受限记录,除非你写 preview: true。从集合继承 public 的未标记记录仍会出现在这些面上(arc#4086 之后)。
collections.<type>.readRole 是存储读取授权,不是这个 HTML 门。
未登录调用方是 guest。已登录的 DID Connect 会话可能带 member、admin 或 owner。本页不说明站点如何授予这些角色。
选择记录字段
| 你写的 | 未登录读者 | 匹配角色,或 admin/owner |
|---|---|---|
无 access,集合 access: public | 全文 | 全文 |
无 access,且没有集合 / 路径 / hatch 默认 | 404 | 404 |
access: public | 全文 | 全文 |
access: member(或 admin / owner),省略 preview,记录可上列表 | 第一屏试读 + 门 | 全文 |
access: member 且 preview: true | 试读 + 门。只有没有试读 HTML 时才用声明的 excerpt | 全文 |
access: member 且 preview: false,记录可上列表 | 只有门,无试读 | 全文 |
access: member 且 preview: false,记录不可上列表 | 404 | 全文 |
access: none | 404 | 404 |
记录上的具名角色只会收紧上层范围。记录上的 access: public 打不开被锁的路径或集合。要在锁下放开某一个 slug,写一条更具体的 accessPaths。见内容访问参考。
记录是否可上列表,看列表路由是不是 public(零配置的 /{locale}/{type}/ 是),或 blocklet.yaml 是否写了 hatch accessDefault: public。集合 access 不会让列表变 public。本站文章列表是 public,所以未写 preview: false 的受限文章会出试读。
预渲染可能把全文写进 .web-cache。闸在 serve 时、回放该文件之前。不要把 .web-cache 当静态文件托管。
被拒绝的读者会看到什么
详情页仍在站点 chrome 里。标题、作者、日期留在 post-hero。封面被清空。正文槽是第一屏试读(除非 preview: false)和 access-gate 截止。

2026-08-15 对一篇列出的 admin 文章的匿名 GET,ARC 2.0.0-beta.35,http://arcblock.localhost:4922/。现场采集,不是 mock。该夹具 URL 已不在本站。
2026-08-15、ARC 2.0.0-beta.35、http://arcblock.localhost:4922/ 上对一篇列出的 access: admin 文章的匿名 GET:
curl -sI http://arcblock.localhost:4922/en/articles/access-fixture-team/HTTP/1.1 200 OK
cache-control: private, no-store
x-robots-tag: noindexHTML 含 access-teaser,随后是:
<aside class="access-gate" data-kind="promo-shell" data-required-role="admin">
<p class="access-gate-message">The rest of this piece is for admins.</p>
<a class="access-gate-signin"
href="/.well-known/service/login?return_to=%2Fen%2Farticles%2Faccess-fixture-team%2F&cancel_to=%2Fen%2Farticles%2Faccess-fixture-team%2F">Sign in</a>
</aside>那次采集里的受保护正文不出现。同一 URL 配上匹配的测试 caller 会返回正文,且没有门。登录走 DID Connect。
试读是对 AUP 树的服务端裁切(约 480 个视觉单位、最多两个顶层块、永远扣下最后一块)。它不是把全文放进页面再用 CSS 渐隐。
检查运行中的站点
使用包含 arc#4065 的运行时(上面采集的 arc --version:2.0.0-beta.35)。把服务指到你自己的 blocklet,探测你在那里声明的记录。本站不发布 access-gate 测试文章。
# 硬拒绝 — access: none 的记录
curl -sI http://arcblock.localhost:4900/en/articles/<your-none-record>/
# HTTP/1.1 404 Not Found
# cache-control: private, no-store
# content-length: 0
# 显式 public
curl -sI http://arcblock.localhost:4900/en/articles/<your-public-record>/
# HTTP/1.1 200 OK
# cache-control: no-cache以 AFS_TEST_ALLOW_CALLER_HEADER=1 启动的本地服务接受测试 caller。两个头都必须带:
curl -s -H 'x-caller-did: z1admin' -H 'x-caller-role: admin' \
http://arcblock.localhost:4900/en/articles/<your-admin-record>/ \
| rg '<只出现在受保护正文里的字符串>'member 调用方能打开 access: member 的记录,在 access: admin 的记录上仍会看到门:
curl -s -H 'x-caller-did: z1member' -H 'x-caller-role: member' \
http://arcblock.localhost:4900/en/articles/<your-member-record>/ \
| rg '<member-only 正文标记>'
curl -s -H 'x-caller-did: z1member' -H 'x-caller-role: member' \
http://arcblock.localhost:4900/en/articles/<your-admin-record>/ \
| rg 'access-gate|<admin-only 正文标记>'只带 x-caller-role 仍会返回门。不要在公开部署上发送这些头。
失败情形
| 你看到的 | 常见原因 |
|---|---|
404,空 body,Cache-Control: private, no-store | 没有范围默认值,或写了 access: none |
| 有门,但没有第一屏试读 | 你写了 preview: false |
| 试读里出现了文章最后一节 | 不符合合同。向上游报 issue;裁切必须扣下最后一个顶层块 |
记录 access: public 仍被挡或 404 | 更严的 accessPaths 或集合默认值是天花板。列表路由 public 时是试读/门,不是 404 |
已登录的 member 仍看到 admin 门 | 承认是对每个具名约束做 AND。member 不满足 admin |
Sitemap / llms.txt / MCP 列出了受限文章 | 发现面只在 preview: true 时放出受限记录(只有壳字段,无正文)。要让它不出现在发现面,省略 preview |
边界
- v1 承认 DID Connect 的
guest/member/admin/owner。其它角色名可以写,也会出现在门的文案里;Connect 当前不会签发它们。 - 可验证凭证角色不是承认路径。跟踪 arc#4056。
- 条目本地媒体和集合 RSS 使用同一套承认规则。试读不会保留 media 块(文件会 404)。
- 共享公共缓存只允许完整的匿名开放页。
- 预渲染旁的
index.access.json不是公开 URL。GET 该路径是 404。
解析顺序、accessPaths 语法、HTTP 头和发现规则见内容访问参考。门的 markup 见 access-gate。