Skip to content

feat(plugin-hono-server)!: 删除 CRUD/discovery 便利面 —— 插件回归纯传输适配器(#4073 终点) - #4296

Merged
os-zhuang merged 4 commits into
mainfrom
claude/vercel-startup-permissions-provider-iwtkqm
Jul 31, 2026
Merged

feat(plugin-hono-server)!: 删除 CRUD/discovery 便利面 —— 插件回归纯传输适配器(#4073 终点)#4296
os-zhuang merged 4 commits into
mainfrom
claude/vercel-startup-permissions-provider-iwtkqm

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

#4073 的终点。前置拆分(#4144)、证据(#4260)、默认值翻转(#4280)都已合并;按决定把删除也放进 17.0.0,不跨 major 拆成两次迁移。

净 −678 行。 HonoServerPlugin 现在只拥有 socket、中间件和三条 current-user 端点 —— 数据面与 discovery 各自单一 owner(ADR-0076 D11)。

删除

  • raw C+R /api/v1/data/:object(含 /:id)—— 直连 ObjectQL 的那份
  • 本插件的第三份 /api/v1/discovery + /.well-known/objectstack payload —— 它早于 DiscoverySchema,且缺 services(D12 的 single source of truth),无法合规
  • registerStandardEndpoints 本身 —— 是删掉,不是默认关掉。传它现在是类型错误;用 as never 硬传也挂不出任何东西(有测试钉住)
  • 随之而去的 DISCOVERY_ROUTE_SEGMENTS 与六个只为它存在的 import

不受影响

/auth/me/* + /me/apps(唯一供给,#4144 起无条件注册);以及所有 composed 宿主 —— os serveobjectstack dev、cloud 的 objectos —— 它们挂的 owner 本来就在应答这些路由,且 #4260 已证两种 flag 位置下响应逐字节相同。

无 owner 的宿主保留 boot warn,措辞改为点名两个 owner(因为"opt in"已不再是出路之一)。

测试:逐个按「它到底在钉什么」决定,而不是一刀切

测试 处置 理由
hono-discoveryhono-anonymous-deny 整体依附于已删路由。#2567 的不变量并未随之丢失 —— 闸门在 core,REST 在存活的面上强制它
server-timing-e2e 保留,改指 /auth/me/permissions #3361 的回归价值是「perf 中间件 + 自行解析 principal 的真实 handler」,不是那条路由;现有权限集 fixture 本就是这个形状
client.hono 保留,改挂 REST 它是 唯一 覆盖 client.connect() 与 discovery 握手的测试,删掉会丢真实信号
hono-standard-endpoints-default 改写为 hono-transport-only 原主题(flag 默认值)已不存在;改钉终态
/me/* 相对 CRUD 块的两条顺序用例 删,留说明 #4088 让 auth catch-all 可穿透,它们防的碰撞已不存在,且已由 auth-catchall-fallthrough.test.ts 直接钉住
七处跨包调用点 去掉选项即可

server-timing-e2e 的匿名用例从断言 401 改为 200 且无 Server-Timing —— 该端点对匿名调用者是"如实回答"而非"拒绝",要钉的不变量是闸门没开,不是状态码。

AGENTS.md:把这条线付过学费的四条规则写下来

一条路由一个 owner · 显式组合优于默认魔法 · 缺席要响亮 · 机器可读面不许撒谎。

外加一条验证方法:「谁在服务这条路径」是关于 composed 且 provisioned 运行时的问题 —— 不是关于谁声明了它、不是关于注册顺序、也不是关于一个能启动的最小 harness。#4073 被答错三次,每次正好对应绕过其中一条。

验证

结果
plugin-hono-server 135/135
client 三套件 9/9
runtime 四个集成套件 19/19
http-conformance 46/46
全量 build 71/71
包内 tsc / 改动文件 lint 通过 / 0 error 0 warning

迁移(changeset 内有完整 FROM → TO)

只有「挂 HonoServerPlugin 但两个 owner 都不挂」的宿主受影响:挂 createRestApiPlugin(完整 CRUD + 全闸门)或 createDispatcherPlugin。没有 flag 可以退回。

关联:#4073(终点)、#4280#4260#4144#4088#4018#3298#2567


🤖 Generated with Claude Code

https://claude.ai/code/session_016gEeLZ4oTeSXG6fKG1r3vd


Generated by Claude Code

…ugin is a transport adapter (#4073)

Completes the retirement. HonoServerPlugin now owns the socket, the middleware
and the three current-user endpoints, and nothing else. The data and discovery
APIs have one owner each — @objectstack/rest and the runtime dispatcher
(ADR-0076 D11).

Deleted: raw C+R `/api/v1/data/:object` (+ `/:id`), this plugin's third
`/api/v1/discovery` + `/.well-known/objectstack` payload, and the
`registerStandardEndpoints` flag itself — gone, not defaulted off. With it go
`DISCOVERY_ROUTE_SEGMENTS` and six imports (`IDataEngine`,
`shouldDenyAnonymous`, both `ANONYMOUS_DENY_*`, `ApiRoutes`,
`makeExecutionContextResolver`) that existed only to serve it.

Unaffected: `/auth/me/*` + `/me/apps` (sole supply, unconditional since #4144),
and every composed host — `os serve`, `objectstack dev`, cloud's objectos —
which mount an owner that already answered these routes byte-identically either
way (#4260). A host with NO owner keeps the boot warn, reworded to name both
remedies now that opting in is not one of them.

Tests, each decided on what it was actually pinning rather than swept:

- `hono-discovery` / `hono-anonymous-deny` — deleted. Both existed wholly to
  test the retired routes. #2567's invariant is not lost with the latter: the
  gate lives in core and REST enforces it on the surface that survives.
- `server-timing-e2e` — KEPT, repointed at `/auth/me/permissions`. #3361's
  regression value is "perf middleware + a handler that resolves the principal
  itself", not the route; the permission-set fixtures already fit. Its anonymous
  case asserts 200-without-timings instead of 401, because that endpoint answers
  anonymous callers rather than denying them — the invariant is the closed gate.
- `client.hono` — KEPT, repointed at a REST-composed host. It is the ONLY
  coverage of `client.connect()` and the discovery handshake, so deleting it
  would have cost real signal; its #4018 assertions now read against REST's
  registry-driven discovery, where `metadata` IS advertised and answers.
- `hono-standard-endpoints-default` → `hono-transport-only`. Its subject was the
  flag's default; it now pins the end state, including that passing the removed
  option resurrects nothing.
- The two cases pinning `/me/*` ordering relative to the CRUD block are gone,
  with a note: #4088 made plugin-auth's catch-all fall through, so the ordering
  fragility they guarded no longer exists and is pinned directly in
  `auth-catchall-fallthrough.test.ts`.
- Seven cross-package call sites simply drop the option.

AGENTS.md gains the four rules this thread paid for — one route one owner,
explicit composition over default magic, absence must be loud, machine-readable
surfaces must not lie — plus the verification note: "who serves this path" is a
question about the composed, PROVISIONED runtime. #4073 was answered wrongly
three times, once per shortcut around that.

Verified: plugin-hono-server 135/135, client 3 suites 9/9, runtime 4 integration
suites 19/19, http-conformance 46/46, full build 71/71, package tsc clean,
changed-file lint 0/0. Net −678 lines.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gEeLZ4oTeSXG6fKG1r3vd
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 31, 2026 4:43am

Request Review

…-permissions-provider-iwtkqm

# Conflicts:
#	packages/plugins/plugin-hono-server/src/hono-plugin.ts
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Jul 31, 2026
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/plugin-hono-server, @objectstack/dogfood.

9 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/getting-started/your-first-project.mdx (via @objectstack/plugin-hono-server)
  • content/docs/permissions/authentication.mdx (via @objectstack/plugin-hono-server)
  • content/docs/permissions/authorization.mdx (via packages/qa/dogfood)
  • content/docs/permissions/delegated-administration.mdx (via packages/qa/dogfood)
  • content/docs/plugins/index.mdx (via @objectstack/plugin-hono-server)
  • content/docs/plugins/packages.mdx (via @objectstack/plugin-hono-server)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/plugin-hono-server)
  • content/docs/releases/implementation-status.mdx (via @objectstack/plugin-hono-server)
  • content/docs/releases/v16.mdx (via @objectstack/plugin-hono-server)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

claude added 2 commits July 31, 2026 04:41
…-deny ledger

The Dogfood Regression Gate caught the deletion, which is the ledger doing its
job:

    STALE covers — surface no longer in source: data:hono-plugin.ts:POST /data/:object
                                                data:hono-plugin.ts:GET /data/:object/:id
                                                data:hono-plugin.ts:GET /data/:object

`anonymous-deny-hono-data` classified an entry point that no longer exists, so
the row goes with its surface. Three places referenced it and each needed a
different answer:

- the matrix row itself — deleted, with a note on the section above it that the
  #2567 invariant is UNCHANGED: it has one fewer implementation to hold it in,
  not one fewer guarantee;
- `HIGH_RISK` — the id dropped from the list;
- the ratchet's own negative test `(a) a row that DROPS its covers` — it used
  that row as its FIXTURE, so it would have passed vacuously or not at all.
  Repointed at `anonymous-deny-meta`, which covers a live surface, so the test
  still has a real classification to lose. This one mattered: silently letting
  it fall through would have disarmed the ratchet that just caught this.

`showcase-anonymous-deny-surfaces.dogfood.test.ts` keeps every assertion — the
surface-level 401 is enforced by @objectstack/rest, the route's sole owner now.
Only its comments, which described the deleted raw-hono routes, are updated.

Verified: authz-conformance 8/8, full dogfood suite 430 passed / 3 skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gEeLZ4oTeSXG6fKG1r3vd
…2567 matrix

The drift check flagged nine docs; eight carry none (the quickstart and
authentication ones were settled in #4280, `http-protocol.mdx` entered only via
the CORS change this branch merged from main, and `delegated-administration.mdx`
came along as a same-package sibling with nothing to say about this).

`authorization.mdx` was real, and it is the kind that matters most: it documents
a SECURITY invariant, and it named the deleted surface twice — once in the list
of HTTP surfaces the anonymous-deny decision is uniform across, and once in the
implementation list, as `plugin-hono-server` `denyAnonymous`. Left alone, the
permissions doc would promise a gate on an entry point that no longer exists.

Both now read as history, matching how the same sentence already handles the
retired GraphQL endpoint: the surface LEFT the matrix (v17, #4073) because the
duplicate was deleted, not because it went ungated. The invariant is unchanged —
`shouldDenyAnonymous` still backs REST `/data` and the dispatcher's
metadata/AI paths, and the source-enumerating ratchet still fails CI on a new
ungated surface. It just has one fewer door to hold shut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gEeLZ4oTeSXG6fKG1r3vd
@os-zhuang
os-zhuang marked this pull request as ready for review July 31, 2026 05:36
@os-zhuang
os-zhuang merged commit e5a4d26 into main Jul 31, 2026
24 of 25 checks passed
@os-zhuang
os-zhuang deleted the claude/vercel-startup-permissions-provider-iwtkqm branch July 31, 2026 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants