feat(auth)!: retire the api.requireAuth opt-out — anonymous data access is always denied (#3963 step 2) - #4043
Merged
Merged
Conversation
…ss is always denied (#3963) `api.requireAuth: false` let a deployment open its ENTIRE data plane with one config key. Removed. Auth is a kernel concern, not a deployment posture: anonymous callers are denied on every HTTP surface that reaches object data, unconditionally. Every surface that legitimately serves a session-less caller already derives its own narrow authorization from a declaration (control-plane allowlist, publicFormGrant, share-link token → SYSTEM, book.audience:'public' §6.7, MCP token), so none needed the global switch. This commit is the production + spec + migration + docs change; the test-suite rework (the seam that used requireAuth:false to dispatch handlers anonymously) follows. - core: shouldDenyAnonymous drops the `requireAuth` input — denies any anonymous, non-system caller outside the control-plane allowlist. - spec: `api.requireAuth` tombstoned (retiredKey) in RestApiConfigSchema and the stack `api` block, so authoring it fails with a fix-it message instead of being silently stripped (ADR-0104 / #3733). Protocol-18 conversion `stack-api-require-auth-removed` drops it via `os migrate meta`; spec-changes.json / upgrade-guide / api-surface regenerated. - rest / runtime / hono: every shouldDenyAnonymous call site loses the posture arg; the dispatcher's per-route gate is unconditional (only `auth:false` on a route opens it); boot warnings for the opt-out removed. - cli / plugin-dev: an auth-less stack that would serve a data API now FAILS AT BOOT (A1) instead of getting an explicit fail-open carve-out. - qa/verify: conformance matrix + harness updated to the unconditional posture. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TzLE9cw4gZKNyPN2ZP4iTt
…reAuth Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TzLE9cw4gZKNyPN2ZP4iTt
Anonymous access to object data is denied unconditionally now, so every test that used `requireAuth: false` to dispatch a handler anonymously needs a resolved caller. 175 rest failures + the runtime/client/qa live-server suites, all one root cause. - rest (mechanical): inject a resolved context via the existing resolveExecCtx override seam where the test exercises route mechanics, not authorization. Forwarding assertions now expect the resolved context to be threaded. - rest (behaviour): rest-meta-auth, the audience-gating block in rest.test.ts, and security-routes/explain reframed to the new posture — anonymous /meta/object is 401, anonymous public-book reads still work (publicBookGrant), explain stays authenticated-only (now via the shared UNAUTHENTICATED gate). - runtime: authenticate the dispatcher mechanics tests (handleMetadata, error passthrough, error leak) with a stub auth service / executionContext; http-dispatcher.requireauth rewritten to assert the unconditional gate. - client / http-conformance: register a minimal stub `auth` service in the live-server harnesses so the anonymous-deny gate is satisfied. - core: anonymous-deny.test drops the `requireAuth` input. - spec: step18 migration wires the stack-api-require-auth-removed conversion into the replay chain; generated reference doc + api-surface refreshed. - cli: merge-boot test uses a live api key (enforceProjectMembership), not the retired requireAuth, as its per-key-merge example. Pre-existing unrelated failure NOT touched: runtime datasource-autoconnect federation test fails identically on pristine origin/main in this sandbox. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TzLE9cw4gZKNyPN2ZP4iTt
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
# Conflicts: # packages/rest/src/rest.test.ts
…dead code block (#3963) Follow-up cleanup after retiring the opt-out. Most were stale comments asserting behaviour that no longer exists ("no-op when requireAuth is off", "when requireAuth is set", "requireAuth=true deployments"), updated to the unconditional anonymous-deny posture across rest-server, the runtime domains, plugin-security, plugin-approvals, and metadata-protocol. One was NOT just a comment: plugin-hono-server still computed `const requireAuth = restConfig?.api?.requireAuth ?? true` and logged a boot warning off it — dead plumbing, since denyAnonymous stopped reading requireAuth. Removed. hono suite green (116). Also merges origin/main (rest.test.ts discovery-route conflict — the route is control-plane/allowlisted, so it takes the serviceExists constructor from main and drops the unnecessary auth injection). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TzLE9cw4gZKNyPN2ZP4iTt
Contributor
📓 Docs Drift CheckThis PR changes 13 package(s): 130 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3963。这一系列的收尾。major —— 走了仓库的完整退役流程(墓碑 + 迁移链 + 生成物)。
做了什么
api.requireAuth: false曾让一个部署用一个布尔值打开整个数据面。删掉。auth 是内核关注点、不是部署姿态:匿名调用者在每一个触及对象数据的 HTTP 面上被无条件 deny。每一个合法地服务"无会话调用者"的面,本就各自从声明派生窄授权,没有一个需要这个全局开关:控制面 allowlist、
publicFormGrant(公开表单)、分享链接 token(以 SYSTEM 读)、book.audience:'public'(#3995)、MCP token。为什么是 major:仓库守门拦住了直接删键 —— 拦得对
第一版直接删
RestApiConfig.requireAuth时,authorable-surface 闸门(ADR-0104 / #3733)报错:这正是这一整轮在关的失败模式本身。 所以按规定改成墓碑化:
RestApiConfigSchema+ stackapi块)用retiredKey(...),把处方编进拒绝消息 —— 作者升级 spec 时看到的就是它;stack-api-require-auth-removed(+step18接入迁移链),os migrate meta自动删键;spec-changes.json/protocol-upgrade-guide.md/api-surface.json/ 生成的 reference doc 已重跑。破坏性变更
api.requireAuth是退役键,写它 → fix-it 报错(不再静默剥除)。shouldDenyAnonymous(@objectstack/core)不再接受requireAuth入参。objectstack serve和 plugin-dev 都是。给出两条出路(启用 auth,或不服务数据 API),并指明公开发布靠声明。顺带补齐 #3960 的实测
这个开关一旦真能用(#4002 修好后),我拿到匿名可达部署,带对照组跑:匿名读
sys_user,带不带伪造context.isSystem/__expandRead结果都是 1 行 —— #3960 的修复成立(伪造 context 被剥),sys_user被读到纯是requireAuth:false的语义(正是退役它的理由)。测试(这是大头)
无条件 deny 后,所有靠
requireAuth:false匿名 dispatch 的测试都需要一个已解析调用者 —— 单根因,175 个 rest 失败 + runtime/client/qa live-server 套件。分两类处理:resolveExecCtxoverride 缝注入已认证 context;转发断言改为期望 context 被透传;rest-meta-auth、rest.test的 audience 块、security-routes/explain、http-dispatcher.requireauth、hono-anonymous-deny逐个重构断言到新姿态(匿名/meta/object401;匿名 public-book 仍可读;explain 仍 authenticated-only,现经共享UNAUTHENTICATEDgate)。逐包全绿:rest 491 / runtime 904 / core 413 / spec 6897 / metadata-protocol 99 / cli 837 / client 200 / http-conformance 46 / plugin-hono-server 116 / plugin-dev 7。全量构建 71/71。
一个如实标注的既有失败(未碰)
runtime/src/datasource-autoconnect.test.ts的一条 federation 测试,在干净的 origin/main 上于本沙箱一致失败(3/3,数据顺序不符、非 401、我的 diff 没碰它)。是环境既有 flaky,不在本 PR 范围。CI 的干净环境会给出它的真实状态。审阅指引
packages/core/src/security/anonymous-deny.ts(无条件 deny)+packages/rest/src/rest-server.ts的enforceAuth。cli/src/commands/serve.ts+plugins/plugin-dev/src/dev-plugin.ts。spec/src/api/rest-server.zod.ts、spec/src/stack.zod.ts、spec/src/conversions/registry.ts、spec/src/migrations/registry.ts。🤖 Generated with Claude Code
https://claude.ai/code/session_01TzLE9cw4gZKNyPN2ZP4iTt
Generated by Claude Code