跳到主要内容

ARC 2.0.0-beta.35 · arc#4065 之后

限制谁能读一页

先声明集合默认权限,再用 access 收紧单条记录,发布前核对 serve-time 门。

Web Device 在回放预渲染 HTML 之前、于 serve time 决定谁能读这一页。public 必须写在某一层策略上。没有集合、路径或 hatch 默认值的未标记记录是 404,站点管理员也不例外。

Connect 当前承认四种角色:guest、member、admin、owner。none 不是角色,而是硬拒绝。

先把集合设为 public,再收紧单条记录

常见写法:集合默认是 public,未标记的记录保持可读。再给少数受限记录打标。

yaml
# blocklet.yaml
collections:
  articles:
    access: public
yaml
# 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 默认404404
access: public全文全文
access: member(或 admin / owner),省略 preview,记录可上列表第一屏试读 + 门全文
access: member 且 preview: true试读 + 门。只有没有试读 HTML 时才用声明的 excerpt全文
access: member 且 preview: false,记录可上列表只有门,无试读全文
access: member 且 preview: false,记录不可上列表404全文
access: none404404

记录上的具名角色只会收紧上层范围。记录上的 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 截止。

未登录读者打开一篇仅限 admin 的文章:hero 还在,第一屏试读,然后是 Sign in 门

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:

bash
curl -sI http://arcblock.localhost:4922/en/articles/access-fixture-team/
text
HTTP/1.1 200 OK
cache-control: private, no-store
x-robots-tag: noindex

HTML 含 access-teaser,随后是:

html
<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&amp;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 测试文章。

bash
# 硬拒绝 — 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。两个头都必须带:

bash
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 的记录上仍会看到门:

bash
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。